diff --git a/OpenRA.Mods.RA/Missions/Allies04Script.cs b/OpenRA.Mods.RA/Missions/Allies04Script.cs index 38f81e02e4..d04525e0aa 100644 --- a/OpenRA.Mods.RA/Missions/Allies04Script.cs +++ b/OpenRA.Mods.RA/Missions/Allies04Script.cs @@ -245,8 +245,6 @@ namespace OpenRA.Mods.RA.Missions foreach (var actor in world.Actors.Where(a => !a.IsDead() && a.HasTrait())) actor.QueueActivity(false, new Transform(actor, actor.Info.Traits.Get().ToActor) { SkipMakeAnims = true }); - - lab.AddTrait(new TransformedAction(self => lab = self)); } } @@ -408,8 +406,10 @@ namespace OpenRA.Mods.RA.Missions actors["PatrolPoint44"].Location, actors["PatrolPoint45"].Location }; + lab = actors["Lab"]; - lab.AddTrait(new Allies04InfiltrateAction(OnLabInfiltrated)); + lab.AddTrait(new InfiltrateAction(OnLabInfiltrated)); + lab.AddTrait(new TransformedAction(self => lab = self)); reinforcementsEntryPoint = actors["ReinforcementsEntryPoint"]; reinforcementsUnloadPoint = actors["ReinforcementsUnloadPoint"]; @@ -504,21 +504,6 @@ namespace OpenRA.Mods.RA.Missions } } - class Allies04InfiltrateAction : IAcceptSpy - { - Action a; - - public Allies04InfiltrateAction(Action a) - { - this.a = a; - } - - public void OnInfiltrate(Actor self, Actor spy) - { - a(spy); - } - } - class Allies04TrivialBuildingInfo : TraitInfo { } class Allies04TrivialBuilding { } diff --git a/OpenRA.Mods.RA/Missions/MissionUtils.cs b/OpenRA.Mods.RA/Missions/MissionUtils.cs index 1e5d5ff81a..12557b98bd 100644 --- a/OpenRA.Mods.RA/Missions/MissionUtils.cs +++ b/OpenRA.Mods.RA/Missions/MissionUtils.cs @@ -8,16 +8,17 @@ */ #endregion -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; using OpenRA.FileFormats; using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Air; using OpenRA.Mods.RA.Buildings; +using OpenRA.Mods.RA.Move; using OpenRA.Network; using OpenRA.Traits; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; namespace OpenRA.Mods.RA.Missions { @@ -226,6 +227,16 @@ namespace OpenRA.Mods.RA.Missions if (res.Ore > res.OreCapacity * 0.8) res.Ore = (int)(res.OreCapacity * 0.8); } + + public static void AttackNearestLandActor(bool queued, Actor self, Player enemyPlayer) + { + var enemies = self.World.Actors.Where(u => u.AppearsHostileTo(self) && u.Owner == enemyPlayer + && ((u.HasTrait() && !u.HasTrait()) || u.HasTrait()) && u.IsInWorld && !u.IsDead()); + + var enemy = enemies.OrderBy(u => (self.CenterLocation - u.CenterLocation).LengthSquared).FirstOrDefault(); + if (enemy != null) + self.QueueActivity(queued, new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(enemy), 3))); + } } class TransformedAction : INotifyTransformed @@ -242,4 +253,19 @@ namespace OpenRA.Mods.RA.Missions a(toActor); } } + + class InfiltrateAction : IAcceptSpy + { + Action a; + + public InfiltrateAction(Action a) + { + this.a = a; + } + + public void OnInfiltrate(Actor self, Actor spy) + { + a(spy); + } + } } diff --git a/OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs b/OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs index f9560c9f02..44874ac137 100644 --- a/OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs +++ b/OpenRA.Mods.RA/Missions/MonsterTankMadnessScript.cs @@ -60,6 +60,7 @@ namespace OpenRA.Mods.RA.Missions Player neutral; Player greece; Player ussr; + Player badGuy; Player turkey; Actor startEntryPoint; @@ -87,12 +88,14 @@ namespace OpenRA.Mods.RA.Missions Actor hospitalCivilianSpawnPoint; Actor hospitalSuperTankPoint; + Actor superTankDome; + bool demitriExtracted; bool hospitalEvacuated; - - bool superTanksAttackingGreece; + bool superTanksDestroyed; int baseTransferredTick = -1; + int superTankDomeInfiltratedTick = -1; void MissionAccomplished(string text) { @@ -135,7 +138,7 @@ namespace OpenRA.Mods.RA.Missions baseTransferredTick = world.FrameNumber; } } - else + else if (superTankDomeInfiltratedTick == -1) { if (world.FrameNumber == baseTransferredTick + 25 * 120) foreach (var tank in superTanks.Where(t => !t.IsDead() && t.IsInWorld)) @@ -145,20 +148,30 @@ namespace OpenRA.Mods.RA.Missions foreach (var tank in superTanks.Where(t => !t.IsDead() && t.IsInWorld)) tank.QueueActivity(false, new Move.Move(alliedBaseBottomRight.Location, 2)); - else if (world.FrameNumber == baseTransferredTick + 25 * 260) + else if (world.FrameNumber == baseTransferredTick + 25 * 300) foreach (var tank in superTanks.Where(t => !t.IsDead() && t.IsInWorld)) tank.QueueActivity(false, new Move.Move(demitriTriggerAreaCenter.Location, 2)); - else if (world.FrameNumber == baseTransferredTick + 25 * 500) + else if (world.FrameNumber == baseTransferredTick + 25 * 540) foreach (var tank in superTanks.Where(t => !t.IsDead() && t.IsInWorld)) - { - tank.QueueActivity(false, new AttackMove.AttackMoveActivity(tank, new Move.Move(demitriLZ.Location, 2))); - superTanksAttackingGreece = true; - } - - if (superTanksAttackingGreece) + tank.QueueActivity(false, new Move.Move(demitriLZ.Location, 4)); + } + else + { + if (world.FrameNumber % 25 == 0) foreach (var tank in superTanks.Where(t => !t.IsDead() && t.IsInWorld && t.IsIdle)) - AttackNearestAlliedActor(tank); + MissionUtils.AttackNearestLandActor(false, tank, ussr); + if (world.FrameNumber == superTankDomeInfiltratedTick + 25 * 300) + { + foreach (var actor in world.Actors.Where(a => !a.IsDead() && (a.Owner == ussr || a.Owner == badGuy))) + actor.Kill(actor); + } + if (world.FrameNumber == superTankDomeInfiltratedTick + 25 * 325) + { + foreach (var tank in superTanks.Where(t => !t.IsDead())) + tank.Kill(tank); + superTanksDestroyed = true; + } } if (!demitriExtracted) { @@ -201,16 +214,16 @@ namespace OpenRA.Mods.RA.Missions OnObjectivesUpdated(true); MissionFailed("The remaining Allied forces in the area have been wiped out."); } - } - - void AttackNearestAlliedActor(Actor self) - { - var enemies = world.Actors.Where(u => u.AppearsHostileTo(self) && u.Owner == greece - && ((u.HasTrait() && !u.HasTrait()) || u.HasTrait()) && u.IsInWorld && !u.IsDead()); - - var enemy = enemies.OrderBy(u => (self.CenterLocation - u.CenterLocation).LengthSquared).FirstOrDefault(); - if (enemy != null) - self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(enemy), 3))); + if (superTankDomeInfiltratedTick == -1 && superTankDome.IsDead()) + { + objectives[BriefingID].Status = ObjectiveStatus.Failed; + OnObjectivesUpdated(true); + MissionFailed("The Soviet radar dome was destroyed."); + } + if (superTanksDestroyed && demitriExtracted) + objectives[BriefingID].Status = ObjectiveStatus.Completed; + OnObjectivesUpdated(true); + MissionUtils.CoopMissionAccomplished(world, "Dr. Demitri has been extracted and the super tanks have been dealt with.", greece); } void TransferActorToAllies(Actor actor) @@ -256,6 +269,18 @@ namespace OpenRA.Mods.RA.Missions .QueueActivity(new Move.Move(alliedBaseMovePoint.Location, 0)); } + void OnSuperTankDomeInfiltrated(Actor spy) + { + if (superTankDomeInfiltratedTick != -1) return; + superTankDome.QueueActivity(new Transform(superTankDome, "dome") { SkipMakeAnims = true }); + turkey.Stances[greece] = turkey.Stances[neutral] = Stance.Ally; + greece.Stances[turkey] = neutral.Stances[turkey] = Stance.Ally; + greece.Shroud.ExploreAll(world); + foreach (var tank in superTanks.Where(t => !t.IsDead() && t.IsInWorld)) + MissionUtils.AttackNearestLandActor(false, tank, ussr); + superTankDomeInfiltratedTick = world.FrameNumber; + } + public void WorldLoaded(World w) { world = w; @@ -263,6 +288,7 @@ namespace OpenRA.Mods.RA.Missions neutral = w.Players.Single(p => p.InternalName == "Neutral"); greece = w.Players.Single(p => p.InternalName == "Greece"); ussr = w.Players.Single(p => p.InternalName == "USSR"); + badGuy = w.Players.Single(p => p.InternalName == "BadGuy"); turkey = w.Players.Single(p => p.InternalName == "Turkey"); greece.PlayerActor.Trait().Cash = 0; @@ -292,6 +318,10 @@ namespace OpenRA.Mods.RA.Missions provingGroundsCameraPoint = actors["ProvingGroundsCameraPoint"]; world.CreateActor("camera", greece, provingGroundsCameraPoint.Location, null); + superTankDome = actors["SuperTankDome"]; + superTankDome.AddTrait(new InfiltrateAction(OnSuperTankDomeInfiltrated)); + superTankDome.AddTrait(new TransformedAction(self => superTankDome = self)); + Game.MoveViewport(startEntryPoint.Location.ToFloat2()); MissionUtils.PlayMissionMusic(); } diff --git a/mods/ra/maps/monster-tank-madness/map.yaml b/mods/ra/maps/monster-tank-madness/map.yaml index dc199f140a..105a2e9d49 100644 --- a/mods/ra/maps/monster-tank-madness/map.yaml +++ b/mods/ra/maps/monster-tank-madness/map.yaml @@ -1434,7 +1434,7 @@ Actors: Owner: BadGuy Health: 1 Facing: 0 - Actor443: dome + SuperTankDome: dome.NoInfiltrate Location: 90,32 Owner: BadGuy Health: 1 @@ -2601,6 +2601,14 @@ Rules: HP: 2000 SILO: InfiltrateForCash: + DOME.NoInfiltrate: + Inherits: DOME + -Buildable: + Tooltip: + Icon: domeicon + RenderBuilding: + Image: DOME + -InfiltrateForExploration: PROC.NoFreeActor: Inherits: PROC -Buildable: