Merge pull request #4761 from ScottNZ/lua-desert-shellmap
Port the desert shellmap to Lua
This commit is contained in:
@@ -45,6 +45,7 @@ NEW:
|
||||
Added a snow variation of the Allied Barracks by Kilkakon.
|
||||
Added a desert variation of the Allied Barracks by Kilkakon.
|
||||
Added a desert variation of the Missile Silo by Kilkakon.
|
||||
Removed the temperate shellmap and improved the design and performance of the desert shellmap.
|
||||
Tiberian Dawn:
|
||||
Commando can now plant C4 on bridges.
|
||||
Added the Asset Browser to the Extras menu.
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.RA.Air;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
class DefaultShellmapScriptInfo : TraitInfo<DefaultShellmapScript> { }
|
||||
|
||||
class DefaultShellmapScript: IWorldLoaded, ITick
|
||||
{
|
||||
Dictionary<string, Actor> Actors;
|
||||
static WPos ViewportOrigin;
|
||||
WorldRenderer worldRenderer;
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
worldRenderer = wr;
|
||||
var b = w.Map.Bounds;
|
||||
ViewportOrigin = new CPos(b.Left + b.Width/2, b.Top + b.Height/2).CenterPosition;
|
||||
worldRenderer.Viewport.Center(ViewportOrigin);
|
||||
|
||||
Actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||
Sound.SoundVolumeModifier = 0.25f;
|
||||
}
|
||||
|
||||
int ticks = 0;
|
||||
float speed = 4f;
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
var t = (ticks + 45) % (360f * speed) * (Math.PI / 180) * 1f / speed;
|
||||
var offset = new float2(15360, 10240) * float2.FromAngle((float)t);
|
||||
worldRenderer.Viewport.Center(ViewportOrigin + new WVec((int)offset.X, (int)offset.Y, 0));
|
||||
|
||||
if (ticks == 50)
|
||||
{
|
||||
Scripting.RASpecialPowers.Chronoshift(self.World, new List<Pair<Actor, CPos>>()
|
||||
{
|
||||
Pair.New(Actors["ca1"], new CPos(96, 70)),
|
||||
Pair.New(Actors["ca2"], new CPos(98, 72))
|
||||
}, Actors["pdox"], -1, false);
|
||||
}
|
||||
|
||||
if (ticks == 100)
|
||||
Actors["mslo1"].Trait<NukePower>().Activate(Actors["mslo1"], new Order() { TargetLocation = new CPos(98, 52) });
|
||||
if (ticks == 140)
|
||||
Actors["mslo2"].Trait<NukePower>().Activate(Actors["mslo2"], new Order() { TargetLocation = new CPos(95, 54) });
|
||||
if (ticks == 180)
|
||||
Actors["mslo3"].Trait<NukePower>().Activate(Actors["mslo3"], new Order() { TargetLocation = new CPos(95, 49) });
|
||||
|
||||
if (ticks == 430)
|
||||
{
|
||||
Actors["mig1"].Trait<AttackPlane>().AttackTarget(Target.FromActor(Actors["greeceweap"]), false, true);
|
||||
Actors["mig2"].Trait<AttackPlane>().AttackTarget(Target.FromActor(Actors["greeceweap"]), false, true);
|
||||
}
|
||||
|
||||
ticks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,319 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Air;
|
||||
using OpenRA.Mods.RA.Buildings;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using OpenRA.Mods.RA.Scripting;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
class DesertShellmapScriptInfo : TraitInfo<DesertShellmapScript>, Requires<SpawnMapActorsInfo> { }
|
||||
|
||||
class DesertShellmapScript : ITick, IWorldLoaded
|
||||
{
|
||||
World world;
|
||||
WorldRenderer worldRenderer;
|
||||
Player allies;
|
||||
Player soviets;
|
||||
Player neutral;
|
||||
|
||||
WPos[] viewportTargets;
|
||||
WPos viewportTarget;
|
||||
int viewportTargetNumber;
|
||||
WPos viewportOrigin;
|
||||
int mul;
|
||||
int div = 400;
|
||||
int waitTicks = 0;
|
||||
|
||||
int nextCivilianMove = 1;
|
||||
|
||||
Actor attackLocation;
|
||||
Actor coastWP1;
|
||||
Actor coastWP2;
|
||||
int coastUnitsLeft;
|
||||
static readonly string[] CoastUnits = { "e1", "e1", "e2", "e3", "e4" };
|
||||
|
||||
Actor paradrop1LZ;
|
||||
Actor paradrop1Entry;
|
||||
Actor paradrop2LZ;
|
||||
Actor paradrop2Entry;
|
||||
static readonly string[] ParadropUnits = { "e1", "e1", "e1", "e2", "e2" };
|
||||
|
||||
Actor offmapAttackerSpawn1;
|
||||
Actor offmapAttackerSpawn2;
|
||||
Actor offmapAttackerSpawn3;
|
||||
Actor[] offmapAttackerSpawns;
|
||||
static readonly string[] OffmapAttackers = { "ftrk", "apc", "ttnk", "1tnk" };
|
||||
static readonly string[] AttackerCargo = { "e1", "e2", "e3", "e4" };
|
||||
|
||||
static readonly string[] HeavyTanks = { "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk" };
|
||||
Actor heavyTankSpawn;
|
||||
Actor heavyTankWP;
|
||||
static readonly string[] MediumTanks = { "2tnk", "2tnk", "2tnk", "2tnk", "2tnk", "2tnk" };
|
||||
Actor mediumTankChronoSpawn;
|
||||
|
||||
static readonly string[] ChinookCargo = { "e1", "e1", "e1", "e1", "e3", "e3" };
|
||||
|
||||
static readonly string[] InfantryProductionUnits = { "e1", "e3" };
|
||||
static readonly string[] VehicleProductionUnits = { "jeep", "1tnk", "2tnk", "arty" };
|
||||
Actor alliedBarracks;
|
||||
Actor alliedWarFactory;
|
||||
|
||||
Dictionary<string, Actor> actors;
|
||||
|
||||
Actor chronosphere;
|
||||
Actor ironCurtain;
|
||||
|
||||
CPos[] mig1Waypoints;
|
||||
CPos[] mig2Waypoints;
|
||||
|
||||
Actor chinook1Entry;
|
||||
Actor chinook1LZ;
|
||||
Actor chinook2Entry;
|
||||
Actor chinook2LZ;
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (world.FrameNumber % 100 == 0)
|
||||
{
|
||||
var actor = OffmapAttackers.Random(world.SharedRandom);
|
||||
var spawn = offmapAttackerSpawns.Random(world.SharedRandom);
|
||||
var u = world.CreateActor(actor, soviets, spawn.Location, Traits.Util.GetFacing(attackLocation.Location - spawn.Location, 0));
|
||||
var cargo = u.TraitOrDefault<Cargo>();
|
||||
if (cargo != null)
|
||||
{
|
||||
while (cargo.HasSpace(1))
|
||||
cargo.Load(u, world.CreateActor(false, AttackerCargo.Random(world.SharedRandom), soviets, null, null));
|
||||
}
|
||||
u.QueueActivity(new AttackMove.AttackMoveActivity(u, new Move.Move(attackLocation.Location, 0)));
|
||||
}
|
||||
|
||||
if (world.FrameNumber % 25 == 0)
|
||||
{
|
||||
foreach (var actor in world.Actors.Where(a => a.IsInWorld && a.IsIdle && !a.IsDead()
|
||||
&& a.HasTrait<AttackBase>() && a.HasTrait<Mobile>()).Except(actors.Values))
|
||||
MissionUtils.AttackNearestLandActor(true, actor, actor.Owner == soviets ? allies : soviets);
|
||||
|
||||
MissionUtils.StartProduction(world, allies, "Infantry", InfantryProductionUnits.Random(world.SharedRandom));
|
||||
MissionUtils.StartProduction(world, allies, "Vehicle", VehicleProductionUnits.Random(world.SharedRandom));
|
||||
}
|
||||
|
||||
if (world.FrameNumber % 20 == 0 && coastUnitsLeft-- > 0)
|
||||
{
|
||||
var u = world.CreateActor(CoastUnits.Random(world.SharedRandom), soviets, coastWP1.Location, null);
|
||||
u.QueueActivity(new Move.Move(coastWP2.Location, 0));
|
||||
u.QueueActivity(new AttackMove.AttackMoveActivity(u, new Move.Move(attackLocation.Location, 0)));
|
||||
}
|
||||
|
||||
if (world.FrameNumber == nextCivilianMove)
|
||||
{
|
||||
var civilians = world.Actors.Where(a => !a.IsDead() && a.IsInWorld && a.Owner == neutral && a.HasTrait<Mobile>());
|
||||
if (civilians.Any())
|
||||
{
|
||||
var civilian = civilians.Random(world.SharedRandom);
|
||||
civilian.Trait<Mobile>().Nudge(civilian, civilian, true);
|
||||
nextCivilianMove += world.SharedRandom.Next(1, 75);
|
||||
}
|
||||
}
|
||||
|
||||
if (world.FrameNumber == 1)
|
||||
{
|
||||
MissionUtils.Paradrop(world, soviets, ParadropUnits, paradrop1Entry.Location, paradrop1LZ.Location);
|
||||
MissionUtils.Paradrop(world, soviets, ParadropUnits, paradrop2Entry.Location, paradrop2LZ.Location);
|
||||
}
|
||||
|
||||
if (--waitTicks <= 0)
|
||||
{
|
||||
if (++mul <= div)
|
||||
worldRenderer.Viewport.Center(WPos.Lerp(viewportOrigin, viewportTarget, mul, div));
|
||||
else
|
||||
{
|
||||
mul = 0;
|
||||
viewportOrigin = viewportTarget;
|
||||
viewportTarget = viewportTargets[(viewportTargetNumber = (viewportTargetNumber + 1) % viewportTargets.Length)];
|
||||
waitTicks = 100;
|
||||
|
||||
if (viewportTargetNumber == 0)
|
||||
{
|
||||
coastUnitsLeft = 15;
|
||||
SendChinookReinforcements(chinook1Entry.Location, chinook1LZ);
|
||||
SendChinookReinforcements(chinook2Entry.Location, chinook2LZ);
|
||||
}
|
||||
if (viewportTargetNumber == 1)
|
||||
{
|
||||
MissionUtils.Paradrop(world, soviets, ParadropUnits, paradrop1Entry.Location, paradrop1LZ.Location);
|
||||
MissionUtils.Paradrop(world, soviets, ParadropUnits, paradrop2Entry.Location, paradrop2LZ.Location);
|
||||
}
|
||||
if (viewportTargetNumber == 2)
|
||||
{
|
||||
AttackWithHeavyTanks();
|
||||
ChronoSpawnMediumTanks();
|
||||
}
|
||||
if (viewportTargetNumber == 4)
|
||||
{
|
||||
FlyMigs(mig1Waypoints);
|
||||
FlyMigs(mig2Waypoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MissionUtils.CapOre(soviets);
|
||||
}
|
||||
|
||||
void AttackWithHeavyTanks()
|
||||
{
|
||||
foreach (var tank in HeavyTanks)
|
||||
{
|
||||
var u = world.CreateActor(tank, soviets, heavyTankSpawn.Location, Traits.Util.GetFacing(heavyTankWP.Location - heavyTankSpawn.Location, 0));
|
||||
u.QueueActivity(new AttackMove.AttackMoveActivity(u, new Move.Move(heavyTankWP.Location, 0)));
|
||||
}
|
||||
ironCurtain.Trait<IronCurtainPower>().Activate(ironCurtain, new Order { TargetLocation = heavyTankSpawn.Location });
|
||||
}
|
||||
|
||||
void ChronoSpawnMediumTanks()
|
||||
{
|
||||
var chronoInfo = new List<Pair<Actor, CPos>>();
|
||||
foreach (var tank in MediumTanks.Select((x, i) => new { x, i }))
|
||||
{
|
||||
var u = world.CreateActor(tank.x, allies, mediumTankChronoSpawn.Location, Traits.Util.GetFacing(heavyTankWP.Location - mediumTankChronoSpawn.Location, 0));
|
||||
chronoInfo.Add(Pair.New(u, new CPos(mediumTankChronoSpawn.Location.X + tank.i, mediumTankChronoSpawn.Location.Y)));
|
||||
}
|
||||
RASpecialPowers.Chronoshift(world, chronoInfo, chronosphere, -1, false);
|
||||
foreach (var tank in chronoInfo)
|
||||
tank.First.QueueActivity(new AttackMove.AttackMoveActivity(tank.First, new Move.Move(heavyTankSpawn.Location, 0)));
|
||||
}
|
||||
|
||||
void FlyMigs(CPos[] waypoints)
|
||||
{
|
||||
var m = world.CreateActor("mig", new TypeDictionary
|
||||
{
|
||||
new OwnerInit(soviets),
|
||||
new LocationInit(waypoints[0]),
|
||||
new FacingInit(Traits.Util.GetFacing(waypoints[1] - waypoints[0], 0))
|
||||
});
|
||||
foreach (var waypoint in waypoints)
|
||||
m.QueueActivity(new Fly(m, Target.FromCell(waypoint)));
|
||||
m.QueueActivity(new RemoveSelf());
|
||||
}
|
||||
|
||||
void SendChinookReinforcements(CPos entry, Actor lz)
|
||||
{
|
||||
var chinook = world.CreateActor("tran", allies, entry, Traits.Util.GetFacing(lz.Location - entry, 0));
|
||||
var cargo = chinook.Trait<Cargo>();
|
||||
|
||||
while (cargo.HasSpace(1))
|
||||
cargo.Load(chinook, world.CreateActor(false, ChinookCargo.Random(world.SharedRandom), allies, null, null));
|
||||
|
||||
var exit = lz.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault();
|
||||
var offset = (exit != null) ? exit.SpawnOffset : WVec.Zero;
|
||||
|
||||
chinook.QueueActivity(new HeliFly(chinook, Target.FromPos(lz.CenterPosition + offset))); // no reservation of hpad but it's not needed
|
||||
chinook.QueueActivity(new Turn(0));
|
||||
chinook.QueueActivity(new HeliLand(false));
|
||||
chinook.QueueActivity(new UnloadCargo(chinook, true));
|
||||
chinook.QueueActivity(new Wait(150));
|
||||
chinook.QueueActivity(new HeliFly(chinook, Target.FromCell(entry)));
|
||||
chinook.QueueActivity(new RemoveSelf());
|
||||
}
|
||||
|
||||
void InitializeAlliedFactories()
|
||||
{
|
||||
alliedBarracks.Trait<PrimaryBuilding>().SetPrimaryProducer(alliedBarracks, true);
|
||||
alliedWarFactory.Trait<PrimaryBuilding>().SetPrimaryProducer(alliedWarFactory, true);
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
worldRenderer = wr;
|
||||
allies = w.Players.Single(p => p.InternalName == "Allies");
|
||||
soviets = w.Players.Single(p => p.InternalName == "Soviets");
|
||||
neutral = w.Players.Single(p => p.InternalName == "Neutral");
|
||||
|
||||
actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||
|
||||
attackLocation = actors["AttackLocation"];
|
||||
coastWP1 = actors["CoastWP1"];
|
||||
coastWP2 = actors["CoastWP2"];
|
||||
|
||||
paradrop1LZ = actors["Paradrop1LZ"];
|
||||
paradrop1Entry = actors["Paradrop1Entry"];
|
||||
paradrop2LZ = actors["Paradrop2LZ"];
|
||||
paradrop2Entry = actors["Paradrop2Entry"];
|
||||
|
||||
var t1 = actors["ViewportTarget1"].CenterPosition;
|
||||
var t2 = actors["ViewportTarget2"].CenterPosition;
|
||||
var t3 = actors["ViewportTarget3"].CenterPosition;
|
||||
var t4 = actors["ViewportTarget4"].CenterPosition;
|
||||
var t5 = actors["ViewportTarget5"].CenterPosition;
|
||||
viewportTargets = new[] { t1, t2, t3, t4, t5 };
|
||||
|
||||
offmapAttackerSpawn1 = actors["OffmapAttackerSpawn1"];
|
||||
offmapAttackerSpawn2 = actors["OffmapAttackerSpawn2"];
|
||||
offmapAttackerSpawn3 = actors["OffmapAttackerSpawn3"];
|
||||
offmapAttackerSpawns = new[] { offmapAttackerSpawn1, offmapAttackerSpawn2, offmapAttackerSpawn3 };
|
||||
|
||||
heavyTankSpawn = actors["HeavyTankSpawn"];
|
||||
heavyTankWP = actors["HeavyTankWP"];
|
||||
mediumTankChronoSpawn = actors["MediumTankChronoSpawn"];
|
||||
|
||||
chronosphere = actors["Chronosphere"];
|
||||
ironCurtain = actors["IronCurtain"];
|
||||
|
||||
mig1Waypoints = new[] { actors["Mig11"], actors["Mig12"], actors["Mig13"], actors["Mig14"] }.Select(a => a.Location).ToArray();
|
||||
mig2Waypoints = new[] { actors["Mig21"], actors["Mig22"], actors["Mig23"], actors["Mig24"] }.Select(a => a.Location).ToArray();
|
||||
|
||||
chinook1Entry = actors["Chinook1Entry"];
|
||||
chinook2Entry = actors["Chinook2Entry"];
|
||||
chinook1LZ = actors["Chinook1LZ"];
|
||||
chinook2LZ = actors["Chinook2LZ"];
|
||||
|
||||
alliedBarracks = actors["AlliedBarracks"];
|
||||
alliedWarFactory = actors["AlliedWarFactory"];
|
||||
|
||||
InitializeAlliedFactories();
|
||||
|
||||
foreach (var actor in actors.Values)
|
||||
{
|
||||
if (actor.Owner == allies && actor.HasTrait<AutoTarget>())
|
||||
actor.Trait<AutoTarget>().Stance = UnitStance.Defend;
|
||||
|
||||
if (actor.IsInWorld && (actor.HasTrait<Bridge>() || actor.Owner == allies || (actor.Owner == soviets && actor.HasTrait<Building>())))
|
||||
actor.AddTrait(new Invulnerable());
|
||||
}
|
||||
|
||||
viewportOrigin = viewportTargets[0];
|
||||
viewportTargetNumber = 1;
|
||||
viewportTarget = viewportTargets[1];
|
||||
|
||||
wr.Viewport.Center(viewportOrigin);
|
||||
Sound.SoundVolumeModifier = 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
class DesertShellmapAutoUnloadInfo : TraitInfo<DesertShellmapAutoUnload>, Requires<CargoInfo> { }
|
||||
|
||||
class DesertShellmapAutoUnload : INotifyDamage
|
||||
{
|
||||
public void Damaged(Actor self, AttackInfo e)
|
||||
{
|
||||
var cargo = self.Trait<Cargo>();
|
||||
if (!cargo.IsEmpty(self) && !(self.GetCurrentActivity() is UnloadCargo))
|
||||
self.QueueActivity(false, new UnloadCargo(self, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,7 +261,6 @@
|
||||
<Compile Include="Lint\CheckTraitPrerequisites.cs" />
|
||||
<Compile Include="Lint\LintBuildablePrerequisites.cs" />
|
||||
<Compile Include="MadTank.cs" />
|
||||
<Compile Include="Missions\DesertShellmapScript.cs" />
|
||||
<Compile Include="Missions\FortLonestarScript.cs" />
|
||||
<Compile Include="Missions\Survival02Script.cs" />
|
||||
<Compile Include="MPStartLocations.cs" />
|
||||
@@ -272,7 +271,6 @@
|
||||
<Compile Include="Missions\Allies03Script.cs" />
|
||||
<Compile Include="Missions\Allies04Script.cs" />
|
||||
<Compile Include="Missions\CountdownTimer.cs" />
|
||||
<Compile Include="Missions\DefaultShellmapScript.cs" />
|
||||
<Compile Include="Missions\MissionUtils.cs" />
|
||||
<Compile Include="Missions\MissionWidgets.cs" />
|
||||
<Compile Include="Missions\MonsterTankMadnessScript.cs" />
|
||||
@@ -353,7 +351,6 @@
|
||||
<Compile Include="Scripting\LuaScriptEvents.cs" />
|
||||
<Compile Include="Scripting\LuaScriptInterface.cs" />
|
||||
<Compile Include="Scripting\Media.cs" />
|
||||
<Compile Include="Scripting\RASpecialPowers.cs" />
|
||||
<Compile Include="Scripting\LuaScriptContext.cs" />
|
||||
<Compile Include="SeedsResource.cs" />
|
||||
<Compile Include="SelfHealing.cs" />
|
||||
|
||||
@@ -15,13 +15,16 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
{
|
||||
public class LuaScriptEventsInfo : TraitInfo<LuaScriptEvents> { }
|
||||
|
||||
public class LuaScriptEvents : INotifyKilled, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyCapture, INotifyDamage
|
||||
public class LuaScriptEvents : INotifyKilled, INotifyAddedToWorld, INotifyRemovedFromWorld,
|
||||
INotifyCapture, INotifyDamage, INotifyIdle, INotifyProduction
|
||||
{
|
||||
public event Action<Actor, AttackInfo> OnKilled = (self, e) => { };
|
||||
public event Action<Actor> OnAddedToWorld = self => { };
|
||||
public event Action<Actor> OnRemovedFromWorld = self => { };
|
||||
public event Action<Actor, Actor, Player, Player> OnCaptured = (self, captor, oldOwner, newOwner) => { };
|
||||
public event Action<Actor, AttackInfo> OnDamaged = (self, e) => { };
|
||||
public event Action<Actor> OnIdle = self => { };
|
||||
public event Action<Actor, Actor, CPos> OnProduced = (self, other, exit) => { };
|
||||
|
||||
public void Killed(Actor self, AttackInfo e)
|
||||
{
|
||||
@@ -47,5 +50,15 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
{
|
||||
OnDamaged(self, e);
|
||||
}
|
||||
|
||||
public void TickIdle(Actor self)
|
||||
{
|
||||
OnIdle(self);
|
||||
}
|
||||
|
||||
public void UnitProduced(Actor self, Actor other, CPos exit)
|
||||
{
|
||||
OnProduced(self, other, exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
public class LuaScriptInterface : IWorldLoaded, ITick
|
||||
{
|
||||
World world;
|
||||
Dictionary<string, Actor> mapActors;
|
||||
SpawnMapActors sma;
|
||||
readonly LuaScriptContext context = new LuaScriptContext();
|
||||
readonly LuaScriptInterfaceInfo info;
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
mapActors = world.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||
sma = world.WorldActor.Trait<SpawnMapActors>();
|
||||
|
||||
context.Lua["World"] = w;
|
||||
context.Lua["WorldRenderer"] = wr;
|
||||
@@ -75,7 +75,7 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
|
||||
void AddMapActorGlobals()
|
||||
{
|
||||
foreach (var kv in mapActors)
|
||||
foreach (var kv in sma.Actors)
|
||||
{
|
||||
if (context.Lua[kv.Key] != null)
|
||||
context.ShowErrorMessage("{0}: The global name '{1}' is reserved and may not be used by map actor {2}".F(GetType().Name, kv.Key, kv.Value), null);
|
||||
@@ -328,7 +328,19 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
[LuaGlobal]
|
||||
public Actor GetNamedActor(string actorName)
|
||||
{
|
||||
return mapActors[actorName];
|
||||
return sma.Actors[actorName];
|
||||
}
|
||||
|
||||
[LuaGlobal]
|
||||
public bool IsNamedActor(Actor actor)
|
||||
{
|
||||
return actor.ActorID <= sma.LastMapActorID && actor.ActorID > sma.LastMapActorID - sma.Actors.Count;
|
||||
}
|
||||
|
||||
[LuaGlobal]
|
||||
public IEnumerable<Actor> GetNamedActors()
|
||||
{
|
||||
return sma.Actors.Values;
|
||||
}
|
||||
|
||||
[LuaGlobal]
|
||||
@@ -343,18 +355,28 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
return world.FindActorsInCircle(location, radius).ToArray();
|
||||
}
|
||||
|
||||
ClassicProductionQueue GetSharedQueueForCategory(Player player, string category)
|
||||
{
|
||||
return world.ActorsWithTrait<ClassicProductionQueue>()
|
||||
.Where(a => a.Actor.Owner == player && a.Trait.Info.Type == category)
|
||||
.Select(a => a.Trait).FirstOrDefault();
|
||||
}
|
||||
|
||||
ClassicProductionQueue GetSharedQueueForUnit(Player player, string unit)
|
||||
{
|
||||
var ri = Rules.Info[unit];
|
||||
|
||||
var bi = ri.Traits.GetOrDefault<BuildableInfo>();
|
||||
if (bi == null)
|
||||
return null;
|
||||
|
||||
return GetSharedQueueForCategory(player, bi.Queue);
|
||||
}
|
||||
|
||||
[LuaGlobal]
|
||||
public void BuildWithSharedQueue(Player player, string unit, double amount)
|
||||
{
|
||||
var ri = Rules.Info[unit];
|
||||
if (ri == null || !ri.Traits.Contains<BuildableInfo>())
|
||||
return;
|
||||
|
||||
var category = ri.Traits.Get<BuildableInfo>().Queue;
|
||||
|
||||
var queue = world.ActorsWithTrait<ClassicProductionQueue>()
|
||||
.Where(a => a.Actor.Owner == player && a.Trait.Info.Type == category)
|
||||
.Select(a => a.Trait).FirstOrDefault();
|
||||
var queue = GetSharedQueueForUnit(player, unit);
|
||||
|
||||
if (queue != null)
|
||||
queue.ResolveOrder(queue.self, Order.StartProduction(queue.self, unit, (int)amount));
|
||||
@@ -363,14 +385,38 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
[LuaGlobal]
|
||||
public void BuildWithPerFactoryQueue(Actor factory, string unit, double amount)
|
||||
{
|
||||
if (!factory.HasTrait<ProductionQueue>())
|
||||
return;
|
||||
|
||||
var ri = Rules.Info[unit];
|
||||
if (ri == null || !ri.Traits.Contains<BuildableInfo>())
|
||||
|
||||
var bi = ri.Traits.GetOrDefault<BuildableInfo>();
|
||||
if (bi == null)
|
||||
return;
|
||||
|
||||
factory.Trait<ProductionQueue>().ResolveOrder(factory, Order.StartProduction(factory, unit, (int)amount));
|
||||
var queue = factory.TraitOrDefault<ProductionQueue>();
|
||||
|
||||
if (queue != null)
|
||||
queue.ResolveOrder(factory, Order.StartProduction(factory, unit, (int)amount));
|
||||
}
|
||||
|
||||
[LuaGlobal]
|
||||
public bool SharedQueueIsBusy(Player player, string category)
|
||||
{
|
||||
var queue = GetSharedQueueForCategory(player, category);
|
||||
|
||||
if (queue == null)
|
||||
return true;
|
||||
|
||||
return queue.CurrentItem() != null;
|
||||
}
|
||||
|
||||
[LuaGlobal]
|
||||
public bool PerFactoryQueueIsBusy(Actor factory)
|
||||
{
|
||||
var queue = factory.TraitOrDefault<ProductionQueue>();
|
||||
|
||||
if (queue == null)
|
||||
return true;
|
||||
|
||||
return queue.CurrentItem() != null;
|
||||
}
|
||||
|
||||
[LuaGlobal]
|
||||
@@ -384,5 +430,11 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
gt.GuardTarget(guard, Target.FromActor(target));
|
||||
}
|
||||
}
|
||||
|
||||
[LuaGlobal]
|
||||
public IEnumerable<CPos> ExpandFootprint(LuaTable cells, bool allowDiagonal)
|
||||
{
|
||||
return Util.ExpandFootprint(cells.Values.Cast<CPos>(), allowDiagonal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Mods.RA.Scripting
|
||||
{
|
||||
public class RASpecialPowers
|
||||
{
|
||||
public static void Chronoshift(World world, List<Pair<Actor, CPos>> units, Actor chronosphere, int duration, bool killCargo)
|
||||
{
|
||||
foreach (var kv in units)
|
||||
{
|
||||
var target = kv.First;
|
||||
var targetCell = kv.Second;
|
||||
var cs = target.Trait<Chronoshiftable>();
|
||||
if (chronosphere.Owner.Shroud.IsExplored(targetCell) && cs.CanChronoshiftTo(target, targetCell))
|
||||
cs.Teleport(target, targetCell, duration, killCargo, chronosphere);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ namespace OpenRA.Mods.RA
|
||||
public class SpawnMapActors : IWorldLoaded
|
||||
{
|
||||
public Dictionary<string, Actor> Actors = new Dictionary<string, Actor>();
|
||||
public uint LastMapActorID { get; private set; }
|
||||
|
||||
public void WorldLoaded(World world, WorldRenderer wr)
|
||||
{
|
||||
@@ -32,7 +33,9 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
var initDict = actorReference.Value.InitDict;
|
||||
initDict.Add(new SkipMakeAnimsInit());
|
||||
Actors[actorReference.Key] = world.CreateActor(actorReference.Value.Type, initDict);
|
||||
var actor = world.CreateActor(actorReference.Value.Type, initDict);
|
||||
Actors[actorReference.Key] = actor;
|
||||
LastMapActorID = actor.ActorID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -971,6 +971,7 @@ Tail:
|
||||
ROF: 30
|
||||
Range: 1c0
|
||||
Projectile: Bullet
|
||||
Speed: 1c682
|
||||
Warhead:
|
||||
Spread: 213
|
||||
Versus:
|
||||
@@ -986,6 +987,7 @@ Horn:
|
||||
ROF: 20
|
||||
Range: 1c0
|
||||
Projectile: Bullet
|
||||
Speed: 1c682
|
||||
Warhead:
|
||||
Spread: 213
|
||||
Versus:
|
||||
@@ -1001,6 +1003,7 @@ Teeth:
|
||||
ROF: 30
|
||||
Range: 1c0
|
||||
Projectile: Bullet
|
||||
Speed: 1c682
|
||||
Warhead:
|
||||
Spread: 213
|
||||
Versus:
|
||||
@@ -1016,6 +1019,7 @@ Claw:
|
||||
ROF: 10
|
||||
Range: 1c0
|
||||
Projectile: Bullet
|
||||
Speed: 1c682
|
||||
Warhead:
|
||||
Spread: 213
|
||||
Versus:
|
||||
|
||||
@@ -76,7 +76,14 @@ Actor.FlyOffMap = function(actor)
|
||||
end
|
||||
|
||||
Actor.Hunt = function(actor)
|
||||
actor:QueueActivity(OpenRA.New("Hunt", { actor }))
|
||||
if Actor.HasTrait(actor, "AttackBase") and Actor.HasTrait(actor, "IMove") then
|
||||
actor:QueueActivity(OpenRA.New("Hunt", { actor }))
|
||||
end
|
||||
end
|
||||
|
||||
Actor.CargoIsEmpty = function(actor)
|
||||
local cargo = Actor.TraitOrDefault(actor, "Cargo")
|
||||
return cargo == nil or cargo:IsEmpty(actor)
|
||||
end
|
||||
|
||||
Actor.UnloadCargo = function(actor, unloadAll)
|
||||
@@ -163,6 +170,14 @@ Actor.OnCaptured = function(actor, eh)
|
||||
Actor.Trait(actor, "LuaScriptEvents").OnCaptured:Add(eh)
|
||||
end
|
||||
|
||||
Actor.OnIdle = function(actor, eh)
|
||||
Actor.Trait(actor, "LuaScriptEvents").OnIdle:Add(eh)
|
||||
end
|
||||
|
||||
Actor.OnProduced = function(actor, eh)
|
||||
Actor.Trait(actor, "LuaScriptEvents").OnProduced:Add(eh)
|
||||
end
|
||||
|
||||
Actor.ActorsWithTrait = function(className)
|
||||
local ret = { }
|
||||
for item in Utils.Enumerate(Internal.ActorsWithTrait(className)) do
|
||||
|
||||
@@ -12,10 +12,18 @@ Map.GetRandomEdgeCell = function()
|
||||
return Internal.GetRandomEdgeCell()
|
||||
end
|
||||
|
||||
Map.IsNamedActor = function(actor)
|
||||
return Internal.IsNamedActor(actor)
|
||||
end
|
||||
|
||||
Map.GetNamedActor = function(actorName)
|
||||
return Internal.GetNamedActor(actorName)
|
||||
end
|
||||
|
||||
Map.GetNamedActors = function()
|
||||
return Internal.GetNamedActors()
|
||||
end
|
||||
|
||||
Map.FindActorsInCircle = function(location, radius, func)
|
||||
local actors = Internal.FindActorsInCircle(location.CenterPosition, WRange.FromCells(radius))
|
||||
return Utils.EnumerableWhere(actors, func)
|
||||
@@ -58,6 +66,10 @@ Map.FindIdleUnitsInBox = function(player, topLeft, bottomRight)
|
||||
return Map.FindActorsInBox(topLeft, bottomRight, function(a) return Map.__FilterByTraitAndIdle(a, player, "Mobile") end)
|
||||
end
|
||||
|
||||
Map.ExpandFootprint = function(cells, allowDiagonal)
|
||||
return Utils.EnumerableToTable(Internal.ExpandFootprint(cells, allowDiagonal))
|
||||
end
|
||||
|
||||
CPos.New = function(x, y)
|
||||
return OpenRA.New("CPos", { { x, "Int32" }, { y, "Int32" } })
|
||||
end
|
||||
@@ -90,4 +102,4 @@ end
|
||||
|
||||
WRange.FromCells = function(cells)
|
||||
return WRange.New(cells * 1024)
|
||||
end
|
||||
end
|
||||
@@ -8,6 +8,14 @@ Production.BuildWithPerFactoryQueue = function(factory, unit, amount)
|
||||
Internal.BuildWithPerFactoryQueue(factory, unit, amount or 1)
|
||||
end
|
||||
|
||||
Production.SharedQueueIsBusy = function(player, category)
|
||||
return Internal.SharedQueueIsBusy(player, category)
|
||||
end
|
||||
|
||||
Production.PerFactoryQueueIsBusy = function(factory)
|
||||
return Internal.PerFactoryQueueIsBusy(factory)
|
||||
end
|
||||
|
||||
Production.SetRallyPoint = function(factory, location)
|
||||
Actor.Trait(factory, "RallyPoint").rallyPoint = location.Location
|
||||
end
|
||||
|
||||
@@ -2,8 +2,8 @@ SupportPowers = { }
|
||||
|
||||
SupportPowers.Airstrike = function(owner, planeName, enterLocation, bombLocation)
|
||||
local facing = { Map.GetFacing(CPos.op_Subtraction(bombLocation, enterLocation), 0), "Int32" }
|
||||
local altitude = { Rules.TraitInfo(planeName, "AircraftInfo").CruiseAltitude, "Int32" }
|
||||
local plane = Actor.Create(planeName, { Location = enterLocation, Owner = owner, Facing = facing, Altitude = altitude })
|
||||
local center = WPos.op_Addition(enterLocation.CenterPosition, WVec.New(0, 0, Rules.InitialAltitude(planeName)))
|
||||
local plane = Actor.Create(planeName, { Location = enterLocation, Owner = owner, Facing = facing, CenterPosition = center })
|
||||
Actor.Trait(plane, "AttackBomber"):SetTarget(bombLocation.CenterPosition)
|
||||
Actor.Fly(plane, bombLocation.CenterPosition)
|
||||
Actor.FlyOffMap(plane)
|
||||
@@ -13,8 +13,8 @@ end
|
||||
|
||||
SupportPowers.Paradrop = function(owner, planeName, passengerNames, enterLocation, dropLocation)
|
||||
local facing = { Map.GetFacing(CPos.op_Subtraction(dropLocation, enterLocation), 0), "Int32" }
|
||||
local altitude = { Rules.TraitInfo(planeName, "AircraftInfo").CruiseAltitude, "Int32" }
|
||||
local plane = Actor.Create(planeName, { Location = enterLocation, Owner = owner, Facing = facing, Altitude = altitude })
|
||||
local center = WPos.op_Addition(enterLocation.CenterPosition, WVec.New(0, 0, Rules.InitialAltitude(planeName)))
|
||||
local plane = Actor.Create(planeName, { Location = enterLocation, Owner = owner, Facing = facing, CenterPosition = center })
|
||||
Actor.FlyAttackCell(plane, dropLocation)
|
||||
Actor.Trait(plane, "ParaDrop"):SetLZ(dropLocation)
|
||||
local cargo = Actor.Trait(plane, "Cargo")
|
||||
@@ -25,4 +25,17 @@ SupportPowers.Paradrop = function(owner, planeName, passengerNames, enterLocatio
|
||||
cargo:Load(plane, passenger)
|
||||
end
|
||||
return plane, passengers
|
||||
end
|
||||
|
||||
SupportPowers.Chronoshift = function(unitLocationPairs, chronosphere, duration, killCargo)
|
||||
duration = duration or -1
|
||||
killCargo = killCargo or true
|
||||
Utils.Do(unitLocationPairs, function(pair)
|
||||
local unit = pair[1]
|
||||
local cell = pair[2]
|
||||
local cs = Actor.TraitOrDefault(unit, "Chronoshiftable")
|
||||
if cs ~= nil and cs:CanChronoshiftTo(unit, cell) then
|
||||
cs:Teleport(unit, cell, duration, killCargo, chronosphere)
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -28,6 +28,14 @@ Utils.EnumerableWhere = function(netEnumerable, func)
|
||||
return ret
|
||||
end
|
||||
|
||||
Utils.EnumerableToTable = function(netEnumerable, func)
|
||||
local ret = { }
|
||||
for item in Utils.Enumerate(netEnumerable) do
|
||||
table.insert(ret, item)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
Utils.Where = function(array, func)
|
||||
local ret = { }
|
||||
for i, item in ipairs(array) do
|
||||
|
||||
154
mods/ra/maps/desert-shellmap/desert-shellmap.lua
Normal file
154
mods/ra/maps/desert-shellmap/desert-shellmap.lua
Normal file
@@ -0,0 +1,154 @@
|
||||
local ants = OpenRA.GetRandomInteger(0, 51) == 0
|
||||
|
||||
if ants then
|
||||
UnitTypes = { "ant", "ant", "ant" }
|
||||
BeachUnitTypes = { "ant", "ant" }
|
||||
ParadropUnitTypes = { "ant", "ant", "ant", "ant", "ant" }
|
||||
ProducedUnitTypes =
|
||||
{
|
||||
{ AlliedBarracks1, { "e1", "e3" } },
|
||||
{ AlliedBarracks2, { "e1", "e3" } },
|
||||
{ SovietBarracks1, { "ant" } },
|
||||
{ SovietBarracks2, { "ant" } },
|
||||
{ SovietBarracks3, { "ant" } },
|
||||
{ AlliedWarFactory1, { "jeep", "1tnk", "2tnk", "arty", "ctnk" } },
|
||||
{ SovietWarFactory1, { "3tnk", "4tnk", "v2rl", "ttnk", "apc" } }
|
||||
}
|
||||
else
|
||||
UnitTypes = { "3tnk", "ftrk", "ttnk", "apc" }
|
||||
BeachUnitTypes = { "e1", "e2", "e3", "e4", "e1", "e2", "e3", "e4", "e1", "e2", "e3", "e4", "e1", "e2", "e3", "e4" }
|
||||
ParadropUnitTypes = { "e1", "e1", "e2", "e3", "e4" }
|
||||
ProducedUnitTypes =
|
||||
{
|
||||
{ AlliedBarracks1, { "e1", "e3" } },
|
||||
{ AlliedBarracks2, { "e1", "e3" } },
|
||||
{ SovietBarracks1, { "dog", "e1", "e2", "e3", "e4", "shok" } },
|
||||
{ SovietBarracks2, { "dog", "e1", "e2", "e3", "e4", "shok" } },
|
||||
{ SovietBarracks3, { "dog", "e1", "e2", "e3", "e4", "shok" } },
|
||||
{ AlliedWarFactory1, { "jeep", "1tnk", "2tnk", "arty", "ctnk" } },
|
||||
{ SovietWarFactory1, { "3tnk", "4tnk", "v2rl", "ttnk", "apc" } }
|
||||
}
|
||||
end
|
||||
ParadropPlaneType = "badr"
|
||||
ParadropWaypointCount = 8
|
||||
|
||||
SendSovietUnits = function(entryCell, unitTypes, interval)
|
||||
local units = Reinforcements.Reinforce(soviets, unitTypes, entryCell, entryCell, interval)
|
||||
local team = Team.New(units)
|
||||
Team.AddEventHandler(team.OnAllKilled, function()
|
||||
SendSovietUnits(entryCell, unitTypes, interval)
|
||||
end)
|
||||
Team.Do(team, function(a)
|
||||
Actor.OnDamaged(a, function()
|
||||
if not Actor.CargoIsEmpty(a) then
|
||||
Actor.Stop(a)
|
||||
Actor.UnloadCargo(a, true)
|
||||
end
|
||||
end)
|
||||
Actor.OnIdle(a, function() Actor.AttackMove(a, AlliedTechnologyCenter.Location) end)
|
||||
end)
|
||||
end
|
||||
|
||||
ShipAlliedUnits = function()
|
||||
local transport, reinforcements = Reinforcements.Insert(allies, "lst", { "1tnk", "1tnk", "jeep", "2tnk", "2tnk" }, { LstEntry.Location, LstUnload.Location }, { LstEntry.Location })
|
||||
Utils.Do(reinforcements, function(a) Actor.OnIdle(a, Actor.Hunt) end)
|
||||
OpenRA.RunAfterDelay(60 * 25, ShipAlliedUnits)
|
||||
end
|
||||
|
||||
ParadropSovietUnits = function()
|
||||
local lz = Map.GetNamedActor("Paradrop" .. OpenRA.GetRandomInteger(1, ParadropWaypointCount - 1)).Location
|
||||
local plane, passengers = SupportPowers.Paradrop(soviets, ParadropPlaneType, ParadropUnitTypes, Map.GetRandomEdgeCell(), lz)
|
||||
Utils.Do(passengers, function(a) Actor.OnIdle(a, Actor.Hunt) end)
|
||||
OpenRA.RunAfterDelay(35 * 25, ParadropSovietUnits)
|
||||
end
|
||||
|
||||
ProduceUnits = function()
|
||||
Utils.Do(ProducedUnitTypes, function(t)
|
||||
local factory = t[1]
|
||||
if not Actor.IsDead(factory) and not Production.PerFactoryQueueIsBusy(factory) then
|
||||
local unitType = t[2][OpenRA.GetRandomInteger(1, #t[2] + 1)]
|
||||
Production.BuildWithPerFactoryQueue(factory, unitType)
|
||||
end
|
||||
end)
|
||||
OpenRA.RunAfterDelay(15, ProduceUnits)
|
||||
end
|
||||
|
||||
SetupAlliedUnits = function()
|
||||
for a in Utils.Enumerate(Map.GetNamedActors()) do
|
||||
if Actor.Owner(a) == allies then
|
||||
if Actor.HasTrait(a, "LuaScriptEvents") then
|
||||
a:AddTrait(OpenRA.New("Invulnerable")) -- todo: replace
|
||||
end
|
||||
Actor.SetStance(a, "Defend")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SetupFactories = function()
|
||||
Utils.Do(ProducedUnitTypes, function(pair)
|
||||
Actor.OnProduced(pair[1], function(self, other, ex)
|
||||
Actor.Hunt(other)
|
||||
Actor.OnDamaged(other, function()
|
||||
if not Actor.CargoIsEmpty(other) then
|
||||
Actor.Stop(other)
|
||||
Actor.UnloadCargo(other, true)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
ChronoshiftAlliedUnits = function()
|
||||
local cells = Map.ExpandFootprint({ ChronoshiftLocation.Location }, false)
|
||||
local units = { }
|
||||
for i = 1, #cells do
|
||||
local unit = Actor.Create("2tnk", { Owner = allies, Facing = { 0, "Int32" } })
|
||||
Actor.OnIdle(unit, Actor.Hunt)
|
||||
table.insert(units, { unit, cells[i] })
|
||||
end
|
||||
SupportPowers.Chronoshift(units, Chronosphere)
|
||||
OpenRA.RunAfterDelay(60 * 25, ChronoshiftAlliedUnits)
|
||||
end
|
||||
|
||||
ticks = 0
|
||||
speed = 5
|
||||
|
||||
Tick = function()
|
||||
ticks = ticks + 1
|
||||
|
||||
local t = (ticks + 45) % (360 * speed) * (math.pi / 180) / speed;
|
||||
OpenRA.SetViewportCenterPosition(WPos.op_Addition(viewportOrigin, WVec.New(19200 * math.sin(t), 20480 * math.cos(t))))
|
||||
|
||||
if ticks % 150 == 0 then
|
||||
Utils.Do(Actor.ActorsWithTrait("AttackBase"), function(a)
|
||||
if Actor.IsIdle(a) and not Map.IsNamedActor(a) and not Actor.IsDead(a) and Actor.IsInWorld(a) and (Actor.Owner(a) == soviets or Actor.Owner(a) == allies) then
|
||||
Actor.Hunt(a)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
WorldLoaded = function()
|
||||
allies = OpenRA.GetPlayer("Allies")
|
||||
soviets = OpenRA.GetPlayer("Soviets")
|
||||
|
||||
viewportOrigin = OpenRA.GetViewportCenterPosition()
|
||||
|
||||
SetupAlliedUnits()
|
||||
SetupFactories()
|
||||
ProduceUnits()
|
||||
ShipAlliedUnits()
|
||||
ParadropSovietUnits()
|
||||
OpenRA.RunAfterDelay(5 * 25, ChronoshiftAlliedUnits)
|
||||
|
||||
OpenRA.GiveCash(allies, 1000000)
|
||||
OpenRA.GiveCash(soviets, 1000000)
|
||||
|
||||
SendSovietUnits(Entry1.Location, UnitTypes, 50)
|
||||
SendSovietUnits(Entry2.Location, UnitTypes, 50)
|
||||
SendSovietUnits(Entry3.Location, UnitTypes, 50)
|
||||
SendSovietUnits(Entry4.Location, UnitTypes, 50)
|
||||
SendSovietUnits(Entry5.Location, UnitTypes, 50)
|
||||
SendSovietUnits(Entry6.Location, UnitTypes, 50)
|
||||
SendSovietUnits(Entry7.Location, BeachUnitTypes, 15)
|
||||
end
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1283,6 +1283,7 @@ Claw:
|
||||
ROF: 30
|
||||
Range: 1c0
|
||||
Projectile: Bullet
|
||||
Speed: 1c682
|
||||
Warhead:
|
||||
Spread: 213
|
||||
Versus:
|
||||
@@ -1298,6 +1299,7 @@ Mandible:
|
||||
ROF: 10
|
||||
Range: 1c0
|
||||
Projectile: Bullet
|
||||
Speed: 1c682
|
||||
Warhead:
|
||||
Spread: 213
|
||||
Versus:
|
||||
|
||||
Reference in New Issue
Block a user