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 "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,446 +0,0 @@
|
||||
Selectable: True
|
||||
|
||||
MapFormat: 6
|
||||
|
||||
RequiresMod: ra
|
||||
|
||||
Title: Allies 01
|
||||
|
||||
Description: Allies' first mission
|
||||
|
||||
Author: Scott_NZ
|
||||
|
||||
Tileset: SNOW
|
||||
|
||||
MapSize: 48,64
|
||||
|
||||
Bounds: 8,8,32,38
|
||||
|
||||
UseAsShellmap: False
|
||||
|
||||
Type: Campaign
|
||||
|
||||
Options:
|
||||
Crates: False
|
||||
Fog: True
|
||||
Shroud: True
|
||||
AllyBuildRadius: False
|
||||
FragileAlliances: False
|
||||
StartingCash: 5000
|
||||
ConfigurableStartingUnits: False
|
||||
Difficulties: Easy,Normal
|
||||
|
||||
Players:
|
||||
PlayerReference@Neutral:
|
||||
Name: Neutral
|
||||
OwnsWorld: True
|
||||
NonCombatant: True
|
||||
Race: allies
|
||||
PlayerReference@Creeps:
|
||||
Name: Creeps
|
||||
NonCombatant: True
|
||||
Race: allies
|
||||
PlayerReference@Allies:
|
||||
Name: Allies
|
||||
Playable: True
|
||||
AllowBots: False
|
||||
Required: True
|
||||
LockRace: True
|
||||
Race: allies
|
||||
LockColor: True
|
||||
ColorRamp: 161,134,200
|
||||
LockSpawn: True
|
||||
LockTeam: True
|
||||
Allies: Creeps
|
||||
Enemies: Soviets
|
||||
PlayerReference@Soviets:
|
||||
Name: Soviets
|
||||
Race: soviet
|
||||
ColorRamp: 3,255,127
|
||||
Enemies: Allies,Creeps
|
||||
|
||||
Actors:
|
||||
Actor1: tc01
|
||||
Location: 13,9
|
||||
Owner: Neutral
|
||||
Actor10: oilb
|
||||
Location: 17,19
|
||||
Owner: Soviets
|
||||
Actor3: t13
|
||||
Location: 17,13
|
||||
Owner: Neutral
|
||||
Actor5: t16
|
||||
Location: 25,9
|
||||
Owner: Neutral
|
||||
Actor4: t17
|
||||
Location: 17,10
|
||||
Owner: Neutral
|
||||
Actor8: brl3
|
||||
Location: 19,21
|
||||
Owner: Soviets
|
||||
Actor7: barl
|
||||
Location: 19,20
|
||||
Owner: Soviets
|
||||
Actor2: brl3
|
||||
Location: 19,19
|
||||
Owner: Soviets
|
||||
Actor6: brl3
|
||||
Location: 20,19
|
||||
Owner: Soviets
|
||||
Actor71: t01
|
||||
Location: 33,31
|
||||
Owner: Neutral
|
||||
Actor11: powr
|
||||
Location: 20,20
|
||||
Owner: Soviets
|
||||
Actor12: powr
|
||||
Location: 24,20
|
||||
Owner: Soviets
|
||||
Actor13: powr
|
||||
Location: 26,20
|
||||
Owner: Soviets
|
||||
Actor14: t08
|
||||
Location: 25,13
|
||||
Owner: Neutral
|
||||
Actor15: fenc
|
||||
Location: 27,18
|
||||
Owner: Soviets
|
||||
Actor16: fenc
|
||||
Location: 28,18
|
||||
Owner: Soviets
|
||||
Actor17: fenc
|
||||
Location: 27,17
|
||||
Owner: Soviets
|
||||
Actor18: jeep
|
||||
Location: 21,13
|
||||
Owner: Allies
|
||||
Actor19: jeep
|
||||
Location: 22,13
|
||||
Owner: Allies
|
||||
Actor20: jeep
|
||||
Location: 23,13
|
||||
Owner: Allies
|
||||
Actor22: e2
|
||||
Location: 21,19
|
||||
Owner: Soviets
|
||||
Actor23: e1
|
||||
Location: 17,23
|
||||
Owner: Soviets
|
||||
Actor28: e1
|
||||
Location: 23,12
|
||||
Owner: Allies
|
||||
Actor26: e1
|
||||
Location: 22,12
|
||||
Owner: Allies
|
||||
Actor25: e1
|
||||
Location: 21,12
|
||||
Owner: Allies
|
||||
Actor65: fenc
|
||||
Location: 33,33
|
||||
Owner: Soviets
|
||||
Actor31: mine
|
||||
Location: 33,14
|
||||
Owner: Neutral
|
||||
Actor32: tc03
|
||||
Location: 28,13
|
||||
Owner: Neutral
|
||||
Actor33: v04
|
||||
Location: 35,8
|
||||
Owner: Neutral
|
||||
Actor34: tsla
|
||||
Location: 30,22
|
||||
Owner: Soviets
|
||||
Actor35: proc
|
||||
Location: 32,21
|
||||
Owner: Soviets
|
||||
Actor37: e1
|
||||
Location: 23,24
|
||||
Owner: Soviets
|
||||
Actor0: e2
|
||||
Location: 22,27
|
||||
Owner: Soviets
|
||||
Actor21: e2
|
||||
Location: 20,27
|
||||
Owner: Soviets
|
||||
Actor40: weap
|
||||
Location: 24,25
|
||||
Owner: Soviets
|
||||
Actor41: fact
|
||||
Location: 28,25
|
||||
Owner: Soviets
|
||||
Actor42: barr
|
||||
Location: 20,28
|
||||
Owner: Soviets
|
||||
Actor43: silo
|
||||
Location: 18,28
|
||||
Owner: Soviets
|
||||
Actor44: dome
|
||||
Location: 26,28
|
||||
Owner: Soviets
|
||||
Actor45: t12
|
||||
Location: 15,19
|
||||
Owner: Neutral
|
||||
Actor46: t12
|
||||
Location: 15,25
|
||||
Owner: Neutral
|
||||
Actor47: fenc
|
||||
Location: 14,27
|
||||
Owner: Soviets
|
||||
Actor48: fenc
|
||||
Location: 14,28
|
||||
Owner: Soviets
|
||||
Actor49: fenc
|
||||
Location: 14,29
|
||||
Owner: Soviets
|
||||
Actor50: fenc
|
||||
Location: 14,30
|
||||
Owner: Soviets
|
||||
Actor51: tsla
|
||||
Location: 19,30
|
||||
Owner: Soviets
|
||||
Actor52: tsla
|
||||
Location: 26,30
|
||||
Owner: Soviets
|
||||
Actor53: fenc
|
||||
Location: 14,31
|
||||
Owner: Soviets
|
||||
Actor54: fenc
|
||||
Location: 15,31
|
||||
Owner: Soviets
|
||||
Actor55: fenc
|
||||
Location: 16,31
|
||||
Owner: Soviets
|
||||
Actor56: fenc
|
||||
Location: 17,31
|
||||
Owner: Soviets
|
||||
Actor57: fenc
|
||||
Location: 17,32
|
||||
Owner: Soviets
|
||||
Actor70: fenc
|
||||
Location: 35,33
|
||||
Owner: Soviets
|
||||
Actor59: e1
|
||||
Location: 23,31
|
||||
Owner: Soviets
|
||||
Actor60: e1
|
||||
Location: 21,31
|
||||
Owner: Soviets
|
||||
Actor61: powr
|
||||
Location: 34,30
|
||||
Owner: Soviets
|
||||
Actor58: powr
|
||||
Location: 36,27
|
||||
Owner: Soviets
|
||||
Actor64: t05
|
||||
Location: 32,27
|
||||
Owner: Neutral
|
||||
Actor62: powr
|
||||
Location: 36,30
|
||||
Owner: Soviets
|
||||
Actor63: fenc
|
||||
Location: 32,33
|
||||
Owner: Soviets
|
||||
Actor30: powr
|
||||
Location: 34,27
|
||||
Owner: Soviets
|
||||
Actor67: fenc
|
||||
Location: 34,33
|
||||
Owner: Soviets
|
||||
Actor68: c1
|
||||
Location: 28,16
|
||||
Owner: Creeps
|
||||
Actor69: c2
|
||||
Location: 30,17
|
||||
Owner: Creeps
|
||||
Actor72: e1
|
||||
Location: 35,29
|
||||
Owner: Soviets
|
||||
Actor66: e1
|
||||
Location: 31,29
|
||||
Owner: Soviets
|
||||
Actor9: barl
|
||||
Location: 18,21
|
||||
Owner: Soviets
|
||||
Actor74: tc02
|
||||
Location: 11,23
|
||||
Owner: Neutral
|
||||
Actor73: tc03
|
||||
Location: 37,22
|
||||
Owner: Neutral
|
||||
Actor75: t02
|
||||
Location: 29,31
|
||||
Owner: Neutral
|
||||
Actor76: t02
|
||||
Location: 12,34
|
||||
Owner: Neutral
|
||||
Actor79: fenc
|
||||
Location: 14,21
|
||||
Owner: Soviets
|
||||
Actor78: fenc
|
||||
Location: 14,22
|
||||
Owner: Soviets
|
||||
Actor77: fenc
|
||||
Location: 14,23
|
||||
Owner: Soviets
|
||||
Actor85: 3tnk
|
||||
Location: 17,25
|
||||
Owner: Soviets
|
||||
Facing: 0
|
||||
Actor92: wood
|
||||
Location: 34,9
|
||||
Owner: Neutral
|
||||
Actor94: c1
|
||||
Location: 19,24
|
||||
Owner: Soviets
|
||||
Actor95: c2
|
||||
Location: 31,23
|
||||
Owner: Soviets
|
||||
InsertionLZ: waypoint
|
||||
Location: 22,10
|
||||
Owner: Neutral
|
||||
Lab: stek.autotargetignore
|
||||
Location: 20,24
|
||||
Owner: Soviets
|
||||
Actor24: e2
|
||||
Location: 27,24
|
||||
Owner: Soviets
|
||||
ShipSpawnPoint: waypoint
|
||||
Location: 23,45
|
||||
Owner: Neutral
|
||||
ShipMovePoint: waypoint
|
||||
Location: 23,40
|
||||
Owner: Neutral
|
||||
InsertionLZEntryPoint: waypoint
|
||||
Location: 22,4
|
||||
Owner: Neutral
|
||||
Actor27: e2
|
||||
Location: 27,27
|
||||
Owner: Soviets
|
||||
ChinookExitPoint: waypoint
|
||||
Location: 55,11
|
||||
Owner: Neutral
|
||||
ExtractionLZEntryPoint: waypoint
|
||||
Location: 31,48
|
||||
Owner: Neutral
|
||||
SovietAttackEntryPoint2: waypoint
|
||||
Location: 39,11
|
||||
Owner: Neutral
|
||||
ExtractionLZ: waypoint
|
||||
Location: 13,12
|
||||
Owner: Neutral
|
||||
Actor36: e1
|
||||
Location: 20,12
|
||||
Owner: Allies
|
||||
Actor38: e1
|
||||
Location: 24,12
|
||||
Owner: Allies
|
||||
Actor39: e3
|
||||
Location: 21,11
|
||||
Owner: Allies
|
||||
Actor80: e3
|
||||
Location: 22,11
|
||||
Owner: Allies
|
||||
Actor81: e3
|
||||
Location: 23,11
|
||||
Owner: Allies
|
||||
SovietAttackEntryPoint1: waypoint
|
||||
Location: 8,30
|
||||
Owner: Neutral
|
||||
Actor29: kenn
|
||||
Location: 23,28
|
||||
Owner: Soviets
|
||||
Actor1000: camera.large
|
||||
Location: 1,1
|
||||
Owner: Soviets
|
||||
|
||||
Smudges:
|
||||
|
||||
Rules:
|
||||
Player:
|
||||
-ConquestVictoryConditions:
|
||||
World:
|
||||
-CrateSpawner:
|
||||
-SpawnMPUnits:
|
||||
-MPStartLocations:
|
||||
Allies01Script:
|
||||
MissionObjectivesPanel:
|
||||
ObjectivesPanel: MISSION_OBJECTIVES
|
||||
TRAN:
|
||||
-Selectable:
|
||||
RevealsShroud:
|
||||
Range: 0c0
|
||||
E7:
|
||||
AutoTarget:
|
||||
InitialStance: Defend
|
||||
Passenger:
|
||||
Weight: 0
|
||||
EINSTEIN:
|
||||
Passenger:
|
||||
Weight: 0
|
||||
STEK.AutoTargetIgnore:
|
||||
Inherits: STEK
|
||||
RenderBuilding:
|
||||
Image: STEK
|
||||
Tooltip:
|
||||
Icon: STEK
|
||||
AutoTargetIgnore:
|
||||
^Vehicle:
|
||||
GivesBounty:
|
||||
Percentage: 0
|
||||
^Tank:
|
||||
GivesBounty:
|
||||
Percentage: 0
|
||||
^Infantry:
|
||||
GivesBounty:
|
||||
Percentage: 0
|
||||
^Ship:
|
||||
GivesBounty:
|
||||
Percentage: 0
|
||||
^Plane:
|
||||
GivesBounty:
|
||||
Percentage: 0
|
||||
^Building:
|
||||
GivesBounty:
|
||||
Percentage: 0
|
||||
CAMERA.Large:
|
||||
Inherits: CAMERA
|
||||
RevealsShroud:
|
||||
Range: 1000c0
|
||||
|
||||
Sequences:
|
||||
|
||||
VoxelSequences:
|
||||
|
||||
Weapons:
|
||||
8Inch:
|
||||
ROF: 200
|
||||
Range: 25c0
|
||||
Burst: 2
|
||||
Report: TURRET1.AUD
|
||||
Projectile: Bullet
|
||||
Speed: 512
|
||||
High: true
|
||||
Angle: 62
|
||||
Inaccuracy: 4c170
|
||||
Image: 120MM
|
||||
ContrailLength: 10
|
||||
Warhead:
|
||||
Spread: 213
|
||||
Versus:
|
||||
None: 60%
|
||||
Wood: 75%
|
||||
Light: 60%
|
||||
Heavy: 25%
|
||||
Explosion: large_explosion
|
||||
WaterExplosion: large_splash
|
||||
InfDeath: 2
|
||||
SmudgeType: Crater
|
||||
Damage: 500
|
||||
ImpactSound: kaboom12.aud
|
||||
WaterImpactSound: splash9.aud
|
||||
|
||||
Voices:
|
||||
|
||||
Notifications:
|
||||
|
||||
Translations:
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,953 +0,0 @@
|
||||
Selectable: True
|
||||
|
||||
MapFormat: 6
|
||||
|
||||
RequiresMod: ra
|
||||
|
||||
Title: Soviet 01 (Classic)
|
||||
|
||||
Description: Lesson in Blood
|
||||
|
||||
Author: Westwood Studios
|
||||
|
||||
Tileset: SNOW
|
||||
|
||||
MapSize: 128,128
|
||||
|
||||
Bounds: 32,47,32,38
|
||||
|
||||
UseAsShellmap: False
|
||||
|
||||
Type: Campaign
|
||||
|
||||
Options:
|
||||
Crates: False
|
||||
Fog: True
|
||||
Shroud: True
|
||||
AllyBuildRadius: False
|
||||
FragileAlliances: False
|
||||
StartingCash: 0
|
||||
ConfigurableStartingUnits: False
|
||||
|
||||
Players:
|
||||
PlayerReference@GoodGuy:
|
||||
Name: GoodGuy
|
||||
Race: allies
|
||||
ColorRamp: 161,134,200
|
||||
Allies: France,Germany,Turkey
|
||||
Enemies: USSR
|
||||
PlayerReference@France:
|
||||
Name: France
|
||||
Race: allies
|
||||
ColorRamp: 115,115,143
|
||||
Allies: GoodGuy,Germany,Turkey
|
||||
Enemies: USSR
|
||||
PlayerReference@Germany:
|
||||
Name: Germany
|
||||
Race: allies
|
||||
ColorRamp: 0,0,80
|
||||
Allies: GoodGuy,France,Turkey
|
||||
Enemies: USSR
|
||||
PlayerReference@USSR:
|
||||
Name: USSR
|
||||
Playable: True
|
||||
AllowBots: False
|
||||
Required: True
|
||||
LockRace: True
|
||||
Race: soviet
|
||||
LockColor: True
|
||||
ColorRamp: 3,255,127
|
||||
LockSpawn: True
|
||||
LockTeam: True
|
||||
Enemies: GoodGuy,France,Germany,Turkey
|
||||
PlayerReference@Turkey:
|
||||
Name: Turkey
|
||||
Race: allies
|
||||
ColorRamp: 14,123,167
|
||||
Allies: GoodGuy,France,Germany
|
||||
Enemies: USSR
|
||||
PlayerReference@Neutral:
|
||||
Name: Neutral
|
||||
OwnsWorld: True
|
||||
NonCombatant: True
|
||||
Race: allies
|
||||
PlayerReference@Creeps:
|
||||
Name: Creeps
|
||||
NonCombatant: True
|
||||
Race: allies
|
||||
|
||||
Actors:
|
||||
Actor0: wood
|
||||
Location: 44,50
|
||||
Owner: Neutral
|
||||
Actor1: wood
|
||||
Location: 44,51
|
||||
Owner: Neutral
|
||||
Actor2: wood
|
||||
Location: 44,52
|
||||
Owner: Neutral
|
||||
Actor3: wood
|
||||
Location: 44,53
|
||||
Owner: Neutral
|
||||
Actor4: wood
|
||||
Location: 45,53
|
||||
Owner: Neutral
|
||||
Actor5: wood
|
||||
Location: 56,65
|
||||
Owner: Neutral
|
||||
Actor6: v14
|
||||
Location: 54,66
|
||||
Owner: Neutral
|
||||
Actor7: v14
|
||||
Location: 55,66
|
||||
Owner: Neutral
|
||||
Actor8: wood
|
||||
Location: 56,66
|
||||
Owner: Neutral
|
||||
Actor9: wood
|
||||
Location: 53,67
|
||||
Owner: Neutral
|
||||
Actor10: wood
|
||||
Location: 55,67
|
||||
Owner: Neutral
|
||||
Actor11: wood
|
||||
Location: 56,67
|
||||
Owner: Neutral
|
||||
Actor12: wood
|
||||
Location: 45,69
|
||||
Owner: Neutral
|
||||
Actor13: wood
|
||||
Location: 46,69
|
||||
Owner: Neutral
|
||||
Actor14: wood
|
||||
Location: 47,69
|
||||
Owner: Neutral
|
||||
Actor15: wood
|
||||
Location: 45,70
|
||||
Owner: Neutral
|
||||
Actor16: wood
|
||||
Location: 51,70
|
||||
Owner: Neutral
|
||||
Actor17: wood
|
||||
Location: 53,71
|
||||
Owner: Neutral
|
||||
Actor18: wood
|
||||
Location: 52,72
|
||||
Owner: Neutral
|
||||
Actor19: wood
|
||||
Location: 53,72
|
||||
Owner: Neutral
|
||||
Actor20: t16
|
||||
Location: 53,52
|
||||
Owner: Neutral
|
||||
Actor21: tc03
|
||||
Location: 60,61
|
||||
Owner: Neutral
|
||||
Actor22: tc01
|
||||
Location: 48,47
|
||||
Owner: Neutral
|
||||
Actor23: t06
|
||||
Location: 73,59
|
||||
Owner: Neutral
|
||||
Actor24: t01
|
||||
Location: 49,74
|
||||
Owner: Neutral
|
||||
Actor25: t14
|
||||
Location: 60,69
|
||||
Owner: Neutral
|
||||
Actor26: t16
|
||||
Location: 59,72
|
||||
Owner: Neutral
|
||||
Actor27: t14
|
||||
Location: 60,72
|
||||
Owner: Neutral
|
||||
Actor28: t07
|
||||
Location: 62,72
|
||||
Owner: Neutral
|
||||
Actor29: t10
|
||||
Location: 54,74
|
||||
Owner: Neutral
|
||||
Actor30: tc02
|
||||
Location: 46,49
|
||||
Owner: Neutral
|
||||
Actor31: t01
|
||||
Location: 53,57
|
||||
Owner: Neutral
|
||||
Actor32: tc05
|
||||
Location: 41,51
|
||||
Owner: Neutral
|
||||
Actor33: t06
|
||||
Location: 44,53
|
||||
Owner: Neutral
|
||||
Actor34: t01
|
||||
Location: 44,70
|
||||
Owner: Neutral
|
||||
Actor35: t16
|
||||
Location: 52,72
|
||||
Owner: Neutral
|
||||
Actor36: tc02
|
||||
Location: 32,51
|
||||
Owner: Neutral
|
||||
Actor37: tc04
|
||||
Location: 32,55
|
||||
Owner: Neutral
|
||||
Actor38: tc05
|
||||
Location: 32,60
|
||||
Owner: Neutral
|
||||
Actor39: tc02
|
||||
Location: 42,57
|
||||
Owner: Neutral
|
||||
Actor40: tc02
|
||||
Location: 43,68
|
||||
Owner: Neutral
|
||||
Actor41: tc01
|
||||
Location: 42,67
|
||||
Owner: Neutral
|
||||
Actor42: tc04
|
||||
Location: 32,72
|
||||
Owner: Neutral
|
||||
Actor43: tc03
|
||||
Location: 51,77
|
||||
Owner: Neutral
|
||||
Actor44: tc01
|
||||
Location: 39,72
|
||||
Owner: Neutral
|
||||
Actor45: t17
|
||||
Location: 35,76
|
||||
Owner: Neutral
|
||||
Actor46: t15
|
||||
Location: 59,75
|
||||
Owner: Neutral
|
||||
Actor47: tc03
|
||||
Location: 35,65
|
||||
Owner: Neutral
|
||||
Actor48: t01
|
||||
Location: 35,56
|
||||
Owner: Neutral
|
||||
Actor49: t10
|
||||
Location: 47,59
|
||||
Owner: Neutral
|
||||
Actor50: t08
|
||||
Location: 48,64
|
||||
Owner: Neutral
|
||||
Actor51: barl
|
||||
Location: 33,54
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor52: brl3
|
||||
Location: 57,53
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor53: v08
|
||||
Location: 41,54
|
||||
Owner: France
|
||||
Health: 0.5195313
|
||||
Facing: 0
|
||||
Actor54: v07.civilians
|
||||
Location: 54,65
|
||||
Owner: France
|
||||
Health: 0.4375
|
||||
Facing: 0
|
||||
Actor55: v07
|
||||
Location: 38,52
|
||||
Owner: France
|
||||
Health: 0.4375
|
||||
Facing: 0
|
||||
Actor56: v06
|
||||
Location: 46,51
|
||||
Owner: France
|
||||
Health: 0.9921875
|
||||
Facing: 0
|
||||
Actor57: v05
|
||||
Location: 36,55
|
||||
Owner: France
|
||||
Health: 0.5
|
||||
Facing: 0
|
||||
Actor58: v04
|
||||
Location: 35,51
|
||||
Owner: France
|
||||
Health: 0.3515625
|
||||
Facing: 0
|
||||
Actor59: v02
|
||||
Location: 36,57
|
||||
Owner: France
|
||||
Health: 0.5625
|
||||
Facing: 0
|
||||
Actor60: brl3
|
||||
Location: 34,52
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor61: barl
|
||||
Location: 57,54
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor62: barl
|
||||
Location: 55,54
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor63: brl3
|
||||
Location: 51,72
|
||||
Owner: Germany
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor64: brl3
|
||||
Location: 51,71
|
||||
Owner: Germany
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor65: brl3
|
||||
Location: 47,71
|
||||
Owner: Germany
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor66: barl
|
||||
Location: 46,71
|
||||
Owner: Germany
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor67: barl
|
||||
Location: 47,70
|
||||
Owner: Germany
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor68: brl3
|
||||
Location: 43,50
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor69: brl3
|
||||
Location: 45,52
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor70: barl
|
||||
Location: 41,51
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor71: barl
|
||||
Location: 50,72
|
||||
Owner: Germany
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor72: barl
|
||||
Location: 42,50
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Airfield1: afld.noproduction
|
||||
Location: 35,81
|
||||
Owner: USSR
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor74: powr
|
||||
Location: 43,82
|
||||
Owner: USSR
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor75: barl
|
||||
Location: 56,53
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor76: barl
|
||||
Location: 58,53
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor77: brl3
|
||||
Location: 59,53
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor78: brl3
|
||||
Location: 54,53
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor79: barl
|
||||
Location: 59,56
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor80: brl3
|
||||
Location: 48,66
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor81: barl
|
||||
Location: 45,65
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor82: barl
|
||||
Location: 34,57
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor83: brl3
|
||||
Location: 35,58
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor84: barl
|
||||
Location: 46,67
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor85: barl
|
||||
Location: 48,67
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor86: brl3
|
||||
Location: 38,65
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor87: barl
|
||||
Location: 40,52
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor88: barl
|
||||
Location: 39,64
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor89: brl3
|
||||
Location: 41,53
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor90: brl3
|
||||
Location: 46,66
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Airfield2: afld.noproduction
|
||||
Location: 39,77
|
||||
Owner: USSR
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor92: powr
|
||||
Location: 45,82
|
||||
Owner: USSR
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Airfield3: afld.noproduction
|
||||
Location: 37,79
|
||||
Owner: USSR
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor94: barl
|
||||
Location: 35,56
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor95: brl3
|
||||
Location: 38,64
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor96: brl3
|
||||
Location: 34,55
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor97: barl
|
||||
Location: 35,55
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor98: barl
|
||||
Location: 45,50
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor99: v04
|
||||
Location: 58,54
|
||||
Owner: France
|
||||
Health: 0.4140625
|
||||
Facing: 0
|
||||
Actor100: v02
|
||||
Location: 56,54
|
||||
Owner: France
|
||||
Health: 0.7070313
|
||||
Facing: 0
|
||||
Actor101: dome
|
||||
Location: 45,79
|
||||
Owner: USSR
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor102: barl
|
||||
Location: 46,61
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor103: brl3
|
||||
Location: 43,66
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor104: barl
|
||||
Location: 43,67
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor105: brl3
|
||||
Location: 59,57
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor106: barl
|
||||
Location: 57,58
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor107: barl
|
||||
Location: 58,58
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor108: brl3
|
||||
Location: 59,58
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor109: brl3
|
||||
Location: 56,58
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor110: barl
|
||||
Location: 56,59
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor111: barl
|
||||
Location: 56,60
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor112: barl
|
||||
Location: 41,68
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor113: barl
|
||||
Location: 42,67
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor114: brl3
|
||||
Location: 49,55
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor115: barl
|
||||
Location: 48,55
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor116: barl
|
||||
Location: 47,56
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor117: brl3
|
||||
Location: 46,56
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor118: pbox.e1
|
||||
Location: 46,55
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor119: pbox.e1
|
||||
Location: 48,54
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor120: barl
|
||||
Location: 34,51
|
||||
Owner: GoodGuy
|
||||
Health: 1
|
||||
Facing: 0
|
||||
Actor121: v05.civilians
|
||||
Location: 48,62
|
||||
Owner: France
|
||||
Health: 0.4140625
|
||||
Facing: 0
|
||||
Church: v01
|
||||
Location: 40,63
|
||||
Owner: France
|
||||
Health: 0.5390625
|
||||
Facing: 0
|
||||
Actor123: jeep
|
||||
Location: 46,52
|
||||
Owner: France
|
||||
Health: 0.6640625
|
||||
Facing: 96
|
||||
StartJeep: jeep
|
||||
Location: 44,76
|
||||
Owner: France
|
||||
Health: 0.5195313
|
||||
Facing: 32
|
||||
Actor125: jeep
|
||||
Location: 55,57
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 160
|
||||
Actor126: jeep
|
||||
Location: 39,65
|
||||
Owner: France
|
||||
Health: 0.625
|
||||
Facing: 64
|
||||
Actor127: c9
|
||||
Location: 50,64
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 192
|
||||
SubCell: 1
|
||||
Actor128: c8
|
||||
Location: 47,61
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 0
|
||||
SubCell: 3
|
||||
Actor129: c8
|
||||
Location: 41,50
|
||||
Owner: Turkey
|
||||
Health: 1
|
||||
Facing: 224
|
||||
SubCell: 3
|
||||
Actor130: c6
|
||||
Location: 46,61
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 128
|
||||
SubCell: 2
|
||||
Actor131: c5
|
||||
Location: 46,61
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 0
|
||||
SubCell: 1
|
||||
Actor132: c4
|
||||
Location: 44,67
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 96
|
||||
SubCell: 1
|
||||
Actor133: c2
|
||||
Location: 40,54
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 160
|
||||
SubCell: 2
|
||||
Actor134: c2
|
||||
Location: 45,61
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 64
|
||||
SubCell: 4
|
||||
Actor135: e1
|
||||
Location: 54,60
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 160
|
||||
SubCell: 4
|
||||
Actor136: e1
|
||||
Location: 49,60
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 128
|
||||
SubCell: 2
|
||||
Actor137: c5
|
||||
Location: 45,51
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 224
|
||||
SubCell: 0
|
||||
Actor138: e1
|
||||
Location: 34,58
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 96
|
||||
SubCell: 0
|
||||
Actor139: e1
|
||||
Location: 53,54
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 128
|
||||
SubCell: 2
|
||||
Actor140: e1
|
||||
Location: 58,56
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 128
|
||||
SubCell: 1
|
||||
Actor141: e1
|
||||
Location: 58,52
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 160
|
||||
SubCell: 0
|
||||
Actor142: e1
|
||||
Location: 54,64
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 160
|
||||
SubCell: 3
|
||||
Actor143: c7
|
||||
Location: 56,54
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 0
|
||||
SubCell: 3
|
||||
Actor144: e1
|
||||
Location: 40,51
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 160
|
||||
SubCell: 0
|
||||
Actor145: e1
|
||||
Location: 35,53
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 96
|
||||
SubCell: 1
|
||||
Actor146: e1
|
||||
Location: 35,54
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 0
|
||||
SubCell: 4
|
||||
Actor147: e1
|
||||
Location: 43,64
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 96
|
||||
SubCell: 0
|
||||
Actor148: e1
|
||||
Location: 56,63
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 192
|
||||
SubCell: 2
|
||||
Actor149: e1
|
||||
Location: 40,67
|
||||
Owner: France
|
||||
Health: 1
|
||||
Facing: 32
|
||||
SubCell: 4
|
||||
Actor150: e1
|
||||
Location: 42,81
|
||||
Owner: USSR
|
||||
Health: 0.1367188
|
||||
Facing: 0
|
||||
SubCell: 2
|
||||
waypoint3: waypoint
|
||||
Location: 47,51
|
||||
Owner: Neutral
|
||||
waypoint6: waypoint
|
||||
Location: 58,55
|
||||
Owner: Neutral
|
||||
waypoint10: waypoint
|
||||
Location: 48,62
|
||||
Owner: Neutral
|
||||
waypoint14: waypoint
|
||||
Location: 66,47
|
||||
Owner: Neutral
|
||||
waypoint15: waypoint
|
||||
Location: 58,54
|
||||
Owner: Neutral
|
||||
StartJeepMovePoint: waypoint
|
||||
Location: 47,66
|
||||
Owner: Neutral
|
||||
waypoint17: waypoint
|
||||
Location: 49,68
|
||||
Owner: Neutral
|
||||
waypoint18: waypoint
|
||||
Location: 54,64
|
||||
Owner: Neutral
|
||||
waypoint19: waypoint
|
||||
Location: 55,64
|
||||
Owner: Neutral
|
||||
ParadropEntryPoint1: waypoint
|
||||
Location: 67,65
|
||||
Owner: Neutral
|
||||
waypoint21: waypoint
|
||||
Location: 58,57
|
||||
Owner: Neutral
|
||||
waypoint22: waypoint
|
||||
Location: 66,73
|
||||
Owner: Neutral
|
||||
waypoint23: waypoint
|
||||
Location: 49,51
|
||||
Owner: Neutral
|
||||
waypoint24: waypoint
|
||||
Location: 54,60
|
||||
Owner: Neutral
|
||||
waypoint25: waypoint
|
||||
Location: 35,59
|
||||
Owner: Neutral
|
||||
waypoint37: waypoint
|
||||
Location: 61,68
|
||||
Owner: Neutral
|
||||
waypoint44: waypoint
|
||||
Location: 34,47
|
||||
Owner: Neutral
|
||||
waypoint57: waypoint
|
||||
Location: 38,57
|
||||
Owner: Neutral
|
||||
waypoint67: waypoint
|
||||
Location: 39,59
|
||||
Owner: Neutral
|
||||
waypoint72: waypoint
|
||||
Location: 47,70
|
||||
Owner: Neutral
|
||||
waypoint78: waypoint
|
||||
Location: 39,67
|
||||
Owner: Neutral
|
||||
waypoint79: waypoint
|
||||
Location: 52,60
|
||||
Owner: Neutral
|
||||
waypoint81: waypoint
|
||||
Location: 42,82
|
||||
Owner: Neutral
|
||||
waypoint82: waypoint
|
||||
Location: 44,77
|
||||
Owner: Neutral
|
||||
ParadropEntryPoint2: waypoint
|
||||
Location: 32,70
|
||||
Owner: Neutral
|
||||
ParadropPoint2: waypoint
|
||||
Location: 47,65
|
||||
Owner: Neutral
|
||||
ParadropPoint1: waypoint
|
||||
Location: 47,67
|
||||
Owner: Neutral
|
||||
waypoint96: waypoint
|
||||
Location: 37,58
|
||||
Owner: Neutral
|
||||
waypoint98: waypoint
|
||||
Location: 44,79
|
||||
Owner: Neutral
|
||||
Actor1000: camera.large
|
||||
Location: 1,1
|
||||
Owner: France
|
||||
|
||||
Smudges:
|
||||
|
||||
Rules:
|
||||
Player:
|
||||
-ConquestVictoryConditions:
|
||||
World:
|
||||
-CrateSpawner:
|
||||
-SpawnMPUnits:
|
||||
-MPStartLocations:
|
||||
Soviet01ClassicScript:
|
||||
MissionObjectivesPanel:
|
||||
ObjectivesPanel: MISSION_OBJECTIVES
|
||||
V01:
|
||||
ContainsCrate:
|
||||
CRATE:
|
||||
GiveCashCrateAction:
|
||||
SelectionShares: 0
|
||||
LevelUpCrateAction:
|
||||
SelectionShares: 0
|
||||
ExplodeCrateAction@fire:
|
||||
SelectionShares: 0
|
||||
ExplodeCrateAction@boom:
|
||||
SelectionShares: 0
|
||||
ExplodeCrateAction@nuke:
|
||||
SelectionShares: 0
|
||||
HideMapCrateAction:
|
||||
SelectionShares: 0
|
||||
HealUnitsCrateAction:
|
||||
SelectionShares: 10000
|
||||
RevealMapCrateAction:
|
||||
SelectionShares: 0
|
||||
SupportPowerCrateAction@parabombs:
|
||||
SelectionShares: 0
|
||||
GiveMcvCrateAction:
|
||||
SelectionShares: 0
|
||||
GiveUnitCrateAction@jeep:
|
||||
SelectionShares: 0
|
||||
GiveUnitCrateAction@arty:
|
||||
SelectionShares: 0
|
||||
GiveUnitCrateAction@v2rl:
|
||||
SelectionShares: 0
|
||||
GiveUnitCrateAction@1tnk:
|
||||
SelectionShares: 0
|
||||
GiveUnitCrateAction@2tnk:
|
||||
SelectionShares: 0
|
||||
GiveUnitCrateAction@3tnk:
|
||||
SelectionShares: 0
|
||||
GiveUnitCrateAction@4tnk:
|
||||
SelectionShares: 0
|
||||
AFLD.NoProduction:
|
||||
Inherits: ^Building
|
||||
Valued:
|
||||
Cost: 500
|
||||
Tooltip:
|
||||
Name: Airfield
|
||||
Building:
|
||||
Power: -20
|
||||
Footprint: xxx xxx
|
||||
Dimensions: 3,2
|
||||
Health:
|
||||
HP: 1000
|
||||
Armor:
|
||||
Type: Wood
|
||||
RevealsShroud:
|
||||
Range: 7c0
|
||||
Exit@1:
|
||||
SpawnOffset: 0,170,0
|
||||
ExitCell: 1,1
|
||||
Facing: 192
|
||||
RenderBuilding:
|
||||
Image: AFLD
|
||||
BelowUnits:
|
||||
Reservable:
|
||||
YAK:
|
||||
Plane:
|
||||
RearmBuildings: afld.noproduction
|
||||
JEEP:
|
||||
Explodes:
|
||||
V05.Civilians:
|
||||
Inherits: V05
|
||||
RenderBuilding:
|
||||
Image: V05
|
||||
Soviet01ClassicContainsActors:
|
||||
Actors: c3, c4, c7
|
||||
V07.Civilians:
|
||||
Inherits: V07
|
||||
RenderBuilding:
|
||||
Image: V07
|
||||
Soviet01ClassicContainsActors:
|
||||
Actors: c1, c6
|
||||
CAMERA.Large:
|
||||
Inherits: CAMERA
|
||||
RevealsShroud:
|
||||
Range: 1000c0
|
||||
|
||||
Sequences:
|
||||
|
||||
VoxelSequences:
|
||||
|
||||
Weapons:
|
||||
|
||||
Voices:
|
||||
|
||||
Notifications:
|
||||
|
||||
Translations:
|
||||
Reference in New Issue
Block a user