Remove hardcoded missions

This commit is contained in:
ScottNZ
2014-03-08 00:26:09 +13:00
parent 1d9681a1d2
commit 856120f2b2
34 changed files with 20 additions and 17510 deletions

View File

@@ -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();
}
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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));
}
}
}
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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!");
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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; } }
}
}

View File

@@ -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;
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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" />

View File

@@ -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]

View File

@@ -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 "";
}
}
}
}