Remove the temperate RA shellmap and port the desert shellmap to Lua.

This commit is contained in:
ScottNZ
2014-03-02 18:47:24 +13:00
parent 79d1a944bc
commit 7d43ecc33f
17 changed files with 858 additions and 2277 deletions

View File

@@ -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++;
}
}
}

View File

@@ -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));
}
}
}

View File

@@ -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" />
@@ -352,7 +350,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" />

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -76,8 +76,15 @@ Actor.FlyOffMap = function(actor)
end
Actor.Hunt = function(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)
actor:QueueActivity(OpenRA.New("UnloadCargo", { 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

View File

@@ -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

View File

@@ -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

View File

@@ -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")
@@ -26,3 +26,16 @@ SupportPowers.Paradrop = function(owner, planeName, passengerNames, enterLocatio
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

View File

@@ -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

View 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