Fix MissionObjectives not properly ending the game

This commit is contained in:
abcdefg30
2020-12-12 10:10:12 +01:00
committed by reaperrr
parent aeaffc0a8e
commit ef9f26a60d

View File

@@ -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))
@@ -153,17 +166,14 @@ namespace OpenRA.Mods.Common.Traits
player.World.SetPauseState(true); player.World.SetPauseState(true);
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))
{ {