Add EVA voices
Use new WaitFor when waiting for Einstein Have a small delay before the Soviets counterattack Have the Soviets Attack-Move towards Einstein during the counterattack, this makes them much more damaging Spawn the signal flare only after Einstein has been spawned, also add EVA voice for this
This commit is contained in:
@@ -19,253 +19,254 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.RA.Missions
|
namespace OpenRA.Mods.RA.Missions
|
||||||
{
|
{
|
||||||
public class Allies01ScriptInfo : TraitInfo<Allies01Script>, Requires<SpawnMapActorsInfo> { }
|
public class Allies01ScriptInfo : TraitInfo<Allies01Script>, Requires<SpawnMapActorsInfo> { }
|
||||||
|
|
||||||
public class Allies01Script : IWorldLoaded, ITick
|
public class Allies01Script : IWorldLoaded, ITick
|
||||||
{
|
{
|
||||||
private string[] objectives =
|
private static readonly string[] objectives =
|
||||||
{
|
{
|
||||||
"Find Einstein.",
|
"Find Einstein.",
|
||||||
"Wait for the helicopter and extract Einstein."
|
"Wait for the helicopter and extract Einstein."
|
||||||
};
|
};
|
||||||
|
|
||||||
private int currentObjective;
|
private int currentObjective;
|
||||||
|
|
||||||
private Player allies;
|
private Player allies;
|
||||||
private Player soviets;
|
private Player soviets;
|
||||||
|
|
||||||
private ISound music;
|
private ISound music;
|
||||||
|
|
||||||
private Actor insertionLZ;
|
private Actor insertionLZ;
|
||||||
private Actor extractionLZ;
|
private Actor extractionLZ;
|
||||||
private Actor lab;
|
private Actor lab;
|
||||||
private Actor insertionLZEntryPoint;
|
private Actor insertionLZEntryPoint;
|
||||||
private Actor extractionLZEntryPoint;
|
private Actor extractionLZEntryPoint;
|
||||||
private Actor chinookExitPoint;
|
private Actor chinookExitPoint;
|
||||||
private Actor shipSpawnPoint;
|
private Actor shipSpawnPoint;
|
||||||
private Actor shipMovePoint;
|
private Actor shipMovePoint;
|
||||||
private Actor einstein;
|
private Actor einstein;
|
||||||
private Actor einsteinChinook;
|
private Actor einsteinChinook;
|
||||||
private Actor tanya;
|
private Actor tanya;
|
||||||
private Actor attackEntryPoint1;
|
private Actor attackEntryPoint1;
|
||||||
private Actor attackEntryPoint2;
|
private Actor attackEntryPoint2;
|
||||||
|
|
||||||
private static readonly string[] taunts = { "laugh1.aud", "lefty1.aud", "cmon1.aud", "gotit1.aud" };
|
private static readonly string[] taunts = { "laugh1.aud", "lefty1.aud", "cmon1.aud", "gotit1.aud" };
|
||||||
|
|
||||||
private static readonly string[] ships = { "ca", "ca", "ca", "ca" };
|
private static readonly string[] ships = { "ca", "ca", "ca", "ca" };
|
||||||
|
|
||||||
private static readonly string[] attackWave = { "e1", "e1", "e1", "e1", "e2", "e2", "e2", "e2", "dog" };
|
private static readonly string[] attackWave = { "e1", "e1", "e1", "e1", "e2", "e2", "e2", "e2", "dog" };
|
||||||
private int currentAttackWaveFrameNumber = -600;
|
private int currentAttackWaveFrameNumber;
|
||||||
private int currentAttackWave;
|
private int currentAttackWave;
|
||||||
private const int einsteinChinookArrivesAtAttackWave = 5;
|
private const int einsteinChinookArrivesAtAttackWave = 5;
|
||||||
|
|
||||||
private const int labRange = 5;
|
private const int labRange = 5;
|
||||||
private const string einsteinName = "c1";
|
private const string einsteinName = "c1";
|
||||||
private const string tanyaName = "e7";
|
private const string tanyaName = "e7";
|
||||||
private const string chinookName = "tran";
|
private const string chinookName = "tran";
|
||||||
|
private const string signalFlareName = "flare";
|
||||||
|
|
||||||
private void NextObjective()
|
private void NextObjective()
|
||||||
{
|
{
|
||||||
currentObjective++;
|
currentObjective++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisplayObjective()
|
private void DisplayObjective()
|
||||||
{
|
{
|
||||||
Game.AddChatLine(Color.LimeGreen, "Objective", objectives[currentObjective]);
|
Game.AddChatLine(Color.LimeGreen, "Objective", objectives[currentObjective]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MissionFailed(Actor self, string text)
|
private void MissionFailed(Actor self, string text)
|
||||||
{
|
{
|
||||||
if (allies.WinState != WinState.Undefined)
|
if (allies.WinState != WinState.Undefined)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
allies.WinState = WinState.Lost;
|
allies.WinState = WinState.Lost;
|
||||||
Game.AddChatLine(Color.Red, "Mission failed", text);
|
Game.AddChatLine(Color.Red, "Mission failed", text);
|
||||||
foreach (var actor in self.World.Actors.Where(a => a.Owner == allies))
|
foreach (var actor in self.World.Actors.Where(a => a.Owner == allies))
|
||||||
{
|
{
|
||||||
actor.Kill(actor);
|
actor.Kill(actor);
|
||||||
}
|
}
|
||||||
self.World.LocalShroud.Disabled = true;
|
self.World.LocalShroud.Disabled = true;
|
||||||
}
|
Sound.Play("misnlst1.aud", 5);
|
||||||
|
}
|
||||||
|
|
||||||
private void MissionAccomplished(Actor self, string text)
|
private void MissionAccomplished(Actor self, string text)
|
||||||
{
|
{
|
||||||
if (allies.WinState != WinState.Undefined)
|
if (allies.WinState != WinState.Undefined)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
allies.WinState = WinState.Won;
|
allies.WinState = WinState.Won;
|
||||||
Game.AddChatLine(Color.Blue, "Mission accomplished", text);
|
Game.AddChatLine(Color.Blue, "Mission accomplished", text);
|
||||||
self.World.LocalShroud.Disabled = true;
|
self.World.LocalShroud.Disabled = true;
|
||||||
}
|
Sound.Play("misnwon1.aud", 5);
|
||||||
|
}
|
||||||
|
|
||||||
public void Tick(Actor self)
|
public void Tick(Actor self)
|
||||||
{
|
{
|
||||||
if (allies.WinState != WinState.Undefined)
|
if (allies.WinState != WinState.Undefined)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// display current objective every so often
|
// display current objective every so often
|
||||||
if (self.World.FrameNumber % 1500 == 1)
|
if (self.World.FrameNumber % 1500 == 1)
|
||||||
{
|
{
|
||||||
DisplayObjective();
|
DisplayObjective();
|
||||||
}
|
}
|
||||||
// taunt every so often
|
// taunt every so often
|
||||||
if (self.World.FrameNumber % 1000 == 0)
|
if (self.World.FrameNumber % 1000 == 0)
|
||||||
{
|
{
|
||||||
Sound.Play(taunts[self.World.SharedRandom.Next(taunts.Length)]);
|
Sound.Play(taunts[self.World.SharedRandom.Next(taunts.Length)]);
|
||||||
}
|
}
|
||||||
// take Tanya to the LZ
|
// take Tanya to the LZ
|
||||||
if (self.World.FrameNumber == 1)
|
if (self.World.FrameNumber == 1)
|
||||||
{
|
{
|
||||||
FlyTanyaToInsertionLZ(self);
|
FlyTanyaToInsertionLZ(self);
|
||||||
}
|
}
|
||||||
// objectives
|
// objectives
|
||||||
if (currentObjective == 0)
|
if (currentObjective == 0)
|
||||||
{
|
{
|
||||||
if (AlliesControlLab(self))
|
if (AlliesControlLab(self))
|
||||||
{
|
{
|
||||||
SpawnEinsteinAtLab(self); // spawn Einstein once the area is clear
|
SpawnSignalFlare(self);
|
||||||
Sound.Play("einok1.aud"); // "Incredible!" - Einstein
|
Sound.Play("flaren1.aud", 5);
|
||||||
SendShips(self);
|
SpawnEinsteinAtLab(self); // spawn Einstein once the area is clear
|
||||||
NextObjective();
|
Sound.Play("einok1.aud"); // "Incredible!" - Einstein
|
||||||
DisplayObjective();
|
SendShips(self);
|
||||||
}
|
NextObjective();
|
||||||
if (lab.Destroyed)
|
DisplayObjective();
|
||||||
{
|
currentAttackWaveFrameNumber = self.World.FrameNumber;
|
||||||
MissionFailed(self, "Einstein was killed.");
|
}
|
||||||
}
|
if (lab.Destroyed)
|
||||||
}
|
{
|
||||||
else if (currentObjective == 1)
|
MissionFailed(self, "Einstein was killed.");
|
||||||
{
|
}
|
||||||
if (self.World.FrameNumber >= currentAttackWaveFrameNumber + 600)
|
}
|
||||||
{
|
else if (currentObjective == 1)
|
||||||
SendAttackWave(self, attackWave);
|
{
|
||||||
currentAttackWave++;
|
if (self.World.FrameNumber >= currentAttackWaveFrameNumber + 600)
|
||||||
currentAttackWaveFrameNumber = self.World.FrameNumber;
|
{
|
||||||
if (currentAttackWave == einsteinChinookArrivesAtAttackWave)
|
Sound.Play("enmyapp1.aud", 5);
|
||||||
{
|
SendAttackWave(self, attackWave);
|
||||||
FlyToExtractionLZ(self);
|
currentAttackWave++;
|
||||||
}
|
currentAttackWaveFrameNumber = self.World.FrameNumber;
|
||||||
}
|
if (currentAttackWave == einsteinChinookArrivesAtAttackWave)
|
||||||
if (einsteinChinook != null)
|
{
|
||||||
{
|
FlyEinsteinFromExtractionLZ(self);
|
||||||
if (einsteinChinook.Trait<Cargo>().Passengers.Contains(einstein))
|
}
|
||||||
{
|
}
|
||||||
FlyEinsteinFromExtractionLZ();
|
if (einsteinChinook != null && !self.World.Map.IsInMap(einsteinChinook.Location) && !einstein.IsInWorld)
|
||||||
}
|
{
|
||||||
if (!self.World.Map.IsInMap(einsteinChinook.Location) && !einstein.IsInWorld)
|
MissionAccomplished(self, "Einstein was rescued.");
|
||||||
{
|
}
|
||||||
MissionAccomplished(self, "Einstein was rescued.");
|
if (einstein.Destroyed)
|
||||||
}
|
{
|
||||||
}
|
MissionFailed(self, "Einstein was killed.");
|
||||||
if (einstein.Destroyed)
|
}
|
||||||
{
|
}
|
||||||
MissionFailed(self, "Einstein was killed.");
|
if (tanya.Destroyed)
|
||||||
}
|
{
|
||||||
}
|
MissionFailed(self, "Tanya was killed.");
|
||||||
if (tanya.Destroyed)
|
}
|
||||||
{
|
}
|
||||||
MissionFailed(self, "Tanya was killed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SendAttackWave(Actor self, IEnumerable<string> wave)
|
private void SpawnSignalFlare(Actor self)
|
||||||
{
|
{
|
||||||
foreach (var unit in wave)
|
self.World.CreateActor(signalFlareName, new TypeDictionary { new OwnerInit(allies), new LocationInit(extractionLZ.Location) });
|
||||||
{
|
}
|
||||||
var spawnActor = self.World.SharedRandom.Next(2) == 0 ? attackEntryPoint1 : attackEntryPoint2;
|
|
||||||
var targetActor = self.World.SharedRandom.Next(2) == 0 ? einstein : tanya;
|
|
||||||
var actor = self.World.CreateActor(unit, new TypeDictionary { new OwnerInit(soviets), new LocationInit(spawnActor.Location) });
|
|
||||||
actor.QueueActivity(new Attack(Target.FromActor(targetActor), 2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<Actor> UnitsNearActor(Actor self, Actor actor, int range)
|
private void SendAttackWave(Actor self, IEnumerable<string> wave)
|
||||||
{
|
{
|
||||||
return self.World.FindUnitsInCircle(actor.CenterLocation, Game.CellSize * range)
|
foreach (var unit in wave)
|
||||||
.Where(a => a.IsInWorld && a != self.World.WorldActor && !a.Destroyed && a.HasTrait<IMove>() && !a.Owner.NonCombatant);
|
{
|
||||||
}
|
var spawnActor = self.World.SharedRandom.Next(2) == 0 ? attackEntryPoint1 : attackEntryPoint2;
|
||||||
|
var actor = self.World.CreateActor(unit, new TypeDictionary { new OwnerInit(soviets), new LocationInit(spawnActor.Location) });
|
||||||
|
actor.QueueActivity(new AttackMove.AttackMoveActivity(actor, new Attack(Target.FromActor(einstein), 3))); // better way of doing this?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool AlliesControlLab(Actor self)
|
private IEnumerable<Actor> UnitsNearActor(Actor self, Actor actor, int range)
|
||||||
{
|
{
|
||||||
var units = UnitsNearActor(self, lab, labRange);
|
return self.World.FindUnitsInCircle(actor.CenterLocation, Game.CellSize * range)
|
||||||
return units.Count() >= 1 && units.All(a => a.Owner == allies);
|
.Where(a => a.IsInWorld && a != self.World.WorldActor && !a.Destroyed && a.HasTrait<IMove>() && !a.Owner.NonCombatant);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SpawnEinsteinAtLab(Actor self)
|
private bool AlliesControlLab(Actor self)
|
||||||
{
|
{
|
||||||
einstein = self.World.CreateActor(einsteinName, new TypeDictionary { new OwnerInit(allies), new LocationInit(lab.Location) });
|
var units = UnitsNearActor(self, lab, labRange);
|
||||||
}
|
return units.Any() && units.All(a => a.Owner == allies);
|
||||||
|
}
|
||||||
|
|
||||||
private void SendShips(Actor self)
|
private void SpawnEinsteinAtLab(Actor self)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ships.Length; i++)
|
einstein = self.World.CreateActor(einsteinName, new TypeDictionary { new OwnerInit(allies), new LocationInit(lab.Location) });
|
||||||
{
|
}
|
||||||
var actor = self.World.CreateActor(ships[i],
|
|
||||||
new TypeDictionary { new OwnerInit(allies), new LocationInit(shipSpawnPoint.Location + new int2(i * 2, 0)) });
|
|
||||||
actor.QueueActivity(new Move.Move(shipMovePoint.Location + new int2(i * 4, 0)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FlyEinsteinFromExtractionLZ()
|
private void SendShips(Actor self)
|
||||||
{
|
{
|
||||||
einsteinChinook.QueueActivity(new Wait(150));
|
for (int i = 0; i < ships.Length; i++)
|
||||||
einsteinChinook.QueueActivity(new HeliFly(chinookExitPoint.CenterLocation));
|
{
|
||||||
einsteinChinook.QueueActivity(new RemoveSelf());
|
var actor = self.World.CreateActor(ships[i],
|
||||||
}
|
new TypeDictionary { new OwnerInit(allies), new LocationInit(shipSpawnPoint.Location + new int2(i * 2, 0)) });
|
||||||
|
actor.QueueActivity(new Move.Move(shipMovePoint.Location + new int2(i * 4, 0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void FlyToExtractionLZ(Actor self)
|
private void FlyEinsteinFromExtractionLZ(Actor self)
|
||||||
{
|
{
|
||||||
einsteinChinook = self.World.CreateActor(chinookName, new TypeDictionary { new OwnerInit(allies), new LocationInit(extractionLZEntryPoint.Location) });
|
einsteinChinook = self.World.CreateActor(chinookName, new TypeDictionary { new OwnerInit(allies), new LocationInit(extractionLZEntryPoint.Location) });
|
||||||
einsteinChinook.QueueActivity(new HeliFly(extractionLZ.CenterLocation));
|
einsteinChinook.QueueActivity(new HeliFly(extractionLZ.CenterLocation));
|
||||||
einsteinChinook.QueueActivity(new Turn(0));
|
einsteinChinook.QueueActivity(new Turn(0));
|
||||||
einsteinChinook.QueueActivity(new HeliLand(true));
|
einsteinChinook.QueueActivity(new HeliLand(true));
|
||||||
}
|
einsteinChinook.QueueActivity(new WaitFor(() => einsteinChinook.Trait<Cargo>().Passengers.Contains(einstein)));
|
||||||
|
einsteinChinook.QueueActivity(new Wait(150));
|
||||||
|
einsteinChinook.QueueActivity(new HeliFly(chinookExitPoint.CenterLocation));
|
||||||
|
einsteinChinook.QueueActivity(new RemoveSelf());
|
||||||
|
}
|
||||||
|
|
||||||
private void FlyTanyaToInsertionLZ(Actor self)
|
private void FlyTanyaToInsertionLZ(Actor self)
|
||||||
{
|
{
|
||||||
tanya = self.World.CreateActor(false, tanyaName, new TypeDictionary { new OwnerInit(allies) });
|
tanya = self.World.CreateActor(false, tanyaName, new TypeDictionary { new OwnerInit(allies) });
|
||||||
var chinook = self.World.CreateActor(chinookName, new TypeDictionary { new OwnerInit(allies), new LocationInit(insertionLZEntryPoint.Location) });
|
var chinook = self.World.CreateActor(chinookName, new TypeDictionary { new OwnerInit(allies), new LocationInit(insertionLZEntryPoint.Location) });
|
||||||
chinook.Trait<Cargo>().Load(chinook, tanya);
|
chinook.Trait<Cargo>().Load(chinook, tanya);
|
||||||
// use CenterLocation for HeliFly, Location for Move
|
// use CenterLocation for HeliFly, Location for Move
|
||||||
chinook.QueueActivity(new HeliFly(insertionLZ.CenterLocation));
|
chinook.QueueActivity(new HeliFly(insertionLZ.CenterLocation));
|
||||||
chinook.QueueActivity(new Turn(0));
|
chinook.QueueActivity(new Turn(0));
|
||||||
chinook.QueueActivity(new HeliLand(true));
|
chinook.QueueActivity(new HeliLand(true));
|
||||||
chinook.QueueActivity(new UnloadCargo());
|
chinook.QueueActivity(new UnloadCargo());
|
||||||
chinook.QueueActivity(new CallFunc(() => Sound.Play("laugh1.aud")));
|
chinook.QueueActivity(new CallFunc(() => Sound.Play("laugh1.aud")));
|
||||||
chinook.QueueActivity(new Wait(150));
|
chinook.QueueActivity(new Wait(150));
|
||||||
chinook.QueueActivity(new HeliFly(chinookExitPoint.CenterLocation));
|
chinook.QueueActivity(new HeliFly(chinookExitPoint.CenterLocation));
|
||||||
chinook.QueueActivity(new RemoveSelf());
|
chinook.QueueActivity(new RemoveSelf());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WorldLoaded(World w)
|
public void WorldLoaded(World w)
|
||||||
{
|
{
|
||||||
allies = w.Players.Single(p => p.InternalName == "Allies");
|
allies = w.Players.Single(p => p.InternalName == "Allies");
|
||||||
soviets = w.Players.Single(p => p.InternalName == "Soviets");
|
soviets = w.Players.Single(p => p.InternalName == "Soviets");
|
||||||
var actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
var actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||||
insertionLZ = actors["InsertionLZ"];
|
insertionLZ = actors["InsertionLZ"];
|
||||||
extractionLZ = actors["ExtractionLZ"];
|
extractionLZ = actors["ExtractionLZ"];
|
||||||
lab = actors["Lab"];
|
lab = actors["Lab"];
|
||||||
insertionLZEntryPoint = actors["InsertionLZEntryPoint"];
|
insertionLZEntryPoint = actors["InsertionLZEntryPoint"];
|
||||||
chinookExitPoint = actors["ChinookExitPoint"];
|
chinookExitPoint = actors["ChinookExitPoint"];
|
||||||
extractionLZEntryPoint = actors["ExtractionLZEntryPoint"];
|
extractionLZEntryPoint = actors["ExtractionLZEntryPoint"];
|
||||||
shipSpawnPoint = actors["ShipSpawnPoint"];
|
shipSpawnPoint = actors["ShipSpawnPoint"];
|
||||||
shipMovePoint = actors["ShipMovePoint"];
|
shipMovePoint = actors["ShipMovePoint"];
|
||||||
attackEntryPoint1 = actors["SovietAttackEntryPoint1"];
|
attackEntryPoint1 = actors["SovietAttackEntryPoint1"];
|
||||||
attackEntryPoint2 = actors["SovietAttackEntryPoint2"];
|
attackEntryPoint2 = actors["SovietAttackEntryPoint2"];
|
||||||
music = Sound.Play("hell226m.aud"); // Hell March
|
music = Sound.Play("hell226m.aud"); // Hell March
|
||||||
Game.ConnectionStateChanged += StopMusic;
|
Game.ConnectionStateChanged += StopMusic;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopMusic(OrderManager orderManager)
|
private void StopMusic(OrderManager orderManager)
|
||||||
{
|
{
|
||||||
if (!orderManager.GameStarted)
|
if (!orderManager.GameStarted)
|
||||||
{
|
{
|
||||||
Sound.StopSound(music);
|
Sound.StopSound(music);
|
||||||
Game.ConnectionStateChanged -= StopMusic;
|
Game.ConnectionStateChanged -= StopMusic;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user