Fix MissionObjectives not properly ending the game
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
@@ -58,15 +59,19 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[NotificationReference("Speech")]
|
[NotificationReference("Speech")]
|
||||||
public readonly string LeaveNotification = null;
|
public readonly string LeaveNotification = null;
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new MissionObjectives(init.World, this); }
|
public override object Create(ActorInitializer init) { return new MissionObjectives(init.Self.Owner, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MissionObjectives : INotifyWinStateChanged, ISync, IResolveOrder
|
public class MissionObjectives : INotifyWinStateChanged, ISync, IResolveOrder, IWorldLoaded
|
||||||
{
|
{
|
||||||
public readonly MissionObjectivesInfo Info;
|
public readonly MissionObjectivesInfo Info;
|
||||||
readonly List<MissionObjective> objectives = new List<MissionObjective>();
|
readonly List<MissionObjective> objectives = new List<MissionObjective>();
|
||||||
|
readonly Player player;
|
||||||
public ReadOnlyList<MissionObjective> Objectives;
|
public ReadOnlyList<MissionObjective> Objectives;
|
||||||
|
|
||||||
|
Player[] enemies;
|
||||||
|
Player[] allies;
|
||||||
|
|
||||||
[Sync]
|
[Sync]
|
||||||
public int ObjectivesHash
|
public int ObjectivesHash
|
||||||
{
|
{
|
||||||
@@ -83,12 +88,21 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
// The player's WinState is only updated when his allies have all completed their objective as well.
|
// The player's WinState is only updated when his allies have all completed their objective as well.
|
||||||
public WinState WinStateCooperative { get; private set; }
|
public WinState WinStateCooperative { get; private set; }
|
||||||
|
|
||||||
public MissionObjectives(World world, MissionObjectivesInfo info)
|
public MissionObjectives(Player player, MissionObjectivesInfo info)
|
||||||
{
|
{
|
||||||
Info = info;
|
Info = info;
|
||||||
|
this.player = player;
|
||||||
Objectives = new ReadOnlyList<MissionObjective>(objectives);
|
Objectives = new ReadOnlyList<MissionObjective>(objectives);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
// Players and NonCombatants are fixed once the game starts, but the result of IsAlliedWith
|
||||||
|
// may change once players are marked as spectators, so cache these
|
||||||
|
allies = player.World.Players.Where(p => !p.NonCombatant && player.IsAlliedWith(p)).ToArray();
|
||||||
|
enemies = player.World.Players.Where(p => !p.NonCombatant && player.RelationshipWith(p) == PlayerRelationship.Enemy).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
public int Add(Player player, string description, string type, bool required = true, bool inhibitAnnouncement = false)
|
public int Add(Player player, string description, string type, bool required = true, bool inhibitAnnouncement = false)
|
||||||
{
|
{
|
||||||
var newID = objectives.Count;
|
var newID = objectives.Count;
|
||||||
@@ -140,10 +154,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
void CheckIfGameIsOver(Player player)
|
void CheckIfGameIsOver(Player player)
|
||||||
{
|
{
|
||||||
var players = player.World.Players.Where(p => !p.NonCombatant);
|
var gameOver = player.World.Players.All(p => p.NonCombatant || p.WinState != WinState.Undefined || !p.HasObjectives);
|
||||||
|
|
||||||
var gameOver = players.All(p => p.WinState != WinState.Undefined || !p.HasObjectives);
|
|
||||||
if (gameOver)
|
if (gameOver)
|
||||||
|
{
|
||||||
Game.RunAfterDelay(Info.GameOverDelay, () =>
|
Game.RunAfterDelay(Info.GameOverDelay, () =>
|
||||||
{
|
{
|
||||||
if (!Game.IsCurrentWorld(player.World))
|
if (!Game.IsCurrentWorld(player.World))
|
||||||
@@ -154,16 +167,13 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
player.World.PauseStateLocked = true;
|
player.World.PauseStateLocked = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void INotifyWinStateChanged.OnPlayerWon(Player player)
|
void INotifyWinStateChanged.OnPlayerWon(Player player)
|
||||||
{
|
{
|
||||||
var players = player.World.Players.Where(p => !p.NonCombatant);
|
|
||||||
var enemies = players.Where(p => !p.IsAlliedWith(player));
|
|
||||||
|
|
||||||
if (Info.Cooperative)
|
if (Info.Cooperative)
|
||||||
{
|
{
|
||||||
WinStateCooperative = WinState.Won;
|
WinStateCooperative = WinState.Won;
|
||||||
var allies = players.Where(p => p.IsAlliedWith(player));
|
|
||||||
|
|
||||||
if (allies.All(p => p.PlayerActor.Trait<MissionObjectives>().WinStateCooperative == WinState.Won))
|
if (allies.All(p => p.PlayerActor.Trait<MissionObjectives>().WinStateCooperative == WinState.Won))
|
||||||
{
|
{
|
||||||
@@ -193,13 +203,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
void INotifyWinStateChanged.OnPlayerLost(Player player)
|
void INotifyWinStateChanged.OnPlayerLost(Player player)
|
||||||
{
|
{
|
||||||
var players = player.World.Players.Where(p => !p.NonCombatant);
|
|
||||||
var enemies = players.Where(p => !p.IsAlliedWith(player));
|
|
||||||
|
|
||||||
if (Info.Cooperative)
|
if (Info.Cooperative)
|
||||||
{
|
{
|
||||||
WinStateCooperative = WinState.Lost;
|
WinStateCooperative = WinState.Lost;
|
||||||
var allies = players.Where(p => p.IsAlliedWith(player));
|
|
||||||
|
|
||||||
if (allies.Any(p => p.PlayerActor.Trait<MissionObjectives>().WinStateCooperative == WinState.Lost))
|
if (allies.Any(p => p.PlayerActor.Trait<MissionObjectives>().WinStateCooperative == WinState.Lost))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user