LCOV - code coverage report
Current view: top level - simulation/components - EndGameManager.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 27 75 36.0 %
Date: 2023-04-02 12:52:40 Functions: 7 15 46.7 %

          Line data    Source code
       1             : /**
       2             :  * System component to store the victory conditions and their settings and
       3             :  * check for allied victory / last-man-standing.
       4             :  */
       5             : function EndGameManager() {}
       6             : 
       7           1 : EndGameManager.prototype.Schema =
       8             :         "<a:component type='system'/><empty/>";
       9             : 
      10           1 : EndGameManager.prototype.Init = function()
      11             : {
      12             :         // Contains settings specific to the victory condition,
      13             :         // for example wonder victory duration.
      14           1 :         this.gameSettings = {};
      15             : 
      16             :         // Allied victory means allied players can win if victory conditions are met for each of them
      17             :         // False for a "last man standing" game
      18           1 :         this.alliedVictory = true;
      19             : 
      20             :         // Don't do any checks before the diplomacies were set for each player
      21             :         // or when marking a player as won.
      22           1 :         this.skipAlliedVictoryCheck = true;
      23             : 
      24           1 :         this.lastManStandingMessage = undefined;
      25             : 
      26           1 :         this.endlessGame = false;
      27             : };
      28             : 
      29           1 : EndGameManager.prototype.GetGameSettings = function()
      30             : {
      31           1 :         return this.gameSettings;
      32             : };
      33             : 
      34           1 : EndGameManager.prototype.GetVictoryConditions = function()
      35             : {
      36           1 :         return this.gameSettings.victoryConditions;
      37             : };
      38             : 
      39           1 : EndGameManager.prototype.SetGameSettings = function(newSettings = {})
      40             : {
      41           1 :         this.gameSettings = newSettings;
      42           1 :         this.skipAlliedVictoryCheck = false;
      43           1 :         this.endlessGame = !this.gameSettings.victoryConditions.length;
      44             : 
      45           1 :         Engine.BroadcastMessage(MT_VictoryConditionsChanged, {});
      46             : };
      47             : 
      48             : /**
      49             :  * Sets the given player (and the allies if allied victory is enabled) as a winner.
      50             :  *
      51             :  * @param {number} playerID - The player that should win.
      52             :  * @param {function} victoryReason - Function that maps from number to plural string, for example
      53             :  *   n => markForPluralTranslation(
      54             :  *       "%(lastPlayer)s has won (game mode).",
      55             :  *       "%(players)s and %(lastPlayer)s have won (game mode).",
      56             :  *       n));
      57             :  */
      58           1 : EndGameManager.prototype.MarkPlayerAndAlliesAsWon = function(playerID, victoryString, defeatString)
      59             : {
      60           0 :         const cmpPlayer = QueryPlayerIDInterface(playerID);
      61           0 :         if (!cmpPlayer.IsActive())
      62             :         {
      63           0 :                 warn("Can't mark player " + playerID + " as won, since the state is " + cmpPlayer.GetState());
      64           0 :                 return;
      65             :         }
      66             : 
      67           0 :         let winningPlayers = [playerID];
      68           0 :         if (this.alliedVictory)
      69           0 :                 winningPlayers = cmpPlayer.GetMutualAllies(playerID).filter(
      70           0 :                         player => QueryPlayerIDInterface(player).IsActive());
      71             : 
      72           0 :         this.MarkPlayersAsWon(winningPlayers, victoryString, defeatString);
      73             : };
      74             : 
      75             : /**
      76             :  * Sets the given players as won and others as defeated.
      77             :  *
      78             :  * @param {array} winningPlayers - The players that should win.
      79             :  * @param {function} victoryReason - Function that maps from number to plural string, for example
      80             :  *   n => markForPluralTranslation(
      81             :  *       "%(lastPlayer)s has won (game mode).",
      82             :  *       "%(players)s and %(lastPlayer)s have won (game mode).",
      83             :  *       n));
      84             :  */
      85           1 : EndGameManager.prototype.MarkPlayersAsWon = function(winningPlayers, victoryString, defeatString)
      86             : {
      87           0 :         this.skipAlliedVictoryCheck = true;
      88           0 :         for (let playerID of winningPlayers)
      89             :         {
      90           0 :                 let cmpPlayer = QueryPlayerIDInterface(playerID);
      91           0 :                 if (!cmpPlayer.IsActive())
      92             :                 {
      93           0 :                         warn("Can't mark player " + playerID + " as won, since the state is " + cmpPlayer.GetState());
      94           0 :                         continue;
      95             :                 }
      96           0 :                 cmpPlayer.Win(undefined);
      97             :         }
      98             : 
      99           0 :         let defeatedPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetActivePlayers().filter(
     100           0 :                 playerID => winningPlayers.indexOf(playerID) == -1);
     101             : 
     102           0 :         for (let playerID of defeatedPlayers)
     103           0 :                 QueryPlayerIDInterface(playerID).Defeat(undefined);
     104             : 
     105           0 :         let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
     106           0 :         cmpGUIInterface.PushNotification({
     107             :                 "type": "won",
     108             :                 "players": [winningPlayers[0]],
     109             :                 "allies": winningPlayers,
     110             :                 "message": victoryString(winningPlayers.length)
     111             :         });
     112             : 
     113           0 :         if (defeatedPlayers.length)
     114           0 :                 cmpGUIInterface.PushNotification({
     115             :                         "type": "defeat",
     116             :                         "players": [defeatedPlayers[0]],
     117             :                         "allies": defeatedPlayers,
     118             :                         "message": defeatString(defeatedPlayers.length)
     119             :                 });
     120             : 
     121           0 :         this.skipAlliedVictoryCheck = false;
     122             : };
     123             : 
     124           1 : EndGameManager.prototype.SetAlliedVictory = function(flag)
     125             : {
     126           1 :         this.alliedVictory = flag;
     127             : };
     128             : 
     129           1 : EndGameManager.prototype.GetAlliedVictory = function()
     130             : {
     131           1 :         return this.alliedVictory;
     132             : };
     133             : 
     134           1 : EndGameManager.prototype.AlliedVictoryCheck = function()
     135             : {
     136           0 :         if (this.skipAlliedVictoryCheck || this.endlessGame)
     137           0 :                 return;
     138             : 
     139           0 :         let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
     140           0 :         cmpGuiInterface.DeleteTimeNotification(this.lastManStandingMessage);
     141             : 
     142             :         // Proceed if only allies are remaining
     143           0 :         let allies = [];
     144           0 :         let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers();
     145           0 :         for (let playerID = 1; playerID < numPlayers; ++playerID)
     146             :         {
     147           0 :                 let cmpPlayer = QueryPlayerIDInterface(playerID);
     148           0 :                 if (!cmpPlayer.IsActive())
     149           0 :                         continue;
     150             : 
     151           0 :                 if (allies.length && !cmpPlayer.IsMutualAlly(allies[0]))
     152           0 :                         return;
     153             : 
     154           0 :                 allies.push(playerID);
     155             :         }
     156             : 
     157           0 :         if (!allies.length)
     158           0 :                 return;
     159             : 
     160           0 :         if (this.alliedVictory || allies.length == 1)
     161             :         {
     162           0 :                 for (const playerID of allies)
     163           0 :                         QueryPlayerIDInterface(playerID)?.Win(undefined);
     164             : 
     165           0 :                 cmpGuiInterface.PushNotification({
     166             :                         "type": "won",
     167             :                         "players": [allies[0]],
     168             :                         "allies": allies,
     169             :                         "message": markForPluralTranslation(
     170             :                                 "%(lastPlayer)s has won (last player alive).",
     171             :                                 "%(players)s and %(lastPlayer)s have won (last players alive).",
     172             :                                 allies.length)
     173             :                 });
     174             :         }
     175             :         else
     176           0 :                 this.lastManStandingMessage = cmpGuiInterface.AddTimeNotification({
     177             :                         "message": markForTranslation("Last remaining player wins."),
     178             :                         "translateMessage": true,
     179             :                 }, 12 * 60 * 60 * 1000); // 12 hours
     180             : };
     181             : 
     182           1 : EndGameManager.prototype.OnInitGame = function(msg)
     183             : {
     184           0 :         this.AlliedVictoryCheck();
     185             : };
     186             : 
     187           1 : EndGameManager.prototype.OnGlobalDiplomacyChanged = function(msg)
     188             : {
     189           0 :         this.AlliedVictoryCheck();
     190             : };
     191             : 
     192           1 : EndGameManager.prototype.OnGlobalPlayerDefeated = function(msg)
     193             : {
     194           0 :         this.AlliedVictoryCheck();
     195             : };
     196             : 
     197           1 : Engine.RegisterSystemComponentType(IID_EndGameManager, "EndGameManager", EndGameManager);

Generated by: LCOV version 1.14