Remove the temperate RA shellmap and port the desert shellmap to Lua.
This commit is contained in:
@@ -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" />
|
||||
@@ -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" />
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user