Remove hardcoded missions
This commit is contained in:
@@ -1,322 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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 System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Air;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using OpenRA.Scripting;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
class Allies01ScriptInfo : TraitInfo<Allies01Script>, Requires<SpawnMapActorsInfo> { }
|
||||
|
||||
class Allies01Script : IHasObjectives, IWorldLoaded, ITick
|
||||
{
|
||||
public event Action<bool> OnObjectivesUpdated = notify => { };
|
||||
|
||||
public IEnumerable<Objective> Objectives { get { return new[] { findEinstein, extractEinstein }; } }
|
||||
|
||||
Objective findEinstein = new Objective(ObjectiveType.Primary, FindEinsteinText, ObjectiveStatus.InProgress);
|
||||
Objective extractEinstein = new Objective(ObjectiveType.Primary, ExtractEinsteinText, ObjectiveStatus.Inactive);
|
||||
|
||||
const string FindEinsteinText = "Find Einstein. Tanya and Einstein must survive.";
|
||||
const string ExtractEinsteinText = "Wait for the helicopter and extract Einstein. Tanya and Einstein must survive.";
|
||||
|
||||
Player allies;
|
||||
Player soviets;
|
||||
|
||||
Actor insertionLZ;
|
||||
Actor extractionLZ;
|
||||
Actor lab;
|
||||
Actor insertionLZEntryPoint;
|
||||
Actor extractionLZEntryPoint;
|
||||
Actor chinookExitPoint;
|
||||
Actor shipSpawnPoint;
|
||||
Actor shipMovePoint;
|
||||
Actor einstein;
|
||||
Actor einsteinChinook;
|
||||
Actor tanya;
|
||||
Actor attackEntryPoint1;
|
||||
Actor attackEntryPoint2;
|
||||
|
||||
World world;
|
||||
|
||||
static readonly string[] Taunts = { "laugh1.aud", "lefty1.aud", "cmon1.aud", "gotit1.aud" };
|
||||
|
||||
static readonly string[] Ships = { "ca", "ca", "ca", "ca" };
|
||||
static readonly string[] Patrol = { "e1", "dog", "e1" };
|
||||
|
||||
static readonly string[] AttackWave = { "e1", "e1", "e1", "e1", "e2", "e2", "e2", "e2", "dog" };
|
||||
static readonly string[] LastAttackWaveAddition = { "3tnk", "e1", "e1", "e1", "e1", "e2", "e2", "e2", "e2" };
|
||||
int currentAttackWaveFrameNumber;
|
||||
int currentAttackWave;
|
||||
const int EinsteinChinookAttackWave = 5;
|
||||
|
||||
const int LabClearRange = 5;
|
||||
const string EinsteinName = "einstein";
|
||||
const string TanyaName = "e7";
|
||||
const string SignalFlareName = "flare";
|
||||
|
||||
string difficulty;
|
||||
|
||||
void MissionAccomplished(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionAccomplished(world, text, allies);
|
||||
}
|
||||
|
||||
void MissionFailed(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionFailed(world, text, allies);
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (allies.WinState != WinState.Undefined) return;
|
||||
|
||||
if (world.FrameNumber % 1000 == 0)
|
||||
Sound.Play(Taunts[world.SharedRandom.Next(Taunts.Length)]);
|
||||
|
||||
if (findEinstein.Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
if (AlliesControlLab())
|
||||
LabSecured();
|
||||
|
||||
if (lab.IsDead())
|
||||
{
|
||||
findEinstein.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("Einstein was killed.");
|
||||
}
|
||||
}
|
||||
if (extractEinstein.Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
if (difficulty != "Easy")
|
||||
{
|
||||
ManageSovietUnits();
|
||||
if (world.FrameNumber >= currentAttackWaveFrameNumber + 400)
|
||||
{
|
||||
SpawnSovietUnits(AttackWave);
|
||||
currentAttackWave++;
|
||||
currentAttackWaveFrameNumber = world.FrameNumber;
|
||||
|
||||
if (currentAttackWave >= EinsteinChinookAttackWave)
|
||||
SpawnSovietUnits(LastAttackWaveAddition);
|
||||
|
||||
if (currentAttackWave == EinsteinChinookAttackWave)
|
||||
ExtractEinsteinAtLZ();
|
||||
}
|
||||
}
|
||||
if (einsteinChinook != null)
|
||||
{
|
||||
if (einsteinChinook.IsDead())
|
||||
{
|
||||
extractEinstein.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("The extraction helicopter was destroyed.");
|
||||
}
|
||||
else if (!world.Map.IsInMap(einsteinChinook.Location) && einsteinChinook.Trait<Cargo>().Passengers.Contains(einstein))
|
||||
{
|
||||
extractEinstein.Status = ObjectiveStatus.Completed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionAccomplished("Einstein was rescued");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tanya != null && tanya.IsDead())
|
||||
MissionFailed("Tanya was killed.");
|
||||
|
||||
else if (einstein != null && einstein.IsDead())
|
||||
MissionFailed("Einstein was killed.");
|
||||
|
||||
MissionUtils.CapOre(soviets);
|
||||
}
|
||||
|
||||
void LabSecured()
|
||||
{
|
||||
SpawnSignalFlare();
|
||||
Sound.Play("flaren1.aud");
|
||||
SpawnEinsteinAtLab();
|
||||
SendShips();
|
||||
lab.QueueActivity(new Transform(lab, "stek") { SkipMakeAnims = true });
|
||||
|
||||
findEinstein.Status = ObjectiveStatus.Completed;
|
||||
extractEinstein.Status = ObjectiveStatus.InProgress;
|
||||
OnObjectivesUpdated(true);
|
||||
|
||||
currentAttackWaveFrameNumber = world.FrameNumber;
|
||||
|
||||
if (difficulty == "Easy")
|
||||
ExtractEinsteinAtLZ();
|
||||
else
|
||||
{
|
||||
var infantry = MissionUtils.FindQueues(world, soviets, "Infantry").FirstOrDefault();
|
||||
if (infantry != null)
|
||||
infantry.ResolveOrder(infantry.self, Order.StartProduction(infantry.self, "e1", 5));
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnSignalFlare()
|
||||
{
|
||||
world.CreateActor(SignalFlareName, new TypeDictionary { new OwnerInit(allies), new LocationInit(extractionLZ.Location) });
|
||||
}
|
||||
|
||||
void SpawnSovietUnits(IEnumerable<string> wave)
|
||||
{
|
||||
foreach (var unit in wave)
|
||||
{
|
||||
var spawnActor = world.SharedRandom.Next(2) == 0 ? attackEntryPoint1 : attackEntryPoint2;
|
||||
world.CreateActor(unit, new TypeDictionary { new OwnerInit(soviets), new LocationInit(spawnActor.Location) });
|
||||
}
|
||||
}
|
||||
|
||||
void ManageSovietUnits()
|
||||
{
|
||||
foreach (var unit in world.Actors.Where(u => u.IsInWorld && u.Owner == soviets && !u.IsDead() && u.IsIdle
|
||||
&& u.HasTrait<Mobile>() && u.HasTrait<AttackBase>()))
|
||||
{
|
||||
Activity innerActivity;
|
||||
if (einstein != null)
|
||||
{
|
||||
if (einstein.IsInWorld)
|
||||
innerActivity = new Move.Move(Target.FromActor(einstein), WRange.FromCells(3));
|
||||
|
||||
else
|
||||
{
|
||||
var container = world.UnitContaining(einstein);
|
||||
|
||||
if (container != null && !container.HasTrait<Aircraft>() && container.HasTrait<Mobile>())
|
||||
innerActivity = new Move.Move(Target.FromActor(container), WRange.FromCells(3));
|
||||
|
||||
else
|
||||
innerActivity = new Move.Move(extractionLZ.Location, 3);
|
||||
}
|
||||
unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, innerActivity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendPatrol()
|
||||
{
|
||||
for (int i = 0; i < Patrol.Length; i++)
|
||||
world.CreateActor(Patrol[i], new TypeDictionary
|
||||
{
|
||||
new OwnerInit(soviets),
|
||||
new LocationInit(insertionLZ.Location + new CVec(-1 + i, 10 + i * 2))
|
||||
})
|
||||
.QueueActivity(new Move.Move(insertionLZ.Location));
|
||||
}
|
||||
|
||||
bool AlliesControlLab()
|
||||
{
|
||||
return MissionUtils.AreaSecuredWithUnits(world, allies, lab.CenterPosition, WRange.FromCells(LabClearRange));
|
||||
}
|
||||
|
||||
void SpawnEinsteinAtLab()
|
||||
{
|
||||
einstein = world.CreateActor(EinsteinName, new TypeDictionary { new OwnerInit(allies), new LocationInit(lab.Location) });
|
||||
einstein.QueueActivity(new Move.Move(lab.Location - new CVec(0, 2)));
|
||||
}
|
||||
|
||||
void SendShips()
|
||||
{
|
||||
for (int i = 0; i < Ships.Length; i++)
|
||||
world.CreateActor(Ships[i], new TypeDictionary
|
||||
{
|
||||
new OwnerInit(allies),
|
||||
new LocationInit(shipSpawnPoint.Location + new CVec(i * 2, 0))
|
||||
})
|
||||
.QueueActivity(new Move.Move(shipMovePoint.Location + new CVec(i * 4, 0)));
|
||||
}
|
||||
|
||||
void ExtractEinsteinAtLZ()
|
||||
{
|
||||
einsteinChinook = MissionUtils.ExtractUnitWithChinook(
|
||||
world,
|
||||
allies,
|
||||
einstein,
|
||||
extractionLZEntryPoint.Location,
|
||||
extractionLZ.Location,
|
||||
chinookExitPoint.Location);
|
||||
}
|
||||
|
||||
void InsertTanyaAtLZ()
|
||||
{
|
||||
tanya = MissionUtils.InsertUnitWithChinook(
|
||||
world,
|
||||
allies,
|
||||
TanyaName,
|
||||
insertionLZEntryPoint.Location,
|
||||
insertionLZ.Location,
|
||||
chinookExitPoint.Location,
|
||||
unit =>
|
||||
{
|
||||
Sound.Play("laugh1.aud");
|
||||
unit.QueueActivity(new Move.Move(insertionLZ.Location - new CVec(1, 0)));
|
||||
}).Second;
|
||||
}
|
||||
|
||||
void SetAlliedUnitsToDefensiveStance()
|
||||
{
|
||||
foreach (var actor in world.Actors.Where(a => a.IsInWorld && a.Owner == allies && !a.IsDead() && a.HasTrait<AutoTarget>()))
|
||||
actor.Trait<AutoTarget>().Stance = UnitStance.Defend;
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
|
||||
difficulty = w.LobbyInfo.GlobalSettings.Difficulty;
|
||||
Game.Debug("{0} difficulty selected".F(difficulty));
|
||||
|
||||
allies = w.Players.Single(p => p.InternalName == "Allies");
|
||||
soviets = w.Players.Single(p => p.InternalName == "Soviets");
|
||||
|
||||
allies.PlayerActor.Trait<PlayerResources>().Cash = 0;
|
||||
|
||||
var actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||
insertionLZ = actors["InsertionLZ"];
|
||||
extractionLZ = actors["ExtractionLZ"];
|
||||
lab = actors["Lab"];
|
||||
insertionLZEntryPoint = actors["InsertionLZEntryPoint"];
|
||||
chinookExitPoint = actors["ChinookExitPoint"];
|
||||
extractionLZEntryPoint = actors["ExtractionLZEntryPoint"];
|
||||
shipSpawnPoint = actors["ShipSpawnPoint"];
|
||||
shipMovePoint = actors["ShipMovePoint"];
|
||||
attackEntryPoint1 = actors["SovietAttackEntryPoint1"];
|
||||
attackEntryPoint2 = actors["SovietAttackEntryPoint2"];
|
||||
SetAlliedUnitsToDefensiveStance();
|
||||
|
||||
wr.Viewport.Center(insertionLZ.CenterPosition);
|
||||
|
||||
if (w.LobbyInfo.IsSinglePlayer)
|
||||
Media.PlayFMVFullscreen(w, "ally1.vqa", () =>
|
||||
Media.PlayFMVFullscreen(w, "landing.vqa", () =>
|
||||
{
|
||||
InsertTanyaAtLZ();
|
||||
SendPatrol();
|
||||
MissionUtils.PlayMissionMusic();
|
||||
})
|
||||
);
|
||||
else
|
||||
{
|
||||
InsertTanyaAtLZ();
|
||||
SendPatrol();
|
||||
MissionUtils.PlayMissionMusic();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,478 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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 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.Effects;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
class Allies02ScriptInfo : TraitInfo<Allies02Script>, Requires<SpawnMapActorsInfo> { }
|
||||
|
||||
class Allies02Script : IHasObjectives, IWorldLoaded, ITick
|
||||
{
|
||||
public event Action<bool> OnObjectivesUpdated = notify => { };
|
||||
|
||||
public IEnumerable<Objective> Objectives { get { return new[] { findEinstein, destroySamSites, extractEinstein, maintainPresence, fewDeaths }; } }
|
||||
|
||||
Objective findEinstein = new Objective(ObjectiveType.Primary, FindEinsteinText, ObjectiveStatus.InProgress);
|
||||
Objective destroySamSites = new Objective(ObjectiveType.Primary, DestroySamSitesText, ObjectiveStatus.InProgress);
|
||||
Objective extractEinstein = new Objective(ObjectiveType.Primary, ExtractEinsteinText, ObjectiveStatus.Inactive);
|
||||
Objective maintainPresence = new Objective(ObjectiveType.Primary, MaintainPresenceText, ObjectiveStatus.InProgress);
|
||||
Objective fewDeaths = new Objective(ObjectiveType.Secondary, "", ObjectiveStatus.InProgress);
|
||||
|
||||
const string FindEinsteinText = "Find Einstein's crashed helicopter. Tanya must survive.";
|
||||
const string DestroySamSitesText = "Destroy the SAM sites. Tanya must survive.";
|
||||
const string ExtractEinsteinText = "Wait for the helicopter and extract Einstein. Tanya and Einstein must survive.";
|
||||
const string MaintainPresenceText = "Maintain an Allied presence in the area. Reinforcements will arrive soon.";
|
||||
|
||||
const string FewDeathsTemplate = "Lose fewer than {0}/{1} units.";
|
||||
|
||||
const int DeathsThreshold = 200;
|
||||
|
||||
Actor sam1;
|
||||
Actor sam2;
|
||||
Actor sam3;
|
||||
Actor sam4;
|
||||
Actor[] sams;
|
||||
Actor tanya;
|
||||
Actor einstein;
|
||||
Actor engineer;
|
||||
|
||||
Actor chinookHusk;
|
||||
Actor allies2BasePoint;
|
||||
Actor reinforcementsEntryPoint;
|
||||
Actor extractionLZEntryPoint;
|
||||
Actor extractionLZ;
|
||||
Actor badgerEntryPoint1;
|
||||
Actor badgerEntryPoint2;
|
||||
Actor badgerDropPoint1;
|
||||
Actor badgerDropPoint2;
|
||||
Actor badgerDropPoint3;
|
||||
Actor parabombPoint1;
|
||||
Actor parabombPoint2;
|
||||
Actor sovietRallyPoint;
|
||||
Actor townPoint;
|
||||
Actor sovietTownAttackPoint1;
|
||||
Actor sovietTownAttackPoint2;
|
||||
Actor yakEntryPoint;
|
||||
Actor yakAttackPoint;
|
||||
Actor yak;
|
||||
|
||||
Actor einsteinChinook;
|
||||
|
||||
World world;
|
||||
Player allies;
|
||||
Player allies1;
|
||||
Player allies2;
|
||||
Player soviets;
|
||||
|
||||
Actor sovietBarracks;
|
||||
Actor sovietWarFactory;
|
||||
|
||||
CountdownTimer reinforcementsTimer;
|
||||
CountdownTimerWidget reinforcementsTimerWidget;
|
||||
|
||||
CPos alliedBaseTopLeft;
|
||||
CPos alliedBaseBottomRight;
|
||||
|
||||
const string InfantryQueueName = "Infantry";
|
||||
const string VehicleQueueName = "Vehicle";
|
||||
static readonly string[] SovietInfantry = { "e1", "e2", "e3" };
|
||||
static readonly string[] SovietVehicles1 = { "3tnk" };
|
||||
static readonly string[] SovietVehicles2 = { "3tnk", "v2rl" };
|
||||
const int SovietVehiclesUpgradeTicks = 1500 * 4;
|
||||
const int SovietGroupSize = 5;
|
||||
|
||||
const int ReinforcementsTicks = 1500 * 16;
|
||||
static readonly string[] Reinforcements =
|
||||
{
|
||||
"2tnk", "2tnk", "2tnk", "2tnk", "2tnk", "2tnk",
|
||||
"1tnk", "1tnk",
|
||||
"jeep",
|
||||
"e1", "e1", "e1", "e1",
|
||||
"e3", "e3",
|
||||
"mcv",
|
||||
"truk", "truk", "truk", "truk", "truk", "truk"
|
||||
};
|
||||
int currentReinforcement = -1;
|
||||
|
||||
const int ParabombTicks = 750;
|
||||
|
||||
const int ParatroopersTicks = 1500 * 5;
|
||||
static readonly string[] Badger1Passengers = { "e1", "e1", "e1", "e2", "3tnk" };
|
||||
static readonly string[] Badger2Passengers = { "e1", "e1", "e1", "e2", "e2" };
|
||||
static readonly string[] Badger3Passengers = { "e1", "e1", "e1", "e2", "e2" };
|
||||
|
||||
const string SignalFlareName = "flare";
|
||||
const string YakName = "yak";
|
||||
|
||||
const int AlliedTownTransferRange = 15;
|
||||
const int SovietTownAttackGroupRange = 5;
|
||||
const int SovietTownMoveNearEnough = 3;
|
||||
|
||||
void MissionFailed(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionFailed(world, text, allies1, allies2);
|
||||
if (reinforcementsTimer != null)
|
||||
reinforcementsTimerWidget.Visible = false;
|
||||
}
|
||||
|
||||
void MissionAccomplished(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionAccomplished(world, text, allies1, allies2);
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (allies1.WinState != WinState.Undefined) return;
|
||||
|
||||
if (world.FrameNumber % 50 == 1 && chinookHusk.IsInWorld)
|
||||
world.Add(new Smoke(world, chinookHusk.CenterPosition, "smoke_m"));
|
||||
|
||||
if (world.FrameNumber == 1)
|
||||
{
|
||||
InitializeSovietFactories();
|
||||
StartReinforcementsTimer();
|
||||
}
|
||||
|
||||
reinforcementsTimer.Tick();
|
||||
|
||||
if (world.FrameNumber == ParatroopersTicks)
|
||||
{
|
||||
MissionUtils.Paradrop(world, soviets, Badger1Passengers, badgerEntryPoint1.Location, badgerDropPoint1.Location);
|
||||
MissionUtils.Paradrop(world, soviets, Badger2Passengers, badgerEntryPoint1.Location + new CVec(3, 0), badgerDropPoint2.Location);
|
||||
MissionUtils.Paradrop(world, soviets, Badger3Passengers, badgerEntryPoint1.Location + new CVec(6, 0), badgerDropPoint3.Location);
|
||||
}
|
||||
if (world.FrameNumber == ParabombTicks)
|
||||
{
|
||||
MissionUtils.Parabomb(world, soviets, badgerEntryPoint2.Location, parabombPoint1.Location);
|
||||
MissionUtils.Parabomb(world, soviets, badgerEntryPoint2.Location + new CVec(0, 3), parabombPoint2.Location);
|
||||
}
|
||||
|
||||
if (allies1 != allies2)
|
||||
{
|
||||
if (yak == null || (yak != null && !yak.IsDead() && (yak.GetCurrentActivity() is FlyCircle || yak.IsIdle)))
|
||||
{
|
||||
var alliedUnitsNearYakPoint = world.FindAliveCombatantActorsInCircle(yakAttackPoint.CenterPosition, WRange.FromCells(10))
|
||||
.Where(a => a.Owner != soviets && a.HasTrait<IPositionable>() && a != tanya && a != einstein && a != engineer);
|
||||
if (alliedUnitsNearYakPoint.Any())
|
||||
YakStrafe(alliedUnitsNearYakPoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentReinforcement > -1 && currentReinforcement < Reinforcements.Length && world.FrameNumber % 25 == 0)
|
||||
SpawnAlliedUnit(Reinforcements[currentReinforcement++]);
|
||||
|
||||
if (world.FrameNumber % 25 == 0)
|
||||
{
|
||||
BuildSovietUnits();
|
||||
ManageSovietUnits();
|
||||
}
|
||||
|
||||
UpdateDeaths();
|
||||
|
||||
if (findEinstein.Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
if (AlliesNearTown())
|
||||
{
|
||||
findEinstein.Status = ObjectiveStatus.Completed;
|
||||
OnObjectivesUpdated(true);
|
||||
TransferTownUnitsToAllies();
|
||||
SovietsAttackTown();
|
||||
}
|
||||
}
|
||||
if (destroySamSites.Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
if (sams.All(s => s.IsDead() || s.Owner != soviets))
|
||||
{
|
||||
destroySamSites.Status = ObjectiveStatus.Completed;
|
||||
extractEinstein.Status = ObjectiveStatus.InProgress;
|
||||
|
||||
OnObjectivesUpdated(true);
|
||||
|
||||
world.CreateActor(SignalFlareName, new TypeDictionary { new OwnerInit(allies1), new LocationInit(extractionLZ.Location) });
|
||||
Sound.Play("flaren1.aud");
|
||||
ExtractEinsteinAtLZ();
|
||||
}
|
||||
}
|
||||
if (extractEinstein.Status == ObjectiveStatus.InProgress && einsteinChinook != null)
|
||||
{
|
||||
if (einsteinChinook.IsDead())
|
||||
{
|
||||
extractEinstein.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("The extraction helicopter was destroyed.");
|
||||
}
|
||||
else if (!world.Map.IsInMap(einsteinChinook.Location) && einsteinChinook.Trait<Cargo>().Passengers.Contains(einstein))
|
||||
{
|
||||
extractEinstein.Status = ObjectiveStatus.Completed;
|
||||
maintainPresence.Status = ObjectiveStatus.Completed;
|
||||
|
||||
if (fewDeaths.Status == ObjectiveStatus.InProgress)
|
||||
fewDeaths.Status = ObjectiveStatus.Completed;
|
||||
|
||||
OnObjectivesUpdated(true);
|
||||
MissionAccomplished("Einstein was rescued.");
|
||||
}
|
||||
}
|
||||
|
||||
if (tanya.IsDead())
|
||||
MissionFailed("Tanya was killed.");
|
||||
|
||||
else if (einstein.IsDead())
|
||||
MissionFailed("Einstein was killed.");
|
||||
|
||||
world.AddFrameEndTask(w =>
|
||||
{
|
||||
if (!w.FindAliveCombatantActorsInBox(alliedBaseTopLeft, alliedBaseBottomRight)
|
||||
.Any(a => (a.Owner == allies || a.Owner == allies2) && (a.HasTrait<Building>() && !a.HasTrait<Wall>()) || a.HasTrait<BaseBuilding>()))
|
||||
{
|
||||
maintainPresence.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("The Allied reinforcements have been defeated.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateDeaths()
|
||||
{
|
||||
var unitDeaths = allies1.PlayerActor.Trait<PlayerStatistics>().UnitsDead + allies2.PlayerActor.Trait<PlayerStatistics>().UnitsDead;
|
||||
fewDeaths.Text = FewDeathsTemplate.F(unitDeaths, DeathsThreshold);
|
||||
OnObjectivesUpdated(false);
|
||||
if (unitDeaths >= DeathsThreshold && fewDeaths.Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
fewDeaths.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
}
|
||||
}
|
||||
|
||||
void YakStrafe(IEnumerable<Actor> candidates)
|
||||
{
|
||||
if (yak == null)
|
||||
{
|
||||
var altitude = Rules.Info[YakName].Traits.Get<PlaneInfo>().CruiseAltitude;
|
||||
yak = world.CreateActor(YakName, new TypeDictionary
|
||||
{
|
||||
new CenterPositionInit(yakEntryPoint.CenterPosition + new WVec(WRange.Zero, WRange.Zero, altitude)),
|
||||
new OwnerInit(soviets),
|
||||
new FacingInit(Traits.Util.GetFacing(yakAttackPoint.Location - yakEntryPoint.Location, 0))
|
||||
});
|
||||
}
|
||||
|
||||
if (yak.Trait<LimitedAmmo>().HasAmmo())
|
||||
yak.QueueActivity(new FlyAttack(Target.FromActor(candidates.Random(world.SharedRandom))));
|
||||
|
||||
else
|
||||
{
|
||||
yak.QueueActivity(new FlyOffMap());
|
||||
yak.QueueActivity(new RemoveSelf());
|
||||
}
|
||||
}
|
||||
|
||||
void BuildSovietUnits()
|
||||
{
|
||||
if (!sovietBarracks.IsDead())
|
||||
BuildSovietUnit(InfantryQueueName, SovietInfantry.Random(world.SharedRandom));
|
||||
|
||||
if (!sovietWarFactory.IsDead())
|
||||
{
|
||||
var vehicles = world.FrameNumber >= SovietVehiclesUpgradeTicks ? SovietVehicles2 : SovietVehicles1;
|
||||
BuildSovietUnit(VehicleQueueName, vehicles.Random(world.SharedRandom));
|
||||
}
|
||||
}
|
||||
|
||||
void ManageSovietUnits()
|
||||
{
|
||||
var units = world.FindAliveCombatantActorsInCircle(sovietRallyPoint.CenterPosition, WRange.FromCells(10))
|
||||
.Where(u => u.IsIdle && u.HasTrait<Mobile>() && u.HasTrait<AttackBase>() && u.Owner == soviets)
|
||||
.Except(world.WorldActor.Trait<SpawnMapActors>().Actors.Values);
|
||||
if (units.Count() >= SovietGroupSize)
|
||||
{
|
||||
foreach (var unit in units)
|
||||
MissionUtils.AttackNearestLandActor(true, unit, allies2);
|
||||
}
|
||||
|
||||
var scatteredUnits = world.Actors.Where(u => u.IsInWorld && !u.IsDead() && u.IsIdle
|
||||
&& u.HasTrait<Mobile>() && u.HasTrait<AttackBase>() && u.Owner == soviets)
|
||||
.Except(world.WorldActor.Trait<SpawnMapActors>().Actors.Values)
|
||||
.Except(units);
|
||||
|
||||
foreach (var unit in scatteredUnits)
|
||||
MissionUtils.AttackNearestLandActor(true, unit, allies2);
|
||||
}
|
||||
|
||||
void SetupAlliedBase()
|
||||
{
|
||||
foreach (var actor in world.Actors.Where(a => a.Owner == allies && a != allies.PlayerActor))
|
||||
{
|
||||
actor.ChangeOwner(allies2);
|
||||
if (actor.Info.Name == "proc")
|
||||
actor.QueueActivity(new Transform(actor, "proc") { SkipMakeAnims = true }); // for harv spawn
|
||||
foreach (var c in actor.TraitsImplementing<INotifyCapture>())
|
||||
c.OnCapture(actor, actor, allies, allies2);
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeSovietFactories()
|
||||
{
|
||||
var sbrp = sovietBarracks.Trait<RallyPoint>();
|
||||
var swrp = sovietWarFactory.Trait<RallyPoint>();
|
||||
sbrp.rallyPoint = swrp.rallyPoint = sovietRallyPoint.Location;
|
||||
sbrp.nearEnough = swrp.nearEnough = 6;
|
||||
sovietBarracks.Trait<PrimaryBuilding>().SetPrimaryProducer(sovietBarracks, true);
|
||||
sovietWarFactory.Trait<PrimaryBuilding>().SetPrimaryProducer(sovietWarFactory, true);
|
||||
}
|
||||
|
||||
void BuildSovietUnit(string category, string unit)
|
||||
{
|
||||
MissionUtils.StartProduction(world, soviets, category, unit);
|
||||
}
|
||||
|
||||
void StartReinforcementsTimer()
|
||||
{
|
||||
Sound.Play("timergo1.aud");
|
||||
reinforcementsTimer = new CountdownTimer(ReinforcementsTicks, ReinforcementsTimerExpired, true);
|
||||
reinforcementsTimerWidget = new CountdownTimerWidget(reinforcementsTimer, "Allied reinforcements arrive in: {0}");
|
||||
Ui.Root.AddChild(reinforcementsTimerWidget);
|
||||
}
|
||||
|
||||
void ReinforcementsTimerExpired(CountdownTimer countdownTimer)
|
||||
{
|
||||
reinforcementsTimerWidget.Visible = false;
|
||||
currentReinforcement++;
|
||||
Sound.Play("aarrivs1.aud");
|
||||
}
|
||||
|
||||
void SpawnAlliedUnit(string unit)
|
||||
{
|
||||
world.CreateActor(unit, new TypeDictionary
|
||||
{
|
||||
new LocationInit(reinforcementsEntryPoint.Location),
|
||||
new FacingInit(0),
|
||||
new OwnerInit(allies2)
|
||||
})
|
||||
.QueueActivity(new Move.Move(allies2BasePoint.Location));
|
||||
}
|
||||
|
||||
void ExtractEinsteinAtLZ()
|
||||
{
|
||||
einsteinChinook = MissionUtils.ExtractUnitWithChinook(
|
||||
world,
|
||||
allies1,
|
||||
einstein,
|
||||
extractionLZEntryPoint.Location,
|
||||
extractionLZ.Location,
|
||||
extractionLZEntryPoint.Location);
|
||||
}
|
||||
|
||||
bool AlliesNearTown()
|
||||
{
|
||||
return world.FindAliveCombatantActorsInCircle(townPoint.CenterPosition, WRange.FromCells(AlliedTownTransferRange))
|
||||
.Any(a => a.Owner == allies1 && a.HasTrait<IPositionable>());
|
||||
}
|
||||
|
||||
void TransferTownUnitsToAllies()
|
||||
{
|
||||
foreach (var unit in world.FindAliveNonCombatantActorsInCircle(townPoint.CenterPosition, WRange.FromCells(AlliedTownTransferRange))
|
||||
.Where(a => a.HasTrait<Mobile>()))
|
||||
unit.ChangeOwner(allies1);
|
||||
}
|
||||
|
||||
void SovietsAttackTown()
|
||||
{
|
||||
var sovietAttackUnits = world.FindAliveCombatantActorsInCircle(sovietTownAttackPoint1.CenterPosition, WRange.FromCells(SovietTownAttackGroupRange))
|
||||
.Union(world.FindAliveCombatantActorsInCircle(sovietTownAttackPoint2.CenterPosition, WRange.FromCells(SovietTownAttackGroupRange)))
|
||||
.Union(world.FindAliveCombatantActorsInCircle(townPoint.CenterPosition, WRange.FromCells(AlliedTownTransferRange)))
|
||||
.Where(a => a.HasTrait<IPositionable>() && a.Owner == soviets);
|
||||
|
||||
foreach (var unit in sovietAttackUnits)
|
||||
unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, new Move.Move(townPoint.Location, SovietTownMoveNearEnough)));
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
|
||||
allies1 = w.Players.Single(p => p.InternalName == "Allies1");
|
||||
allies2 = w.Players.SingleOrDefault(p => p.InternalName == "Allies2");
|
||||
|
||||
allies1.PlayerActor.Trait<PlayerResources>().Cash = 5000;
|
||||
if (allies2 == null)
|
||||
allies2 = allies1;
|
||||
else
|
||||
allies2.PlayerActor.Trait<PlayerResources>().Cash = 5000;
|
||||
|
||||
allies = w.Players.Single(p => p.InternalName == "Allies");
|
||||
soviets = w.Players.Single(p => p.InternalName == "Soviets");
|
||||
|
||||
soviets.PlayerActor.Trait<PlayerResources>().Cash = 1000;
|
||||
|
||||
var actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||
sam1 = actors["SAM1"];
|
||||
sam2 = actors["SAM2"];
|
||||
sam3 = actors["SAM3"];
|
||||
sam4 = actors["SAM4"];
|
||||
sams = new[] { sam1, sam2, sam3, sam4 };
|
||||
tanya = actors["Tanya"];
|
||||
einstein = actors["Einstein"];
|
||||
engineer = actors["Engineer"];
|
||||
chinookHusk = actors["ChinookHusk"];
|
||||
allies2BasePoint = actors["Allies2BasePoint"];
|
||||
reinforcementsEntryPoint = actors["ReinforcementsEntryPoint"];
|
||||
extractionLZ = actors["ExtractionLZ"];
|
||||
extractionLZEntryPoint = actors["ExtractionLZEntryPoint"];
|
||||
|
||||
badgerEntryPoint1 = actors["BadgerEntryPoint1"];
|
||||
badgerEntryPoint2 = actors["BadgerEntryPoint2"];
|
||||
badgerDropPoint1 = actors["BadgerDropPoint1"];
|
||||
badgerDropPoint2 = actors["BadgerDropPoint2"];
|
||||
badgerDropPoint3 = actors["BadgerDropPoint3"];
|
||||
|
||||
parabombPoint1 = actors["ParabombPoint1"];
|
||||
parabombPoint2 = actors["ParabombPoint2"];
|
||||
sovietBarracks = actors["SovietBarracks"];
|
||||
sovietWarFactory = actors["SovietWarFactory"];
|
||||
sovietRallyPoint = actors["SovietRallyPoint"];
|
||||
townPoint = actors["TownPoint"];
|
||||
sovietTownAttackPoint1 = actors["SovietTownAttackPoint1"];
|
||||
sovietTownAttackPoint2 = actors["SovietTownAttackPoint2"];
|
||||
yakEntryPoint = actors["YakEntryPoint"];
|
||||
yakAttackPoint = actors["YakAttackPoint"];
|
||||
|
||||
alliedBaseTopLeft = actors["AlliedBaseTopLeft"].Location;
|
||||
alliedBaseBottomRight = actors["AlliedBaseBottomRight"].Location;
|
||||
|
||||
SetupAlliedBase();
|
||||
|
||||
var shroud = allies1.Shroud;
|
||||
shroud.Explore(w, sam1.Location, WRange.FromCells(2));
|
||||
shroud.Explore(w, sam2.Location, WRange.FromCells(2));
|
||||
shroud.Explore(w, sam3.Location, WRange.FromCells(2));
|
||||
shroud.Explore(w, sam4.Location, WRange.FromCells(2));
|
||||
|
||||
if (w.LocalPlayer == null || w.LocalPlayer == allies1)
|
||||
wr.Viewport.Center(chinookHusk.CenterPosition);
|
||||
else
|
||||
wr.Viewport.Center(allies2BasePoint.CenterPosition);
|
||||
|
||||
MissionUtils.PlayMissionMusic();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,459 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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 System.Drawing;
|
||||
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.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
class Allies03ScriptInfo : TraitInfo<Allies03Script>, Requires<SpawnMapActorsInfo> { }
|
||||
|
||||
class Allies03Script : IHasObjectives, IWorldLoaded, ITick
|
||||
{
|
||||
public event Action<bool> OnObjectivesUpdated = notify => { };
|
||||
|
||||
public IEnumerable<Objective> Objectives { get { return new[] { evacuateUnits, destroyAirbases, evacuateMgg }; } }
|
||||
|
||||
Objective evacuateUnits = new Objective(ObjectiveType.Primary, EvacuateUnitsText, ObjectiveStatus.InProgress);
|
||||
Objective destroyAirbases = new Objective(ObjectiveType.Secondary, DestroyAirbasesText, ObjectiveStatus.InProgress);
|
||||
Objective evacuateMgg = new Objective(ObjectiveType.Secondary, EvacuateMggText, ObjectiveStatus.InProgress);
|
||||
|
||||
const string EvacuateUnitsText = "Following the rescue of Einstein, the Allies are now being flanked from both sides."
|
||||
+ " Evacuate {0} units before the remaining Allied forces in the area are wiped out.";
|
||||
const string DestroyAirbasesText = "Destroy the nearby Soviet airbases.";
|
||||
const string EvacuateMggText = "Einstein has recently developed a technology which allows us to obscure units from the enemy."
|
||||
+ " Evacuate at least one prototype mobile gap generator intact.";
|
||||
|
||||
const string ShortEvacuateTemplate = "{0}/{1} units evacuated";
|
||||
|
||||
int unitsEvacuatedThreshold;
|
||||
int unitsEvacuated;
|
||||
InfoWidget evacuateWidget;
|
||||
|
||||
World world;
|
||||
Player allies1;
|
||||
Player allies2;
|
||||
Player allies;
|
||||
Player soviets;
|
||||
|
||||
Actor exit1TopLeft;
|
||||
Actor exit1BottomRight;
|
||||
Actor exit1ExitPoint;
|
||||
|
||||
Actor exit2TopLeft;
|
||||
Actor exit2BottomRight;
|
||||
Actor exit2ExitPoint;
|
||||
|
||||
Actor sovietEntryPoint1;
|
||||
Actor sovietEntryPoint2;
|
||||
Actor sovietEntryPoint3;
|
||||
Actor sovietEntryPoint4;
|
||||
Actor sovietEntryPoint5;
|
||||
Actor sovietEntryPoint6;
|
||||
CPos[] sovietEntryPoints;
|
||||
Actor sovietRallyPoint1;
|
||||
Actor sovietRallyPoint2;
|
||||
Actor sovietRallyPoint3;
|
||||
Actor sovietRallyPoint4;
|
||||
Actor sovietRallyPoint5;
|
||||
Actor sovietRallyPoint6;
|
||||
CPos[] sovietRallyPoints;
|
||||
|
||||
Actor[] sovietAirfields;
|
||||
|
||||
Rectangle paradropBox;
|
||||
|
||||
const int ReinforcementsTicks1 = 1500 * 5;
|
||||
static readonly string[] Reinforcements1 = { "mgg", "2tnk", "2tnk", "2tnk", "2tnk", "1tnk", "1tnk", "jeep", "jeep", "e1", "e1", "e1", "e1", "e3", "e3" };
|
||||
int currentReinforcement1;
|
||||
|
||||
const int ReinforcementsTicks2 = 1500 * 10;
|
||||
static readonly string[] Reinforcements2 = { "mgg", "2tnk", "2tnk", "2tnk", "2tnk", "truk", "truk", "truk", "truk", "truk", "truk", "1tnk", "1tnk", "jeep", "jeep" };
|
||||
int currentReinforcement2;
|
||||
|
||||
static readonly string[] SovietUnits1 = { "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "v2rl", "v2rl", "ftrk", "apc", "e1", "e1", "e2", "e3", "e3", "e4" };
|
||||
static readonly string[] SovietUnits2 = { "4tnk", "4tnk", "4tnk", "4tnk", "3tnk", "3tnk", "3tnk", "3tnk", "v2rl", "v2rl", "ftrk", "apc", "e1", "e1", "e2", "e3", "e3", "e4" };
|
||||
int sovietUnits2Ticks;
|
||||
const int SovietGroupSize = 5;
|
||||
|
||||
int sovietParadropTicks;
|
||||
const int ParadropIncrement = 200;
|
||||
static readonly string[] ParadropTerrainTypes = { "Clear", "Road", "Rough", "Beach", "Ore" };
|
||||
static readonly string[] SovietParadroppers = { "e1", "e1", "e3", "e3", "e4" };
|
||||
int sovietParadrops;
|
||||
int maxSovietYaks;
|
||||
|
||||
int attackAtFrame;
|
||||
int attackAtFrameIncrement;
|
||||
int minAttackAtFrame;
|
||||
|
||||
Actor allies1EntryPoint;
|
||||
Actor allies1MovePoint;
|
||||
|
||||
Actor allies2EntryPoint;
|
||||
Actor allies2MovePoint;
|
||||
|
||||
const string McvName = "mcv";
|
||||
const string YakName = "yak";
|
||||
|
||||
string difficulty;
|
||||
|
||||
void MissionFailed(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionFailed(world, text, allies1, allies2);
|
||||
}
|
||||
|
||||
void MissionAccomplished(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionAccomplished(world, text, allies1, allies2);
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (allies1.WinState != WinState.Undefined) return;
|
||||
|
||||
if (world.FrameNumber == 1)
|
||||
{
|
||||
SpawnAlliedUnit(McvName);
|
||||
evacuateWidget = new InfoWidget("");
|
||||
Ui.Root.AddChild(evacuateWidget);
|
||||
UpdateUnitsEvacuated();
|
||||
}
|
||||
if (world.FrameNumber == attackAtFrame)
|
||||
{
|
||||
SpawnSovietUnits();
|
||||
attackAtFrame += attackAtFrameIncrement;
|
||||
attackAtFrameIncrement = Math.Max(attackAtFrameIncrement - 5, minAttackAtFrame);
|
||||
}
|
||||
|
||||
if (world.FrameNumber == ReinforcementsTicks1 || world.FrameNumber == ReinforcementsTicks2)
|
||||
Sound.Play("reinfor1.aud");
|
||||
|
||||
if (world.FrameNumber % 25 == 0)
|
||||
{
|
||||
if (world.FrameNumber >= ReinforcementsTicks1 && currentReinforcement1 < Reinforcements1.Length)
|
||||
SpawnAlliedUnit(Reinforcements1[currentReinforcement1++]);
|
||||
|
||||
if (world.FrameNumber >= ReinforcementsTicks2 && currentReinforcement2 < Reinforcements2.Length)
|
||||
SpawnAlliedUnit(Reinforcements2[currentReinforcement2++]);
|
||||
}
|
||||
|
||||
|
||||
if (sovietParadrops > 0)
|
||||
{
|
||||
if (world.FrameNumber == sovietParadropTicks)
|
||||
Sound.Play("sovfapp1.aud");
|
||||
|
||||
if (world.FrameNumber >= sovietParadropTicks && world.FrameNumber % ParadropIncrement == 0)
|
||||
{
|
||||
CPos lz;
|
||||
CPos entry;
|
||||
do
|
||||
{
|
||||
var x = world.SharedRandom.Next(paradropBox.X, paradropBox.X + paradropBox.Width);
|
||||
var y = world.SharedRandom.Next(paradropBox.Y, paradropBox.Y + paradropBox.Height);
|
||||
entry = new CPos(0, y);
|
||||
lz = new CPos(x, y);
|
||||
}
|
||||
while (!ParadropTerrainTypes.Contains(world.GetTerrainType(lz)));
|
||||
MissionUtils.Paradrop(world, soviets, SovietParadroppers, entry, lz);
|
||||
sovietParadrops--;
|
||||
}
|
||||
}
|
||||
if (world.FrameNumber % 25 == 0)
|
||||
ManageSovietUnits();
|
||||
|
||||
if (destroyAirbases.Status != ObjectiveStatus.Completed)
|
||||
{
|
||||
if (world.FrameNumber % 25 == 0)
|
||||
BuildSovietAircraft();
|
||||
|
||||
ManageSovietAircraft();
|
||||
}
|
||||
|
||||
EvacuateAlliedUnits(exit1TopLeft.Location, exit1BottomRight.Location, exit1ExitPoint.Location);
|
||||
EvacuateAlliedUnits(exit2TopLeft.Location, exit2BottomRight.Location, exit2ExitPoint.Location);
|
||||
|
||||
CheckSovietAirbases();
|
||||
|
||||
if (!world.Actors.Any(a => (a.Owner == allies1 || a.Owner == allies2) && a.IsInWorld && !a.IsDead()
|
||||
&& ((a.HasTrait<Building>() && !a.HasTrait<Wall>()) || a.HasTrait<BaseBuilding>())))
|
||||
{
|
||||
evacuateUnits.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("The remaining Allied forces in the area have been wiped out.");
|
||||
}
|
||||
}
|
||||
|
||||
Actor FirstUnshroudedOrDefault(IEnumerable<Actor> actors, World world, int shroudRange)
|
||||
{
|
||||
return actors.FirstOrDefault(u => world.FindAliveCombatantActorsInCircle(u.CenterPosition, WRange.FromCells(shroudRange)).All(a => !a.HasTrait<CreatesShroud>()));
|
||||
}
|
||||
|
||||
void ManageSovietAircraft()
|
||||
{
|
||||
var enemies = world.Actors
|
||||
.Where(u => (u.Owner == allies1 || u.Owner == allies2)
|
||||
&& ((u.HasTrait<Building>() && !u.HasTrait<Wall>()) || u.HasTrait<Mobile>()) && u.IsInWorld && !u.IsDead()
|
||||
&& (!u.HasTrait<Spy>() || !u.Trait<Spy>().Disguised || (u.Trait<Spy>().Disguised && u.Trait<Spy>().disguisedAsPlayer != soviets)));
|
||||
|
||||
foreach (var aircraft in SovietAircraft())
|
||||
{
|
||||
var pos = aircraft.CenterPosition;
|
||||
var plane = aircraft.Trait<Plane>();
|
||||
var ammo = aircraft.Trait<LimitedAmmo>();
|
||||
if ((pos.Z == 0 && ammo.FullAmmo()) || (pos.Z != 0 && ammo.HasAmmo()))
|
||||
{
|
||||
var enemy = FirstUnshroudedOrDefault(enemies.OrderBy(u => (aircraft.CenterPosition - u.CenterPosition).LengthSquared), world, 10);
|
||||
if (enemy != null)
|
||||
{
|
||||
if (!aircraft.IsIdle && aircraft.GetCurrentActivity().GetType() != typeof(FlyAttack))
|
||||
aircraft.CancelActivity();
|
||||
|
||||
if (pos.Z == 0)
|
||||
plane.UnReserve();
|
||||
|
||||
aircraft.QueueActivity(new FlyAttack(Target.FromActor(enemy)));
|
||||
}
|
||||
}
|
||||
else if (pos.Z != 0 && !LandIsQueued(aircraft))
|
||||
{
|
||||
aircraft.CancelActivity();
|
||||
aircraft.QueueActivity(new ReturnToBase(aircraft, null));
|
||||
aircraft.QueueActivity(new ResupplyAircraft());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LandIsQueued(Actor actor)
|
||||
{
|
||||
for (var a = actor.GetCurrentActivity(); a != null; a = a.NextActivity)
|
||||
if (a is ReturnToBase || a is Land) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void BuildSovietAircraft()
|
||||
{
|
||||
var queue = MissionUtils.FindQueues(world, soviets, "Plane").FirstOrDefault(q => q.CurrentItem() == null);
|
||||
if (queue == null || SovietAircraft().Count() >= maxSovietYaks) return;
|
||||
|
||||
queue.ResolveOrder(queue.self, Order.StartProduction(queue.self, YakName, 1));
|
||||
}
|
||||
|
||||
IEnumerable<Actor> SovietAircraft()
|
||||
{
|
||||
return world.Actors.Where(a => a.HasTrait<AttackPlane>() && a.Owner == soviets && a.IsInWorld && !a.IsDead());
|
||||
}
|
||||
|
||||
void CheckSovietAirbases()
|
||||
{
|
||||
if (destroyAirbases.Status != ObjectiveStatus.Completed && sovietAirfields.All(a => a.IsDead() || a.Owner != soviets))
|
||||
{
|
||||
destroyAirbases.Status = ObjectiveStatus.Completed;
|
||||
OnObjectivesUpdated(true);
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnSovietUnits()
|
||||
{
|
||||
var route = world.SharedRandom.Next(sovietEntryPoints.Length);
|
||||
var spawnPoint = sovietEntryPoints[route];
|
||||
var rallyPoint = sovietRallyPoints[route];
|
||||
|
||||
IEnumerable<string> units;
|
||||
if (world.FrameNumber >= sovietUnits2Ticks)
|
||||
units = SovietUnits2;
|
||||
else
|
||||
units = SovietUnits1;
|
||||
|
||||
var unit = world.CreateActor(units.Random(world.SharedRandom),
|
||||
new TypeDictionary
|
||||
{
|
||||
new LocationInit(spawnPoint),
|
||||
new OwnerInit(soviets)
|
||||
});
|
||||
unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, new Move.Move(rallyPoint, 3)));
|
||||
}
|
||||
|
||||
void AttackNearestAlliedActor(Actor self)
|
||||
{
|
||||
var enemies = world.Actors.Where(u => u.AppearsHostileTo(self) && (u.Owner == allies1 || u.Owner == allies2)
|
||||
&& ((u.HasTrait<Building>() && !u.HasTrait<Wall>()) || u.HasTrait<Mobile>()) && u.IsInWorld && !u.IsDead());
|
||||
|
||||
var enemy = FirstUnshroudedOrDefault(enemies.OrderBy(u => (self.CenterPosition - u.CenterPosition).LengthSquared), world, 10);
|
||||
if (enemy != null)
|
||||
self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(enemy), WRange.FromCells(3))));
|
||||
}
|
||||
|
||||
void ManageSovietUnits()
|
||||
{
|
||||
foreach (var rallyPoint in sovietRallyPoints)
|
||||
{
|
||||
var units = world.FindAliveCombatantActorsInCircle(rallyPoint.CenterPosition, WRange.FromCells(10))
|
||||
.Where(u => u.IsIdle && u.HasTrait<Mobile>() && u.HasTrait<AttackBase>() && u.Owner == soviets);
|
||||
if (units.Count() >= SovietGroupSize)
|
||||
{
|
||||
foreach (var unit in units)
|
||||
AttackNearestAlliedActor(unit);
|
||||
}
|
||||
}
|
||||
|
||||
var scatteredUnits = world.Actors.Where(u => u.IsInWorld && !u.IsDead() && u.HasTrait<Mobile>() && u.IsIdle && u.Owner == soviets)
|
||||
.Except(world.WorldActor.Trait<SpawnMapActors>().Actors.Values)
|
||||
.Except(sovietRallyPoints.SelectMany(rp => world.FindAliveCombatantActorsInCircle(rp.CenterPosition, WRange.FromCells(10))));
|
||||
|
||||
foreach (var unit in scatteredUnits)
|
||||
AttackNearestAlliedActor(unit);
|
||||
}
|
||||
|
||||
void SpawnAlliedUnit(string actor)
|
||||
{
|
||||
SpawnAndMove(actor, allies1, allies1EntryPoint.Location, allies1MovePoint.Location);
|
||||
if (allies1 != allies2)
|
||||
SpawnAndMove(actor, allies2, allies2EntryPoint.Location, allies2MovePoint.Location);
|
||||
}
|
||||
|
||||
Actor SpawnAndMove(string actor, Player owner, CPos entry, CPos to)
|
||||
{
|
||||
var unit = world.CreateActor(actor, new TypeDictionary
|
||||
{
|
||||
new OwnerInit(owner),
|
||||
new LocationInit(entry),
|
||||
new FacingInit(Traits.Util.GetFacing(to - entry, 0))
|
||||
});
|
||||
unit.QueueActivity(new Move.Move(to));
|
||||
return unit;
|
||||
}
|
||||
|
||||
void UpdateUnitsEvacuated()
|
||||
{
|
||||
evacuateWidget.Text = ShortEvacuateTemplate.F(unitsEvacuated, unitsEvacuatedThreshold);
|
||||
if (evacuateUnits.Status == ObjectiveStatus.InProgress && unitsEvacuated >= unitsEvacuatedThreshold)
|
||||
{
|
||||
evacuateUnits.Status = ObjectiveStatus.Completed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionAccomplished("The remaining Allied forces in the area have evacuated.");
|
||||
}
|
||||
}
|
||||
|
||||
void EvacuateAlliedUnits(CPos tl, CPos br, CPos exit)
|
||||
{
|
||||
var units = world.FindAliveCombatantActorsInBox(tl, br)
|
||||
.Where(u => u.HasTrait<Mobile>() && !u.HasTrait<Aircraft>() && (u.Owner == allies1 || u.Owner == allies2));
|
||||
|
||||
foreach (var unit in units)
|
||||
{
|
||||
unit.CancelActivity();
|
||||
unit.ChangeOwner(allies);
|
||||
unitsEvacuated++;
|
||||
|
||||
var createsShroud = unit.TraitOrDefault<CreatesShroud>();
|
||||
if (createsShroud != null && evacuateMgg.Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
evacuateMgg.Status = ObjectiveStatus.Completed;
|
||||
OnObjectivesUpdated(true);
|
||||
}
|
||||
|
||||
var cargo = unit.TraitOrDefault<Cargo>();
|
||||
if (cargo != null)
|
||||
unitsEvacuated += cargo.Passengers.Count();
|
||||
|
||||
UpdateUnitsEvacuated();
|
||||
unit.QueueActivity(new Move.Move(exit));
|
||||
unit.QueueActivity(new RemoveSelf());
|
||||
}
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
|
||||
difficulty = w.LobbyInfo.GlobalSettings.Difficulty;
|
||||
Game.Debug("{0} difficulty selected".F(difficulty));
|
||||
|
||||
allies1 = w.Players.Single(p => p.InternalName == "Allies1");
|
||||
allies2 = w.Players.SingleOrDefault(p => p.InternalName == "Allies2");
|
||||
|
||||
var res = allies1.PlayerActor.Trait<PlayerResources>();
|
||||
if (allies2 == null)
|
||||
{
|
||||
res.Cash = 10000;
|
||||
allies2 = allies1;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.Cash = 5000;
|
||||
res = allies2.PlayerActor.Trait<PlayerResources>();
|
||||
res.Cash = 5000;
|
||||
}
|
||||
|
||||
attackAtFrame = attackAtFrameIncrement = difficulty == "Hard" || difficulty == "Normal" ? 500 : 600;
|
||||
minAttackAtFrame = difficulty == "Hard" || difficulty == "Normal" ? 100 : 150;
|
||||
unitsEvacuatedThreshold = difficulty == "Hard" ? 200 : difficulty == "Normal" ? 100 : 50;
|
||||
maxSovietYaks = difficulty == "Hard" ? 4 : difficulty == "Normal" ? 2 : 0;
|
||||
sovietParadrops = difficulty == "Hard" ? 40 : difficulty == "Normal" ? 20 : 0;
|
||||
sovietParadropTicks = difficulty == "Hard" ? 1500 * 17 : 1500 * 20;
|
||||
sovietUnits2Ticks = difficulty == "Hard" ? 1500 * 12 : 1500 * 15;
|
||||
|
||||
evacuateUnits.Text = evacuateUnits.Text.F(unitsEvacuatedThreshold);
|
||||
|
||||
allies = w.Players.Single(p => p.InternalName == "Allies");
|
||||
soviets = w.Players.Single(p => p.InternalName == "Soviets");
|
||||
|
||||
var actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||
exit1TopLeft = actors["Exit1TopLeft"];
|
||||
exit1BottomRight = actors["Exit1BottomRight"];
|
||||
exit1ExitPoint = actors["Exit1ExitPoint"];
|
||||
exit2TopLeft = actors["Exit2TopLeft"];
|
||||
exit2BottomRight = actors["Exit2BottomRight"];
|
||||
exit2ExitPoint = actors["Exit2ExitPoint"];
|
||||
allies1EntryPoint = actors["Allies1EntryPoint"];
|
||||
allies1MovePoint = actors["Allies1MovePoint"];
|
||||
allies2EntryPoint = actors["Allies2EntryPoint"];
|
||||
allies2MovePoint = actors["Allies2MovePoint"];
|
||||
sovietEntryPoint1 = actors["SovietEntryPoint1"];
|
||||
sovietEntryPoint2 = actors["SovietEntryPoint2"];
|
||||
sovietEntryPoint3 = actors["SovietEntryPoint3"];
|
||||
sovietEntryPoint4 = actors["SovietEntryPoint4"];
|
||||
sovietEntryPoint5 = actors["SovietEntryPoint5"];
|
||||
sovietEntryPoint6 = actors["SovietEntryPoint6"];
|
||||
sovietEntryPoints = new[] { sovietEntryPoint1, sovietEntryPoint2, sovietEntryPoint3, sovietEntryPoint4, sovietEntryPoint5, sovietEntryPoint6 }.Select(p => p.Location).ToArray();
|
||||
sovietRallyPoint1 = actors["SovietRallyPoint1"];
|
||||
sovietRallyPoint2 = actors["SovietRallyPoint2"];
|
||||
sovietRallyPoint3 = actors["SovietRallyPoint3"];
|
||||
sovietRallyPoint4 = actors["SovietRallyPoint4"];
|
||||
sovietRallyPoint5 = actors["SovietRallyPoint5"];
|
||||
sovietRallyPoint6 = actors["SovietRallyPoint6"];
|
||||
sovietRallyPoints = new[] { sovietRallyPoint1, sovietRallyPoint2, sovietRallyPoint3, sovietRallyPoint4, sovietRallyPoint5, sovietRallyPoint6 }.Select(p => p.Location).ToArray();
|
||||
sovietAirfields = actors.Values.Where(a => a.Owner == soviets && a.HasTrait<Production>() && a.Info.Traits.Get<ProductionInfo>().Produces.Contains("Plane")).ToArray();
|
||||
var topLeft = actors["ParadropBoxTopLeft"];
|
||||
var bottomRight = actors["ParadropBoxBottomRight"];
|
||||
paradropBox = new Rectangle(topLeft.Location.X, topLeft.Location.Y, bottomRight.Location.X - topLeft.Location.X, bottomRight.Location.Y - topLeft.Location.Y);
|
||||
|
||||
if (w.LocalPlayer == null || w.LocalPlayer == allies1)
|
||||
wr.Viewport.Center(allies1EntryPoint.CenterPosition);
|
||||
else
|
||||
wr.Viewport.Center(allies2EntryPoint.CenterPosition);
|
||||
|
||||
OnObjectivesUpdated(false);
|
||||
MissionUtils.PlayMissionMusic();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,576 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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 System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Buildings;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using OpenRA.Mods.RA.Render;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
class Allies04ScriptInfo : TraitInfo<Allies04Script>, Requires<SpawnMapActorsInfo> { }
|
||||
|
||||
class Allies04Script : IHasObjectives, IWorldLoaded, ITick
|
||||
{
|
||||
public event Action<bool> OnObjectivesUpdated = notify => { };
|
||||
|
||||
public IEnumerable<Objective> Objectives { get { return new[] { infiltrateLab, destroyBase }; } }
|
||||
|
||||
Objective infiltrateLab = new Objective(ObjectiveType.Primary, "", ObjectiveStatus.InProgress);
|
||||
Objective destroyBase = new Objective(ObjectiveType.Primary, DestroyBaseText, ObjectiveStatus.Inactive);
|
||||
|
||||
const string InfiltrateLabTemplate = "The Soviets are currently developing a new defensive system named the \"Iron Curtain\" at their main research laboratory."
|
||||
+ " Get our {0} into the laboratory undetected.";
|
||||
|
||||
const string DestroyBaseText = "Secure the laboratory and destroy the rest of the Soviet base. Ensure that the laboratory is not destroyed.";
|
||||
|
||||
Actor hijackTruck;
|
||||
Actor baseGuard;
|
||||
Actor baseGuardMovePos;
|
||||
Actor baseGuardTruckPos;
|
||||
Actor lab;
|
||||
int baseGuardTicks = 100;
|
||||
|
||||
Actor allies1Spy;
|
||||
Actor allies2Spy;
|
||||
bool allies1SpyInfiltratedLab;
|
||||
bool allies2SpyInfiltratedLab;
|
||||
int frameInfiltrated = -1;
|
||||
|
||||
CountdownTimer destroyBaseTimer;
|
||||
CountdownTimerWidget destroyBaseTimerWidget;
|
||||
|
||||
Player allies1;
|
||||
Player allies2;
|
||||
Player soviets;
|
||||
Player creeps;
|
||||
World world;
|
||||
WorldRenderer worldRenderer;
|
||||
|
||||
List<Patrol> patrols;
|
||||
CPos[] patrolPoints1;
|
||||
CPos[] patrolPoints2;
|
||||
CPos[] patrolPoints3;
|
||||
CPos[] patrolPoints4;
|
||||
CPos[] patrolPoints5;
|
||||
|
||||
Actor reinforcementsEntryPoint;
|
||||
Actor reinforcementsUnloadPoint;
|
||||
|
||||
Actor spyReinforcementsEntryPoint;
|
||||
Actor spyReinforcementsUnloadPoint;
|
||||
Actor spyReinforcementsExitPoint;
|
||||
|
||||
string difficulty;
|
||||
int destroyBaseTicks;
|
||||
|
||||
int nextCivilianMove = 1;
|
||||
|
||||
Actor bridgeTank;
|
||||
Actor bridgeAttackPoint;
|
||||
Actor bridge;
|
||||
bool attackingBridge;
|
||||
|
||||
bool attackingTown = true;
|
||||
Actor[] townAttackers;
|
||||
|
||||
void MissionFailed(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionFailed(world, text, allies1, allies2);
|
||||
}
|
||||
|
||||
void MissionAccomplished(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionAccomplished(world, text, allies1, allies2);
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (allies1.WinState != WinState.Undefined) return;
|
||||
|
||||
if (world.FrameNumber == 1)
|
||||
InsertSpies();
|
||||
|
||||
if (frameInfiltrated != -1)
|
||||
{
|
||||
if (world.FrameNumber == frameInfiltrated + 100)
|
||||
{
|
||||
Sound.Play("aarrivs1.aud");
|
||||
worldRenderer.Viewport.Center(reinforcementsUnloadPoint.CenterPosition);
|
||||
world.AddFrameEndTask(w => SendReinforcements());
|
||||
}
|
||||
if (world.FrameNumber == frameInfiltrated + 200)
|
||||
{
|
||||
Sound.Play("timergo1.aud");
|
||||
destroyBaseTimer = new CountdownTimer(destroyBaseTicks, OnDestroyBaseTimerExpired, true);
|
||||
destroyBaseTimerWidget = new CountdownTimerWidget(destroyBaseTimer, "Secure lab in: {0}");
|
||||
Ui.Root.AddChild(destroyBaseTimerWidget);
|
||||
}
|
||||
|
||||
if (world.FrameNumber >= frameInfiltrated + 200)
|
||||
destroyBaseTimer.Tick();
|
||||
|
||||
if (world.FrameNumber == frameInfiltrated + 1500 * 12 && !bridgeTank.IsDead() && bridgeTank.IsInWorld && !bridge.IsDead())
|
||||
{
|
||||
bridgeTank.QueueActivity(new Attack(Target.FromPos(bridge.CenterPosition), WRange.FromCells(4)));
|
||||
attackingBridge = true;
|
||||
}
|
||||
if (attackingBridge && bridge.IsDead())
|
||||
{
|
||||
if (!bridgeTank.IsDead())
|
||||
bridgeTank.CancelActivity();
|
||||
attackingBridge = false;
|
||||
}
|
||||
|
||||
if (world.FrameNumber == frameInfiltrated + 1500 * 6)
|
||||
foreach (var attacker in townAttackers.Where(a => !a.IsDead() && a.IsInWorld))
|
||||
{
|
||||
attacker.CancelActivity();
|
||||
attacker.QueueActivity(new AttackMove.AttackMoveActivity(attacker, new Move.Move(reinforcementsUnloadPoint.Location + new CVec(10, -15), 3)));
|
||||
}
|
||||
}
|
||||
|
||||
if (attackingTown)
|
||||
{
|
||||
foreach (var attacker in townAttackers.Where(u => u.IsIdle && !u.IsDead() && u.IsInWorld))
|
||||
{
|
||||
var enemies = world.Actors.Where(u => u.Owner == creeps && u.HasTrait<ITargetable>()
|
||||
&& ((u.HasTrait<Building>() && !u.HasTrait<Wall>() && !u.HasTrait<Bridge>()) || u.HasTrait<Mobile>()) && !u.IsDead() && u.IsInWorld);
|
||||
|
||||
var enemy = enemies.ClosestTo(attacker);
|
||||
if (enemy != null)
|
||||
attacker.QueueActivity(new AttackMove.AttackMoveActivity(attacker, new Attack(Target.FromActor(enemy), WRange.FromCells(3))));
|
||||
else
|
||||
{
|
||||
attackingTown = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var patrol in patrols)
|
||||
patrol.DoPatrol();
|
||||
|
||||
MissionUtils.CapOre(soviets);
|
||||
|
||||
BaseGuardTick();
|
||||
|
||||
if (world.FrameNumber == nextCivilianMove)
|
||||
{
|
||||
var civilians = world.Actors.Where(a => !a.IsDead() && a.IsInWorld && a.Owner == creeps && 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);
|
||||
}
|
||||
}
|
||||
|
||||
world.AddFrameEndTask(w =>
|
||||
{
|
||||
if ((allies1Spy.IsDead() && !allies1SpyInfiltratedLab) || (allies2Spy != null && allies2Spy.IsDead() && !allies2SpyInfiltratedLab))
|
||||
{
|
||||
infiltrateLab.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("{0} spy was killed.".F(allies1 != allies2 ? "A" : "The"));
|
||||
}
|
||||
else if (lab.IsDead())
|
||||
{
|
||||
if (infiltrateLab.Status == ObjectiveStatus.InProgress)
|
||||
infiltrateLab.Status = ObjectiveStatus.Failed;
|
||||
else if (destroyBase.Status == ObjectiveStatus.InProgress)
|
||||
destroyBase.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("The Soviet research laboratory was destroyed.");
|
||||
}
|
||||
else if (!world.Actors.Any(a => (a.Owner == allies1 || a.Owner == allies2) && !a.IsDead()
|
||||
&& (a.HasTrait<Building>() && !a.HasTrait<Wall>()) || a.HasTrait<BaseBuilding>()))
|
||||
{
|
||||
destroyBase.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("The remaining Allied forces in the area have been wiped out.");
|
||||
}
|
||||
else if (SovietBaseDestroyed() && infiltrateLab.Status == ObjectiveStatus.Completed)
|
||||
{
|
||||
destroyBase.Status = ObjectiveStatus.Completed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionAccomplished("The Soviet research laboratory has been secured successfully.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool SovietBaseDestroyed()
|
||||
{
|
||||
return !world.Actors.Any(a => a.Owner == soviets && a.IsInWorld && !a.IsDead()
|
||||
&& a.HasTrait<Building>() && !a.HasTrait<Wall>() && !a.HasTrait<Allies04TrivialBuilding>() && a != lab);
|
||||
}
|
||||
|
||||
void OnDestroyBaseTimerExpired(CountdownTimer t)
|
||||
{
|
||||
if (SovietBaseDestroyed() && infiltrateLab.Status == ObjectiveStatus.Completed) return;
|
||||
destroyBase.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("The Soviet research laboratory was not secured in time.");
|
||||
}
|
||||
|
||||
void BaseGuardTick()
|
||||
{
|
||||
if (baseGuardTicks <= 0 || baseGuard.IsDead() || !baseGuard.IsInWorld) return;
|
||||
|
||||
if (hijackTruck.Location == baseGuardTruckPos.Location)
|
||||
{
|
||||
if (--baseGuardTicks <= 0)
|
||||
baseGuard.QueueActivity(new Move.Move(baseGuardMovePos.Location));
|
||||
}
|
||||
else
|
||||
baseGuardTicks = 100;
|
||||
}
|
||||
|
||||
void OnLabInfiltrated(Actor spy)
|
||||
{
|
||||
if (spy == allies1Spy) allies1SpyInfiltratedLab = true;
|
||||
else if (spy == allies2Spy) allies2SpyInfiltratedLab = true;
|
||||
|
||||
if (allies1SpyInfiltratedLab && (allies2SpyInfiltratedLab || allies2Spy == null))
|
||||
{
|
||||
infiltrateLab.Status = ObjectiveStatus.Completed;
|
||||
destroyBase.Status = ObjectiveStatus.InProgress;
|
||||
OnObjectivesUpdated(true);
|
||||
frameInfiltrated = world.FrameNumber;
|
||||
|
||||
foreach (var actor in world.Actors.Where(a => !a.IsDead() && a.HasTrait<Allies04TransformOnLabInfiltrate>()))
|
||||
actor.QueueActivity(false, new Transform(actor, actor.Info.Traits.Get<Allies04TransformOnLabInfiltrateInfo>().ToActor) { SkipMakeAnims = true });
|
||||
}
|
||||
}
|
||||
|
||||
void SendReinforcements()
|
||||
{
|
||||
var lst = world.CreateActor("lst.unselectable", new TypeDictionary
|
||||
{
|
||||
new OwnerInit(allies1),
|
||||
new LocationInit(reinforcementsEntryPoint.Location)
|
||||
});
|
||||
lst.Trait<Cargo>().Load(lst, world.CreateActor(false, "mcv", new TypeDictionary { new OwnerInit(allies1) }));
|
||||
if (allies1 != allies2)
|
||||
lst.Trait<Cargo>().Load(lst, world.CreateActor(false, "mcv", new TypeDictionary { new OwnerInit(allies2) }));
|
||||
|
||||
lst.QueueActivity(new Move.Move(reinforcementsUnloadPoint.Location));
|
||||
lst.QueueActivity(new Wait(10));
|
||||
|
||||
lst.QueueActivity(new CallFunc(() =>
|
||||
{
|
||||
allies1.PlayerActor.Trait<PlayerResources>().GiveCash(allies1 == allies2 ? 5000 : 2500);
|
||||
if (allies1 != allies2)
|
||||
allies2.PlayerActor.Trait<PlayerResources>().GiveCash(2500);
|
||||
}));
|
||||
|
||||
lst.AddTrait(new TransformedAction(self =>
|
||||
{
|
||||
self.QueueActivity(new Wait(10));
|
||||
self.QueueActivity(new Move.Move(reinforcementsEntryPoint.Location));
|
||||
self.QueueActivity(new RemoveSelf());
|
||||
}));
|
||||
lst.QueueActivity(new UnloadCargo(lst, true));
|
||||
lst.QueueActivity(new Transform(lst, "lst.unselectable.nocargo") { SkipMakeAnims = true });
|
||||
}
|
||||
|
||||
class Patrol
|
||||
{
|
||||
Actor[] actors;
|
||||
CPos[] points;
|
||||
int pointIndex;
|
||||
World world;
|
||||
|
||||
public Patrol(World world, string[] actorNames, Player owner, CPos[] points, int pointIndex)
|
||||
{
|
||||
this.world = world;
|
||||
this.points = points;
|
||||
this.pointIndex = pointIndex;
|
||||
var td = new TypeDictionary { new OwnerInit(owner), new LocationInit(points[pointIndex]) };
|
||||
actors = actorNames.Select(a => world.CreateActor(a, td)).ToArray();
|
||||
}
|
||||
|
||||
public void DoPatrol()
|
||||
{
|
||||
if (actors.Any(a => a.IsDead() || !a.IsIdle || !a.IsInWorld)) return;
|
||||
|
||||
pointIndex = (pointIndex + 1) % points.Length;
|
||||
foreach (var actor in actors.Where(a => !a.IsDead() && a.IsInWorld))
|
||||
{
|
||||
actor.QueueActivity(new Wait(world.SharedRandom.Next(50, 75)));
|
||||
actor.QueueActivity(new AttackMove.AttackMoveActivity(actor, new Move.Move(points[pointIndex], 0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsertSpies()
|
||||
{
|
||||
var lst = world.CreateActor("lst.unselectable", new TypeDictionary
|
||||
{
|
||||
new OwnerInit(allies1),
|
||||
new LocationInit(spyReinforcementsEntryPoint.Location)
|
||||
});
|
||||
|
||||
allies1Spy = world.CreateActor(false, "spy.strong", new TypeDictionary { new OwnerInit(allies1) });
|
||||
lst.Trait<Cargo>().Load(lst, allies1Spy);
|
||||
if (allies1 != allies2)
|
||||
{
|
||||
allies2Spy = world.CreateActor(false, "spy.strong", new TypeDictionary { new OwnerInit(allies2) });
|
||||
lst.Trait<Cargo>().Load(lst, allies2Spy);
|
||||
}
|
||||
|
||||
lst.AddTrait(new TransformedAction(self =>
|
||||
{
|
||||
self.QueueActivity(new Wait(10));
|
||||
self.QueueActivity(new Move.Move(spyReinforcementsExitPoint.Location));
|
||||
self.QueueActivity(new RemoveSelf());
|
||||
}));
|
||||
lst.QueueActivity(new Move.Move(spyReinforcementsUnloadPoint.Location));
|
||||
lst.QueueActivity(new Wait(10));
|
||||
lst.QueueActivity(new UnloadCargo(lst, true));
|
||||
lst.QueueActivity(new Transform(lst, "lst.unselectable.nocargo") { SkipMakeAnims = true });
|
||||
}
|
||||
|
||||
void SetupSubStances()
|
||||
{
|
||||
foreach (var actor in world.Actors.Where(a => a.IsInWorld && a.Owner == soviets && !a.IsDead() && a.HasTrait<TargetableSubmarine>()))
|
||||
actor.Trait<AutoTarget>().Stance = UnitStance.Defend;
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
worldRenderer = wr;
|
||||
|
||||
difficulty = w.LobbyInfo.GlobalSettings.Difficulty;
|
||||
Game.Debug("{0} difficulty selected".F(difficulty));
|
||||
|
||||
allies1 = w.Players.Single(p => p.InternalName == "Allies1");
|
||||
allies2 = w.Players.SingleOrDefault(p => p.InternalName == "Allies2");
|
||||
|
||||
allies1.PlayerActor.Trait<PlayerResources>().Cash = 0;
|
||||
if (allies2 == null)
|
||||
allies2 = allies1;
|
||||
else
|
||||
allies2.PlayerActor.Trait<PlayerResources>().Cash = 0;
|
||||
|
||||
soviets = w.Players.Single(p => p.InternalName == "Soviets");
|
||||
creeps = w.Players.Single(p => p.InternalName == "Creeps");
|
||||
infiltrateLab.Text = InfiltrateLabTemplate.F(allies1 != allies2 ? "spies" : "spy");
|
||||
|
||||
destroyBaseTicks = difficulty == "Hard" ? 1500 * 25 : difficulty == "Normal" ? 1500 * 28 : 1500 * 31;
|
||||
|
||||
var actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||
|
||||
spyReinforcementsEntryPoint = actors["SpyReinforcementsEntryPoint"];
|
||||
spyReinforcementsUnloadPoint = actors["SpyReinforcementsUnloadPoint"];
|
||||
spyReinforcementsExitPoint = actors["SpyReinforcementsExitPoint"];
|
||||
|
||||
hijackTruck = actors["HijackTruck"];
|
||||
baseGuard = actors["BaseGuard"];
|
||||
baseGuardMovePos = actors["BaseGuardMovePos"];
|
||||
baseGuardTruckPos = actors["BaseGuardTruckPos"];
|
||||
patrolPoints1 = new[]
|
||||
{
|
||||
actors["PatrolPoint11"].Location,
|
||||
actors["PatrolPoint12"].Location,
|
||||
actors["PatrolPoint13"].Location,
|
||||
actors["PatrolPoint14"].Location,
|
||||
actors["PatrolPoint15"].Location
|
||||
};
|
||||
patrolPoints2 = patrolPoints1;
|
||||
patrolPoints3 = new[]
|
||||
{
|
||||
actors["PatrolPoint21"].Location,
|
||||
actors["PatrolPoint22"].Location,
|
||||
actors["PatrolPoint23"].Location,
|
||||
actors["PatrolPoint24"].Location,
|
||||
actors["PatrolPoint25"].Location
|
||||
};
|
||||
patrolPoints4 = new[]
|
||||
{
|
||||
actors["PatrolPoint31"].Location,
|
||||
actors["PatrolPoint32"].Location,
|
||||
actors["PatrolPoint33"].Location,
|
||||
actors["PatrolPoint34"].Location
|
||||
};
|
||||
patrolPoints5 = new[]
|
||||
{
|
||||
actors["PatrolPoint41"].Location,
|
||||
actors["PatrolPoint42"].Location,
|
||||
actors["PatrolPoint43"].Location,
|
||||
actors["PatrolPoint44"].Location,
|
||||
actors["PatrolPoint45"].Location
|
||||
};
|
||||
|
||||
lab = actors["Lab"];
|
||||
lab.AddTrait(new InfiltrateAction(OnLabInfiltrated));
|
||||
lab.AddTrait(new TransformedAction(self => lab = self));
|
||||
|
||||
reinforcementsEntryPoint = actors["ReinforcementsEntryPoint"];
|
||||
reinforcementsUnloadPoint = actors["ReinforcementsUnloadPoint"];
|
||||
|
||||
patrols = new List<Patrol>
|
||||
{
|
||||
new Patrol(world, new[] { "e1", "e1", "e1", "e1", "e1" }, soviets, patrolPoints1, 0),
|
||||
new Patrol(world, new[] { "e1", "dog.patrol", "dog.patrol" }, soviets, patrolPoints2, 2),
|
||||
new Patrol(world, new[] { "e1", "dog.patrol", "dog.patrol" }, soviets, patrolPoints4, 0),
|
||||
new Patrol(world, new[] { "e1", "dog.patrol", "dog.patrol" }, soviets, patrolPoints5, 0),
|
||||
};
|
||||
if (difficulty == "Hard")
|
||||
patrols.Add(new Patrol(world, new[] { "e1", "e1", "dog.patrol" }, soviets, patrolPoints3, 0));
|
||||
|
||||
bridgeTank = actors["BridgeTank"];
|
||||
bridgeAttackPoint = actors["BridgeAttackPoint"];
|
||||
bridge = world.Actors
|
||||
.Where(a => a.HasTrait<Bridge>() && !a.IsDead())
|
||||
.OrderBy(a => (a.Location - bridgeAttackPoint.Location).LengthSquared)
|
||||
.FirstOrDefault();
|
||||
|
||||
var ta1 = actors["TownAttacker1"];
|
||||
var ta2 = actors["TownAttacker2"];
|
||||
var ta3 = actors["TownAttacker3"];
|
||||
var ta4 = actors["TownAttacker4"];
|
||||
var ta5 = actors["TownAttacker5"];
|
||||
var ta6 = actors["TownAttacker6"];
|
||||
var ta7 = actors["TownAttacker7"];
|
||||
|
||||
townAttackers = new[] { ta1, ta2, ta3, ta4, ta5, ta6, ta7 };
|
||||
|
||||
OnObjectivesUpdated(false);
|
||||
SetupSubStances();
|
||||
|
||||
worldRenderer.Viewport.Center(spyReinforcementsEntryPoint.CenterPosition);
|
||||
MissionUtils.PlayMissionMusic();
|
||||
}
|
||||
}
|
||||
|
||||
class Allies04HijackableInfo : ITraitInfo, Requires<InfiltratableInfo>
|
||||
{
|
||||
public object Create(ActorInitializer init) { return new Allies04Hijackable(init.self); }
|
||||
}
|
||||
|
||||
class Allies04Hijackable : IAcceptInfiltrator, INotifyPassengerExited
|
||||
{
|
||||
public Player OldOwner;
|
||||
|
||||
void OnTruckHijacked(Actor spy) { }
|
||||
|
||||
public Allies04Hijackable(Actor self)
|
||||
{
|
||||
OldOwner = self.Owner;
|
||||
|
||||
self.AddTrait(new InfiltrateAction(OnTruckHijacked));
|
||||
}
|
||||
|
||||
public void OnInfiltrate(Actor self, Actor spy)
|
||||
{
|
||||
if (self.Trait<Cargo>().IsEmpty(self))
|
||||
self.ChangeOwner(spy.Owner);
|
||||
|
||||
self.Trait<Cargo>().Load(self, spy);
|
||||
}
|
||||
|
||||
public void PassengerExited(Actor self, Actor passenger)
|
||||
{
|
||||
if (self.Trait<Cargo>().IsEmpty(self))
|
||||
{
|
||||
self.CancelActivity();
|
||||
self.ChangeOwner(OldOwner);
|
||||
}
|
||||
else if (self.Owner == passenger.Owner)
|
||||
self.ChangeOwner(self.Trait<Cargo>().Passengers.First().Owner);
|
||||
}
|
||||
}
|
||||
|
||||
class Allies04RenderHijackedInfo : RenderUnitInfo
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new Allies04RenderHijacked(init.self, this); }
|
||||
}
|
||||
|
||||
class Allies04RenderHijacked : RenderUnit
|
||||
{
|
||||
Allies04Hijackable hijackable;
|
||||
Allies04RenderHijackedInfo info;
|
||||
|
||||
public Allies04RenderHijacked(Actor self, Allies04RenderHijackedInfo info)
|
||||
: base(self)
|
||||
{
|
||||
this.info = info;
|
||||
hijackable = self.Trait<Allies04Hijackable>();
|
||||
}
|
||||
|
||||
protected override string PaletteName(Actor self)
|
||||
{
|
||||
return info.Palette ?? info.PlayerPalette + hijackable.OldOwner.InternalName;
|
||||
}
|
||||
}
|
||||
|
||||
class Allies04TrivialBuildingInfo : TraitInfo<Allies04TrivialBuilding> { }
|
||||
class Allies04TrivialBuilding { }
|
||||
|
||||
class Allies04MaintainBuildingInfo : TraitInfo<Allies04MaintainBuilding>
|
||||
{
|
||||
public readonly string Player = null;
|
||||
}
|
||||
|
||||
class Allies04MaintainBuilding : INotifyDamageStateChanged
|
||||
{
|
||||
public void DamageStateChanged(Actor self, AttackInfo e)
|
||||
{
|
||||
if (self.Owner.InternalName != self.Info.Traits.Get<Allies04MaintainBuildingInfo>().Player) return;
|
||||
|
||||
if (self.HasTrait<Sellable>() && e.DamageState == DamageState.Critical && e.PreviousDamageState < DamageState.Critical)
|
||||
self.Trait<Sellable>().Sell(self);
|
||||
|
||||
else if (self.HasTrait<RepairableBuilding>() && e.DamageState > DamageState.Undamaged && e.PreviousDamageState == DamageState.Undamaged)
|
||||
self.Trait<RepairableBuilding>().RepairBuilding(self, self.Owner);
|
||||
}
|
||||
}
|
||||
|
||||
class Allies04TransformOnLabInfiltrateInfo : TraitInfo<Allies04TransformOnLabInfiltrate>
|
||||
{
|
||||
[ActorReference]
|
||||
public readonly string ToActor = null;
|
||||
}
|
||||
|
||||
class Allies04TransformOnLabInfiltrate { }
|
||||
|
||||
class Allies04HazyPaletteEffectInfo : TraitInfo<Allies04HazyPaletteEffect> { }
|
||||
|
||||
class Allies04HazyPaletteEffect : IPaletteModifier
|
||||
{
|
||||
static readonly string[] ExcludePalettes = { "cursor", "chrome", "colorpicker", "fog", "shroud" };
|
||||
|
||||
public void AdjustPalette(Dictionary<string, Palette> palettes)
|
||||
{
|
||||
foreach (var pal in palettes)
|
||||
{
|
||||
if (ExcludePalettes.Contains(pal.Key))
|
||||
continue;
|
||||
|
||||
for (var x = 0; x < 256; x++)
|
||||
{
|
||||
var from = pal.Value.GetColor(x);
|
||||
var to = Color.FromArgb(from.A, Color.FromKnownColor(KnownColor.DarkOrange));
|
||||
pal.Value.SetColor(x, Exts.ColorLerp(0.15f, from, to));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
public class CountdownTimer
|
||||
{
|
||||
public int TicksLeft;
|
||||
|
||||
public event Action<CountdownTimer> OnExpired = t => { };
|
||||
public event Action<CountdownTimer> OnOneMinuteRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnTwoMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnThreeMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnFourMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnFiveMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnTenMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnTwentyMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnThirtyMinutesRemaining = t => { };
|
||||
public event Action<CountdownTimer> OnFortyMinutesRemaining = t => { };
|
||||
|
||||
public CountdownTimer(int ticksLeft, Action<CountdownTimer> onExpired, bool withNotifications)
|
||||
{
|
||||
TicksLeft = ticksLeft;
|
||||
OnExpired += onExpired;
|
||||
if (withNotifications)
|
||||
{
|
||||
OnOneMinuteRemaining += t => Sound.Play("1minr.aud");
|
||||
OnTwoMinutesRemaining += t => Sound.Play("2minr.aud");
|
||||
OnThreeMinutesRemaining += t => Sound.Play("3minr.aud");
|
||||
OnFourMinutesRemaining += t => Sound.Play("4minr.aud");
|
||||
OnFiveMinutesRemaining += t => Sound.Play("5minr.aud");
|
||||
OnTenMinutesRemaining += t => Sound.Play("10minr.aud");
|
||||
OnTwentyMinutesRemaining += t => Sound.Play("20minr.aud");
|
||||
OnThirtyMinutesRemaining += t => Sound.Play("30minr.aud");
|
||||
OnFortyMinutesRemaining += t => Sound.Play("40minr.aud");
|
||||
}
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
if (TicksLeft <= 0) return;
|
||||
|
||||
TicksLeft--;
|
||||
switch (TicksLeft)
|
||||
{
|
||||
case 1500 * 00: OnExpired(this); break;
|
||||
case 1500 * 01: OnOneMinuteRemaining(this); break;
|
||||
case 1500 * 02: OnTwoMinutesRemaining(this); break;
|
||||
case 1500 * 03: OnThreeMinutesRemaining(this); break;
|
||||
case 1500 * 04: OnFourMinutesRemaining(this); break;
|
||||
case 1500 * 05: OnFiveMinutesRemaining(this); break;
|
||||
case 1500 * 10: OnTenMinutesRemaining(this); break;
|
||||
case 1500 * 20: OnTwentyMinutesRemaining(this); break;
|
||||
case 1500 * 30: OnThirtyMinutesRemaining(this); break;
|
||||
case 1500 * 40: OnFortyMinutesRemaining(this); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 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.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Buildings;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
class FortLonestarScriptInfo : TraitInfo<FortLonestarScript>, Requires<SpawnMapActorsInfo> { }
|
||||
|
||||
class FortLonestarScript : IWorldLoaded, ITick
|
||||
{
|
||||
Player multi0;
|
||||
Player soviets;
|
||||
|
||||
Actor entry1;
|
||||
Actor entry2;
|
||||
Actor entry3;
|
||||
Actor entry4;
|
||||
Actor entry5;
|
||||
Actor entry6;
|
||||
Actor entry7;
|
||||
Actor entry8;
|
||||
CPos[] sovietEntryPoints;
|
||||
Actor paradrop1;
|
||||
Actor paradrop2;
|
||||
Actor paradrop3;
|
||||
Actor paradrop4;
|
||||
Actor patrol1;
|
||||
Actor patrol2;
|
||||
Actor patrol3;
|
||||
Actor patrol4;
|
||||
World world;
|
||||
|
||||
int WaveNumber = 0;
|
||||
InfoWidget evacuateWidget;
|
||||
const string ShortEvacuateTemplate = "Wave {0}";
|
||||
static readonly string[] Patrol = { "e1", "e2", "e1" };
|
||||
static readonly string[] Infantry = { "e4", "e1", "e1", "e2", "e1", "e2" };
|
||||
static readonly string[] Vehicles = { "arty", "ftrk", "ftrk", "apc", "apc" };
|
||||
const string tank = "3tnk";
|
||||
const string v2 = "v2rl";
|
||||
const string boss = "4tnk";
|
||||
|
||||
const int TimerTicks = 1;
|
||||
|
||||
int AttackSquad = 6;
|
||||
int AttackSquadCount = 1;
|
||||
int VehicleSquad = 2;
|
||||
int VehicleSquadCount = 1;
|
||||
|
||||
int patrolAttackFrame;
|
||||
int patrolattackAtFrameIncrement;
|
||||
int WaveAttackFrame;
|
||||
int WaveAttackAtFrameIncrement;
|
||||
int VehicleAttackFrame;
|
||||
int VehicleAttackAtFrameIncrement;
|
||||
|
||||
void MissionAccomplished(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionAccomplished(world, text, multi0);
|
||||
}
|
||||
|
||||
void AttackNearestAlliedActor(Actor self)
|
||||
{
|
||||
var enemies = world.Actors.Where(u => u.IsInWorld && !u.IsDead() && (u.Owner == multi0)
|
||||
&& ((u.HasTrait<Building>() && !u.HasTrait<Mobile>())));
|
||||
|
||||
var targetEnemy = enemies.ClosestTo(self);
|
||||
if (targetEnemy != null)
|
||||
self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(targetEnemy), WRange.FromCells(6))));
|
||||
}
|
||||
|
||||
void SendVehicles()
|
||||
{
|
||||
if (SpawnVehicles == true)
|
||||
{
|
||||
for (int i = 1; i <= VehicleSquadCount; i++)
|
||||
{
|
||||
var route = world.SharedRandom.Next(sovietEntryPoints.Length);
|
||||
var spawnPoint = sovietEntryPoints[route];
|
||||
for (int r = 1; r <= VehicleSquad; r++)
|
||||
{
|
||||
var squad = world.CreateActor(Vehicles.Random(world.SharedRandom),
|
||||
new TypeDictionary
|
||||
{
|
||||
new LocationInit(spawnPoint),
|
||||
new OwnerInit(soviets)
|
||||
});
|
||||
squad.QueueActivity(new AttackMove.AttackMoveActivity(squad, new Move.Move(paradrop1.Location, 3)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendWave()
|
||||
{
|
||||
if (SpawnWave == true)
|
||||
{
|
||||
for (int i = 1; i <= AttackSquadCount; i++)
|
||||
{
|
||||
world.Actors.Where(u => u.IsInWorld && !u.IsDead() && (u.Owner == soviets)
|
||||
&& !u.HasTrait<Mobile>());
|
||||
var route = world.SharedRandom.Next(sovietEntryPoints.Length);
|
||||
var spawnPoint = sovietEntryPoints[route];
|
||||
for (int r = 1; r < AttackSquad; r++)
|
||||
{
|
||||
var squad = world.CreateActor(Infantry.Random(world.SharedRandom),
|
||||
new TypeDictionary
|
||||
{
|
||||
new LocationInit(spawnPoint),
|
||||
new OwnerInit(soviets)
|
||||
});
|
||||
squad.QueueActivity(new AttackMove.AttackMoveActivity(squad, new Move.Move(paradrop1.Location, 3)));
|
||||
var scatteredUnits = world.FindAliveCombatantActorsInCircle(paradrop1.Location.CenterPosition, WRange.FromCells(15))
|
||||
.Where(unit => unit.IsIdle && unit.HasTrait<Mobile>() && unit.Owner == soviets);
|
||||
foreach (var unit in scatteredUnits)
|
||||
{
|
||||
AttackNearestAlliedActor(unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendPatrol(string[] squad, Player owner, CPos location, CPos move)
|
||||
{
|
||||
if (SpawnPatrol)
|
||||
{
|
||||
for (int i = 0; i < squad.Length; i++)
|
||||
{
|
||||
var actor = world.CreateActor(squad[i], new TypeDictionary
|
||||
{
|
||||
new OwnerInit(owner),
|
||||
new LocationInit(location)
|
||||
});
|
||||
actor.QueueActivity(new AttackMove.AttackMoveActivity(actor, new Move.Move(move, 3)));
|
||||
AttackNearestAlliedActor(actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendBoss(string unit)
|
||||
{
|
||||
var route = world.SharedRandom.Next(sovietEntryPoints.Length);
|
||||
var spawnPoint = sovietEntryPoints[route];
|
||||
var actor = world.CreateActor(unit, new TypeDictionary
|
||||
{
|
||||
new OwnerInit(soviets),
|
||||
new LocationInit(spawnPoint)
|
||||
});
|
||||
if (multi0 != null)
|
||||
{
|
||||
AttackNearestAlliedActor(actor);
|
||||
}
|
||||
}
|
||||
|
||||
void Wave(string text)
|
||||
{
|
||||
Game.AddChatLine(Color.Cyan, "Wave Sequence", text);
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (multi0.WinState != WinState.Undefined) return;
|
||||
|
||||
if (world.FrameNumber == patrolAttackFrame)
|
||||
{
|
||||
patrolAttackFrame += patrolattackAtFrameIncrement;
|
||||
patrolattackAtFrameIncrement = Math.Max(patrolattackAtFrameIncrement - 5, 100);
|
||||
SendPatrol(Patrol, soviets, patrol1.Location, paradrop1.Location);
|
||||
SendPatrol(Patrol, soviets, patrol2.Location, paradrop2.Location);
|
||||
SendPatrol(Patrol, soviets, patrol3.Location, paradrop3.Location);
|
||||
SendPatrol(Patrol, soviets, patrol4.Location, paradrop4.Location);
|
||||
}
|
||||
if (world.FrameNumber == WaveAttackFrame)
|
||||
{
|
||||
WaveAttackFrame += WaveAttackAtFrameIncrement;
|
||||
WaveAttackAtFrameIncrement = Math.Max(WaveAttackAtFrameIncrement - 5, 100);
|
||||
SendWave();
|
||||
}
|
||||
if (world.FrameNumber == VehicleAttackFrame)
|
||||
{
|
||||
VehicleAttackFrame += VehicleAttackAtFrameIncrement;
|
||||
VehicleAttackAtFrameIncrement = Math.Max(VehicleAttackAtFrameIncrement - 5, 100);
|
||||
SendVehicles();
|
||||
}
|
||||
if (world.FrameNumber == TimerTicks)
|
||||
{
|
||||
evacuateWidget = new InfoWidget("");
|
||||
Ui.Root.AddChild(evacuateWidget);
|
||||
WaveNumber++;
|
||||
Wave("One Initializing");
|
||||
UpdateWaveSequence();
|
||||
}
|
||||
if (world.FrameNumber == 1500 * 2)
|
||||
{
|
||||
WaveNumber++;
|
||||
Wave("Two Initializing");
|
||||
SpawnPatrol = false;
|
||||
AttackSquad = 7;
|
||||
AttackSquadCount = 2;
|
||||
UpdateWaveSequence();
|
||||
MissionUtils.Parabomb(world, soviets, entry1.Location, paradrop1.Location);
|
||||
MissionUtils.Parabomb(world, soviets, entry1.Location, paradrop1.Location + new CVec(0, -2));
|
||||
}
|
||||
if (world.FrameNumber == 1500 * 4)
|
||||
{
|
||||
WaveNumber++;
|
||||
Wave("Three Initializing");
|
||||
UpdateWaveSequence();
|
||||
AttackSquad = 8;
|
||||
}
|
||||
if (world.FrameNumber == 1500 * 6)
|
||||
{
|
||||
WaveNumber++;
|
||||
Wave("Four Initializing");
|
||||
UpdateWaveSequence();
|
||||
AttackSquad = 9;
|
||||
MissionUtils.Parabomb(world, soviets, entry1.Location, paradrop1.Location);
|
||||
MissionUtils.Parabomb(world, soviets, entry2.Location, paradrop3.Location);
|
||||
AttackSquadCount = 3;
|
||||
VehicleSquad = 3;
|
||||
}
|
||||
if (world.FrameNumber == 1500 * 8)
|
||||
{
|
||||
WaveNumber++;
|
||||
Wave("Five Initializing");
|
||||
UpdateWaveSequence();
|
||||
AttackSquad = 10;
|
||||
VehicleSquad = 4;
|
||||
VehicleSquadCount = 2;
|
||||
SendBoss(tank);
|
||||
}
|
||||
if (world.FrameNumber == 1500 * 11)
|
||||
{
|
||||
WaveNumber++;
|
||||
Wave("Six Initializing");
|
||||
UpdateWaveSequence();
|
||||
AttackSquad = 11;
|
||||
AttackSquadCount = 4;
|
||||
MissionUtils.Parabomb(world, soviets, entry1.Location, paradrop1.Location);
|
||||
MissionUtils.Parabomb(world, soviets, entry4.Location, paradrop1.Location);
|
||||
MissionUtils.Parabomb(world, soviets, entry6.Location, paradrop3.Location);
|
||||
MissionUtils.Parabomb(world, soviets, entry5.Location, paradrop3.Location);
|
||||
SendBoss(tank);
|
||||
SendBoss(tank);
|
||||
}
|
||||
if (world.FrameNumber == 1500 * 14)
|
||||
{
|
||||
WaveNumber++;
|
||||
Wave("Seven Initializing");
|
||||
UpdateWaveSequence();
|
||||
AttackSquad = 12;
|
||||
VehicleSquad = 5;
|
||||
VehicleSquadCount = 3;
|
||||
SendBoss(v2);
|
||||
}
|
||||
if (world.FrameNumber == 1500 * 17)
|
||||
{
|
||||
SpawnVehicles = true;
|
||||
WaveNumber++;
|
||||
Wave("Eight Initializing");
|
||||
UpdateWaveSequence();
|
||||
AttackSquad = 13;
|
||||
AttackSquadCount = 5;
|
||||
MissionUtils.Parabomb(world, soviets, entry1.Location, paradrop1.Location);
|
||||
MissionUtils.Parabomb(world, soviets, entry4.Location, paradrop1.Location);
|
||||
MissionUtils.Parabomb(world, soviets, entry6.Location, paradrop3.Location);
|
||||
MissionUtils.Parabomb(world, soviets, entry5.Location, paradrop3.Location);
|
||||
MissionUtils.Parabomb(world, soviets, entry2.Location, paradrop2.Location);
|
||||
MissionUtils.Parabomb(world, soviets, entry3.Location, paradrop2.Location);
|
||||
SendBoss(v2);
|
||||
SendBoss(tank);
|
||||
SendBoss(v2);
|
||||
}
|
||||
if (world.FrameNumber == 1500 * 21)
|
||||
{
|
||||
WaveNumber++;
|
||||
Wave("Nine Initializing");
|
||||
UpdateWaveSequence();
|
||||
AttackSquad = 14;
|
||||
VehicleSquad = 6;
|
||||
VehicleSquadCount = 4;
|
||||
SendBoss(v2);
|
||||
SendBoss(tank);
|
||||
SendBoss(tank);
|
||||
}
|
||||
if (world.FrameNumber == 1500 * 25)
|
||||
{
|
||||
WaveNumber++;
|
||||
Wave("Ten Initializing");
|
||||
UpdateWaveSequence();
|
||||
AttackSquad = 15;
|
||||
AttackSquadCount = 6;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
MissionUtils.Parabomb(world, soviets, entry1.Location, paradrop1.Location + new CVec(0, -2));
|
||||
MissionUtils.Parabomb(world, soviets, entry2.Location, paradrop3.Location + new CVec(0, -2));
|
||||
MissionUtils.Parabomb(world, soviets, entry4.Location, paradrop2.Location + new CVec(0, -2));
|
||||
MissionUtils.Parabomb(world, soviets, entry5.Location, paradrop4.Location + new CVec(0, -2));
|
||||
MissionUtils.Parabomb(world, soviets, entry2.Location, paradrop1.Location + new CVec(0, 2));
|
||||
MissionUtils.Parabomb(world, soviets, entry4.Location, paradrop3.Location + new CVec(0, 2));
|
||||
MissionUtils.Parabomb(world, soviets, entry3.Location, paradrop2.Location + new CVec(0, 2));
|
||||
MissionUtils.Parabomb(world, soviets, entry5.Location, paradrop4.Location + new CVec(0, 2));
|
||||
}
|
||||
SendBoss(boss);
|
||||
}
|
||||
if (world.FrameNumber == 1500 * 30)
|
||||
{
|
||||
SpawnWave = false;
|
||||
SpawnVehicles = false;
|
||||
}
|
||||
if (world.FrameNumber == 1500 * 31)
|
||||
{
|
||||
MissionAccomplished("You and your mates have Survived the Onslaught!");
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateWaveSequence()
|
||||
{
|
||||
evacuateWidget.Text = ShortEvacuateTemplate.F(WaveNumber);
|
||||
}
|
||||
|
||||
bool SpawnPatrol = true;
|
||||
|
||||
bool SpawnWave = true;
|
||||
|
||||
bool SpawnVehicles = true;
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
soviets = w.Players.Single(p => p.InternalName == "Soviets");
|
||||
multi0 = w.Players.Single(p => p.InternalName == "Multi0");
|
||||
patrolAttackFrame = 750;
|
||||
patrolattackAtFrameIncrement = 750;
|
||||
WaveAttackFrame = 500;
|
||||
WaveAttackAtFrameIncrement = 500;
|
||||
VehicleAttackFrame = 2000;
|
||||
VehicleAttackAtFrameIncrement = 2000;
|
||||
var actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||
entry1 = actors["Entry1"];
|
||||
entry2 = actors["Entry2"];
|
||||
entry3 = actors["Entry3"];
|
||||
entry4 = actors["Entry4"];
|
||||
entry5 = actors["Entry5"];
|
||||
entry6 = actors["Entry6"];
|
||||
entry7 = actors["Entry7"];
|
||||
entry8 = actors["Entry8"];
|
||||
sovietEntryPoints = new[] { entry1, entry2, entry3, entry4, entry5, entry6, entry7, entry8 }.Select(p => p.Location).ToArray();
|
||||
paradrop1 = actors["Paradrop1"];
|
||||
paradrop2 = actors["Paradrop2"];
|
||||
paradrop3 = actors["Paradrop3"];
|
||||
paradrop4 = actors["Paradrop4"];
|
||||
patrol1 = actors["Patrol1"];
|
||||
patrol2 = actors["Patrol2"];
|
||||
patrol3 = actors["Patrol3"];
|
||||
patrol4 = actors["Patrol4"];
|
||||
MissionUtils.PlayMissionMusic();
|
||||
Game.AddChatLine(Color.Cyan, "Mission", "Defend Fort LoneStar At All costs!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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 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;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
public static class MissionUtils
|
||||
{
|
||||
public static IEnumerable<Actor> FindAliveCombatantActorsInCircle(this World world, WPos location, WRange range)
|
||||
{
|
||||
return world.FindActorsInCircle(location, range)
|
||||
.Where(u => u.IsInWorld && u != world.WorldActor && !u.IsDead() && !u.Owner.NonCombatant);
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> FindAliveCombatantActorsInBox(this World world, CPos a, CPos b)
|
||||
{
|
||||
return world.FindActorsInBox(a, b)
|
||||
.Where(u => u.IsInWorld && u != world.WorldActor && !u.IsDead() && !u.Owner.NonCombatant);
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> FindAliveNonCombatantActorsInCircle(this World world, WPos location, WRange range)
|
||||
{
|
||||
return world.FindActorsInCircle(location, range)
|
||||
.Where(u => u.IsInWorld && u != world.WorldActor && !u.IsDead() && u.Owner.NonCombatant);
|
||||
}
|
||||
|
||||
public static Actor ExtractUnitWithChinook(World world, Player owner, Actor unit, CPos entry, CPos lz, CPos exit)
|
||||
{
|
||||
var chinook = world.CreateActor("tran", new TypeDictionary { new OwnerInit(owner), new LocationInit(entry) });
|
||||
chinook.QueueActivity(new HeliFly(chinook, Target.FromCell(lz)));
|
||||
chinook.QueueActivity(new Turn(0));
|
||||
chinook.QueueActivity(new HeliLand(true));
|
||||
chinook.QueueActivity(new WaitFor(() => chinook.Trait<Cargo>().Passengers.Contains(unit)));
|
||||
chinook.QueueActivity(new Wait(150));
|
||||
chinook.QueueActivity(new HeliFly(chinook, Target.FromCell(exit)));
|
||||
chinook.QueueActivity(new RemoveSelf());
|
||||
return chinook;
|
||||
}
|
||||
|
||||
public static Pair<Actor, Actor> InsertUnitWithChinook(World world, Player owner, string unitName, CPos entry, CPos lz, CPos exit, Action<Actor> afterUnload)
|
||||
{
|
||||
var unit = world.CreateActor(false, unitName, new TypeDictionary { new OwnerInit(owner) });
|
||||
var chinook = world.CreateActor("tran", new TypeDictionary { new OwnerInit(owner), new LocationInit(entry) });
|
||||
chinook.Trait<Cargo>().Load(chinook, unit);
|
||||
chinook.QueueActivity(new HeliFly(chinook, Target.FromCell(lz)));
|
||||
chinook.QueueActivity(new Turn(0));
|
||||
chinook.QueueActivity(new HeliLand(true));
|
||||
chinook.QueueActivity(new UnloadCargo(chinook, true));
|
||||
chinook.QueueActivity(new CallFunc(() => afterUnload(unit)));
|
||||
chinook.QueueActivity(new Wait(150));
|
||||
chinook.QueueActivity(new HeliFly(chinook, Target.FromCell(exit)));
|
||||
chinook.QueueActivity(new RemoveSelf());
|
||||
return Pair.New(chinook, unit);
|
||||
}
|
||||
|
||||
public static void Paradrop(World world, Player owner, IEnumerable<string> units, CPos entry, CPos location)
|
||||
{
|
||||
var altitude = Rules.Info["badr"].Traits.Get<PlaneInfo>().CruiseAltitude;
|
||||
var badger = world.CreateActor("badr", new TypeDictionary
|
||||
{
|
||||
new CenterPositionInit(entry.CenterPosition + new WVec(WRange.Zero, WRange.Zero, altitude)),
|
||||
new OwnerInit(owner),
|
||||
new FacingInit(Util.GetFacing(location - entry, 0))
|
||||
});
|
||||
|
||||
badger.QueueActivity(new FlyAttack(Target.FromCell(location)));
|
||||
badger.Trait<ParaDrop>().SetLZ(location);
|
||||
var cargo = badger.Trait<Cargo>();
|
||||
foreach (var unit in units)
|
||||
{
|
||||
cargo.Load(badger, world.CreateActor(false, unit, new TypeDictionary { new OwnerInit(owner) }));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Parabomb(World world, Player owner, CPos entry, CPos location)
|
||||
{
|
||||
var altitude = Rules.Info["badr.bomber"].Traits.Get<PlaneInfo>().CruiseAltitude;
|
||||
var badger = world.CreateActor("badr.bomber", new TypeDictionary
|
||||
{
|
||||
new CenterPositionInit(entry.CenterPosition + new WVec(WRange.Zero, WRange.Zero, altitude)),
|
||||
new OwnerInit(owner),
|
||||
new FacingInit(Util.GetFacing(location - entry, 0))
|
||||
});
|
||||
|
||||
badger.Trait<AttackBomber>().SetTarget(location.CenterPosition);
|
||||
badger.QueueActivity(new Fly(badger, Target.FromCell(location)));
|
||||
badger.QueueActivity(new FlyOffMap());
|
||||
badger.QueueActivity(new RemoveSelf());
|
||||
}
|
||||
|
||||
public static bool AreaSecuredWithUnits(World world, Player player, WPos location, WRange range)
|
||||
{
|
||||
var units = world.FindAliveCombatantActorsInCircle(location, range).Where(a => a.HasTrait<IPositionable>());
|
||||
return units.Any() && units.All(a => a.Owner == player);
|
||||
}
|
||||
|
||||
public static IEnumerable<ProductionQueue> FindQueues(World world, Player player, string category)
|
||||
{
|
||||
return world.ActorsWithTrait<ProductionQueue>()
|
||||
.Where(a => a.Actor.Owner == player && a.Trait.Info.Type == category)
|
||||
.Select(a => a.Trait);
|
||||
}
|
||||
|
||||
public static void StartProduction(World world, Player player, string category, string item)
|
||||
{
|
||||
var queue = FindQueues(world, player, category).FirstOrDefault(q => q.CurrentItem() == null);
|
||||
if (queue != null)
|
||||
queue.ResolveOrder(queue.self, Order.StartProduction(queue.self, item, 1));
|
||||
}
|
||||
|
||||
public static Actor UnitContaining(this World world, Actor actor)
|
||||
{
|
||||
return world.Actors.FirstOrDefault(a => a.HasTrait<Cargo>() && a.Trait<Cargo>().Passengers.Contains(actor));
|
||||
}
|
||||
|
||||
public static void PlayMissionMusic()
|
||||
{
|
||||
if (!Rules.InstalledMusic.Any() || !Game.Settings.Sound.MapMusic)
|
||||
return;
|
||||
Game.ConnectionStateChanged += StopMusic;
|
||||
PlayMusic();
|
||||
}
|
||||
|
||||
static void PlayMusic()
|
||||
{
|
||||
var track = Rules.InstalledMusic.Random(Game.CosmeticRandom);
|
||||
Sound.PlayMusicThen(track.Value, PlayMusic);
|
||||
}
|
||||
|
||||
static void StopMusic(OrderManager orderManager)
|
||||
{
|
||||
if (!orderManager.GameStarted)
|
||||
{
|
||||
Sound.StopMusic();
|
||||
Game.ConnectionStateChanged -= StopMusic;
|
||||
}
|
||||
}
|
||||
|
||||
public static void CoopMissionAccomplished(World world, string text, params Player[] players)
|
||||
{
|
||||
if (players.First().WinState != WinState.Undefined)
|
||||
return;
|
||||
|
||||
foreach (var player in players)
|
||||
player.WinState = WinState.Won;
|
||||
|
||||
if (text != null)
|
||||
Game.AddChatLine(Color.Blue, "Mission accomplished", text);
|
||||
|
||||
Sound.Play("misnwon1.aud");
|
||||
}
|
||||
|
||||
public static void CoopMissionFailed(World world, string text, params Player[] players)
|
||||
{
|
||||
if (players.First().WinState != WinState.Undefined)
|
||||
return;
|
||||
|
||||
foreach (var player in players)
|
||||
{
|
||||
player.WinState = WinState.Lost;
|
||||
foreach (var actor in world.Actors.Where(a => a.IsInWorld && a.Owner == player && !a.IsDead()))
|
||||
{
|
||||
actor.Kill(actor);
|
||||
}
|
||||
}
|
||||
|
||||
if (text != null)
|
||||
Game.AddChatLine(Color.Red, "Mission failed", text);
|
||||
|
||||
Sound.Play("misnlst1.aud");
|
||||
}
|
||||
|
||||
public static Actor CreateActor(this World world, bool addToWorld, string name, Player owner, CPos? location, int? facing)
|
||||
{
|
||||
var td = new TypeDictionary { new OwnerInit(owner) };
|
||||
if (location.HasValue)
|
||||
td.Add(new LocationInit(location.Value));
|
||||
if (facing.HasValue)
|
||||
td.Add(new FacingInit(facing.Value));
|
||||
return world.CreateActor(addToWorld, name, td);
|
||||
}
|
||||
|
||||
public static Actor CreateActor(this World world, string name, Player owner, CPos? location, int? facing)
|
||||
{
|
||||
return CreateActor(world, true, name, owner, location, facing);
|
||||
}
|
||||
|
||||
public static void CapOre(Player player)
|
||||
{
|
||||
var res = player.PlayerActor.Trait<PlayerResources>();
|
||||
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<Building>() && !u.HasTrait<Wall>()) || (u.HasTrait<Mobile>() && !u.HasTrait<Aircraft>())) && u.IsInWorld && !u.IsDead());
|
||||
|
||||
var enemy = enemies.ClosestTo(self);
|
||||
if (enemy != null)
|
||||
self.QueueActivity(queued, new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(enemy), WRange.FromCells(3))));
|
||||
}
|
||||
}
|
||||
|
||||
class TransformedAction : INotifyTransformed
|
||||
{
|
||||
Action<Actor> a;
|
||||
|
||||
public TransformedAction(Action<Actor> a)
|
||||
{
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public void OnTransformed(Actor toActor)
|
||||
{
|
||||
a(toActor);
|
||||
}
|
||||
}
|
||||
|
||||
class InfiltrateAction : IAcceptInfiltrator
|
||||
{
|
||||
Action<Actor> a;
|
||||
|
||||
public InfiltrateAction(Action<Actor> a)
|
||||
{
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public void OnInfiltrate(Actor self, Actor spy)
|
||||
{
|
||||
a(spy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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.Drawing;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
public class CountdownTimerWidget : Widget
|
||||
{
|
||||
public CountdownTimer Timer;
|
||||
public string Format;
|
||||
|
||||
public CountdownTimerWidget(CountdownTimer timer, string format)
|
||||
{
|
||||
Timer = timer;
|
||||
Format = format;
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
if (!IsVisible()) return;
|
||||
|
||||
// TODO: Don't hardcode the screen position
|
||||
var font = Game.Renderer.Fonts["Bold"];
|
||||
var text = Format.F(WidgetUtils.FormatTime(Timer.TicksLeft));
|
||||
var pos = new float2(Game.Renderer.Resolution.Width * 0.5f - font.Measure(text).X / 2, Game.Renderer.Resolution.Height * 0.1f);
|
||||
font.DrawTextWithContrast(text, pos, Timer.TicksLeft <= 25 * 60 && Game.LocalTick % 50 < 25 ? Color.Red : Color.White, Color.Black, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public class InfoWidget : Widget
|
||||
{
|
||||
public string Text;
|
||||
|
||||
public InfoWidget(string text) { Text = text; }
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
if (!IsVisible()) return;
|
||||
|
||||
// TODO: Don't hardcode the screen position
|
||||
var font = Game.Renderer.Fonts["Bold"];
|
||||
var pos = new float2(Game.Renderer.Resolution.Width * 0.5f - font.Measure(Text).X / 2, Game.Renderer.Resolution.Height * 0.1f);
|
||||
font.DrawTextWithContrast(Text, pos, Color.White, Color.Black, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,342 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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 System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Buildings;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
class MonsterTankMadnessScriptInfo : ITraitInfo, Requires<SpawnMapActorsInfo>
|
||||
{
|
||||
public readonly string[] FirstStartUnits = null;
|
||||
public readonly string[] SecondStartUnits = null;
|
||||
public readonly string[] ThirdStartUnits = null;
|
||||
public readonly string[] FirstBaseUnits = null;
|
||||
public readonly string[] CivilianEvacuees = null;
|
||||
|
||||
public object Create(ActorInitializer init) { return new MonsterTankMadnessScript(this); }
|
||||
}
|
||||
|
||||
class MonsterTankMadnessScript : IHasObjectives, IWorldLoaded, ITick
|
||||
{
|
||||
MonsterTankMadnessScriptInfo info;
|
||||
|
||||
public MonsterTankMadnessScript(MonsterTankMadnessScriptInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public event Action<bool> OnObjectivesUpdated = notify => { };
|
||||
|
||||
public IEnumerable<Objective> Objectives { get { return new[] { findOutpost, evacuateDemitri, infiltrateRadarDome }; } }
|
||||
|
||||
Objective findOutpost = new Objective(ObjectiveType.Primary, FindOutpostText, ObjectiveStatus.InProgress);
|
||||
Objective evacuateDemitri = new Objective(ObjectiveType.Primary, EvacuateDemitriText, ObjectiveStatus.InProgress);
|
||||
Objective infiltrateRadarDome = new Objective(ObjectiveType.Primary, InfiltrateRadarDomeText, ObjectiveStatus.InProgress);
|
||||
|
||||
const string FindOutpostText = "Find our outpost and start repairs on it.";
|
||||
const string EvacuateDemitriText = "Find and evacuate Dr. Demitri. He is missing -- likely hiding in the village to the far south.";
|
||||
const string InfiltrateRadarDomeText = "Reprogram the Super Tanks by sending a spy into the Soviet radar dome.";
|
||||
|
||||
//const string Briefing = "Dr. Demitri, creator of a Soviet Super Tank, wants to defect."
|
||||
// + " We planned to extract him while the Soviets were testing their new weapon, but something has gone wrong."
|
||||
// + " The Super Tanks are out of control, and Demitri is missing -- likely hiding in the village to the far south."
|
||||
// + " Find our outpost and start repairs on it, then find and evacuate Demitri."
|
||||
// + " As for the tanks, we can reprogram them. Send a spy into the Soviet radar dome in the NE, turning the tanks on their creators.";
|
||||
|
||||
World world;
|
||||
|
||||
Player neutral;
|
||||
Player greece;
|
||||
Player ussr;
|
||||
Player badGuy;
|
||||
Player turkey;
|
||||
|
||||
Actor startEntryPoint;
|
||||
Actor startMovePoint;
|
||||
Actor startBridgeEndPoint;
|
||||
Actor alliedBaseTopLeft;
|
||||
Actor alliedBaseBottomRight;
|
||||
Actor alliedBaseEntryPoint;
|
||||
Actor alliedBaseMovePoint;
|
||||
|
||||
Actor demitriChurch;
|
||||
Actor demitriChurchSpawnPoint;
|
||||
Actor demitriTriggerAreaCenter;
|
||||
Actor demitri;
|
||||
Actor demitriLZ;
|
||||
Actor demitriLZFlare;
|
||||
Actor demitriChinook;
|
||||
|
||||
Actor provingGroundsCameraPoint;
|
||||
|
||||
Actor[] superTanks;
|
||||
|
||||
Actor hospital;
|
||||
Actor hospitalCivilianSpawnPoint;
|
||||
Actor hospitalSuperTankPoint;
|
||||
|
||||
Actor superTankDome;
|
||||
|
||||
bool hospitalEvacuated;
|
||||
bool superTanksDestroyed;
|
||||
|
||||
int baseTransferredTick = -1;
|
||||
int superTankDomeInfiltratedTick = -1;
|
||||
|
||||
void MissionAccomplished(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionAccomplished(world, text, greece);
|
||||
}
|
||||
|
||||
void MissionFailed(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionFailed(world, text, greece);
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (greece.WinState != WinState.Undefined) return;
|
||||
|
||||
if (world.FrameNumber == 1)
|
||||
SpawnAndMoveBridgeUnits(info.FirstStartUnits);
|
||||
|
||||
else if (world.FrameNumber == 25 * 3)
|
||||
SpawnAndMoveBridgeUnits(info.SecondStartUnits);
|
||||
|
||||
else if (world.FrameNumber == 25 * 8)
|
||||
SpawnAndMoveBridgeUnits(info.ThirdStartUnits);
|
||||
|
||||
MissionUtils.CapOre(ussr);
|
||||
|
||||
if (!hospitalEvacuated && !hospital.IsDead() && MissionUtils.AreaSecuredWithUnits(world, greece, hospital.CenterPosition, WRange.FromCells(5)))
|
||||
{
|
||||
EvacuateCivilians();
|
||||
hospitalEvacuated = true;
|
||||
}
|
||||
|
||||
if (baseTransferredTick == -1)
|
||||
{
|
||||
var actorsInBase = world.FindActorsInBox(alliedBaseTopLeft.Location, alliedBaseBottomRight.Location).Where(a => a != a.Owner.PlayerActor);
|
||||
if (actorsInBase.Any(a => a.Owner == greece))
|
||||
{
|
||||
SetupAlliedBase(actorsInBase);
|
||||
baseTransferredTick = world.FrameNumber;
|
||||
findOutpost.Status = ObjectiveStatus.Completed;
|
||||
OnObjectivesUpdated(true);
|
||||
}
|
||||
}
|
||||
else if (superTankDomeInfiltratedTick == -1)
|
||||
{
|
||||
if (world.FrameNumber == baseTransferredTick + 25 * 100)
|
||||
foreach (var tank in superTanks.Where(t => !t.IsDead() && t.IsInWorld))
|
||||
tank.QueueActivity(false, new Move.Move(hospitalSuperTankPoint.Location, 2));
|
||||
|
||||
else if (world.FrameNumber == baseTransferredTick + 25 * 180)
|
||||
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 * 280)
|
||||
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 * 480)
|
||||
foreach (var tank in superTanks.Where(t => !t.IsDead() && t.IsInWorld))
|
||||
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))
|
||||
MissionUtils.AttackNearestLandActor(false, tank, ussr);
|
||||
if (world.FrameNumber == superTankDomeInfiltratedTick + 25 * 180)
|
||||
{
|
||||
foreach (var actor in world.Actors.Where(a => !a.IsDead() && (a.Owner == ussr || a.Owner == badGuy)))
|
||||
actor.Kill(actor);
|
||||
}
|
||||
if (world.FrameNumber == superTankDomeInfiltratedTick + 25 * 181)
|
||||
{
|
||||
foreach (var tank in superTanks.Where(t => !t.IsDead()))
|
||||
tank.Kill(tank);
|
||||
superTanksDestroyed = true;
|
||||
}
|
||||
}
|
||||
if (evacuateDemitri.Status != ObjectiveStatus.Completed)
|
||||
{
|
||||
if (demitri == null)
|
||||
{
|
||||
if (demitriChurch.IsDead())
|
||||
{
|
||||
evacuateDemitri.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("Dr. Demitri was killed.");
|
||||
}
|
||||
|
||||
else if (MissionUtils.AreaSecuredWithUnits(world, greece, demitriTriggerAreaCenter.CenterPosition, WRange.FromCells(3)))
|
||||
{
|
||||
demitri = world.CreateActor("demitri", greece, demitriChurchSpawnPoint.Location, null);
|
||||
demitri.QueueActivity(new Move.Move(demitriTriggerAreaCenter.Location, 0));
|
||||
demitriLZFlare = world.CreateActor("flare", greece, demitriLZ.Location, null);
|
||||
Sound.Play("flaren1.aud");
|
||||
var chinookEntry = new CPos(demitriLZ.Location.X, 0);
|
||||
demitriChinook = MissionUtils.ExtractUnitWithChinook(world, greece, demitri, chinookEntry, demitriLZ.Location, chinookEntry);
|
||||
}
|
||||
}
|
||||
else if (demitri.IsDead())
|
||||
{
|
||||
evacuateDemitri.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("Dr. Demitri was killed.");
|
||||
}
|
||||
else if (demitriChinook != null && !demitriChinook.IsDead() && !world.Map.IsInMap(demitriChinook.Location) && demitriChinook.Trait<Cargo>().Passengers.Contains(demitri))
|
||||
{
|
||||
demitriLZFlare.Destroy();
|
||||
SpawnAndMoveAlliedBaseUnits(info.FirstBaseUnits);
|
||||
evacuateDemitri.Status = ObjectiveStatus.Completed;
|
||||
OnObjectivesUpdated(true);
|
||||
}
|
||||
}
|
||||
if (!world.Actors.Any(a => a.Owner == greece && a.IsInWorld && !a.IsDead()
|
||||
&& ((a.HasTrait<Building>() && !a.HasTrait<Wall>()) || a.HasTrait<BaseBuilding>() || a.HasTrait<Mobile>())))
|
||||
{
|
||||
MissionFailed("The remaining Allied forces in the area have been wiped out.");
|
||||
}
|
||||
if (superTankDomeInfiltratedTick == -1 && superTankDome.IsDead())
|
||||
{
|
||||
infiltrateRadarDome.Status = ObjectiveStatus.Failed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionFailed("The Soviet radar dome was destroyed.");
|
||||
}
|
||||
if (superTanksDestroyed && evacuateDemitri.Status == ObjectiveStatus.Completed)
|
||||
{
|
||||
MissionAccomplished("Dr. Demitri has been extracted and the super tanks have been dealt with.");
|
||||
}
|
||||
}
|
||||
|
||||
void SetupAlliedBase(IEnumerable<Actor> actors)
|
||||
{
|
||||
foreach (var actor in actors)
|
||||
{
|
||||
// hack hack hack
|
||||
actor.ChangeOwner(greece);
|
||||
if (actor.Info.Name == "pbox")
|
||||
{
|
||||
actor.AddTrait(new TransformedAction(s => s.Trait<Cargo>().Load(s, world.CreateActor(false, "e1", greece, null, null))));
|
||||
actor.QueueActivity(new Transform(actor, "hbox.e1") { SkipMakeAnims = true });
|
||||
}
|
||||
else if (actor.Info.Name == "proc")
|
||||
actor.QueueActivity(new Transform(actor, "proc") { SkipMakeAnims = true });
|
||||
foreach (var c in actor.TraitsImplementing<INotifyCapture>())
|
||||
c.OnCapture(actor, actor, neutral, greece);
|
||||
}
|
||||
}
|
||||
|
||||
void EvacuateCivilians()
|
||||
{
|
||||
foreach (var unit in info.CivilianEvacuees)
|
||||
{
|
||||
var actor = world.CreateActor(unit, neutral, hospitalCivilianSpawnPoint.Location, null);
|
||||
actor.Trait<Mobile>().Nudge(actor, actor, true);
|
||||
actor.QueueActivity(new Move.Move(alliedBaseEntryPoint.Location, 0));
|
||||
actor.QueueActivity(new RemoveSelf());
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnAndMoveBridgeUnits(string[] units)
|
||||
{
|
||||
Sound.Play("reinfor1.aud");
|
||||
foreach (var unit in units)
|
||||
world.CreateActor(unit, greece, startEntryPoint.Location, Traits.Util.GetFacing(startBridgeEndPoint.CenterPosition - startEntryPoint.CenterPosition, 0))
|
||||
.QueueActivity(new Move.Move(startMovePoint.Location, 0));
|
||||
}
|
||||
|
||||
void SpawnAndMoveAlliedBaseUnits(string[] units)
|
||||
{
|
||||
Sound.Play("reinfor1.aud");
|
||||
foreach (var unit in units)
|
||||
world.CreateActor(unit, greece, alliedBaseEntryPoint.Location, Traits.Util.GetFacing(alliedBaseMovePoint.CenterPosition - alliedBaseEntryPoint.CenterPosition, 0))
|
||||
.QueueActivity(new Move.Move(alliedBaseMovePoint.Location, 0));
|
||||
}
|
||||
|
||||
void OnSuperTankDomeInfiltrated(Actor spy)
|
||||
{
|
||||
if (superTankDomeInfiltratedTick != -1) return;
|
||||
|
||||
superTankDome.QueueActivity(new Transform(superTankDome, "dome") { SkipMakeAnims = true });
|
||||
|
||||
world.AddFrameEndTask(_ =>
|
||||
{
|
||||
superTanks.Do(world.Remove);
|
||||
turkey.Stances[greece] = turkey.Stances[neutral] = Stance.Ally;
|
||||
greece.Stances[turkey] = neutral.Stances[turkey] = Stance.Ally;
|
||||
greece.Shroud.ExploreAll(world);
|
||||
superTanks.Do(world.Add);
|
||||
});
|
||||
|
||||
foreach (var tank in superTanks.Where(t => !t.IsDead() && t.IsInWorld))
|
||||
MissionUtils.AttackNearestLandActor(false, tank, ussr);
|
||||
|
||||
superTankDomeInfiltratedTick = world.FrameNumber;
|
||||
|
||||
infiltrateRadarDome.Status = ObjectiveStatus.Completed;
|
||||
OnObjectivesUpdated(true);
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
|
||||
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<PlayerResources>().Cash = 0;
|
||||
ussr.PlayerActor.Trait<PlayerResources>().Cash = 2000;
|
||||
|
||||
var actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||
startEntryPoint = actors["StartEntryPoint"];
|
||||
startMovePoint = actors["StartMovePoint"];
|
||||
startBridgeEndPoint = actors["StartBridgeEndPoint"];
|
||||
alliedBaseTopLeft = actors["AlliedBaseTopLeft"];
|
||||
alliedBaseBottomRight = actors["AlliedBaseBottomRight"];
|
||||
alliedBaseEntryPoint = actors["AlliedBaseEntryPoint"];
|
||||
alliedBaseMovePoint = actors["AlliedBaseMovePoint"];
|
||||
|
||||
demitriChurch = actors["DemitriChurch"];
|
||||
demitriChurchSpawnPoint = actors["DemitriChurchSpawnPoint"];
|
||||
demitriTriggerAreaCenter = actors["DemitriTriggerAreaCenter"];
|
||||
demitriLZ = actors["DemitriLZ"];
|
||||
|
||||
hospital = actors["Hospital"];
|
||||
hospitalCivilianSpawnPoint = actors["HospitalCivilianSpawnPoint"];
|
||||
hospitalSuperTankPoint = actors["HospitalSuperTankPoint"];
|
||||
|
||||
superTanks = actors.Values.Where(a => a.Info.Name == "5tnk" && a.Owner == turkey).ToArray();
|
||||
|
||||
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));
|
||||
|
||||
wr.Viewport.Center(startEntryPoint.CenterPosition);
|
||||
MissionUtils.PlayMissionMusic();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
public class Objective
|
||||
{
|
||||
public ObjectiveType Type;
|
||||
public string Text;
|
||||
public ObjectiveStatus Status;
|
||||
|
||||
public Objective(ObjectiveType type, string text, ObjectiveStatus status)
|
||||
{
|
||||
Type = type;
|
||||
Text = text;
|
||||
Status = status;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ObjectiveType { Primary, Secondary }
|
||||
public enum ObjectiveStatus { Inactive, InProgress, Completed, Failed }
|
||||
|
||||
public interface IHasObjectives
|
||||
{
|
||||
event Action<bool> OnObjectivesUpdated;
|
||||
IEnumerable<Objective> Objectives { get; }
|
||||
}
|
||||
|
||||
public class MissionObjectivesPanelInfo : ITraitInfo
|
||||
{
|
||||
public string ObjectivesPanel = null;
|
||||
public object Create(ActorInitializer init) { return new MissionObjectivesPanel(this); }
|
||||
}
|
||||
|
||||
public class MissionObjectivesPanel : IObjectivesPanel
|
||||
{
|
||||
MissionObjectivesPanelInfo info;
|
||||
public MissionObjectivesPanel(MissionObjectivesPanelInfo info) { this.info = info; }
|
||||
public string ObjectivesPanel { get { return info.ObjectivesPanel; } }
|
||||
}
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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 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.Scripting;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
class Soviet01ClassicScriptInfo : TraitInfo<Soviet01ClassicScript>, Requires<SpawnMapActorsInfo> { }
|
||||
|
||||
class Soviet01ClassicScript : IHasObjectives, IWorldLoaded, ITick
|
||||
{
|
||||
public event Action<bool> OnObjectivesUpdated = notify => { };
|
||||
|
||||
public IEnumerable<Objective> Objectives { get { return new[] { destroy }; } }
|
||||
|
||||
Objective destroy = new Objective(ObjectiveType.Primary, DestroyText, ObjectiveStatus.InProgress);
|
||||
|
||||
const string DestroyText = "A pitiful excuse for resistance has blockaded itself in this village."
|
||||
+ " Stalin has decided to make an example of them. Kill them all and destroy their homes."
|
||||
+ " You will have Yak aircraft to use in teaching these rebels a lesson.";
|
||||
|
||||
World world;
|
||||
|
||||
Player ussr;
|
||||
Player france;
|
||||
|
||||
Actor startJeep;
|
||||
Actor startJeepMovePoint;
|
||||
Actor church;
|
||||
bool startJeepParadropped;
|
||||
bool churchParadropped;
|
||||
|
||||
Actor paradropPoint1;
|
||||
Actor paradropEntryPoint1;
|
||||
Actor paradropPoint2;
|
||||
Actor paradropEntryPoint2;
|
||||
|
||||
Actor airfield1;
|
||||
Actor airfield2;
|
||||
Actor airfield3;
|
||||
Actor[] airfields;
|
||||
|
||||
const string BadgerName = "badr";
|
||||
static readonly string[] Reinforcements = { "e1", "e1", "e1", "e2", "e2" };
|
||||
|
||||
void MissionAccomplished(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionAccomplished(world, text, ussr);
|
||||
}
|
||||
|
||||
void MissionFailed(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionFailed(world, text, ussr);
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (ussr.WinState != WinState.Undefined) return;
|
||||
|
||||
var unitsAndBuildings = world.Actors.Where(a => !a.IsDead() && a.IsInWorld && (a.HasTrait<Mobile>() || (a.HasTrait<Building>() && !a.HasTrait<Wall>())));
|
||||
if (!unitsAndBuildings.Any(a => a.Owner == france))
|
||||
{
|
||||
destroy.Status = ObjectiveStatus.Completed;
|
||||
MissionAccomplished("We destroyed the resistance.");
|
||||
}
|
||||
else if (!unitsAndBuildings.Any(a => a.Owner == ussr))
|
||||
{
|
||||
destroy.Status = ObjectiveStatus.Failed;
|
||||
MissionFailed("We were destroyed by the resistance.");
|
||||
}
|
||||
if (!startJeepParadropped && startJeep.IsDead())
|
||||
{
|
||||
Sound.Play("reinfor1.aud");
|
||||
MissionUtils.Paradrop(world, ussr, Reinforcements, paradropEntryPoint1.Location, paradropPoint1.Location);
|
||||
startJeepParadropped = true;
|
||||
}
|
||||
if (!churchParadropped && church.IsDead())
|
||||
{
|
||||
Sound.Play("reinfor1.aud");
|
||||
MissionUtils.Paradrop(world, ussr, Reinforcements, paradropEntryPoint2.Location, paradropPoint2.Location);
|
||||
churchParadropped = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LandYaks()
|
||||
{
|
||||
foreach (var airfield in airfields)
|
||||
{
|
||||
var entry = airfield.Location - new CVec(10, 0);
|
||||
var altitude = Rules.Info["yak"].Traits.Get<PlaneInfo>().CruiseAltitude;
|
||||
var yak = world.CreateActor("yak", new TypeDictionary
|
||||
{
|
||||
new CenterPositionInit(entry.CenterPosition + new WVec(WRange.Zero, WRange.Zero, altitude)),
|
||||
new OwnerInit(ussr),
|
||||
new FacingInit(Traits.Util.GetFacing(airfield.Location - entry, 0))
|
||||
});
|
||||
|
||||
while (yak.Trait<LimitedAmmo>().TakeAmmo()) { }
|
||||
|
||||
yak.QueueActivity(new ReturnToBase(yak, airfield));
|
||||
yak.QueueActivity(new ResupplyAircraft());
|
||||
}
|
||||
}
|
||||
|
||||
void MoveJeep()
|
||||
{
|
||||
startJeep.QueueActivity(new Move.Move(startJeepMovePoint.Location, 0));
|
||||
startJeep.QueueActivity(new Turn(128));
|
||||
startJeep.QueueActivity(new CallFunc(() =>
|
||||
{
|
||||
var bridge = world.Actors.Where(a => a.HasTrait<BridgeHut>()).ClosestTo(startJeep);
|
||||
bridge.Trait<BridgeHut>().Demolish(bridge, startJeep);
|
||||
}));
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
|
||||
ussr = w.Players.Single(p => p.InternalName == "USSR");
|
||||
france = w.Players.Single(p => p.InternalName == "France");
|
||||
|
||||
var actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||
startJeep = actors["StartJeep"];
|
||||
startJeepMovePoint = actors["StartJeepMovePoint"];
|
||||
paradropPoint1 = actors["ParadropPoint1"];
|
||||
paradropEntryPoint1 = actors["ParadropEntryPoint1"];
|
||||
paradropPoint2 = actors["ParadropPoint2"];
|
||||
paradropEntryPoint2 = actors["ParadropEntryPoint2"];
|
||||
church = actors["Church"];
|
||||
airfield1 = actors["Airfield1"];
|
||||
airfield2 = actors["Airfield2"];
|
||||
airfield3 = actors["Airfield3"];
|
||||
airfields = new[] { airfield1, airfield2, airfield3 };
|
||||
|
||||
wr.Viewport.Center(startJeep.CenterPosition);
|
||||
|
||||
if (w.LobbyInfo.IsSinglePlayer)
|
||||
{
|
||||
Media.PlayFMVFullscreen(w, "soviet1.vqa", () =>
|
||||
{
|
||||
LandYaks();
|
||||
MoveJeep();
|
||||
MissionUtils.PlayMissionMusic();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
LandYaks();
|
||||
MoveJeep();
|
||||
MissionUtils.PlayMissionMusic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Soviet01ClassicContainsActorsInfo : ITraitInfo
|
||||
{
|
||||
public readonly string[] Actors = { };
|
||||
|
||||
public object Create(ActorInitializer init) { return new Soviet01ClassicContainsActors(this); }
|
||||
}
|
||||
|
||||
class Soviet01ClassicContainsActors : INotifyDamage
|
||||
{
|
||||
bool spawned;
|
||||
Soviet01ClassicContainsActorsInfo info;
|
||||
|
||||
public Soviet01ClassicContainsActors(Soviet01ClassicContainsActorsInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public void Damaged(Actor self, AttackInfo e)
|
||||
{
|
||||
if (spawned || self.IsDead())
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var actor in info.Actors)
|
||||
{
|
||||
var unit = self.World.CreateActor(actor, new TypeDictionary
|
||||
{
|
||||
new OwnerInit(self.Owner),
|
||||
new LocationInit(self.Location)
|
||||
});
|
||||
unit.Trait<Mobile>().Nudge(unit, unit, true);
|
||||
}
|
||||
spawned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,346 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 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 System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Buildings;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
class Survival01ScriptInfo : TraitInfo<Survival01Script>, Requires<SpawnMapActorsInfo> { }
|
||||
|
||||
class Survival01Script : IHasObjectives, IWorldLoaded, ITick
|
||||
{
|
||||
public event Action<bool> OnObjectivesUpdated = notify => { };
|
||||
|
||||
public IEnumerable<Objective> Objectives { get { return new[] { maintainPresence, destroySoviets }; } }
|
||||
|
||||
Objective maintainPresence = new Objective(ObjectiveType.Primary, MaintainPresenceText, ObjectiveStatus.InProgress);
|
||||
Objective destroySoviets = new Objective(ObjectiveType.Primary, DestroySovietsText, ObjectiveStatus.Inactive);
|
||||
|
||||
const string MaintainPresenceText = "Enforce your position and hold-out the onslaught until reinforcements arrive. We must not lose the base!";
|
||||
const string DestroySovietsText = "Take control of French reinforcements and dismantle the nearby Soviet base.";
|
||||
|
||||
Player allies;
|
||||
Player soviets;
|
||||
|
||||
Actor sovietEntryPoint1;
|
||||
Actor sovietEntryPoint2;
|
||||
Actor sovietEntryPoint3;
|
||||
Actor sovietEntryPoint4;
|
||||
Actor sovietEntryPoint5;
|
||||
CPos[] sovietEntryPoints;
|
||||
Actor sovietRallyPoint1;
|
||||
Actor sovietRallyPoint2;
|
||||
Actor sovietRallyPoint3;
|
||||
Actor sovietRallyPoint4;
|
||||
Actor sovietRallyPoint5;
|
||||
CPos[] sovietRallyPoints;
|
||||
|
||||
Actor sovietinfantryentry1;
|
||||
Actor sovietinfantryrally1;
|
||||
|
||||
Actor badgerEntryPoint1;
|
||||
Actor badgerEntryPoint2;
|
||||
Actor paraDrop1;
|
||||
Actor paraDrop2;
|
||||
Actor sovietEntryPoint7;
|
||||
|
||||
Actor alliesbase1;
|
||||
Actor alliesbase2;
|
||||
Actor alliesbase;
|
||||
Actor sam1;
|
||||
Actor sam2;
|
||||
Actor barrack1;
|
||||
World world;
|
||||
|
||||
CountdownTimer survivalTimer;
|
||||
CountdownTimerWidget survivalTimerWidget;
|
||||
|
||||
int attackAtFrame;
|
||||
int attackAtFrameIncrement;
|
||||
int attackAtFrameInf;
|
||||
int attackAtFrameIncrementInf;
|
||||
|
||||
const int paradropTicks = 750;
|
||||
static readonly string[] badger1Passengers = { "e1", "e1", "e1", "e2", "e2" };
|
||||
|
||||
const int factoryClearRange = 10;
|
||||
static readonly string[] squad1 = { "e1", "e1" };
|
||||
static readonly string[] squad2 = { "e2", "e2" };
|
||||
static readonly string[] sovietVehicles = { "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "3tnk", "v2rl", "v2rl", "ftrk", "ftrk", "ftrk", "apc", "apc" };
|
||||
static readonly string[] sovietInfantry = { "e1", "e1", "e1", "e1", "e2", "e2", "e2", "e4", "e4", "e3", };
|
||||
static readonly string[] reinforcements = { "2tnk", "2tnk", "2tnk", "2tnk", "2tnk", "1tnk", "1tnk", "1tnk", "arty", "arty", "arty", "jeep", "jeep" };
|
||||
const int sovietAttackGroupSize = 5;
|
||||
const int sovietInfantryGroupSize = 7;
|
||||
|
||||
const int timerTicks = 1500 * 25;
|
||||
bool spawningSovietUnits = true;
|
||||
bool spawningInfantry = true;
|
||||
string difficulty;
|
||||
|
||||
void MissionAccomplished(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionAccomplished(world, text, allies);
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (allies.WinState != WinState.Undefined)
|
||||
return;
|
||||
|
||||
survivalTimer.Tick();
|
||||
|
||||
if (world.FrameNumber == attackAtFrame)
|
||||
{
|
||||
attackAtFrame += attackAtFrameIncrement;
|
||||
attackAtFrameIncrement = Math.Max(attackAtFrameIncrement - 5, 100);
|
||||
SpawnSovietUnits();
|
||||
ManageSovietUnits();
|
||||
MissionUtils.CapOre(soviets);
|
||||
}
|
||||
|
||||
if (world.FrameNumber == attackAtFrameInf)
|
||||
{
|
||||
attackAtFrameInf += attackAtFrameIncrementInf;
|
||||
attackAtFrameIncrementInf = Math.Max(attackAtFrameIncrementInf - 5, 100);
|
||||
SpawnSovietInfantry();
|
||||
}
|
||||
|
||||
if (barrack1.Destroyed)
|
||||
{
|
||||
spawningInfantry = false;
|
||||
}
|
||||
|
||||
if (world.FrameNumber == paradropTicks)
|
||||
{
|
||||
MissionUtils.Paradrop(world, soviets, badger1Passengers, badgerEntryPoint1.Location, paraDrop1.Location);
|
||||
MissionUtils.Paradrop(world, soviets, badger1Passengers, badgerEntryPoint2.Location, paraDrop2.Location);
|
||||
}
|
||||
|
||||
if (world.FrameNumber == paradropTicks * 2)
|
||||
{
|
||||
MissionUtils.Paradrop(world, soviets, badger1Passengers, badgerEntryPoint1.Location, alliesbase2.Location);
|
||||
MissionUtils.Paradrop(world, soviets, badger1Passengers, badgerEntryPoint2.Location, alliesbase1.Location);
|
||||
}
|
||||
|
||||
if (world.FrameNumber == 1500 * 23)
|
||||
{
|
||||
attackAtFrame = 100;
|
||||
attackAtFrameIncrement = 100;
|
||||
}
|
||||
|
||||
if (world.FrameNumber == 1500 * 25)
|
||||
{
|
||||
spawningSovietUnits = false;
|
||||
spawningInfantry = false;
|
||||
}
|
||||
|
||||
if (destroySoviets.Status == ObjectiveStatus.InProgress)
|
||||
{
|
||||
if (barrack1.Destroyed)
|
||||
{
|
||||
destroySoviets.Status = ObjectiveStatus.Completed;
|
||||
OnObjectivesUpdated(true);
|
||||
MissionAccomplished("The French forces have survived and dismantled the soviet presence in the area!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendSquad1()
|
||||
{
|
||||
for (int i = 0; i < squad1.Length; i++)
|
||||
{
|
||||
var actor = world.CreateActor(squad1[i], new TypeDictionary { new OwnerInit(soviets), new LocationInit(alliesbase1.Location + new CVec(-2 + i, -6 + i * 2)) });
|
||||
actor.QueueActivity(new Move.Move(alliesbase1.Location));
|
||||
}
|
||||
}
|
||||
|
||||
void SendSquad2()
|
||||
{
|
||||
for (int i = 0; i < squad2.Length; i++)
|
||||
{
|
||||
var actor = world.CreateActor(squad2[i], new TypeDictionary { new OwnerInit(soviets), new LocationInit(alliesbase2.Location + new CVec(-9 + i, -2 + i * 2)) });
|
||||
actor.QueueActivity(new Move.Move(alliesbase2.Location));
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnSovietInfantry()
|
||||
{
|
||||
if (spawningInfantry)
|
||||
{
|
||||
var units = world.CreateActor((sovietInfantry).Random(world.SharedRandom), new TypeDictionary { new LocationInit(sovietinfantryentry1.Location), new OwnerInit(soviets) });
|
||||
units.QueueActivity(new Move.Move(sovietinfantryrally1.Location, 3));
|
||||
var unitsincircle = world.FindAliveCombatantActorsInCircle(sovietinfantryrally1.CenterPosition, WRange.FromCells(10))
|
||||
.Where(a => a.Owner == soviets && a.IsIdle && a.HasTrait<IPositionable>());
|
||||
if (unitsincircle.Count() >= sovietInfantryGroupSize)
|
||||
{
|
||||
foreach (var scatteredunits in unitsincircle)
|
||||
AttackNearestAlliedActor(scatteredunits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnSovietUnits()
|
||||
{
|
||||
if (spawningSovietUnits)
|
||||
{
|
||||
var route = world.SharedRandom.Next(sovietEntryPoints.Length);
|
||||
var spawnPoint = sovietEntryPoints[route];
|
||||
var rallyPoint = sovietRallyPoints[route];
|
||||
var unit = world.CreateActor(sovietVehicles.Random(world.SharedRandom),
|
||||
new TypeDictionary { new LocationInit(spawnPoint), new OwnerInit(soviets) });
|
||||
unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, new Move.Move(rallyPoint, 3)));
|
||||
}
|
||||
}
|
||||
|
||||
void AttackNearestAlliedActor(Actor self)
|
||||
{
|
||||
var enemies = world.Actors.Where(u => u.IsInWorld && !u.IsDead() && (u.Owner == allies)
|
||||
&& ((u.HasTrait<Building>() && !u.HasTrait<Wall>()) || u.HasTrait<Mobile>()));
|
||||
|
||||
var targetEnemy = enemies.ClosestTo(self);
|
||||
if (targetEnemy != null)
|
||||
self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(targetEnemy), WRange.FromCells(3))));
|
||||
}
|
||||
|
||||
void ManageSovietUnits()
|
||||
{
|
||||
foreach (var rallyPoint in sovietRallyPoints)
|
||||
{
|
||||
var units = world.FindAliveCombatantActorsInCircle(rallyPoint.CenterPosition, WRange.FromCells(4))
|
||||
.Where(u => u.IsIdle && u.HasTrait<Mobile>() && u.Owner == soviets);
|
||||
if (units.Count() >= sovietAttackGroupSize)
|
||||
{
|
||||
foreach (var unit in units)
|
||||
{
|
||||
AttackNearestAlliedActor(unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
var scatteredUnits = world.Actors.Where(u => u.IsInWorld && !u.IsDead() && u.HasTrait<Mobile>() && u.IsIdle && u.Owner == soviets)
|
||||
.Except(world.WorldActor.Trait<SpawnMapActors>().Actors.Values)
|
||||
.Except(sovietRallyPoints.SelectMany(rp => world.FindAliveCombatantActorsInCircle(rp.CenterPosition, WRange.FromCells(4))));
|
||||
foreach (var unit in scatteredUnits)
|
||||
{
|
||||
AttackNearestAlliedActor(unit);
|
||||
}
|
||||
}
|
||||
|
||||
void StartCountDownTimer()
|
||||
{
|
||||
Sound.Play("timergo1.aud");
|
||||
survivalTimer = new CountdownTimer(timerTicks, CountDownTimerExpired, true);
|
||||
survivalTimerWidget = new CountdownTimerWidget(survivalTimer, "Survive: {0}");
|
||||
Ui.Root.AddChild(survivalTimerWidget);
|
||||
}
|
||||
|
||||
void SendReinforcements()
|
||||
{
|
||||
foreach (var unit in reinforcements)
|
||||
{
|
||||
var u = world.CreateActor(unit, new TypeDictionary
|
||||
{
|
||||
new LocationInit(sovietEntryPoint7.Location),
|
||||
new FacingInit(0),
|
||||
new OwnerInit(allies)
|
||||
});
|
||||
u.QueueActivity(new Move.Move(alliesbase.Location));
|
||||
}
|
||||
}
|
||||
|
||||
void CountDownTimerExpired(CountdownTimer countDownTimer)
|
||||
{
|
||||
survivalTimerWidget.Visible = false;
|
||||
SendReinforcements();
|
||||
maintainPresence.Status = ObjectiveStatus.Completed;
|
||||
destroySoviets.Status = ObjectiveStatus.InProgress;
|
||||
OnObjectivesUpdated(true);
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
|
||||
allies = w.Players.SingleOrDefault(p => p.InternalName == "Allies");
|
||||
if (allies != null)
|
||||
{
|
||||
attackAtFrameInf = 300;
|
||||
attackAtFrameIncrementInf = 300;
|
||||
attackAtFrame = 450;
|
||||
attackAtFrameIncrement = 450;
|
||||
}
|
||||
|
||||
difficulty = w.LobbyInfo.GlobalSettings.Difficulty;
|
||||
Game.Debug("{0} difficulty selected".F(difficulty));
|
||||
|
||||
switch (difficulty)
|
||||
{
|
||||
case "Hard":
|
||||
attackAtFrameIncrement = 350;
|
||||
attackAtFrameIncrementInf = 200;
|
||||
break;
|
||||
case "Normal":
|
||||
attackAtFrameIncrement = 450;
|
||||
attackAtFrameIncrementInf = 300;
|
||||
break;
|
||||
case "Easy":
|
||||
attackAtFrameIncrement = 550;
|
||||
attackAtFrameIncrementInf = 400;
|
||||
break;
|
||||
}
|
||||
|
||||
soviets = w.Players.Single(p => p.InternalName == "Soviets");
|
||||
var actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||
sovietEntryPoint1 = actors["sovietEntryPoint1"];
|
||||
sovietEntryPoint2 = actors["sovietEntryPoint2"];
|
||||
sovietEntryPoint3 = actors["sovietEntryPoint3"];
|
||||
sovietEntryPoint4 = actors["sovietEntryPoint4"];
|
||||
sovietEntryPoint5 = actors["sovietEntryPoint5"];
|
||||
sovietEntryPoints = new[] { sovietEntryPoint1, sovietEntryPoint2, sovietEntryPoint3, sovietEntryPoint4, sovietEntryPoint5 }.Select(p => p.Location).ToArray();
|
||||
sovietRallyPoint1 = actors["sovietRallyPoint1"];
|
||||
sovietRallyPoint2 = actors["sovietRallyPoint2"];
|
||||
sovietRallyPoint3 = actors["sovietRallyPoint3"];
|
||||
sovietRallyPoint4 = actors["sovietRallyPoint4"];
|
||||
sovietRallyPoint5 = actors["sovietRallyPoint5"];
|
||||
sovietRallyPoints = new[] { sovietRallyPoint1, sovietRallyPoint2, sovietRallyPoint3, sovietRallyPoint4, sovietRallyPoint5 }.Select(p => p.Location).ToArray();
|
||||
alliesbase = actors["alliesbase"];
|
||||
alliesbase1 = actors["alliesbase1"];
|
||||
alliesbase2 = actors["alliesbase2"];
|
||||
badgerEntryPoint1 = actors["BadgerEntryPoint1"];
|
||||
badgerEntryPoint2 = actors["BadgerEntryPoint2"];
|
||||
sovietEntryPoint7 = actors["sovietEntryPoint7"];
|
||||
sovietinfantryentry1 = actors["SovietInfantryEntry1"];
|
||||
sovietinfantryrally1 = actors["SovietInfantryRally1"];
|
||||
paraDrop1 = actors["ParaDrop1"];
|
||||
paraDrop2 = actors["ParaDrop2"];
|
||||
barrack1 = actors["Barrack1"];
|
||||
sam1 = actors["Sam1"];
|
||||
sam2 = actors["Sam2"];
|
||||
|
||||
var shroud = allies.PlayerActor.Trait<Shroud>();
|
||||
shroud.Explore(w, sam1.Location, WRange.FromCells(4));
|
||||
shroud.Explore(w, sam2.Location, WRange.FromCells(4));
|
||||
|
||||
wr.Viewport.Center(alliesbase.CenterPosition);
|
||||
StartCountDownTimer();
|
||||
SendSquad1();
|
||||
SendSquad2();
|
||||
MissionUtils.PlayMissionMusic();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,411 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 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 System;
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Move;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
using OpenRA.Mods.RA.Buildings;
|
||||
|
||||
namespace OpenRA.Mods.RA.Missions
|
||||
{
|
||||
class Survival02ScriptInfo : TraitInfo<Survival02Script>, Requires<SpawnMapActorsInfo> { }
|
||||
|
||||
class Survival02Script : IHasObjectives, IWorldLoaded, ITick
|
||||
{
|
||||
public event Action<bool> OnObjectivesUpdated = notify => { };
|
||||
|
||||
public IEnumerable<Objective> Objectives { get { return objectives.Values; } }
|
||||
|
||||
Dictionary<int, Objective> objectives = new Dictionary<int, Objective>
|
||||
{
|
||||
{ maintainPresenceID, new Objective(ObjectiveType.Primary, maintainPresence, ObjectiveStatus.InProgress) },
|
||||
{ destroySovietsID, new Objective(ObjectiveType.Primary, destroySoviets, ObjectiveStatus.Inactive) },
|
||||
};
|
||||
const int destroySovietsID = 0;
|
||||
const string destroySoviets = "Excellent work Commander! We have reinforced our position enough to initiate a counter-attack. Destroy the remaining Soviet forces in the area!";
|
||||
const int maintainPresenceID = 1;
|
||||
const string maintainPresence = "Commander! The Soviets have rendered us useless... Reports indicate Soviet reinforcements are coming to finish us off... the situation looks bleak...";
|
||||
|
||||
Player allies;
|
||||
Player soviets;
|
||||
|
||||
Actor sovietEntry1;
|
||||
Actor sovietEntry2;
|
||||
Actor sovietEntry3;
|
||||
CPos[] sovietentrypoints;
|
||||
CPos[] newsovietentrypoints;
|
||||
|
||||
Actor sovietrally;
|
||||
Actor sovietrally1;
|
||||
Actor sovietrally2;
|
||||
Actor sovietrally3;
|
||||
Actor sovietrally4;
|
||||
Actor sovietrally5;
|
||||
Actor sovietrally6;
|
||||
Actor sovietrally8;
|
||||
CPos[] sovietrallypoints;
|
||||
CPos[] newsovietrallypoints;
|
||||
|
||||
Actor sovietparadrop1;
|
||||
Actor sovietparadrop2;
|
||||
Actor sovietparadrop3;
|
||||
Actor sovietparadropEntry;
|
||||
|
||||
Actor alliesbase;
|
||||
Actor factory;
|
||||
Actor barrack1;
|
||||
|
||||
Actor drum1;
|
||||
Actor drum2;
|
||||
Actor drum3;
|
||||
Actor FranceEntry;
|
||||
Actor FranceRally;
|
||||
Actor FranceparaEntry1;
|
||||
Actor FranceparaEntry2;
|
||||
Actor FranceparaEntry3;
|
||||
|
||||
World world;
|
||||
WorldRenderer worldRenderer;
|
||||
|
||||
CountdownTimer survivalTimer;
|
||||
CountdownTimerWidget survivalTimerWidget;
|
||||
|
||||
const int timerTicks = 1500 * 10;
|
||||
const int attackTicks = 1500 * 1;
|
||||
const int sovietAttackGroupSize = 7;
|
||||
const int SovietGroupSize = 4;
|
||||
|
||||
const string Camera = "Camera";
|
||||
const string InfantryQueueName = "Infantry";
|
||||
const string Flare = "flare";
|
||||
|
||||
static readonly string[] FrenchSquad = { "2tnk", "2tnk", "mcv" };
|
||||
static readonly string[] SovietInfantry = { "e1", "e4", "e2" };
|
||||
static readonly string[] SovietVehicles = { "3tnk", "3tnk", "v2rl" };
|
||||
static readonly string[] SovietTanks = { "3tnk", "3tnk", "3tnk" };
|
||||
static readonly string[] squad = { "e1", "e1", "e2", "e4", "e4" };
|
||||
static readonly string[] platoon = { "e1", "e1", "e2", "e4", "e4", "e1", "e1", "e2", "e4", "e4" };
|
||||
|
||||
int ProduceAtFrame;
|
||||
int ProduceAtFrameIncrement;
|
||||
int attackAtFrame;
|
||||
int attackAtFrameIncrement;
|
||||
|
||||
void MissionAccomplished(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionAccomplished(world, text, allies);
|
||||
}
|
||||
|
||||
void MissionFailed(string text)
|
||||
{
|
||||
MissionUtils.CoopMissionFailed(world, text, allies);
|
||||
}
|
||||
|
||||
void Message(string text)
|
||||
{
|
||||
Game.AddChatLine(Color.Aqua, "Incoming Report", text);
|
||||
}
|
||||
|
||||
void SetSovietUnitsToDefensiveStance()
|
||||
{
|
||||
foreach (var actor in world.Actors.Where(a => a.IsInWorld && a.Owner == soviets && !a.IsDead() && a.HasTrait<AutoTarget>()))
|
||||
actor.Trait<AutoTarget>().Stance = UnitStance.Defend;
|
||||
}
|
||||
|
||||
Actor FirstUnshroudedOrDefault(IEnumerable<Actor> actors, World world, int shroudRange)
|
||||
{
|
||||
return actors.FirstOrDefault(u => world.FindAliveCombatantActorsInCircle(u.CenterPosition, WRange.FromCells(shroudRange)).All(a => !a.HasTrait<CreatesShroud>()));
|
||||
}
|
||||
|
||||
void AttackNearestAlliedActor(Actor self)
|
||||
{
|
||||
var enemies = world.Actors.Where(u => u.AppearsHostileTo(self) && (u.Owner == allies)
|
||||
&& ((u.HasTrait<Building>() && !u.HasTrait<Wall>()) || u.HasTrait<Mobile>()) && u.IsInWorld && !u.IsDead());
|
||||
|
||||
var enemy = FirstUnshroudedOrDefault(enemies.OrderBy(u => (self.CenterPosition - u.CenterPosition).LengthSquared), world, 20);
|
||||
if (enemy != null)
|
||||
self.QueueActivity(new AttackMove.AttackMoveActivity(self, new Attack(Target.FromActor(enemy), WRange.FromCells(3))));
|
||||
}
|
||||
|
||||
void SpawnAndAttack(string[] squad, Player owner, CPos location)
|
||||
{
|
||||
for (int i = 0; i < squad.Length; i++)
|
||||
{
|
||||
var actor = world.CreateActor(squad[i], new TypeDictionary { new OwnerInit(owner), new LocationInit(location) });
|
||||
AttackNearestAlliedActor(actor);
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnFlare(Player owner, Actor location)
|
||||
{
|
||||
world.CreateActor(Flare, new TypeDictionary { new OwnerInit(owner), new LocationInit(location.Location) });
|
||||
}
|
||||
|
||||
void FinalAttack()
|
||||
{
|
||||
SpawnAndAttack(SovietTanks, soviets, sovietEntry1.Location);
|
||||
SpawnAndAttack(SovietTanks, soviets, sovietEntry1.Location);
|
||||
SpawnAndAttack(SovietTanks, soviets, sovietEntry2.Location);
|
||||
SpawnAndAttack(platoon, soviets, sovietEntry1.Location);
|
||||
SpawnAndAttack(platoon, soviets, sovietEntry2.Location);
|
||||
}
|
||||
|
||||
void FrenchReinforcements()
|
||||
{
|
||||
worldRenderer.Viewport.Center(sovietrally1.CenterPosition);
|
||||
MissionUtils.Parabomb(world, allies, FranceparaEntry1.Location, drum3.Location);
|
||||
MissionUtils.Parabomb(world, allies, FranceparaEntry3.Location, drum2.Location);
|
||||
MissionUtils.Parabomb(world, allies, FranceparaEntry2.Location, drum1.Location);
|
||||
for (int i = 0; i < FrenchSquad.Length; i++)
|
||||
{
|
||||
var actor = world.CreateActor(FrenchSquad[i], new TypeDictionary { new OwnerInit(allies), new LocationInit(FranceEntry.Location) });
|
||||
actor.QueueActivity(new Move.Move(FranceRally.Location));
|
||||
}
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (allies.WinState != WinState.Undefined)
|
||||
return;
|
||||
|
||||
survivalTimer.Tick();
|
||||
if (allies != null)
|
||||
{
|
||||
ManageSovietUnits();
|
||||
}
|
||||
|
||||
var unitsAndBuildings = world.Actors.Where(a => !a.IsDead() && a.IsInWorld && (a.HasTrait<Mobile>() || (a.HasTrait<Building>() && !a.HasTrait<Wall>())));
|
||||
if (!unitsAndBuildings.Any(a => a.Owner == soviets))
|
||||
{
|
||||
objectives[destroySovietsID].Status = ObjectiveStatus.Completed;
|
||||
MissionAccomplished("We have destroyed the remaining Soviet presence!");
|
||||
}
|
||||
|
||||
if (world.FrameNumber == ProduceAtFrame)
|
||||
{
|
||||
ProduceAtFrame += ProduceAtFrameIncrement;
|
||||
ProduceAtFrameIncrement = Math.Max(ProduceAtFrameIncrement - 5, 100);
|
||||
InitializeSovietFactories(barrack1, sovietrally.Location);
|
||||
BuildSovietUnits(factory, barrack1);
|
||||
}
|
||||
if (world.FrameNumber == attackAtFrame)
|
||||
{
|
||||
attackAtFrame += attackAtFrameIncrement;
|
||||
attackAtFrameIncrement = Math.Max(attackAtFrameIncrement - 5, 100);
|
||||
ManageSovietVehicles();
|
||||
if (producing)
|
||||
{
|
||||
BuildSovietVehicles(sovietentrypoints, sovietrallypoints);
|
||||
}
|
||||
else
|
||||
BuildSovietVehicles(newsovietentrypoints, newsovietrallypoints);
|
||||
}
|
||||
if (world.FrameNumber == attackTicks)
|
||||
{
|
||||
SpawnAndAttack(squad, soviets, sovietrally5.Location);
|
||||
SpawnAndAttack(squad, soviets, sovietrally6.Location);
|
||||
}
|
||||
if (world.FrameNumber == attackTicks * 3)
|
||||
{
|
||||
SpawnFlare(soviets, sovietparadrop3);
|
||||
MissionUtils.Paradrop(world, soviets, squad, sovietparadropEntry.Location, sovietparadrop3.Location);
|
||||
SpawnAndAttack(squad, soviets, sovietrally2.Location);
|
||||
SpawnAndAttack(platoon, soviets, sovietrally5.Location);
|
||||
SpawnAndAttack(platoon, soviets, sovietrally6.Location);
|
||||
}
|
||||
if (world.FrameNumber == attackTicks * 5)
|
||||
{
|
||||
SpawnFlare(soviets, sovietparadrop2);
|
||||
MissionUtils.Paradrop(world, soviets, squad, sovietparadropEntry.Location, sovietparadrop2.Location);
|
||||
}
|
||||
if (world.FrameNumber == attackTicks * 7)
|
||||
{
|
||||
SpawnFlare(soviets, sovietparadrop1);
|
||||
MissionUtils.Paradrop(world, soviets, squad, sovietparadropEntry.Location, sovietparadrop1.Location);
|
||||
}
|
||||
if (world.FrameNumber == attackTicks * 10)
|
||||
{
|
||||
SpawnFlare(soviets, sovietparadrop1);
|
||||
MissionUtils.Paradrop(world, soviets, squad, sovietparadropEntry.Location, sovietparadrop1.Location);
|
||||
ManageSovietUnits();
|
||||
}
|
||||
if (world.FrameNumber == attackTicks * 12)
|
||||
{
|
||||
Sound.Play("reinfor1.aud");
|
||||
FrenchReinforcements();
|
||||
}
|
||||
}
|
||||
|
||||
void StartCountDownTimer()
|
||||
{
|
||||
Sound.Play("timergo1.aud");
|
||||
survivalTimer = new CountdownTimer(timerTicks, CountDownTimerExpired, true);
|
||||
survivalTimerWidget = new CountdownTimerWidget(survivalTimer, "Time Until Soviet Reinforcements Arrive: {0}");
|
||||
Ui.Root.AddChild(survivalTimerWidget);
|
||||
}
|
||||
|
||||
void CountDownTimerExpired(CountdownTimer countDownTimer)
|
||||
{
|
||||
survivalTimerWidget.Visible = false;
|
||||
Message("The Soviet reinforcements are approuching!");
|
||||
BuildSovietVehicles(newsovietentrypoints, newsovietrallypoints);
|
||||
FinalAttack();
|
||||
producing = false;
|
||||
objectives[maintainPresenceID].Status = ObjectiveStatus.Completed;
|
||||
objectives[destroySovietsID].Status = ObjectiveStatus.InProgress;
|
||||
OnObjectivesUpdated(true);
|
||||
}
|
||||
|
||||
void InitializeSovietFactories(Actor tent, CPos rally)
|
||||
{
|
||||
if (tent.IsInWorld && !tent.IsDead())
|
||||
{
|
||||
var sbrp = tent.Trait<RallyPoint>();
|
||||
sbrp.rallyPoint = rally;
|
||||
sbrp.nearEnough = 6;
|
||||
}
|
||||
}
|
||||
|
||||
void BuildSovietUnit(string category, string unit)
|
||||
{
|
||||
var queueTent = MissionUtils.FindQueues(world, soviets, category).FirstOrDefault(q => q.CurrentItem() == null);
|
||||
if (queueTent == null) return;
|
||||
queueTent.ResolveOrder(queueTent.self, Order.StartProduction(queueTent.self, unit, 1));
|
||||
}
|
||||
|
||||
void BuildSovietUnits(Actor factory, Actor tent)
|
||||
{
|
||||
if (barrack1.IsInWorld && !barrack1.IsDead())
|
||||
{
|
||||
BuildSovietUnit(InfantryQueueName, SovietInfantry.Random(world.SharedRandom));
|
||||
}
|
||||
}
|
||||
|
||||
void ManageSovietUnits()
|
||||
{
|
||||
var units = world.FindAliveCombatantActorsInCircle(sovietrally.CenterPosition, WRange.FromCells(3))
|
||||
.Where(u => u.IsIdle && u.HasTrait<IPositionable>() && u.HasTrait<AttackBase>() && u.Owner == soviets);
|
||||
if (units.Count() >= sovietAttackGroupSize)
|
||||
{
|
||||
foreach (var unit in units)
|
||||
{
|
||||
var route = world.SharedRandom.Next(sovietrallypoints.Length);
|
||||
unit.QueueActivity(new Move.Move(sovietrally3.Location));
|
||||
unit.QueueActivity(new Wait(300));
|
||||
unit.QueueActivity(new Move.Move(sovietrallypoints[route]));
|
||||
AttackNearestAlliedActor(unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BuildSovietVehicles(CPos[] spawnpoints, CPos[] rallypoints)
|
||||
{
|
||||
var route = world.SharedRandom.Next(spawnpoints.Length);
|
||||
var spawnPoint = spawnpoints[route];
|
||||
var rally = world.SharedRandom.Next(rallypoints.Length);
|
||||
var rallyPoint = rallypoints[rally];
|
||||
var unit = world.CreateActor(SovietVehicles.Random(world.SharedRandom),
|
||||
new TypeDictionary
|
||||
{
|
||||
new LocationInit(spawnPoint),
|
||||
new OwnerInit(soviets)
|
||||
});
|
||||
unit.QueueActivity(new AttackMove.AttackMoveActivity(unit, new Move.Move(rallyPoint, 3)));
|
||||
}
|
||||
|
||||
void ManageSovietVehicles()
|
||||
{
|
||||
foreach (var rallyPoint in sovietrallypoints)
|
||||
{
|
||||
var units = world.FindAliveCombatantActorsInCircle(rallyPoint.CenterPosition, WRange.FromCells(10))
|
||||
.Where(u => u.IsIdle && u.HasTrait<Mobile>() && u.HasTrait<AttackBase>() && u.Owner == soviets);
|
||||
if (units.Count() >= SovietGroupSize)
|
||||
{
|
||||
foreach (var unit in units)
|
||||
AttackNearestAlliedActor(unit);
|
||||
}
|
||||
}
|
||||
|
||||
var scatteredUnits = world.Actors.Where(u => u.IsInWorld && !u.IsDead() && u.HasTrait<Mobile>() && u.IsIdle && u.Owner == soviets)
|
||||
.Except(world.WorldActor.Trait<SpawnMapActors>().Actors.Values)
|
||||
.Except(sovietrallypoints.SelectMany(rp => world.FindAliveCombatantActorsInCircle(rp.CenterPosition, WRange.FromCells(10))));
|
||||
|
||||
foreach (var unit in scatteredUnits)
|
||||
AttackNearestAlliedActor(unit);
|
||||
}
|
||||
|
||||
bool producing = true;
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
worldRenderer = wr;
|
||||
|
||||
allies = w.Players.SingleOrDefault(p => p.InternalName == "Allies");
|
||||
if (allies != null)
|
||||
{
|
||||
ProduceAtFrame = 300;
|
||||
ProduceAtFrameIncrement = 300;
|
||||
attackAtFrame = 450;
|
||||
attackAtFrameIncrement = 450;
|
||||
}
|
||||
soviets = w.Players.Single(p => p.InternalName == "Soviets");
|
||||
var actors = w.WorldActor.Trait<SpawnMapActors>().Actors;
|
||||
sovietEntry1 = actors["SovietEntry1"];
|
||||
sovietEntry2 = actors["SovietEntry2"];
|
||||
sovietEntry3 = actors["SovietEntry3"];
|
||||
sovietentrypoints = new[] { sovietEntry1, sovietEntry2, sovietEntry3 }.Select(p => p.Location).ToArray();
|
||||
sovietrally = actors["SovietRally"];
|
||||
sovietrally1 = actors["SovietRally1"];
|
||||
sovietrally2 = actors["SovietRally2"];
|
||||
sovietrally3 = actors["SovietRally3"];
|
||||
sovietrally4 = actors["SovietRally4"];
|
||||
sovietrally5 = actors["SovietRally5"];
|
||||
sovietrally6 = actors["SovietRally6"];
|
||||
sovietrally8 = actors["SovietRally8"];
|
||||
sovietrallypoints = new[] { sovietrally2, sovietrally4, sovietrally5, sovietrally6 }.Select(p => p.Location).ToArray();
|
||||
alliesbase = actors["AlliesBase"];
|
||||
sovietparadropEntry = actors["SovietParaDropEntry"];
|
||||
sovietparadrop1 = actors["SovietParaDrop1"];
|
||||
sovietparadrop2 = actors["SovietParaDrop2"];
|
||||
sovietparadrop3 = actors["SovietParaDrop3"];
|
||||
barrack1 = actors["barrack1"];
|
||||
factory = actors["Factory"];
|
||||
drum1 = actors["drum1"];
|
||||
drum2 = actors["drum2"];
|
||||
drum3 = actors["drum3"];
|
||||
FranceEntry = actors["FranceEntry"];
|
||||
FranceRally = actors["FranceRally"];
|
||||
FranceparaEntry1 = actors["FranceparaEntry1"];
|
||||
FranceparaEntry2 = actors["FranceparaEntry2"];
|
||||
FranceparaEntry3 = actors["FranceparaEntry3"];
|
||||
newsovietentrypoints = new[] { sovietparadropEntry, sovietEntry3 }.Select(p => p.Location).ToArray();
|
||||
newsovietrallypoints = new[] { sovietrally3, sovietrally4, sovietrally8 }.Select(p => p.Location).ToArray();
|
||||
|
||||
worldRenderer.Viewport.Center(alliesbase.CenterPosition);
|
||||
StartCountDownTimer();
|
||||
SetSovietUnitsToDefensiveStance();
|
||||
world.CreateActor(Camera, new TypeDictionary
|
||||
{
|
||||
new OwnerInit(allies),
|
||||
new LocationInit(sovietrally1.Location),
|
||||
});
|
||||
MissionUtils.PlayMissionMusic();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -261,22 +261,9 @@
|
||||
<Compile Include="Lint\CheckTraitPrerequisites.cs" />
|
||||
<Compile Include="Lint\LintBuildablePrerequisites.cs" />
|
||||
<Compile Include="MadTank.cs" />
|
||||
<Compile Include="Missions\FortLonestarScript.cs" />
|
||||
<Compile Include="Missions\Survival02Script.cs" />
|
||||
<Compile Include="MPStartLocations.cs" />
|
||||
<Compile Include="Mine.cs" />
|
||||
<Compile Include="Minelayer.cs" />
|
||||
<Compile Include="Missions\Allies01Script.cs" />
|
||||
<Compile Include="Missions\Allies02Script.cs" />
|
||||
<Compile Include="Missions\Allies03Script.cs" />
|
||||
<Compile Include="Missions\Allies04Script.cs" />
|
||||
<Compile Include="Missions\CountdownTimer.cs" />
|
||||
<Compile Include="Missions\MissionUtils.cs" />
|
||||
<Compile Include="Missions\MissionWidgets.cs" />
|
||||
<Compile Include="Missions\MonsterTankMadnessScript.cs" />
|
||||
<Compile Include="Missions\Objective.cs" />
|
||||
<Compile Include="Missions\Soviet01ClassicScript.cs" />
|
||||
<Compile Include="Missions\Survival01Script.cs" />
|
||||
<Compile Include="Modifiers\FrozenUnderFog.cs" />
|
||||
<Compile Include="Modifiers\HiddenUnderFog.cs" />
|
||||
<Compile Include="Move\Drag.cs" />
|
||||
@@ -407,7 +394,6 @@
|
||||
<Compile Include="Widgets\Logic\LobbyUtils.cs" />
|
||||
<Compile Include="Widgets\Logic\MainMenuLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\MapChooserLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\MissionObjectivesLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\MusicPlayerLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\ObserverStatsLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\OrderButtonsChromeLogic.cs" />
|
||||
|
||||
@@ -17,7 +17,7 @@ using OpenRA.Effects;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Mods.RA.Air;
|
||||
using OpenRA.Mods.RA.Missions;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Scripting;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
@@ -245,7 +245,25 @@ namespace OpenRA.Mods.RA.Scripting
|
||||
[LuaGlobal]
|
||||
public void PlayRandomMusic()
|
||||
{
|
||||
MissionUtils.PlayMissionMusic();
|
||||
if (!Rules.InstalledMusic.Any() || !Game.Settings.Sound.MapMusic)
|
||||
return;
|
||||
Game.ConnectionStateChanged += StopMusic;
|
||||
PlayMusic();
|
||||
}
|
||||
|
||||
void PlayMusic()
|
||||
{
|
||||
var track = Rules.InstalledMusic.Random(Game.CosmeticRandom);
|
||||
Sound.PlayMusicThen(track.Value, PlayMusic);
|
||||
}
|
||||
|
||||
void StopMusic(OrderManager orderManager)
|
||||
{
|
||||
if (!orderManager.GameStarted)
|
||||
{
|
||||
Sound.StopMusic();
|
||||
Game.ConnectionStateChanged -= StopMusic;
|
||||
}
|
||||
}
|
||||
|
||||
[LuaGlobal]
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2012 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.Linq;
|
||||
using OpenRA.Mods.RA.Missions;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.RA.Widgets.Logic
|
||||
{
|
||||
public class MissionObjectivesLogic
|
||||
{
|
||||
IHasObjectives objectives;
|
||||
Widget primaryPanel;
|
||||
Widget secondaryPanel;
|
||||
Widget primaryTemplate;
|
||||
Widget secondaryTemplate;
|
||||
ButtonWidget objectivesButton;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
public MissionObjectivesLogic(World world, Widget widget)
|
||||
{
|
||||
var gameRoot = Ui.Root.Get("INGAME_ROOT");
|
||||
primaryPanel = widget.Get("PRIMARY_OBJECTIVES");
|
||||
secondaryPanel = widget.Get("SECONDARY_OBJECTIVES");
|
||||
primaryTemplate = primaryPanel.Get("PRIMARY_OBJECTIVE_TEMPLATE");
|
||||
secondaryTemplate = secondaryPanel.Get("SECONDARY_OBJECTIVE_TEMPLATE");
|
||||
|
||||
objectives = world.WorldActor.TraitsImplementing<IHasObjectives>().First();
|
||||
|
||||
objectivesButton = gameRoot.Get<ButtonWidget>("OBJECTIVES_BUTTON");
|
||||
objectivesButton.IsHighlighted = () => Game.LocalTick % 50 < 25 && objectivesButton.Highlighted;
|
||||
objectivesButton.OnClick += () => objectivesButton.Highlighted = false;
|
||||
|
||||
objectives.OnObjectivesUpdated += UpdateObjectives;
|
||||
UpdateObjectives(true);
|
||||
Game.ConnectionStateChanged += RemoveHandlers;
|
||||
}
|
||||
|
||||
public void RemoveHandlers(OrderManager orderManager)
|
||||
{
|
||||
if (!orderManager.GameStarted)
|
||||
{
|
||||
Game.ConnectionStateChanged -= RemoveHandlers;
|
||||
objectives.OnObjectivesUpdated -= UpdateObjectives;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateObjectives(bool notify)
|
||||
{
|
||||
if (notify)
|
||||
objectivesButton.Highlighted = true;
|
||||
|
||||
primaryPanel.RemoveChildren();
|
||||
secondaryPanel.RemoveChildren();
|
||||
|
||||
foreach (var o in objectives.Objectives.Where(o => o.Status != ObjectiveStatus.Inactive))
|
||||
{
|
||||
var objective = o;
|
||||
|
||||
Widget widget;
|
||||
LabelWidget objectiveText;
|
||||
LabelWidget objectiveStatus;
|
||||
|
||||
if (objective.Type == ObjectiveType.Primary)
|
||||
{
|
||||
widget = primaryTemplate.Clone();
|
||||
objectiveText = widget.Get<LabelWidget>("PRIMARY_OBJECTIVE");
|
||||
objectiveStatus = widget.Get<LabelWidget>("PRIMARY_STATUS");
|
||||
SetupWidget(widget, objectiveText, objectiveStatus, objective);
|
||||
primaryPanel.AddChild(widget);
|
||||
}
|
||||
else
|
||||
{
|
||||
widget = secondaryTemplate.Clone();
|
||||
objectiveText = widget.Get<LabelWidget>("SECONDARY_OBJECTIVE");
|
||||
objectiveStatus = widget.Get<LabelWidget>("SECONDARY_STATUS");
|
||||
SetupWidget(widget, objectiveText, objectiveStatus, objective);
|
||||
secondaryPanel.AddChild(widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetupWidget(Widget widget, LabelWidget objectiveText, LabelWidget objectiveStatus, Objective objective)
|
||||
{
|
||||
var font = Game.Renderer.Fonts[objectiveText.Font];
|
||||
var text = WidgetUtils.WrapText(objective.Text, objectiveText.Bounds.Width, font);
|
||||
widget.Bounds.Height = objectiveText.Bounds.Height = objectiveStatus.Bounds.Height = font.Measure(text).Y;
|
||||
objectiveText.GetText = () => text;
|
||||
objectiveStatus.GetText = () => GetObjectiveStatusText(objective.Status);
|
||||
}
|
||||
|
||||
static string GetObjectiveStatusText(ObjectiveStatus status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case ObjectiveStatus.InProgress: return "In Progress";
|
||||
case ObjectiveStatus.Completed: return "Completed";
|
||||
case ObjectiveStatus.Failed: return "Failed";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user