Make Conquest- and StrategicVictoryConditions use objectives backend

Note: 3rd party KotH maps will need to be modified to work correctly
with this change.  Previously, StrategicVictoryConditions was a
supplement to ConquestVictoryConditions.  After this change, each works
by itself.  So KotH maps will need to remove the ConquestVictoryConditions
trait from the player definitions, or both victory conditions will have
to be satisfied to win the game.
This commit is contained in:
Oliver Brakmann
2014-07-25 09:25:32 +02:00
parent a3bf3e7403
commit 6e3000ab0e
7 changed files with 125 additions and 60 deletions

View File

@@ -13,80 +13,79 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class ConquestVictoryConditionsInfo : ITraitInfo
public class ConquestVictoryConditionsInfo : ITraitInfo, Requires<MissionObjectivesInfo>
{
[Desc("Milliseconds")]
[Desc("Delay for the end game notification in milliseconds.")]
public int NotificationDelay = 1500;
public object Create(ActorInitializer init) { return new ConquestVictoryConditions(init.world, this); }
public object Create(ActorInitializer init) { return new ConquestVictoryConditions(init.self, this); }
}
public class ConquestVictoryConditions : ITick, IResolveOrder
public class ConquestVictoryConditions : ITick, IResolveOrder, INotifyObjectivesUpdated
{
ConquestVictoryConditionsInfo Info;
public ConquestVictoryConditions(World world, ConquestVictoryConditionsInfo info)
readonly ConquestVictoryConditionsInfo info;
readonly MissionObjectives mo;
int objectiveID = -1;
public ConquestVictoryConditions(Actor self, ConquestVictoryConditionsInfo cvcInfo)
{
world.ObserveAfterWinOrLose = true;
Info = info;
info = cvcInfo;
mo = self.Trait<MissionObjectives>();
}
public void Tick(Actor self)
{
if (self.Owner.WinState != WinState.Undefined || self.Owner.NonCombatant) return;
var hasAnything = self.World.ActorsWithTrait<MustBeDestroyed>()
.Any(a => a.Actor.Owner == self.Owner);
if (objectiveID < 0)
objectiveID = mo.Add(self.Owner, "Destroy all opposition!");
if (!hasAnything && !self.Owner.NonCombatant)
Lose(self);
if (!self.Owner.NonCombatant && self.Owner.HasNoRequiredUnits())
mo.MarkFailed(self.Owner, objectiveID);
var others = self.World.Players.Where(p => !p.NonCombatant
&& p != self.Owner && p.Stances[self.Owner] != Stance.Ally);
&& !p.IsAlliedWith(self.Owner));
if (!others.Any()) return;
if (others.All(p => p.WinState == WinState.Lost))
Win(self);
mo.MarkCompleted(self.Owner, objectiveID);
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Surrender")
Lose(self);
mo.MarkFailed(self.Owner, objectiveID);
}
public void Lose(Actor self)
public void OnPlayerLost(Player player)
{
if (self.Owner.WinState == WinState.Lost) return;
self.Owner.WinState = WinState.Lost;
self.World.OnPlayerWinStateChanged(self.Owner);
Game.Debug("{0} is defeated.".F(player.PlayerName));
Game.Debug("{0} is defeated.".F(self.Owner.PlayerName));
foreach (var a in self.World.Actors.Where(a => a.Owner == self.Owner))
foreach (var a in player.World.Actors.Where(a => a.Owner == player))
a.Kill(a);
if (self.Owner == self.World.LocalPlayer)
if (player == player.World.LocalPlayer)
{
Game.RunAfterDelay(Info.NotificationDelay, () =>
Game.RunAfterDelay(info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(self.World))
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "Lose", self.Owner.Country.Race);
if (Game.IsCurrentWorld(player.World))
Sound.PlayNotification(player.World.Map.Rules, player, "Speech", "Lose", player.Country.Race);
});
}
}
public void Win(Actor self)
public void OnPlayerWon(Player player)
{
if (self.Owner.WinState == WinState.Won) return;
self.Owner.WinState = WinState.Won;
self.World.OnPlayerWinStateChanged(self.Owner);
Game.Debug("{0} is victorious.".F(player.PlayerName));
Game.Debug("{0} is victorious.".F(self.Owner.PlayerName));
if (self.Owner == self.World.LocalPlayer)
Game.RunAfterDelay(Info.NotificationDelay, () => Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", "Win", self.Owner.Country.Race));
if (player == player.World.LocalPlayer)
Game.RunAfterDelay(info.NotificationDelay, () => Sound.PlayNotification(player.World.Map.Rules, player, "Speech", "Win", player.Country.Race));
}
public void OnObjectiveAdded(Player player, int id) {}
public void OnObjectiveCompleted(Player player, int id) {}
public void OnObjectiveFailed(Player player, int id) {}
}
[Desc("Tag trait for things that must be destroyed for a short game to end.")]