Merge pull request #3372 from ScottNZ/missions

Mission objectives refactoring
This commit is contained in:
Matthias Mailänder
2013-06-05 09:37:44 -07:00
11 changed files with 148 additions and 175 deletions

View File

@@ -26,19 +26,13 @@ namespace OpenRA.Mods.RA.Missions
{ {
public event Action<bool> OnObjectivesUpdated = notify => { }; public event Action<bool> OnObjectivesUpdated = notify => { };
public IEnumerable<Objective> Objectives { get { return objectives.Values; } } public IEnumerable<Objective> Objectives { get { return new[] { findEinstein, extractEinstein }; } }
Dictionary<int, Objective> objectives = new Dictionary<int, Objective> Objective findEinstein = new Objective(ObjectiveType.Primary, FindEinsteinText, ObjectiveStatus.InProgress);
{ Objective extractEinstein = new Objective(ObjectiveType.Primary, ExtractEinsteinText, ObjectiveStatus.Inactive);
{ FindEinsteinID, new Objective(ObjectiveType.Primary, FindEinstein, ObjectiveStatus.InProgress) },
{ ExtractEinsteinID, new Objective(ObjectiveType.Primary, ExtractEinstein, ObjectiveStatus.Inactive) }
};
const int FindEinsteinID = 0; const string FindEinsteinText = "Find Einstein. Tanya and Einstein must survive.";
const int ExtractEinsteinID = 1; const string ExtractEinsteinText = "Wait for the helicopter and extract Einstein. Tanya and Einstein must survive.";
const string FindEinstein = "Find Einstein. Tanya and Einstein must survive.";
const string ExtractEinstein = "Wait for the helicopter and extract Einstein. Tanya and Einstein must survive.";
Player allies; Player allies;
Player soviets; Player soviets;
@@ -94,19 +88,19 @@ namespace OpenRA.Mods.RA.Missions
if (world.FrameNumber % 1000 == 0) if (world.FrameNumber % 1000 == 0)
Sound.Play(Taunts[world.SharedRandom.Next(Taunts.Length)]); Sound.Play(Taunts[world.SharedRandom.Next(Taunts.Length)]);
if (objectives[FindEinsteinID].Status == ObjectiveStatus.InProgress) if (findEinstein.Status == ObjectiveStatus.InProgress)
{ {
if (AlliesControlLab()) if (AlliesControlLab())
LabSecured(); LabSecured();
if (lab.Destroyed) if (lab.IsDead())
{ {
objectives[FindEinsteinID].Status = ObjectiveStatus.Failed; findEinstein.Status = ObjectiveStatus.Failed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionFailed("Einstein was killed."); MissionFailed("Einstein was killed.");
} }
} }
if (objectives[ExtractEinsteinID].Status == ObjectiveStatus.InProgress) if (extractEinstein.Status == ObjectiveStatus.InProgress)
{ {
if (difficulty != "Easy") if (difficulty != "Easy")
{ {
@@ -126,25 +120,25 @@ namespace OpenRA.Mods.RA.Missions
} }
if (einsteinChinook != null) if (einsteinChinook != null)
{ {
if (einsteinChinook.Destroyed) if (einsteinChinook.IsDead())
{ {
objectives[ExtractEinsteinID].Status = ObjectiveStatus.Failed; extractEinstein.Status = ObjectiveStatus.Failed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionFailed("The extraction helicopter was destroyed."); MissionFailed("The extraction helicopter was destroyed.");
} }
else if (!world.Map.IsInMap(einsteinChinook.Location) && einsteinChinook.Trait<Cargo>().Passengers.Contains(einstein)) else if (!world.Map.IsInMap(einsteinChinook.Location) && einsteinChinook.Trait<Cargo>().Passengers.Contains(einstein))
{ {
objectives[ExtractEinsteinID].Status = ObjectiveStatus.Completed; extractEinstein.Status = ObjectiveStatus.Completed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionAccomplished("Einstein was rescued"); MissionAccomplished("Einstein was rescued");
} }
} }
} }
if (tanya != null && tanya.Destroyed) if (tanya != null && tanya.IsDead())
MissionFailed("Tanya was killed."); MissionFailed("Tanya was killed.");
else if (einstein != null && einstein.Destroyed) else if (einstein != null && einstein.IsDead())
MissionFailed("Einstein was killed."); MissionFailed("Einstein was killed.");
MissionUtils.CapOre(soviets); MissionUtils.CapOre(soviets);
@@ -158,9 +152,10 @@ namespace OpenRA.Mods.RA.Missions
SendShips(); SendShips();
lab.QueueActivity(new Transform(lab, "stek") { SkipMakeAnims = true }); lab.QueueActivity(new Transform(lab, "stek") { SkipMakeAnims = true });
objectives[FindEinsteinID].Status = ObjectiveStatus.Completed; findEinstein.Status = ObjectiveStatus.Completed;
objectives[ExtractEinsteinID].Status = ObjectiveStatus.InProgress; extractEinstein.Status = ObjectiveStatus.InProgress;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
currentAttackWaveFrameNumber = world.FrameNumber; currentAttackWaveFrameNumber = world.FrameNumber;
if (difficulty == "Easy") if (difficulty == "Easy")

View File

@@ -28,27 +28,19 @@ namespace OpenRA.Mods.RA.Missions
{ {
public event Action<bool> OnObjectivesUpdated = notify => { }; public event Action<bool> OnObjectivesUpdated = notify => { };
public IEnumerable<Objective> Objectives { get { return objectives.Values; } } public IEnumerable<Objective> Objectives { get { return new[] { findEinstein, destroySamSites, extractEinstein, maintainPresence, fewDeaths }; } }
Dictionary<int, Objective> objectives = new Dictionary<int, Objective>() Objective findEinstein = new Objective(ObjectiveType.Primary, FindEinsteinText, ObjectiveStatus.InProgress);
{ Objective destroySamSites = new Objective(ObjectiveType.Primary, DestroySamSitesText, ObjectiveStatus.InProgress);
{ FindEinsteinID, new Objective(ObjectiveType.Primary, FindEinstein, ObjectiveStatus.InProgress) }, Objective extractEinstein = new Objective(ObjectiveType.Primary, ExtractEinsteinText, ObjectiveStatus.Inactive);
{ DestroySamSitesID, new Objective(ObjectiveType.Primary, DestroySamSites, ObjectiveStatus.InProgress) }, Objective maintainPresence = new Objective(ObjectiveType.Primary, MaintainPresenceText, ObjectiveStatus.InProgress);
{ ExtractEinsteinID, new Objective(ObjectiveType.Primary, ExtractEinstein, ObjectiveStatus.Inactive) }, Objective fewDeaths = new Objective(ObjectiveType.Secondary, "", ObjectiveStatus.InProgress);
{ MaintainPresenceID, new Objective(ObjectiveType.Primary, MaintainPresence, ObjectiveStatus.InProgress) },
{ FewDeathsID, new Objective(ObjectiveType.Secondary, "", ObjectiveStatus.InProgress) }
};
const int FindEinsteinID = 0; const string FindEinsteinText = "Find Einstein's crashed helicopter. Tanya must survive.";
const int DestroySamSitesID = 1; const string DestroySamSitesText = "Destroy the SAM sites. Tanya must survive.";
const int ExtractEinsteinID = 2; const string ExtractEinsteinText = "Wait for the helicopter and extract Einstein. Tanya and Einstein must survive.";
const int MaintainPresenceID = 3; const string MaintainPresenceText = "Maintain an Allied presence in the area. Reinforcements will arrive soon.";
const int FewDeathsID = 4;
const string FindEinstein = "Find Einstein's crashed helicopter. Tanya must survive.";
const string DestroySamSites = "Destroy the SAM sites. Tanya must survive.";
const string ExtractEinstein = "Wait for the helicopter and extract Einstein. Tanya and Einstein must survive.";
const string MaintainPresence = "Maintain an Allied presence in the area. Reinforcements will arrive soon.";
const string FewDeathsTemplate = "Lose fewer than {0}/{1} units."; const string FewDeathsTemplate = "Lose fewer than {0}/{1} units.";
const int DeathsThreshold = 200; const int DeathsThreshold = 200;
@@ -195,44 +187,45 @@ namespace OpenRA.Mods.RA.Missions
UpdateDeaths(); UpdateDeaths();
if (objectives[FindEinsteinID].Status == ObjectiveStatus.InProgress) if (findEinstein.Status == ObjectiveStatus.InProgress)
{ {
if (AlliesNearTown()) if (AlliesNearTown())
{ {
objectives[FindEinsteinID].Status = ObjectiveStatus.Completed; findEinstein.Status = ObjectiveStatus.Completed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
TransferTownUnitsToAllies(); TransferTownUnitsToAllies();
SovietsAttackTown(); SovietsAttackTown();
} }
} }
if (objectives[DestroySamSitesID].Status == ObjectiveStatus.InProgress) if (destroySamSites.Status == ObjectiveStatus.InProgress)
{ {
if (sams.All(s => s.IsDead() || s.Owner != soviets)) if (sams.All(s => s.IsDead() || s.Owner != soviets))
{ {
objectives[DestroySamSitesID].Status = ObjectiveStatus.Completed; destroySamSites.Status = ObjectiveStatus.Completed;
objectives[ExtractEinsteinID].Status = ObjectiveStatus.InProgress; extractEinstein.Status = ObjectiveStatus.InProgress;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
world.CreateActor(SignalFlareName, new TypeDictionary { new OwnerInit(allies1), new LocationInit(extractionLZ.Location) }); world.CreateActor(SignalFlareName, new TypeDictionary { new OwnerInit(allies1), new LocationInit(extractionLZ.Location) });
Sound.Play("flaren1.aud"); Sound.Play("flaren1.aud");
ExtractEinsteinAtLZ(); ExtractEinsteinAtLZ();
} }
} }
if (objectives[ExtractEinsteinID].Status == ObjectiveStatus.InProgress && einsteinChinook != null) if (extractEinstein.Status == ObjectiveStatus.InProgress && einsteinChinook != null)
{ {
if (einsteinChinook.IsDead()) if (einsteinChinook.IsDead())
{ {
objectives[ExtractEinsteinID].Status = ObjectiveStatus.Failed; extractEinstein.Status = ObjectiveStatus.Failed;
objectives[MaintainPresenceID].Status = ObjectiveStatus.Failed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionFailed("The extraction helicopter was destroyed."); MissionFailed("The extraction helicopter was destroyed.");
} }
else if (!world.Map.IsInMap(einsteinChinook.Location) && einsteinChinook.Trait<Cargo>().Passengers.Contains(einstein)) else if (!world.Map.IsInMap(einsteinChinook.Location) && einsteinChinook.Trait<Cargo>().Passengers.Contains(einstein))
{ {
objectives[ExtractEinsteinID].Status = ObjectiveStatus.Completed; extractEinstein.Status = ObjectiveStatus.Completed;
objectives[MaintainPresenceID].Status = ObjectiveStatus.Completed; maintainPresence.Status = ObjectiveStatus.Completed;
if (objectives[FewDeathsID].Status == ObjectiveStatus.InProgress) if (fewDeaths.Status == ObjectiveStatus.InProgress)
objectives[FewDeathsID].Status = ObjectiveStatus.Completed; fewDeaths.Status = ObjectiveStatus.Completed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionAccomplished("Einstein was rescued."); MissionAccomplished("Einstein was rescued.");
@@ -250,7 +243,7 @@ namespace OpenRA.Mods.RA.Missions
if (!w.FindAliveCombatantActorsInBox(alliedBaseTopLeft.ToPPos(), alliedBaseBottomRight.ToPPos()) if (!w.FindAliveCombatantActorsInBox(alliedBaseTopLeft.ToPPos(), alliedBaseBottomRight.ToPPos())
.Any(a => (a.Owner == allies || a.Owner == allies2) && (a.HasTrait<Building>() && !a.HasTrait<Wall>()) || a.HasTrait<BaseBuilding>())) .Any(a => (a.Owner == allies || a.Owner == allies2) && (a.HasTrait<Building>() && !a.HasTrait<Wall>()) || a.HasTrait<BaseBuilding>()))
{ {
objectives[MaintainPresenceID].Status = ObjectiveStatus.Failed; maintainPresence.Status = ObjectiveStatus.Failed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionFailed("The Allied reinforcements have been defeated."); MissionFailed("The Allied reinforcements have been defeated.");
} }
@@ -260,11 +253,11 @@ namespace OpenRA.Mods.RA.Missions
void UpdateDeaths() void UpdateDeaths()
{ {
var unitDeaths = allies1.Deaths + allies2.Deaths; var unitDeaths = allies1.Deaths + allies2.Deaths;
objectives[FewDeathsID].Text = FewDeathsTemplate.F(unitDeaths, DeathsThreshold); fewDeaths.Text = FewDeathsTemplate.F(unitDeaths, DeathsThreshold);
OnObjectivesUpdated(false); OnObjectivesUpdated(false);
if (unitDeaths >= DeathsThreshold && objectives[FewDeathsID].Status == ObjectiveStatus.InProgress) if (unitDeaths >= DeathsThreshold && fewDeaths.Status == ObjectiveStatus.InProgress)
{ {
objectives[FewDeathsID].Status = ObjectiveStatus.Failed; fewDeaths.Status = ObjectiveStatus.Failed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
} }
} }

View File

@@ -28,29 +28,23 @@ namespace OpenRA.Mods.RA.Missions
{ {
public event Action<bool> OnObjectivesUpdated = notify => { }; public event Action<bool> OnObjectivesUpdated = notify => { };
public IEnumerable<Objective> Objectives { get { return objectives.Values; } } public IEnumerable<Objective> Objectives { get { return new[] { evacuateUnits, destroyAirbases, evacuateMgg }; } }
Dictionary<int, Objective> objectives = new Dictionary<int, Objective> Objective evacuateUnits = new Objective(ObjectiveType.Primary, EvacuateUnitsText, ObjectiveStatus.InProgress);
{ Objective destroyAirbases = new Objective(ObjectiveType.Secondary, DestroyAirbasesText, ObjectiveStatus.InProgress);
{ EvacuateID, new Objective(ObjectiveType.Primary, Evacuate, ObjectiveStatus.InProgress) }, Objective evacuateMgg = new Objective(ObjectiveType.Secondary, EvacuateMggText, ObjectiveStatus.InProgress);
{ AirbaseID, new Objective(ObjectiveType.Secondary, Airbase, ObjectiveStatus.InProgress) },
{ GapGeneratorID, new Objective(ObjectiveType.Secondary, GapGenerator , ObjectiveStatus.InProgress) }
};
const int EvacuateID = 0; const string EvacuateUnitsText = "Following the rescue of Einstein, the Allies are now being flanked from both sides."
const int AirbaseID = 1;
const int GapGeneratorID = 2;
const string Evacuate = "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."; + " Evacuate {0} units before the remaining Allied forces in the area are wiped out.";
const string Airbase = "Destroy the nearby Soviet airbases."; const string DestroyAirbasesText = "Destroy the nearby Soviet airbases.";
const string GapGenerator = "Einstein has recently developed a technology which allows us to obscure units from the enemy." 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."; + " Evacuate at least one prototype mobile gap generator intact.";
const string ShortEvacuateTemplate = "{0}/{1} units evacuated";
int unitsEvacuatedThreshold; int unitsEvacuatedThreshold;
int unitsEvacuated; int unitsEvacuated;
InfoWidget evacuateWidget; InfoWidget evacuateWidget;
const string ShortEvacuateTemplate = "{0}/{1} units evacuated";
World world; World world;
Player allies1; Player allies1;
@@ -185,7 +179,7 @@ namespace OpenRA.Mods.RA.Missions
if (world.FrameNumber % 25 == 0) if (world.FrameNumber % 25 == 0)
ManageSovietUnits(); ManageSovietUnits();
if (objectives[AirbaseID].Status != ObjectiveStatus.Completed) if (destroyAirbases.Status != ObjectiveStatus.Completed)
{ {
if (world.FrameNumber % 25 == 0) if (world.FrameNumber % 25 == 0)
BuildSovietAircraft(); BuildSovietAircraft();
@@ -196,12 +190,12 @@ namespace OpenRA.Mods.RA.Missions
EvacuateAlliedUnits(exit1TopLeft.CenterLocation, exit1BottomRight.CenterLocation, exit1ExitPoint.Location); EvacuateAlliedUnits(exit1TopLeft.CenterLocation, exit1BottomRight.CenterLocation, exit1ExitPoint.Location);
EvacuateAlliedUnits(exit2TopLeft.CenterLocation, exit2BottomRight.CenterLocation, exit2ExitPoint.Location); EvacuateAlliedUnits(exit2TopLeft.CenterLocation, exit2BottomRight.CenterLocation, exit2ExitPoint.Location);
CheckSovietAirbase(); CheckSovietAirbases();
if (!world.Actors.Any(a => (a.Owner == allies1 || a.Owner == allies2) && a.IsInWorld && !a.IsDead() if (!world.Actors.Any(a => (a.Owner == allies1 || a.Owner == allies2) && a.IsInWorld && !a.IsDead()
&& ((a.HasTrait<Building>() && !a.HasTrait<Wall>()) || a.HasTrait<BaseBuilding>()))) && ((a.HasTrait<Building>() && !a.HasTrait<Wall>()) || a.HasTrait<BaseBuilding>())))
{ {
objectives[EvacuateID].Status = ObjectiveStatus.Failed; evacuateUnits.Status = ObjectiveStatus.Failed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionFailed("The remaining Allied forces in the area have been wiped out."); MissionFailed("The remaining Allied forces in the area have been wiped out.");
} }
@@ -266,11 +260,11 @@ namespace OpenRA.Mods.RA.Missions
return world.Actors.Where(a => a.HasTrait<AttackPlane>() && a.Owner == soviets && a.IsInWorld && !a.IsDead()); return world.Actors.Where(a => a.HasTrait<AttackPlane>() && a.Owner == soviets && a.IsInWorld && !a.IsDead());
} }
void CheckSovietAirbase() void CheckSovietAirbases()
{ {
if (objectives[AirbaseID].Status != ObjectiveStatus.Completed && sovietAirfields.All(a => a.IsDead() || a.Owner != soviets)) if (destroyAirbases.Status != ObjectiveStatus.Completed && sovietAirfields.All(a => a.IsDead() || a.Owner != soviets))
{ {
objectives[AirbaseID].Status = ObjectiveStatus.Completed; destroyAirbases.Status = ObjectiveStatus.Completed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
} }
} }
@@ -349,9 +343,9 @@ namespace OpenRA.Mods.RA.Missions
void UpdateUnitsEvacuated() void UpdateUnitsEvacuated()
{ {
evacuateWidget.Text = ShortEvacuateTemplate.F(unitsEvacuated, unitsEvacuatedThreshold); evacuateWidget.Text = ShortEvacuateTemplate.F(unitsEvacuated, unitsEvacuatedThreshold);
if (objectives[EvacuateID].Status == ObjectiveStatus.InProgress && unitsEvacuated >= unitsEvacuatedThreshold) if (evacuateUnits.Status == ObjectiveStatus.InProgress && unitsEvacuated >= unitsEvacuatedThreshold)
{ {
objectives[EvacuateID].Status = ObjectiveStatus.Completed; evacuateUnits.Status = ObjectiveStatus.Completed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionAccomplished("The remaining Allied forces in the area have evacuated."); MissionAccomplished("The remaining Allied forces in the area have evacuated.");
} }
@@ -369,9 +363,9 @@ namespace OpenRA.Mods.RA.Missions
unitsEvacuated++; unitsEvacuated++;
var createsShroud = unit.TraitOrDefault<CreatesShroud>(); var createsShroud = unit.TraitOrDefault<CreatesShroud>();
if (createsShroud != null && objectives[GapGeneratorID].Status == ObjectiveStatus.InProgress) if (createsShroud != null && evacuateMgg.Status == ObjectiveStatus.InProgress)
{ {
objectives[GapGeneratorID].Status = ObjectiveStatus.Completed; evacuateMgg.Status = ObjectiveStatus.Completed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
} }
@@ -416,7 +410,7 @@ namespace OpenRA.Mods.RA.Missions
sovietParadropTicks = difficulty == "Hard" ? 1500 * 17 : 1500 * 20; sovietParadropTicks = difficulty == "Hard" ? 1500 * 17 : 1500 * 20;
sovietUnits2Ticks = difficulty == "Hard" ? 1500 * 12 : 1500 * 15; sovietUnits2Ticks = difficulty == "Hard" ? 1500 * 12 : 1500 * 15;
objectives[EvacuateID].Text = objectives[EvacuateID].Text.F(unitsEvacuatedThreshold); evacuateUnits.Text = evacuateUnits.Text.F(unitsEvacuatedThreshold);
allies = w.Players.Single(p => p.InternalName == "Allies"); allies = w.Players.Single(p => p.InternalName == "Allies");
soviets = w.Players.Single(p => p.InternalName == "Soviets"); soviets = w.Players.Single(p => p.InternalName == "Soviets");

View File

@@ -17,7 +17,6 @@ using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Buildings; using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Move; using OpenRA.Mods.RA.Move;
using OpenRA.Mods.RA.Render; using OpenRA.Mods.RA.Render;
using OpenRA.Graphics;
using OpenRA.Traits; using OpenRA.Traits;
using OpenRA.Widgets; using OpenRA.Widgets;
@@ -29,20 +28,16 @@ namespace OpenRA.Mods.RA.Missions
{ {
public event Action<bool> OnObjectivesUpdated = notify => { }; public event Action<bool> OnObjectivesUpdated = notify => { };
public IEnumerable<Objective> Objectives { get { return objectives.Values; } } public IEnumerable<Objective> Objectives { get { return new[] { infiltrateLab, destroyBase }; } }
Dictionary<int, Objective> objectives = new Dictionary<int, Objective> Objective infiltrateLab = new Objective(ObjectiveType.Primary, "", ObjectiveStatus.InProgress);
{ Objective destroyBase = new Objective(ObjectiveType.Primary, DestroyBaseText, ObjectiveStatus.Inactive);
{ InfiltrateID, new Objective(ObjectiveType.Primary, "", ObjectiveStatus.InProgress) },
{ DestroyID, new Objective(ObjectiveType.Primary, Destroy, ObjectiveStatus.Inactive) }
};
const int InfiltrateID = 0; const string InfiltrateLabTemplate = "The Soviets are currently developing a new defensive system named the \"Iron Curtain\" at their main research laboratory."
const int DestroyID = 1;
const string Destroy = "Secure the laboratory and destroy the rest of the Soviet base. Ensure that the laboratory is not destroyed.";
const string Infiltrate = "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."; + " 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 hijackTruck;
Actor baseGuard; Actor baseGuard;
Actor baseGuardMovePos; Actor baseGuardMovePos;
@@ -175,7 +170,7 @@ namespace OpenRA.Mods.RA.Missions
if (allies1Spy.IsDead() || (allies2Spy != null && allies2Spy.IsDead())) if (allies1Spy.IsDead() || (allies2Spy != null && allies2Spy.IsDead()))
{ {
objectives[InfiltrateID].Status = ObjectiveStatus.Failed; infiltrateLab.Status = ObjectiveStatus.Failed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionFailed("{0} spy was killed.".F(allies1 != allies2 ? "A" : "The")); MissionFailed("{0} spy was killed.".F(allies1 != allies2 ? "A" : "The"));
} }
@@ -184,13 +179,13 @@ namespace OpenRA.Mods.RA.Missions
else if (!world.Actors.Any(a => (a.Owner == allies1 || a.Owner == allies2) && !a.IsDead() else if (!world.Actors.Any(a => (a.Owner == allies1 || a.Owner == allies2) && !a.IsDead()
&& (a.HasTrait<Building>() && !a.HasTrait<Wall>()) || a.HasTrait<BaseBuilding>())) && (a.HasTrait<Building>() && !a.HasTrait<Wall>()) || a.HasTrait<BaseBuilding>()))
{ {
objectives[DestroyID].Status = ObjectiveStatus.Failed; destroyBase.Status = ObjectiveStatus.Failed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionFailed("The remaining Allied forces in the area have been wiped out."); MissionFailed("The remaining Allied forces in the area have been wiped out.");
} }
else if (SovietBaseDestroyed() && objectives[InfiltrateID].Status == ObjectiveStatus.Completed) else if (SovietBaseDestroyed() && infiltrateLab.Status == ObjectiveStatus.Completed)
{ {
objectives[DestroyID].Status = ObjectiveStatus.Completed; destroyBase.Status = ObjectiveStatus.Completed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionAccomplished("The Soviet research laboratory has been secured successfully."); MissionAccomplished("The Soviet research laboratory has been secured successfully.");
} }
@@ -214,8 +209,8 @@ namespace OpenRA.Mods.RA.Missions
void OnDestroyBaseTimerExpired(CountdownTimer t) void OnDestroyBaseTimerExpired(CountdownTimer t)
{ {
if (SovietBaseDestroyed() && objectives[InfiltrateID].Status == ObjectiveStatus.Completed) return; if (SovietBaseDestroyed() && infiltrateLab.Status == ObjectiveStatus.Completed) return;
objectives[DestroyID].Status = ObjectiveStatus.Failed; destroyBase.Status = ObjectiveStatus.Failed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionFailed("The Soviet research laboratory was not secured in time."); MissionFailed("The Soviet research laboratory was not secured in time.");
} }
@@ -240,8 +235,8 @@ namespace OpenRA.Mods.RA.Missions
if (allies1SpyInfiltratedLab && (allies2SpyInfiltratedLab || allies2Spy == null)) if (allies1SpyInfiltratedLab && (allies2SpyInfiltratedLab || allies2Spy == null))
{ {
objectives[InfiltrateID].Status = ObjectiveStatus.Completed; infiltrateLab.Status = ObjectiveStatus.Completed;
objectives[DestroyID].Status = ObjectiveStatus.InProgress; destroyBase.Status = ObjectiveStatus.InProgress;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
frameInfiltrated = world.FrameNumber; frameInfiltrated = world.FrameNumber;
@@ -362,7 +357,7 @@ namespace OpenRA.Mods.RA.Missions
soviets = w.Players.Single(p => p.InternalName == "Soviets"); soviets = w.Players.Single(p => p.InternalName == "Soviets");
creeps = w.Players.Single(p => p.InternalName == "Creeps"); creeps = w.Players.Single(p => p.InternalName == "Creeps");
objectives[InfiltrateID].Text = Infiltrate.F(allies1 != allies2 ? "spies" : "spy"); infiltrateLab.Text = InfiltrateLabTemplate.F(allies1 != allies2 ? "spies" : "spy");
destroyBaseTicks = difficulty == "Hard" ? 1500 * 25 : difficulty == "Normal" ? 1500 * 28 : 1500 * 31; destroyBaseTicks = difficulty == "Hard" ? 1500 * 25 : difficulty == "Normal" ? 1500 * 28 : 1500 * 31;

View File

@@ -8,6 +8,10 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Air; using OpenRA.Mods.RA.Air;
@@ -15,10 +19,6 @@ using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Move; using OpenRA.Mods.RA.Move;
using OpenRA.Network; using OpenRA.Network;
using OpenRA.Traits; using OpenRA.Traits;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
namespace OpenRA.Mods.RA.Missions namespace OpenRA.Mods.RA.Missions
{ {

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.RA.Missions
var font = Game.Renderer.Fonts["Bold"]; var font = Game.Renderer.Fonts["Bold"];
var text = Format.F(WidgetUtils.FormatTime(Timer.TicksLeft)); var text = Format.F(WidgetUtils.FormatTime(Timer.TicksLeft));
var pos = new float2(Game.viewport.Width * 0.5f - font.Measure(text).X / 2, Game.viewport.Height * 0.1f); var pos = new float2(Game.viewport.Width * 0.5f - font.Measure(text).X / 2, Game.viewport.Height * 0.1f);
font.DrawTextWithContrast(text, pos, Timer.TicksLeft <= 25 * 10 && Game.LocalTick % 50 < 25 ? Color.Red : Color.White, Color.Black, 1); font.DrawTextWithContrast(text, pos, Timer.TicksLeft <= 25 * 60 && Game.LocalTick % 50 < 25 ? Color.Red : Color.White, Color.Black, 1);
} }
} }

View File

@@ -40,23 +40,15 @@ namespace OpenRA.Mods.RA.Missions
public event Action<bool> OnObjectivesUpdated = notify => { }; public event Action<bool> OnObjectivesUpdated = notify => { };
public IEnumerable<Objective> Objectives { get { return objectives.Values; } } public IEnumerable<Objective> Objectives { get { return new[] { findOutpost, evacuateDemitri, infiltrateRadarDome }; } }
Dictionary<int, Objective> objectives = new Dictionary<int, Objective> Objective findOutpost = new Objective(ObjectiveType.Primary, FindOutpostText, ObjectiveStatus.InProgress);
{ Objective evacuateDemitri = new Objective(ObjectiveType.Primary, EvacuateDemitriText, ObjectiveStatus.InProgress);
{ FindOutpostID, new Objective(ObjectiveType.Primary, FindOutpost, ObjectiveStatus.InProgress) }, Objective infiltrateRadarDome = new Objective(ObjectiveType.Primary, InfiltrateRadarDomeText, ObjectiveStatus.InProgress);
{ EvacuateDemitriID, new Objective(ObjectiveType.Primary, EvacuateDemitri, ObjectiveStatus.InProgress) },
{ InfiltrateRadarDomeID, new Objective(ObjectiveType.Primary, InfiltrateRadarDome, ObjectiveStatus.InProgress) },
};
const int FindOutpostID = 0; const string FindOutpostText = "Find our outpost and start repairs on it.";
const string FindOutpost = "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 int EvacuateDemitriID = 1;
const string EvacuateDemitri = "Find and evacuate Dr. Demitri. He is missing -- likely hiding in the village to the far south.";
const int InfiltrateRadarDomeID = 2;
const string InfiltrateRadarDome = "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." //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." // + " We planned to extract him while the Soviets were testing their new weapon, but something has gone wrong."
@@ -142,7 +134,7 @@ namespace OpenRA.Mods.RA.Missions
{ {
SetupAlliedBase(actorsInBase); SetupAlliedBase(actorsInBase);
baseTransferredTick = world.FrameNumber; baseTransferredTick = world.FrameNumber;
objectives[FindOutpostID].Status = ObjectiveStatus.Completed; findOutpost.Status = ObjectiveStatus.Completed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
} }
} }
@@ -181,13 +173,13 @@ namespace OpenRA.Mods.RA.Missions
superTanksDestroyed = true; superTanksDestroyed = true;
} }
} }
if (objectives[EvacuateDemitriID].Status != ObjectiveStatus.Completed) if (evacuateDemitri.Status != ObjectiveStatus.Completed)
{ {
if (demitri == null) if (demitri == null)
{ {
if (demitriChurch.IsDead()) if (demitriChurch.IsDead())
{ {
objectives[EvacuateDemitriID].Status = ObjectiveStatus.Failed; evacuateDemitri.Status = ObjectiveStatus.Failed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionFailed("Dr. Demitri was killed."); MissionFailed("Dr. Demitri was killed.");
} }
@@ -204,7 +196,7 @@ namespace OpenRA.Mods.RA.Missions
} }
else if (demitri.IsDead()) else if (demitri.IsDead())
{ {
objectives[EvacuateDemitriID].Status = ObjectiveStatus.Failed; evacuateDemitri.Status = ObjectiveStatus.Failed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionFailed("Dr. Demitri was killed."); MissionFailed("Dr. Demitri was killed.");
} }
@@ -212,7 +204,7 @@ namespace OpenRA.Mods.RA.Missions
{ {
demitriLZFlare.Destroy(); demitriLZFlare.Destroy();
SpawnAndMoveAlliedBaseUnits(info.FirstBaseUnits); SpawnAndMoveAlliedBaseUnits(info.FirstBaseUnits);
objectives[EvacuateDemitriID].Status = ObjectiveStatus.Completed; evacuateDemitri.Status = ObjectiveStatus.Completed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
} }
} }
@@ -223,11 +215,11 @@ namespace OpenRA.Mods.RA.Missions
} }
if (superTankDomeInfiltratedTick == -1 && superTankDome.IsDead()) if (superTankDomeInfiltratedTick == -1 && superTankDome.IsDead())
{ {
objectives[InfiltrateRadarDomeID].Status = ObjectiveStatus.Failed; infiltrateRadarDome.Status = ObjectiveStatus.Failed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionFailed("The Soviet radar dome was destroyed."); MissionFailed("The Soviet radar dome was destroyed.");
} }
if (superTanksDestroyed && objectives[EvacuateDemitriID].Status == ObjectiveStatus.Completed) if (superTanksDestroyed && evacuateDemitri.Status == ObjectiveStatus.Completed)
{ {
MissionAccomplished("Dr. Demitri has been extracted and the super tanks have been dealt with."); MissionAccomplished("Dr. Demitri has been extracted and the super tanks have been dealt with.");
} }
@@ -298,7 +290,7 @@ namespace OpenRA.Mods.RA.Missions
superTankDomeInfiltratedTick = world.FrameNumber; superTankDomeInfiltratedTick = world.FrameNumber;
objectives[InfiltrateRadarDomeID].Status = ObjectiveStatus.Completed; infiltrateRadarDome.Status = ObjectiveStatus.Completed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
} }

View File

@@ -27,15 +27,11 @@ namespace OpenRA.Mods.RA.Missions
{ {
public event Action<bool> OnObjectivesUpdated = notify => { }; public event Action<bool> OnObjectivesUpdated = notify => { };
public IEnumerable<Objective> Objectives { get { return objectives.Values; } } public IEnumerable<Objective> Objectives { get { return new[] { destroy }; } }
Dictionary<int, Objective> objectives = new Dictionary<int, Objective> Objective destroy = new Objective(ObjectiveType.Primary, DestroyText, ObjectiveStatus.InProgress);
{
{ DestroyID, new Objective(ObjectiveType.Primary, Destroy, ObjectiveStatus.InProgress) }
};
const int DestroyID = 0; const string DestroyText = "A pitiful excuse for resistance has blockaded itself in this village."
const string Destroy = "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." + " 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."; + " You will have Yak aircraft to use in teaching these rebels a lesson.";
@@ -80,12 +76,12 @@ namespace OpenRA.Mods.RA.Missions
var unitsAndBuildings = world.Actors.Where(a => !a.IsDead() && a.IsInWorld && (a.HasTrait<Mobile>() || (a.HasTrait<Building>() && !a.HasTrait<Wall>()))); 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)) if (!unitsAndBuildings.Any(a => a.Owner == france))
{ {
objectives[DestroyID].Status = ObjectiveStatus.Completed; destroy.Status = ObjectiveStatus.Completed;
MissionAccomplished("We destroyed the resistance."); MissionAccomplished("We destroyed the resistance.");
} }
else if (!unitsAndBuildings.Any(a => a.Owner == ussr)) else if (!unitsAndBuildings.Any(a => a.Owner == ussr))
{ {
objectives[DestroyID].Status = ObjectiveStatus.Failed; destroy.Status = ObjectiveStatus.Failed;
MissionFailed("We were destroyed by the resistance."); MissionFailed("We were destroyed by the resistance.");
} }
if (!startJeepParadropped && startJeep.IsDead()) if (!startJeepParadropped && startJeep.IsDead())

View File

@@ -8,15 +8,15 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Move; using OpenRA.Mods.RA.Move;
using OpenRA.Traits; using OpenRA.Traits;
using OpenRA.Widgets; using OpenRA.Widgets;
using OpenRA.Mods.RA.Buildings;
namespace OpenRA.Mods.RA.Missions namespace OpenRA.Mods.RA.Missions
{ {
@@ -26,19 +26,13 @@ namespace OpenRA.Mods.RA.Missions
{ {
public event Action<bool> OnObjectivesUpdated = notify => { }; public event Action<bool> OnObjectivesUpdated = notify => { };
public IEnumerable<Objective> Objectives { get { return objectives.Values; } } public IEnumerable<Objective> Objectives { get { return new[] { maintainPresence, destroySoviets }; } }
Dictionary<int, Objective> objectives = new Dictionary<int, Objective> Objective maintainPresence = new Objective(ObjectiveType.Primary, MaintainPresenceText, ObjectiveStatus.InProgress);
{ Objective destroySoviets = new Objective(ObjectiveType.Primary, DestroySovietsText, ObjectiveStatus.Inactive);
{ maintainPresenceID, new Objective(ObjectiveType.Primary, maintainPresence, ObjectiveStatus.InProgress) },
{ destroySovietsID, new Objective(ObjectiveType.Primary, destroySoviets, ObjectiveStatus.Inactive) }
};
const int maintainPresenceID = 0; const string MaintainPresenceText = "Enforce your position and hold-out the onslaught until reinforcements arrive. We must not lose the base!";
const int destroySovietsID = 1; const string DestroySovietsText = "Take control of French reinforcements and dismantle the nearby Soviet base.";
const string maintainPresence = "Enforce your position and hold-out the onslaught until reinforcements arrive. We must not lose the base!";
const string destroySoviets = "Take control of french reinforcements and dismantle the nearby Soviet base.";
Player allies; Player allies;
Player soviets; Player soviets;
@@ -155,11 +149,11 @@ namespace OpenRA.Mods.RA.Missions
spawningInfantry = false; spawningInfantry = false;
} }
if (objectives[destroySovietsID].Status == ObjectiveStatus.InProgress) if (destroySoviets.Status == ObjectiveStatus.InProgress)
{ {
if (barrack1.Destroyed) if (barrack1.Destroyed)
{ {
objectives[destroySovietsID].Status = ObjectiveStatus.Completed; destroySoviets.Status = ObjectiveStatus.Completed;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
MissionAccomplished("The French forces have survived and dismantled the soviet presence in the area!"); MissionAccomplished("The French forces have survived and dismantled the soviet presence in the area!");
} }
@@ -273,8 +267,8 @@ namespace OpenRA.Mods.RA.Missions
{ {
survivalTimerWidget.Visible = false; survivalTimerWidget.Visible = false;
SendReinforcements(); SendReinforcements();
objectives[maintainPresenceID].Status = ObjectiveStatus.Completed; maintainPresence.Status = ObjectiveStatus.Completed;
objectives[destroySovietsID].Status = ObjectiveStatus.InProgress; destroySoviets.Status = ObjectiveStatus.InProgress;
OnObjectivesUpdated(true); OnObjectivesUpdated(true);
} }

View File

@@ -56,31 +56,47 @@ namespace OpenRA.Mods.RA.Widgets.Logic
public void UpdateObjectives(bool notify) public void UpdateObjectives(bool notify)
{ {
if (notify) if (notify)
{
objectivesButton.Highlighted = true; objectivesButton.Highlighted = true;
}
primaryPanel.RemoveChildren(); primaryPanel.RemoveChildren();
secondaryPanel.RemoveChildren(); secondaryPanel.RemoveChildren();
foreach (var o in objectives.Objectives.Where(o => o.Status != ObjectiveStatus.Inactive)) foreach (var o in objectives.Objectives.Where(o => o.Status != ObjectiveStatus.Inactive))
{ {
var objective = o; var objective = o;
if (objective.Type == ObjectiveType.Secondary)
Widget widget;
LabelWidget objectiveText;
LabelWidget objectiveStatus;
if (objective.Type == ObjectiveType.Primary)
{ {
var template = secondaryTemplate.Clone(); widget = primaryTemplate.Clone();
template.Get<LabelWidget>("SECONDARY_OBJECTIVE").GetText = () => objective.Text; objectiveText = widget.Get<LabelWidget>("PRIMARY_OBJECTIVE");
template.Get<LabelWidget>("SECONDARY_STATUS").GetText = () => GetObjectiveStatusText(objective.Status); objectiveStatus = widget.Get<LabelWidget>("PRIMARY_STATUS");
secondaryPanel.AddChild(template); SetupWidget(widget, objectiveText, objectiveStatus, objective);
primaryPanel.AddChild(widget);
} }
else else
{ {
var template = primaryTemplate.Clone(); widget = secondaryTemplate.Clone();
template.Get<LabelWidget>("PRIMARY_OBJECTIVE").GetText = () => objective.Text; objectiveText = widget.Get<LabelWidget>("SECONDARY_OBJECTIVE");
template.Get<LabelWidget>("PRIMARY_STATUS").GetText = () => GetObjectiveStatusText(objective.Status); objectiveStatus = widget.Get<LabelWidget>("SECONDARY_STATUS");
primaryPanel.AddChild(template); 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) static string GetObjectiveStatusText(ObjectiveStatus status)
{ {
switch (status) switch (status)

View File

@@ -34,13 +34,12 @@ Background@MISSION_OBJECTIVES:
Y:70 Y:70
Width:PARENT_RIGHT-50 Width:PARENT_RIGHT-50
Height:200 Height:200
ItemSpacing:5 ItemSpacing:20
Children: Children:
Container@PRIMARY_OBJECTIVE_TEMPLATE: Container@PRIMARY_OBJECTIVE_TEMPLATE:
X:15 X:15
Y:0-15 Y:0
Width:PARENT_RIGHT Width:PARENT_RIGHT
Height:60
Children: Children:
Label@PRIMARY_OBJECTIVE: Label@PRIMARY_OBJECTIVE:
X:0 X:0
@@ -75,13 +74,12 @@ Background@MISSION_OBJECTIVES:
Y:305 Y:305
Width:PARENT_RIGHT-50 Width:PARENT_RIGHT-50
Height:200 Height:200
ItemSpacing:5 ItemSpacing:20
Children: Children:
Container@SECONDARY_OBJECTIVE_TEMPLATE: Container@SECONDARY_OBJECTIVE_TEMPLATE:
X:15 X:15
Y:0-15 Y:0
Width:PARENT_RIGHT Width:PARENT_RIGHT
Height:60
Children: Children:
Label@SECONDARY_OBJECTIVE: Label@SECONDARY_OBJECTIVE:
X:0 X:0