Index: ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/StanceButton.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/StanceButton.js +++ ps/trunk/binaries/data/mods/public/gui/session/diplomacy/playercontrols/StanceButton.js @@ -11,7 +11,7 @@ update(playerInactive) { - let hidden = playerInactive || GetSimState().ceasefireActive || g_Players[g_ViewedPlayer].teamsLocked; + let hidden = playerInactive || GetSimState().ceasefireActive || g_Players[g_ViewedPlayer].teamLocked; for (let button of this.buttons) button.update(hidden); Index: ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Players.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Players.js +++ ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Players.js @@ -9,7 +9,7 @@ "playerStates": playerStates.map(playerState => playerState.state).join(",") + ",", "civs": playerStates.map(playerState => playerState.civ).join(",") + ",", "teams": playerStates.map(playerState => playerState.team).join(",") + ",", - "teamsLocked": String(playerStates.every(playerState => playerState.teamsLocked)) + "teamsLocked": String(playerStates.every(playerState => playerState.teamLocked)) }); } }; Index: ps/trunk/binaries/data/mods/public/gui/session/session.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/session/session.js +++ ps/trunk/binaries/data/mods/public/gui/session/session.js @@ -391,7 +391,7 @@ "a": playerState.color.a * 255 }, "team": playerState.team, - "teamsLocked": playerState.teamsLocked, + "teamLocked": playerState.teamLocked, "cheatsEnabled": playerState.cheatsEnabled, "state": playerState.state, "isAlly": playerState.isAlly, Index: ps/trunk/binaries/data/mods/public/maps/scripts/CaptureTheRelic.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/scripts/CaptureTheRelic.js +++ ps/trunk/binaries/data/mods/public/maps/scripts/CaptureTheRelic.js @@ -67,7 +67,7 @@ } let winningPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager).GetAlliedVictory() ? - activePlayers.filter(playerID => relicOwners.every(owner => QueryPlayerIDInterface(playerID).IsMutualAlly(owner))) : + activePlayers.filter(playerID => relicOwners.every(owner => QueryPlayerIDInterface(playerID, IID_Diplomacy).IsMutualAlly(owner))) : [relicOwners[0]]; // All relicOwners should be mutually allied Index: ps/trunk/binaries/data/mods/public/maps/scripts/WonderVictory.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/scripts/WonderVictory.js +++ ps/trunk/binaries/data/mods/public/maps/scripts/WonderVictory.js @@ -36,7 +36,7 @@ let owner = this.wonderVictoryMessages[ent].playerID; let otherPlayer = owner == data.player ? data.otherPlayer : data.player; - let newAllies = new Set(QueryPlayerIDInterface(owner).GetPlayersByDiplomacy("IsExclusiveMutualAlly")); + let newAllies = new Set(QueryPlayerIDInterface(owner, IID_Diplomacy).GetPlayersByDiplomacy("IsExclusiveMutualAlly")); if (newAllies.has(otherPlayer) && !this.wonderVictoryMessages[ent].allies.has(otherPlayer) || !newAllies.has(otherPlayer) && this.wonderVictoryMessages[ent].allies.has(otherPlayer)) { @@ -53,7 +53,7 @@ { let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); let allies = cmpEndGameManager.GetAlliedVictory() ? - QueryPlayerIDInterface(player).GetPlayersByDiplomacy("IsExclusiveMutualAlly") : []; + QueryPlayerIDInterface(player, IID_Diplomacy).GetPlayersByDiplomacy("IsExclusiveMutualAlly") : []; let others = [-1]; for (let playerID = 1; playerID < TriggerHelper.GetNumberOfPlayers(); ++playerID) Index: ps/trunk/binaries/data/mods/public/simulation/components/AlertRaiser.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/AlertRaiser.js +++ ps/trunk/binaries/data/mods/public/simulation/components/AlertRaiser.js @@ -37,8 +37,8 @@ return; let owner = cmpOwnership.GetOwner(); - let cmpPlayer = QueryOwnerInterface(this.entity); - let mutualAllies = cmpPlayer ? cmpPlayer.GetMutualAllies() : [owner]; + const cmpDiplomacy = QueryPlayerIDInterface(owner, IID_Diplomacy); + const mutualAllies = cmpDiplomacy ? cmpDiplomacy.GetMutualAllies() : [owner]; let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); // Store the number of available garrison spots so that units don't try to garrison in buildings that will be full @@ -98,8 +98,8 @@ return; let owner = cmpOwnership.GetOwner(); - let cmpPlayer = QueryOwnerInterface(this.entity); - let mutualAllies = cmpPlayer ? cmpPlayer.GetMutualAllies() : [owner]; + const cmpDiplomacy = QueryPlayerIDInterface(owner, IID_Diplomacy); + const mutualAllies = cmpDiplomacy ? cmpDiplomacy.GetMutualAllies() : [owner]; let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); // Units that are not garrisoned should go back to work Index: ps/trunk/binaries/data/mods/public/simulation/components/Attack.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/Attack.js +++ ps/trunk/binaries/data/mods/public/simulation/components/Attack.js @@ -270,6 +270,7 @@ const entityOwner = cmpEntityPlayer.GetPlayerID(); const targetOwner = cmpTargetPlayer.GetPlayerID(); const cmpCapturable = QueryMiragedInterface(target, IID_Capturable); + const cmpDiplomacy = QueryPlayerIDInterface(entityOwner, IID_Diplomacy); // Check if the relative height difference is larger than the attack range // If the relative height is bigger, it means they will never be able to @@ -278,7 +279,7 @@ for (const type of types) { - if (type != "Capture" && (!cmpEntityPlayer.IsEnemy(targetOwner) || !cmpHealth || !cmpHealth.GetHitpoints())) + if (type != "Capture" && (!cmpDiplomacy?.IsEnemy(targetOwner) || !cmpHealth || !cmpHealth.GetHitpoints())) continue; if (type == "Capture" && (!cmpCapturable || !cmpCapturable.CanCapture(entityOwner))) Index: ps/trunk/binaries/data/mods/public/simulation/components/Auras.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/Auras.js +++ ps/trunk/binaries/data/mods/public/simulation/components/Auras.js @@ -123,6 +123,10 @@ if (!cmpPlayer || cmpPlayer.IsDefeated()) return; + const playerID = cmpPlayer.GetPlayerID(); + const cmpDiplomacy = Engine.QueryInterface(this.entity, IID_Diplomacy) ?? + QueryPlayerIDInterface(playerID, IID_Diplomacy); + let cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); for (let i of cmpPlayerManager.GetAllPlayers()) { @@ -130,7 +134,7 @@ if (!cmpAffectedPlayer || cmpAffectedPlayer.IsDefeated()) continue; - if (affectedPlayers.some(p => p == "Player" ? cmpPlayer.GetPlayerID() == i : cmpPlayer["Is" + p](i))) + if (affectedPlayers.some(p => p == "Player" ? playerID == i : cmpDiplomacy["Is" + p](i))) this.affectedPlayers[name].push(i); } }; Index: ps/trunk/binaries/data/mods/public/simulation/components/BuildRestrictions.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/BuildRestrictions.js +++ ps/trunk/binaries/data/mods/public/simulation/components/BuildRestrictions.js @@ -175,11 +175,16 @@ if (!cmpTerritoryManager || !cmpPosition || !cmpPosition.IsInWorld()) return result; // Fail + const playerID = cmpPlayer.GetPlayerID(); + const cmpDiplomacy = QueryPlayerIDInterface(playerID, IID_Diplomacy); + if (!cmpDiplomacy) + return result; + var pos = cmpPosition.GetPosition2D(); var tileOwner = cmpTerritoryManager.GetOwner(pos.x, pos.y); var isConnected = !cmpTerritoryManager.IsTerritoryBlinking(pos.x, pos.y); - var isOwn = tileOwner == cmpPlayer.GetPlayerID(); - var isMutualAlly = cmpPlayer.IsExclusiveMutualAlly(tileOwner); + var isOwn = tileOwner == playerID; + var isMutualAlly = cmpDiplomacy.IsExclusiveMutualAlly(tileOwner); var isNeutral = tileOwner == 0; var invalidTerritory = ""; Index: ps/trunk/binaries/data/mods/public/simulation/components/BuildingAI.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/BuildingAI.js +++ ps/trunk/binaries/data/mods/public/simulation/components/BuildingAI.js @@ -111,11 +111,11 @@ this.enemyUnitsQuery = undefined; } - var cmpPlayer = QueryOwnerInterface(this.entity); - if (!cmpPlayer) + const cmpDiplomacy = QueryOwnerInterface(this.entity, IID_Diplomacy); + if (!cmpDiplomacy) return; - var enemies = cmpPlayer.GetEnemies(); + const enemies = cmpDiplomacy.GetEnemies(); // Remove gaia. if (enemies.length && enemies[0] == 0) enemies.shift(); @@ -148,8 +148,7 @@ this.gaiaUnitsQuery = undefined; } - var cmpPlayer = QueryOwnerInterface(this.entity); - if (!cmpPlayer || !cmpPlayer.IsEnemy(0)) + if (!QueryOwnerInterface(this.entity, IID_Diplomacy)?.IsEnemy(0)) return; const range = cmpAttack.GetRange(attackType); Index: ps/trunk/binaries/data/mods/public/simulation/components/Capturable.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/Capturable.js +++ ps/trunk/binaries/data/mods/public/simulation/components/Capturable.js @@ -83,8 +83,8 @@ if (!cmpOwnership || cmpOwnership.GetOwner() == INVALID_PLAYER) return 0; - let cmpPlayerSource = QueryPlayerIDInterface(playerID); - if (!cmpPlayerSource) + const cmpDiplomacySource = QueryPlayerIDInterface(playerID, IID_Diplomacy); + if (!cmpDiplomacySource) return 0; // Before changing the value, activate Fogging if necessary to hide changes. @@ -92,7 +92,7 @@ if (cmpFogging) cmpFogging.Activate(); - let numberOfEnemies = this.capturePoints.filter((v, i) => v > 0 && cmpPlayerSource.IsEnemy(i)).length; + let numberOfEnemies = this.capturePoints.filter((v, i) => v > 0 && cmpDiplomacySource.IsEnemy(i)).length; if (numberOfEnemies == 0) return 0; @@ -105,7 +105,7 @@ numberOfEnemies = 0; for (let i in this.capturePoints) { - if (!this.capturePoints[i] || !cmpPlayerSource.IsEnemy(i)) + if (!this.capturePoints[i] || !cmpDiplomacySource.IsEnemy(i)) continue; if (this.capturePoints[i] > distributedAmount) { @@ -138,14 +138,14 @@ */ Capturable.prototype.CanCapture = function(playerID) { - let cmpPlayerSource = QueryPlayerIDInterface(playerID); + const cmpDiplomacySource = QueryPlayerIDInterface(playerID, IID_Diplomacy); - if (!cmpPlayerSource) - warn(playerID + " has no player component defined on its id."); + if (!cmpDiplomacySource) + warn(playerID + " has no diplomacy component defined on its id."); let capturePoints = this.GetCapturePoints(); let sourceEnemyCapturePoints = 0; for (let i in this.GetCapturePoints()) - if (cmpPlayerSource.IsEnemy(i)) + if (cmpDiplomacySource.IsEnemy(i)) sourceEnemyCapturePoints += capturePoints[i]; return sourceEnemyCapturePoints > 0; }; Index: ps/trunk/binaries/data/mods/public/simulation/components/CeasefireManager.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/CeasefireManager.js +++ ps/trunk/binaries/data/mods/public/simulation/components/CeasefireManager.js @@ -71,13 +71,13 @@ // Save diplomacy let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); for (let i = 1; i < numPlayers; ++i) - this.diplomacyBeforeCeasefire.push(QueryPlayerIDInterface(i).GetDiplomacy()); + this.diplomacyBeforeCeasefire.push(QueryPlayerIDInterface(i, IID_Diplomacy).GetDiplomacy()); // Set every enemy (except gaia) to neutral for (let i = 1; i < numPlayers; ++i) for (let j = 1; j < numPlayers; ++j) if (this.diplomacyBeforeCeasefire[i-1][j] < 0) - QueryPlayerIDInterface(i).SetNeutral(j); + QueryPlayerIDInterface(i, IID_Diplomacy).SetNeutral(j); } this.ceasefireIsActive = true; @@ -116,7 +116,7 @@ // Reset diplomacies to original settings let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); for (let i = 1; i < numPlayers; ++i) - QueryPlayerIDInterface(i).SetDiplomacy(this.diplomacyBeforeCeasefire[i-1]); + QueryPlayerIDInterface(i, IID_Diplomacy).SetDiplomacy(this.diplomacyBeforeCeasefire[i-1]); this.ceasefireIsActive = false; this.ceasefireTime = 0; Index: ps/trunk/binaries/data/mods/public/simulation/components/Diplomacy.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/Diplomacy.js +++ ps/trunk/binaries/data/mods/public/simulation/components/Diplomacy.js @@ -0,0 +1,347 @@ +function Diplomacy() {} + +Diplomacy.prototype.Schema = + "" + + "" + + "" + + "" + + "" + + ""; + +Diplomacy.prototype.SerializableAttributes = [ + "team", + "teamLocked", + "diplomacy", + "sharedDropsites", +]; + +Diplomacy.prototype.Serialize = function() +{ + const state = {}; + for (const key in this.SerializableAttributes) + if (this.hasOwnProperty(key)) + state[key] = this[key]; + + return state; +}; + +Diplomacy.prototype.Deserialize = function(state) +{ + for (const prop in state) + this[prop] = state[prop]; +}; + +Diplomacy.prototype.Init = function() +{ + // Team number of the player, players on the same team will always have ally diplomatic status. Also this is useful for team emblems, scoring, etc. + this.team = -1; + + // Array of diplomatic stances for this player with respect to other players (including gaia and self). + this.diplomacy = []; +}; + +/** + * @param {Object} color - r, g, b values of the diplomacy colour. + */ +Diplomacy.prototype.SetDiplomacyColor = function(color) +{ + this.diplomacyColor = { "r": color.r / 255, "g": color.g / 255, "b": color.b / 255, "a": 1 }; +}; + +/** + * @return {Object} - + */ +Diplomacy.prototype.GetColor = function() +{ + return this.diplomacyColor; +}; + +/** + * @return {number} - + */ +Diplomacy.prototype.GetTeam = function() +{ + return this.team; +}; + +/** + * @param {number} team - The new team number, -1 for no team. + */ +Diplomacy.prototype.ChangeTeam = function(team) +{ + if (this.teamLocked || this.team === team) + return; + + const playerID = Engine.QueryInterface(this.entity, IID_Player)?.GetPlayerID(); + if (!playerID) + return; + + // ToDo: Fix this. + if (this.team !== -1) + warn("A change in teams is requested while the player already had a team, previous alliances are maintained."); + + this.team = team; + + if (this.team !== -1) + { + const numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); + for (let i = 0; i < numPlayers; ++i) + { + const cmpDiplomacy = QueryPlayerIDInterface(i, IID_Diplomacy); + if (this.team !== cmpDiplomacy.GetTeam()) + continue; + + this.Ally(i); + cmpDiplomacy.Ally(playerID); + } + } + + Engine.BroadcastMessage(MT_DiplomacyChanged, { + "player": playerID, + "otherPlayer": null + }); +}; + +Diplomacy.prototype.LockTeam = function() +{ + this.teamLocked = true; +}; + +Diplomacy.prototype.UnLockTeam = function() +{ + delete this.teamLocked; +}; + +/** + * @return {boolean} - + */ +Diplomacy.prototype.IsTeamLocked = function() +{ + return !!this.teamLocked; +}; + +/** + * @return {number[]} - Current diplomatic stances. + */ +Diplomacy.prototype.GetDiplomacy = function() +{ + return this.diplomacy.slice(); +}; + +/** + * @param {number[]} dipl - The diplomacy array to set. + */ +Diplomacy.prototype.SetDiplomacy = function(dipl) +{ + const playerID = Engine.QueryInterface(this.entity, IID_Player)?.GetPlayerID(); + if (!playerID) + return + + this.diplomacy = dipl.slice(); + + Engine.BroadcastMessage(MT_DiplomacyChanged, { + "player": playerID, + "otherPlayer": null + }); +}; + +/** + * Helper function for allying etc. + * @param {number} idx - The player number. + * @param {number} value - The diplomacy value. + */ +Diplomacy.prototype.SetDiplomacyIndex = function(idx, value) +{ + if (!QueryPlayerIDInterface(idx)?.IsActive()) + return; + + const cmpPlayer = Engine.QueryInterface(this.entity, IID_Player); + if (!cmpPlayer?.IsActive()) + return; + + this.diplomacy[idx] = value; + + const playerID = cmpPlayer.GetPlayerID(); + Engine.BroadcastMessage(MT_DiplomacyChanged, { + "player": playerID, + "otherPlayer": idx, + "value": value + }); +}; + +/** + * Helper function for getting allies etc. + * @param {string} func - Name of the function to test. + * @return {number[]} - Player IDs matching the function. + */ +Diplomacy.prototype.GetPlayersByDiplomacy = function(func) +{ + const players = []; + for (let i = 0; i < this.diplomacy.length; ++i) + if (this[func](i)) + players.push(i); + return players; +}; + +/** + * @param {number} - id + */ +Diplomacy.prototype.Ally = function(id) +{ + this.SetDiplomacyIndex(id, 1); +}; + +/** + * Check if given player is our ally. + * @param {number} id - + * @return {boolean} - + */ +Diplomacy.prototype.IsAlly = function(id) +{ + return this.diplomacy[id] > 0; +}; + +/** + * @return {number[]} - + */ +Diplomacy.prototype.GetAllies = function() +{ + return this.GetPlayersByDiplomacy("IsAlly"); +}; + +/** + * Check if given player is our ally excluding ourself. + * @param {number} id - + * @return {boolean} - + */ +Diplomacy.prototype.IsExclusiveAlly = function(id) +{ + return Engine.QueryInterface(this.entity, IID_Player)?.GetPlayerID() !== id && this.IsAlly(id); +}; + +/** + * Check if given player is our ally, and we are its ally. + * @param {number} id - + * @return {boolean} - + */ +Diplomacy.prototype.IsMutualAlly = function(id) +{ + const playerID = Engine.QueryInterface(this.entity, IID_Player)?.GetPlayerID(); + return this.IsAlly(id) && playerID && QueryPlayerIDInterface(id, IID_Diplomacy)?.IsAlly(playerID); +}; + +/** + * @return {number[]} - + */ +Diplomacy.prototype.GetMutualAllies = function() +{ + return this.GetPlayersByDiplomacy("IsMutualAlly"); +}; + +/** + * Check if given player is our ally, and we are its ally, excluding ourself. + * @param {number} id - + * @return {boolean} - + */ +Diplomacy.prototype.IsExclusiveMutualAlly = function(id) +{ + const playerID = Engine.QueryInterface(this.entity, IID_Player)?.GetPlayerID(); + return playerID && playerID !== id && this.IsMutualAlly(id); +}; + +/** + * @param {number} id - + */ +Diplomacy.prototype.SetEnemy = function(id) +{ + this.SetDiplomacyIndex(id, -1); +}; + +/** + * Check if given player is our enemy. + * @param {number} id - + * @return {boolean} - + */ +Diplomacy.prototype.IsEnemy = function(id) +{ + return this.diplomacy[id] < 0; +}; + +/** + * @return {number[]} - + */ +Diplomacy.prototype.GetEnemies = function() +{ + return this.GetPlayersByDiplomacy("IsEnemy"); +}; + +/** + * @param {number} id - + */ +Diplomacy.prototype.SetNeutral = function(id) +{ + this.SetDiplomacyIndex(id, 0); +}; + +/** + * Check if given player is neutral. + * @param {number} id - + * @return {boolean} - + */ +Diplomacy.prototype.IsNeutral = function(id) +{ + return this.diplomacy[id] === 0; +}; + +/** + * @return {boolean} - + */ +Diplomacy.prototype.HasSharedDropsites = function() +{ + return this.sharedDropsites; +}; + +/** + * @return {boolean} - + */ +Diplomacy.prototype.HasSharedLos = function() +{ + const cmpTechnologyManager = Engine.QueryInterface(this.entity, IID_TechnologyManager); + return cmpTechnologyManager && cmpTechnologyManager.IsTechnologyResearched(this.template.SharedLosTech); +}; + +Diplomacy.prototype.UpdateSharedLos = function() +{ + const playerID = Engine.QueryInterface(this.entity, IID_Player).GetPlayerID(); + if (!playerID) + return; + + Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager)?. + SetSharedLos(playerID, this.HasSharedLos() ? this.GetMutualAllies() : [playerID]); +}; + +Diplomacy.prototype.OnResearchFinished = function(msg) +{ + if (msg.tech === this.template.SharedLosTech) + this.UpdateSharedLos(); + else if (msg.tech === this.template.SharedDropsitesTech) + this.sharedDropsites = true; +}; + +Diplomacy.prototype.OnDiplomacyChanged = function(msg) +{ + this.UpdateSharedLos(); + + if (msg.otherPlayer === null) + return; + + const cmpPlayer = Engine.QueryInterface(this.entity, IID_Player); + if (!cmpPlayer || cmpPlayer.GetPlayerID() != msg.otherPlayer) + return; + + // Mutual worsening of relations. + if (this.diplomacy[msg.player] > msg.value) + this.SetDiplomacyIndex(msg.player, msg.value); +}; + +Engine.RegisterComponentType(IID_Diplomacy, "Diplomacy", Diplomacy); Index: ps/trunk/binaries/data/mods/public/simulation/components/EndGameManager.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/EndGameManager.js +++ ps/trunk/binaries/data/mods/public/simulation/components/EndGameManager.js @@ -66,7 +66,7 @@ let winningPlayers = [playerID]; if (this.alliedVictory) - winningPlayers = cmpPlayer.GetMutualAllies(playerID).filter( + winningPlayers = QueryPlayerIDInterface(playerID, IID_Diplomacy).GetMutualAllies(playerID).filter( player => QueryPlayerIDInterface(player).IsActive()); this.MarkPlayersAsWon(winningPlayers, victoryString, defeatString); @@ -148,7 +148,7 @@ if (!cmpPlayer.IsActive()) continue; - if (allies.length && !cmpPlayer.IsMutualAlly(allies[0])) + if (allies.length && !QueryPlayerIDInterface(playerID, IID_Diplomacy).IsMutualAlly(allies[0])) return; allies.push(playerID); Index: ps/trunk/binaries/data/mods/public/simulation/components/Gate.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/Gate.js +++ ps/trunk/binaries/data/mods/public/simulation/components/Gate.js @@ -72,7 +72,7 @@ cmpRangeManager.DestroyActiveQuery(this.unitsQuery); // Only allied units can make the gate open. - var players = QueryPlayerIDInterface(owner).GetAllies(); + const players = QueryPlayerIDInterface(owner, IID_Diplomacy).GetAllies(); var range = this.GetPassRange(); if (range > 0) Index: ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js +++ ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js @@ -3,6 +3,8 @@ GuiInterface.prototype.Schema = ""; +GuiInterface.prototype.WHITE = { "r": 1, "g": 1, "b": 1 }; + GuiInterface.prototype.Serialize = function() { // This component isn't network-synchronized for the biggest part, @@ -66,6 +68,7 @@ const cmpPlayer = Engine.QueryInterface(playerEnt, IID_Player); const cmpPlayerEntityLimits = Engine.QueryInterface(playerEnt, IID_EntityLimits); const cmpIdentity = Engine.QueryInterface(playerEnt, IID_Identity); + const cmpDiplomacy = Engine.QueryInterface(playerEnt, IID_Diplomacy); // Work out which phase we are in. let phase = ""; @@ -87,10 +90,10 @@ for (let j = 0; j < numPlayers; ++j) { - allies[j] = cmpPlayer.IsAlly(j); - mutualAllies[j] = cmpPlayer.IsMutualAlly(j); - neutrals[j] = cmpPlayer.IsNeutral(j); - enemies[j] = cmpPlayer.IsEnemy(j); + allies[j] = cmpDiplomacy.IsAlly(j); + mutualAllies[j] = cmpDiplomacy.IsMutualAlly(j); + neutrals[j] = cmpDiplomacy.IsNeutral(j); + enemies[j] = cmpDiplomacy.IsEnemy(j); } ret.players.push({ @@ -107,13 +110,13 @@ "resourceGatherers": cmpPlayer.GetResourceGatherers(), "trainingBlocked": cmpPlayer.IsTrainingBlocked(), "state": cmpPlayer.GetState(), - "team": cmpPlayer.GetTeam(), - "teamsLocked": cmpPlayer.GetLockTeams(), + "team": cmpDiplomacy.GetTeam(), + "teamLocked": cmpDiplomacy.IsTeamLocked(), "cheatsEnabled": cmpPlayer.GetCheatsEnabled(), "disabledTemplates": cmpPlayer.GetDisabledTemplates(), "disabledTechnologies": cmpPlayer.GetDisabledTechnologies(), - "hasSharedDropsites": cmpPlayer.HasSharedDropsites(), - "hasSharedLos": cmpPlayer.HasSharedLos(), + "hasSharedDropsites": cmpDiplomacy.HasSharedDropsites(), + "hasSharedLos": cmpDiplomacy.HasSharedLos(), "spyCostMultiplier": cmpPlayer.GetSpyCostMultiplier(), "phase": phase, "isAlly": allies, @@ -910,13 +913,13 @@ let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); for (let i = 1; i < numPlayers; ++i) { - let cmpPlayer = QueryPlayerIDInterface(i, IID_Player); - if (!cmpPlayer) + const cmpDiplomacy = QueryPlayerIDInterface(i, IID_Diplomacy); + if (!cmpDiplomacy) continue; - cmpPlayer.SetDisplayDiplomacyColor(data.displayDiplomacyColors); + QueryPlayerIDInterface(i, IID_Player).SetDisplayDiplomacyColor(data.displayDiplomacyColors); if (data.displayDiplomacyColors) - cmpPlayer.SetDiplomacyColor(data.displayedPlayerColors[i]); + cmpDiplomacy.SetDiplomacyColor(data.displayedPlayerColors[i]); updateEntityColor(data.showAllStatusBars && (i == player || player == -1) ? [IID_Minimap, IID_RangeOverlayRenderer, IID_RallyPointRenderer, IID_StatusBars] : @@ -947,10 +950,7 @@ let color = playerColors[owner]; if (!color) { - color = { "r": 1, "g": 1, "b": 1 }; - let cmpPlayer = QueryPlayerIDInterface(owner); - if (cmpPlayer) - color = cmpPlayer.GetDisplayedColor(); + color = QueryPlayerIDInterface(owner, IID_Player)?.GetDisplayedColor() || this.WHITE; playerColors[owner] = color; } Index: ps/trunk/binaries/data/mods/public/simulation/components/Player.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/Player.js +++ ps/trunk/binaries/data/mods/public/simulation/components/Player.js @@ -17,12 +17,6 @@ "" + "" + "" + - "" + - "" + - "" + - "" + - "" + - "" + "" + "" + ""; @@ -32,9 +26,6 @@ Player.prototype.STATE_DEFEATED = "defeated"; Player.prototype.STATE_WON = "won"; -/** - * Don't serialize diplomacyColor or displayDiplomacyColor since they're modified by the GUI. - */ Player.prototype.Serialize = function() { let state = {}; @@ -42,8 +33,8 @@ if (this.hasOwnProperty(key)) state[key] = this[key]; - state.diplomacyColor = undefined; - state.displayDiplomacyColor = false; + // Modified by GUI, so don't serialise. + delete state.displayDiplomacyColor; return state; }; @@ -62,8 +53,6 @@ { this.playerID = undefined; this.color = undefined; - this.diplomacyColor = undefined; - this.displayDiplomacyColor = false; this.popUsed = 0; // Population of units owned or trained by this player. this.popBonuses = 0; // Sum of population bonuses of player's entities. this.maxPop = 300; // Maximum population. @@ -71,11 +60,7 @@ this.resourceCount = {}; this.resourceGatherers = {}; this.tradingGoods = []; // Goods for next trade-route and its probabilities * 100. - this.team = -1; // Team number of the player, players on the same team will always have ally diplomatic status. Also this is useful for team emblems, scoring, etc. - this.teamsLocked = false; this.state = this.STATE_ACTIVE; - this.diplomacy = []; // Array of diplomatic stances for this player with respect to other players (including gaia and self). - this.sharedDropsites = false; this.formations = this.template.Formations._string.split(" "); this.startCam = undefined; this.controlAllUnits = false; @@ -134,11 +119,6 @@ }); }; -Player.prototype.SetDiplomacyColor = function(color) -{ - this.diplomacyColor = { "r": color.r / 255, "g": color.g / 255, "b": color.b / 255, "a": 1 }; -}; - Player.prototype.SetDisplayDiplomacyColor = function(displayDiplomacyColor) { this.displayDiplomacyColor = displayDiplomacyColor; @@ -151,7 +131,7 @@ Player.prototype.GetDisplayedColor = function() { - return this.displayDiplomacyColor ? this.diplomacyColor : this.color; + return this.displayDiplomacyColor ? Engine.QueryInterface(this.entity, IID_Diplomacy).GetColor() : this.color; }; // Try reserving num population slots. Returns 0 on success or number of missing slots otherwise. @@ -543,101 +523,6 @@ Engine.PostMessage(this.entity, won ? MT_PlayerWon : MT_PlayerDefeated, { "playerId": this.playerID }); }; -Player.prototype.GetTeam = function() -{ - return this.team; -}; - -Player.prototype.SetTeam = function(team) -{ - if (this.teamsLocked) - return; - - this.team = team; - - // Set all team members as allies. - if (this.team != -1) - { - let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); - for (let i = 0; i < numPlayers; ++i) - { - let cmpPlayer = QueryPlayerIDInterface(i); - if (this.team != cmpPlayer.GetTeam()) - continue; - - this.SetAlly(i); - cmpPlayer.SetAlly(this.playerID); - } - } - - Engine.BroadcastMessage(MT_DiplomacyChanged, { - "player": this.playerID, - "otherPlayer": null - }); -}; - -Player.prototype.SetLockTeams = function(value) -{ - this.teamsLocked = value; -}; - -Player.prototype.GetLockTeams = function() -{ - return this.teamsLocked; -}; - -Player.prototype.GetDiplomacy = function() -{ - return this.diplomacy.slice(); -}; - -Player.prototype.SetDiplomacy = function(dipl) -{ - this.diplomacy = dipl.slice(); - - Engine.BroadcastMessage(MT_DiplomacyChanged, { - "player": this.playerID, - "otherPlayer": null - }); -}; - -Player.prototype.SetDiplomacyIndex = function(idx, value) -{ - let cmpPlayer = QueryPlayerIDInterface(idx); - if (!cmpPlayer) - return; - - if (!this.IsActive() || !cmpPlayer.IsActive()) - return; - - this.diplomacy[idx] = value; - - Engine.BroadcastMessage(MT_DiplomacyChanged, { - "player": this.playerID, - "otherPlayer": cmpPlayer.GetPlayerID() - }); - - // Mutual worsening of relations. - if (cmpPlayer.diplomacy[this.playerID] > value) - cmpPlayer.SetDiplomacyIndex(this.playerID, value); -}; - -Player.prototype.UpdateSharedLos = function() -{ - let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - let cmpTechnologyManager = Engine.QueryInterface(this.entity, IID_TechnologyManager); - if (!cmpRangeManager || !cmpTechnologyManager) - return; - - if (!cmpTechnologyManager.IsTechnologyResearched(this.template.SharedLosTech)) - { - cmpRangeManager.SetSharedLos(this.playerID, [this.playerID]); - return; - } - - cmpRangeManager.SetSharedLos(this.playerID, this.GetMutualAllies()); -}; - Player.prototype.GetFormations = function() { return this.formations; @@ -668,16 +553,6 @@ return this.startCam !== undefined; }; -Player.prototype.HasSharedLos = function() -{ - let cmpTechnologyManager = Engine.QueryInterface(this.entity, IID_TechnologyManager); - return cmpTechnologyManager && cmpTechnologyManager.IsTechnologyResearched(this.template.SharedLosTech); -}; -Player.prototype.HasSharedDropsites = function() -{ - return this.sharedDropsites; -}; - Player.prototype.SetControlAllUnits = function(c) { this.controlAllUnits = c; @@ -698,94 +573,6 @@ return this.isAI; }; -Player.prototype.GetPlayersByDiplomacy = function(func) -{ - let players = []; - for (let i = 0; i < this.diplomacy.length; ++i) - if (this[func](i)) - players.push(i); - return players; -}; - -Player.prototype.SetAlly = function(id) -{ - this.SetDiplomacyIndex(id, 1); -}; - -/** - * Check if given player is our ally. - */ -Player.prototype.IsAlly = function(id) -{ - return this.diplomacy[id] > 0; -}; - -Player.prototype.GetAllies = function() -{ - return this.GetPlayersByDiplomacy("IsAlly"); -}; - -/** - * Check if given player is our ally excluding ourself - */ -Player.prototype.IsExclusiveAlly = function(id) -{ - return this.playerID != id && this.IsAlly(id); -}; - -/** - * Check if given player is our ally, and we are its ally - */ -Player.prototype.IsMutualAlly = function(id) -{ - let cmpPlayer = QueryPlayerIDInterface(id); - return this.IsAlly(id) && cmpPlayer && cmpPlayer.IsAlly(this.playerID); -}; - -Player.prototype.GetMutualAllies = function() -{ - return this.GetPlayersByDiplomacy("IsMutualAlly"); -}; - -/** - * Check if given player is our ally, and we are its ally, excluding ourself - */ -Player.prototype.IsExclusiveMutualAlly = function(id) -{ - return this.playerID != id && this.IsMutualAlly(id); -}; - -Player.prototype.SetEnemy = function(id) -{ - this.SetDiplomacyIndex(id, -1); -}; - -/** - * Check if given player is our enemy - */ -Player.prototype.IsEnemy = function(id) -{ - return this.diplomacy[id] < 0; -}; - -Player.prototype.GetEnemies = function() -{ - return this.GetPlayersByDiplomacy("IsEnemy"); -}; - -Player.prototype.SetNeutral = function(id) -{ - this.SetDiplomacyIndex(id, 0); -}; - -/** - * Check if given player is neutral - */ -Player.prototype.IsNeutral = function(id) -{ - return this.diplomacy[id] == 0; -}; - /** * Do some map dependant initializations */ @@ -841,19 +628,6 @@ } }; -Player.prototype.OnResearchFinished = function(msg) -{ - if (msg.tech == this.template.SharedLosTech) - this.UpdateSharedLos(); - else if (msg.tech == this.template.SharedDropsitesTech) - this.sharedDropsites = true; -}; - -Player.prototype.OnDiplomacyChanged = function() -{ - this.UpdateSharedLos(); -}; - Player.prototype.OnValueModification = function(msg) { if (msg.component != "Player") @@ -983,7 +757,7 @@ if (!cmpSound) return; - const soundGroup = cmpSound.GetSoundGroup(this.playerID === msg.playerId ? "defeated" : this.IsAlly(msg.playerId) ? "defeated_ally" : this.HasWon() ? "won" : "defeated_enemy"); + const soundGroup = cmpSound.GetSoundGroup(this.playerID === msg.playerId ? "defeated" : Engine.QueryInterface(this.entity, IID_Diplomacy).IsAlly(msg.playerId) ? "defeated_ally" : this.HasWon() ? "won" : "defeated_enemy"); if (soundGroup) Engine.QueryInterface(SYSTEM_ENTITY, IID_SoundManager).PlaySoundGroupForPlayer(soundGroup, this.playerID); }; Index: ps/trunk/binaries/data/mods/public/simulation/components/PlayerManager.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/PlayerManager.js +++ ps/trunk/binaries/data/mods/public/simulation/components/PlayerManager.js @@ -17,18 +17,17 @@ { const ent = Engine.AddEntity(templateName); const id = this.playerEntities.length; - const cmpPlayer = Engine.QueryInterface(ent, IID_Player); - cmpPlayer.SetPlayerID(id); + Engine.QueryInterface(ent, IID_Player).SetPlayerID(id); this.playerEntities.push(ent); const newDiplo = []; for (let i = 0; i < id; i++) { - Engine.QueryInterface(this.GetPlayerByID(i), IID_Player).diplomacy[id] = -1; + Engine.QueryInterface(this.GetPlayerByID(i), IID_Diplomacy).diplomacy[id] = -1; newDiplo[i] = -1; } newDiplo[id] = 1; - cmpPlayer.SetDiplomacy(newDiplo); + Engine.QueryInterface(ent, IID_Diplomacy).SetDiplomacy(newDiplo); Engine.BroadcastMessage(MT_PlayerEntityChanged, { "player": id, @@ -61,7 +60,7 @@ this.playerEntities[id] = ent; newCmpPlayer.SetColor(oldCmpPlayer.GetColor()); - newCmpPlayer.SetDiplomacy(oldCmpPlayer.GetDiplomacy()); + Engine.QueryInterface(ent, IID_Diplomacy).SetDiplomacy(Engine.QueryInterface(oldent, IID_Diplomacy).GetDiplomacy()); Engine.BroadcastMessage(MT_PlayerEntityChanged, { "player": id, Index: ps/trunk/binaries/data/mods/public/simulation/components/ResourceGatherer.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/ResourceGatherer.js +++ ps/trunk/binaries/data/mods/public/simulation/components/ResourceGatherer.js @@ -373,12 +373,17 @@ return false; } - let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); - if (cmpOwnership && IsOwnedByPlayer(cmpOwnership.GetOwner(), target)) + const cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); + if (!cmpOwnership) + return false; + + const playerID = cmpOwnership.GetOwner(); + if (IsOwnedByPlayer(playerID, target)) return true; - let cmpPlayer = QueryOwnerInterface(this.entity); - return cmpPlayer && cmpPlayer.HasSharedDropsites() && cmpResourceDropsite.IsShared() && - cmpOwnership && IsOwnedByMutualAllyOfPlayer(cmpOwnership.GetOwner(), target); + + return QueryPlayerIDInterface(playerID, IID_Diplomacy)?.HasSharedDropsites() && + cmpResourceDropsite.IsShared() && + IsOwnedByMutualAllyOfPlayer(playerID, target); }; /** Index: ps/trunk/binaries/data/mods/public/simulation/components/StatisticsTracker.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/StatisticsTracker.js +++ ps/trunk/binaries/data/mods/public/simulation/components/StatisticsTracker.js @@ -416,24 +416,26 @@ */ StatisticsTracker.prototype.GetTeamPercentMapExplored = function() { - let cmpPlayer = Engine.QueryInterface(this.entity, IID_Player); - if (!cmpPlayer) + const cmpDiplomacy = Engine.QueryInterface(this.entity, IID_Diplomacy); + if (!cmpDiplomacy) return 0; - let team = cmpPlayer.GetTeam(); - let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); + const team = cmpDiplomacy.GetTeam(); + const cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); // If teams are not locked, this statistic won't be displayed, so don't bother computing - if (team == -1 || !cmpPlayer.GetLockTeams()) + if (team == -1 || !cmpDiplomacy.IsTeamLocked()) + { + const cmpPlayer = Engine.QueryInterface(this.entity, IID_Player); + if (!cmpPlayer) + return 0; return cmpRangeManager.GetPercentMapExplored(cmpPlayer.GetPlayerID()); + } - let teamPlayers = []; - let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); + const teamPlayers = []; + const numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); for (let i = 1; i < numPlayers; ++i) - { - let cmpOtherPlayer = QueryPlayerIDInterface(i); - if (cmpOtherPlayer && cmpOtherPlayer.GetTeam() == team) + if (QueryPlayerIDInterface(i, IID_Diplomacy)?.GetTeam() === team) teamPlayers.push(i); - } return cmpRangeManager.GetUnionPercentMapExplored(teamPlayers); }; @@ -449,23 +451,25 @@ StatisticsTracker.prototype.GetTeamPercentMapControlled = function() { - let cmpPlayer = Engine.QueryInterface(this.entity, IID_Player); - if (!cmpPlayer) + const cmpDiplomacy = Engine.QueryInterface(this.entity, IID_Diplomacy); + if (!cmpDiplomacy) return 0; - let team = cmpPlayer.GetTeam(); - let cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager); - if (team == -1 || !cmpPlayer.GetLockTeams()) + const team = cmpDiplomacy.GetTeam(); + const cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager); + if (team === -1 || !cmpDiplomacy.IsTeamLocked()) + { + let cmpPlayer = Engine.QueryInterface(this.entity, IID_Player); + if (!cmpPlayer) + return 0; return cmpTerritoryManager.GetTerritoryPercentage(cmpPlayer.GetPlayerID()); + } let teamPercent = 0; - let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); + const numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); for (let i = 1; i < numPlayers; ++i) - { - let cmpOtherPlayer = QueryPlayerIDInterface(i); - if (cmpOtherPlayer && cmpOtherPlayer.GetTeam() == team) + if (QueryPlayerIDInterface(i, IID_Diplomacy)?.GetTeam() === team) teamPercent += cmpTerritoryManager.GetTerritoryPercentage(i); - } return teamPercent; }; Index: ps/trunk/binaries/data/mods/public/simulation/components/TerritoryDecay.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/TerritoryDecay.js +++ ps/trunk/binaries/data/mods/public/simulation/components/TerritoryDecay.js @@ -35,6 +35,11 @@ if (!cmpPlayer) return true;// something without ownership can't decay + const playerID = cmpPlayer.GetPlayerID(); + const cmpDiplomacy = QueryPlayerIDInterface(playerID, IID_Diplomacy); + if (!cmpDiplomacy) + return true; + const decayTerritory = ApplyValueModificationsToEntity("TerritoryDecay/Territory", this.template.Territory, this.entity); var cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager); @@ -43,11 +48,11 @@ if (tileOwner == 0) { this.connectedNeighbours[0] = 1; - return cmpPlayer.GetPlayerID() == 0 || decayTerritory.indexOf("neutral") === -1; + return playerID == 0 || decayTerritory.indexOf("neutral") === -1; } var tileConnected = cmpTerritoryManager.IsConnected(pos.x, pos.y); - if (tileConnected && !cmpPlayer.IsMutualAlly(tileOwner)) + if (tileConnected && !cmpDiplomacy.IsMutualAlly(tileOwner)) { this.connectedNeighbours[tileOwner] = 1; return decayTerritory.indexOf("enemy") === -1; @@ -58,7 +63,7 @@ // Special-case: if the tile is unconnected, non-own territory, decay towards gaia. // TODO: this is not great, see #4749 - if (cmpPlayer.GetPlayerID() != tileOwner) + if (playerID != tileOwner) { this.connectedNeighbours[0] = 1; return false; @@ -68,7 +73,7 @@ let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); for (var i = 1; i < numPlayers; ++i) - if (this.connectedNeighbours[i] > 0 && cmpPlayer.IsMutualAlly(i)) + if (this.connectedNeighbours[i] > 0 && cmpDiplomacy.IsMutualAlly(i)) { // don't decay if connected to a connected ally; disable blinking cmpTerritoryManager.SetTerritoryBlinking(pos.x, pos.y, false); Index: ps/trunk/binaries/data/mods/public/simulation/components/Trader.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/Trader.js +++ ps/trunk/binaries/data/mods/public/simulation/components/Trader.js @@ -181,10 +181,10 @@ !(cmpTraderIdentity.HasClass("Ship") && cmpTargetMarket.HasType("naval"))) return false; - let cmpTraderPlayer = QueryOwnerInterface(this.entity, IID_Player); + let cmpTraderDiplomacy = QueryOwnerInterface(this.entity, IID_Diplomacy); let cmpTargetPlayer = QueryOwnerInterface(target, IID_Player); - return cmpTraderPlayer && cmpTargetPlayer && !cmpTraderPlayer.IsEnemy(cmpTargetPlayer.GetPlayerID()); + return cmpTraderPlayer && cmpTargetPlayer && !cmpTraderDiplomacy.IsEnemy(cmpTargetPlayer.GetPlayerID()); }; Trader.prototype.AddResources = function(ent, gain) Index: ps/trunk/binaries/data/mods/public/simulation/components/UnitAI.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/UnitAI.js +++ ps/trunk/binaries/data/mods/public/simulation/components/UnitAI.js @@ -3764,12 +3764,11 @@ this.losRangeQuery = undefined; } - let cmpPlayer = QueryOwnerInterface(this.entity); - // If we are being destructed (owner == -1), creating a range query is pointless. - if (!cmpPlayer) + const cmpDiplomacy = QueryOwnerInterface(this.entity, IID_Diplomacy); + if (!cmpDiplomacy) return; - let players = cmpPlayer.GetEnemies(); + const players = cmpDiplomacy.GetEnemies(); if (!players.length) return; @@ -3798,13 +3797,12 @@ this.losHealRangeQuery = undefined; } - let cmpPlayer = QueryOwnerInterface(this.entity); - // If we are being destructed (owner == -1), creating a range query is pointless. - if (!cmpPlayer) + const cmpDiplomacy = QueryOwnerInterface(this.entity, IID_Diplomacy); + if (!cmpDiplomacy) return; - let players = cmpPlayer.GetAllies(); - let range = this.GetQueryRange(IID_Heal); + const players = cmpDiplomacy.GetAllies(); + const range = this.GetQueryRange(IID_Heal); // Do not compensate for entity sizes: LOS doesn't, and UnitAI relies on that. this.losHealRangeQuery = cmpRangeManager.CreateActiveQuery(this.entity, @@ -3830,13 +3828,12 @@ this.losAttackRangeQuery = undefined; } - let cmpPlayer = QueryOwnerInterface(this.entity); - // If we are being destructed (owner == -1), creating a range query is pointless. - if (!cmpPlayer) + const cmpDiplomacy = QueryOwnerInterface(this.entity, IID_Diplomacy); + if (!cmpDiplomacy) return; // TODO: How to handle neutral players - Special query to attack military only? - let players = cmpPlayer.GetEnemies(); + const players = cmpDiplomacy.GetEnemies(); if (!players.length) return; @@ -4470,8 +4467,8 @@ let maxDifference = 40; let owner = cmpOwnership.GetOwner(); - let cmpPlayer = QueryOwnerInterface(this.entity); - let players = cmpPlayer && cmpPlayer.HasSharedDropsites() ? cmpPlayer.GetMutualAllies() : [owner]; + let cmpDiplomacy = QueryOwnerInterface(this.entity, IID_Diplomacy); + let players = cmpDiplomacy && cmpDiplomacy.HasSharedDropsites() ? cmpDiplomacy.GetMutualAllies() : [owner]; let nearestDropsites = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).ExecuteQuery(this.entity, 0, -1, players, IID_ResourceDropsite, false); let isShip = Engine.QueryInterface(this.entity, IID_Identity).HasClass("Ship"); Index: ps/trunk/binaries/data/mods/public/simulation/components/interfaces/Diplomacy.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/interfaces/Diplomacy.js +++ ps/trunk/binaries/data/mods/public/simulation/components/interfaces/Diplomacy.js @@ -0,0 +1,7 @@ +Engine.RegisterInterface("Diplomacy"); + +/** + * Message of the form { "player": number, "otherPlayer": number } + * sent from Diplomacy component when diplomacy changed for one player or between two players. + */ +Engine.RegisterMessageType("DiplomacyChanged"); Index: ps/trunk/binaries/data/mods/public/simulation/components/interfaces/Player.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/interfaces/Player.js +++ ps/trunk/binaries/data/mods/public/simulation/components/interfaces/Player.js @@ -1,10 +1,4 @@ /** - * Message of the form { "player": number, "otherPlayer": number } - * sent from Player component when diplomacy changed for one player or between two players. - */ -Engine.RegisterMessageType("DiplomacyChanged"); - -/** * Message of the form {} * sent from Player component. */ Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Attack.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Attack.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Attack.js @@ -26,6 +26,7 @@ Engine.LoadHelperScript("ValueModification.js"); Engine.LoadComponentScript("interfaces/Auras.js"); Engine.LoadComponentScript("interfaces/Capturable.js"); +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/ModifiersManager.js"); Engine.LoadComponentScript("interfaces/Formation.js"); Engine.LoadComponentScript("interfaces/Health.js"); @@ -45,6 +46,9 @@ AddMock(playerEnt1, IID_Player, { "GetPlayerID": () => 1, + }); + + AddMock(playerEnt1, IID_Diplomacy, { "IsEnemy": () => isEnemy }); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Auras.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Auras.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Auras.js @@ -1,6 +1,7 @@ Engine.LoadHelperScript("Player.js"); Engine.LoadHelperScript("ValueModification.js"); Engine.LoadComponentScript("interfaces/Auras.js"); +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/RangeOverlayManager.js"); Engine.LoadComponentScript("interfaces/TechnologyManager.js"); Engine.LoadComponentScript("interfaces/ModifiersManager.js"); @@ -52,19 +53,25 @@ }); AddMock(playerEnt[1], IID_Player, { - "IsAlly": id => id == playerID[1] || id == playerID[2], - "IsEnemy": id => id != playerID[1] || id != playerID[2], "GetPlayerID": () => playerID[1], "IsDefeated": () => playerDefeated[1] }); - AddMock(playerEnt[2], IID_Player, { + AddMock(playerEnt[1], IID_Diplomacy, { "IsAlly": id => id == playerID[1] || id == playerID[2], "IsEnemy": id => id != playerID[1] || id != playerID[2], + }); + + AddMock(playerEnt[2], IID_Player, { "GetPlayerID": () => playerID[2], "IsDefeated": () => playerDefeated[2] }); + AddMock(playerEnt[2], IID_Diplomacy, { + "IsAlly": id => id == playerID[1] || id == playerID[2], + "IsEnemy": id => id != playerID[1] || id != playerID[2], + }); + AddMock(targetEnt, IID_Identity, { "GetClassesList": () => ["CorrectClass", "OtherClass"] }); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Builder.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Builder.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Builder.js @@ -1,6 +1,7 @@ Engine.LoadHelperScript("Player.js"); Engine.LoadComponentScript("interfaces/Builder.js"); Engine.LoadComponentScript("interfaces/Cost.js"); +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/Foundation.js"); Engine.LoadComponentScript("interfaces/Health.js"); Engine.LoadComponentScript("interfaces/Repairable.js"); @@ -110,7 +111,7 @@ "Entities": { "_string": "" } }); - AddMock(playerEntityID, IID_Player, { + AddMock(playerEntityID, IID_Diplomacy, { "IsAlly": (p) => p == playerId }); @@ -140,7 +141,7 @@ function testRepairing() { - AddMock(playerEntityID, IID_Player, { + AddMock(playerEntityID, IID_Diplomacy, { "IsAlly": (p) => p == playerId }); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Capturable.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Capturable.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Capturable.js @@ -2,6 +2,7 @@ Engine.LoadHelperScript("ValueModification.js"); Engine.LoadComponentScript("interfaces/Auras.js"); Engine.LoadComponentScript("interfaces/Capturable.js"); +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/GarrisonHolder.js"); Engine.LoadComponentScript("interfaces/StatisticsTracker.js"); Engine.LoadComponentScript("interfaces/ModifiersManager.js"); @@ -48,19 +49,19 @@ "Activate": () => {} }); - AddMock(10, IID_Player, { + AddMock(10, IID_Diplomacy, { "IsEnemy": id => id != 0 }); - AddMock(11, IID_Player, { + AddMock(11, IID_Diplomacy, { "IsEnemy": id => id != 1 && id != 2 }); - AddMock(12, IID_Player, { + AddMock(12, IID_Diplomacy, { "IsEnemy": id => id != 1 && id != 2 }); - AddMock(13, IID_Player, { + AddMock(13, IID_Diplomacy, { "IsEnemy": id => id != 3 }); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Damage.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Damage.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Damage.js @@ -16,6 +16,7 @@ Engine.LoadHelperScript("Position.js"); Engine.LoadHelperScript("ValueModification.js"); Engine.LoadComponentScript("interfaces/DelayedDamage.js"); +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/Health.js"); Engine.LoadComponentScript("interfaces/Loot.js"); Engine.LoadComponentScript("interfaces/Promotion.js"); @@ -77,7 +78,7 @@ "direction": new Vector3D(1, 0, 0) }; - AddMock(atkPlayerEntity, IID_Player, { + AddMock(atkPlayerEntity, IID_Diplomacy, { "GetEnemies": () => [targetOwner] }); @@ -161,7 +162,7 @@ TestDamage(); atkPlayerEntity = 1; - AddMock(atkPlayerEntity, IID_Player, { + AddMock(atkPlayerEntity, IID_Diplomacy, { "GetEnemies": () => [2, 3] }); TS_ASSERT_UNEVAL_EQUALS(AttackHelper.GetPlayersToDamage(atkPlayerEntity, true), [0, 1, 2, 3, 4]); @@ -199,7 +200,7 @@ let hitEnts = new Set(); - AddMock(attackerOwner, IID_Player, { + AddMock(attackerOwner, IID_Diplomacy, { "GetEnemies": () => [2] }); @@ -295,7 +296,7 @@ return 1 - r * r / (radius * radius); }; - AddMock(attackerOwner, IID_Player, { + AddMock(attackerOwner, IID_Diplomacy, { "GetEnemies": () => [2] }); @@ -474,7 +475,7 @@ "IsInWorld": () => true, }); - AddMock(10, IID_Player, { + AddMock(10, IID_Diplomacy, { "GetEnemies": () => [2] }); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Diplomacy.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Diplomacy.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Diplomacy.js @@ -0,0 +1,79 @@ +Engine.LoadComponentScript("interfaces/Diplomacy.js"); +Engine.LoadComponentScript("interfaces/PlayerManager.js"); +Engine.LoadComponentScript("Diplomacy.js"); +Engine.LoadHelperScript("Player.js"); + +const players = [10, 11]; + +ConstructComponent(players[0], "Diplomacy", null) +const cmpDiplomacy = ConstructComponent(players[1], "Diplomacy", {}) +TS_ASSERT_EQUALS(cmpDiplomacy.GetTeam(), -1); +TS_ASSERT_UNEVAL_EQUALS(cmpDiplomacy.GetAllies(), []); +TS_ASSERT_UNEVAL_EQUALS(cmpDiplomacy.GetEnemies(), []); + +AddMock(SYSTEM_ENTITY, IID_PlayerManager, { + "GetNumPlayers": () => players.length, + "GetPlayerByID": (i) => players[i] +}); + +for (const player in players) + AddMock(players[player], IID_Player, { + "GetPlayerID": () => player, + "IsActive": () => true, + }); + +cmpDiplomacy.ChangeTeam(1); +TS_ASSERT_EQUALS(cmpDiplomacy.GetTeam(), 1); +TS_ASSERT_UNEVAL_EQUALS(cmpDiplomacy.GetAllies(), [1]); +TS_ASSERT_UNEVAL_EQUALS(cmpDiplomacy.GetEnemies(), []); + +cmpDiplomacy.LockTeam(); +cmpDiplomacy.ChangeTeam(2); +TS_ASSERT_EQUALS(cmpDiplomacy.GetTeam(), 1); + +cmpDiplomacy.UnLockTeam(); +cmpDiplomacy.SetEnemy(0); + +TS_ASSERT(!cmpDiplomacy.IsAlly(0)); +TS_ASSERT(!cmpDiplomacy.IsNeutral(0)); +TS_ASSERT(cmpDiplomacy.IsEnemy(0)); +TS_ASSERT_UNEVAL_EQUALS(cmpDiplomacy.GetAllies(), [1]); +TS_ASSERT_UNEVAL_EQUALS(cmpDiplomacy.GetEnemies(), [0]); + +cmpDiplomacy.Ally(0); + +TS_ASSERT(cmpDiplomacy.IsAlly(0)); +TS_ASSERT(!cmpDiplomacy.IsNeutral(0)); +TS_ASSERT(!cmpDiplomacy.IsEnemy(0)); +TS_ASSERT_UNEVAL_EQUALS(cmpDiplomacy.GetAllies(), [0, 1]); +TS_ASSERT_UNEVAL_EQUALS(cmpDiplomacy.GetEnemies(), []); +TS_ASSERT_UNEVAL_EQUALS(cmpDiplomacy.GetMutualAllies(), [1]); + +cmpDiplomacy.SetNeutral(0); + +TS_ASSERT(!cmpDiplomacy.IsAlly(0)); +TS_ASSERT(cmpDiplomacy.IsNeutral(0)); +TS_ASSERT(!cmpDiplomacy.IsEnemy(0)); + +// Mutual worsening of relations. +cmpDiplomacy.OnDiplomacyChanged({ + "player": 0, + "otherPlayer": 1, + "value": -1 +}); +TS_ASSERT(cmpDiplomacy.IsEnemy(0)); + + +cmpDiplomacy.SetDiplomacy([-1, 1, 0, 1, -1]); +TS_ASSERT_UNEVAL_EQUALS(cmpDiplomacy.GetAllies(), [1, 3]); +TS_ASSERT_UNEVAL_EQUALS(cmpDiplomacy.GetEnemies(), [0, 4]); + +// Check diplomacy is not editable outside of the component. +var diplo = cmpDiplomacy.GetDiplomacy(); +diplo[0] = 1; +TS_ASSERT(cmpDiplomacy.IsEnemy(0)); + +diplo = [1, 1, 0]; +cmpDiplomacy.SetDiplomacy(diplo); +diplo[1] = -1; +TS_ASSERT(cmpDiplomacy.IsAlly(1)); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js @@ -1,5 +1,6 @@ Engine.LoadHelperScript("ValueModification.js"); Engine.LoadHelperScript("Player.js"); +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/Garrisonable.js"); Engine.LoadComponentScript("interfaces/GarrisonHolder.js"); Engine.LoadComponentScript("interfaces/Health.js"); @@ -31,16 +32,14 @@ "GetOwner": () => player }); -AddMock(player, IID_Player, { +AddMock(player, IID_Diplomacy, { "IsAlly": id => id != enemyPlayer, "IsMutualAlly": id => id != enemyPlayer, - "GetPlayerID": () => player }); -AddMock(friendlyPlayer, IID_Player, { +AddMock(friendlyPlayer, IID_Diplomacy, { "IsAlly": id => true, "IsMutualAlly": id => true, - "GetPlayerID": () => friendlyPlayer }); AddMock(SYSTEM_ENTITY, IID_Timer, { Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Garrisoning.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Garrisoning.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Garrisoning.js @@ -1,6 +1,7 @@ Engine.LoadHelperScript("ValueModification.js"); Engine.LoadHelperScript("Player.js"); Engine.LoadHelperScript("Position.js"); +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/Garrisonable.js"); Engine.LoadComponentScript("interfaces/GarrisonHolder.js"); Engine.LoadComponentScript("interfaces/Health.js"); @@ -50,16 +51,14 @@ "GetOwner": () => player }); -AddMock(player, IID_Player, { +AddMock(player, IID_Diplomacy, { "IsAlly": id => id != enemyPlayer, "IsMutualAlly": id => id != enemyPlayer, - "GetPlayerID": () => player }); -AddMock(friendlyPlayer, IID_Player, { +AddMock(friendlyPlayer, IID_Diplomacy, { "IsAlly": id => true, "IsMutualAlly": id => true, - "GetPlayerID": () => friendlyPlayer }); AddMock(SYSTEM_ENTITY, IID_Timer, { Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Gate.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Gate.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Gate.js @@ -1,3 +1,4 @@ +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/Gate.js"); Engine.LoadComponentScript("interfaces/UnitAI.js"); Engine.LoadComponentScript("Gate.js"); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js @@ -7,6 +7,7 @@ Engine.LoadComponentScript("interfaces/Capturable.js"); Engine.LoadComponentScript("interfaces/CeasefireManager.js"); Engine.LoadComponentScript("interfaces/DeathDamage.js"); +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/EndGameManager.js"); Engine.LoadComponentScript("interfaces/EntityLimits.js"); Engine.LoadComponentScript("interfaces/Formation.js"); @@ -111,20 +112,23 @@ "GetPanelEntities": function() { return []; }, "IsTrainingBlocked": function() { return false; }, "GetState": function() { return "active"; }, - "GetTeam": function() { return -1; }, - "GetLockTeams": function() { return false; }, "GetCheatsEnabled": function() { return false; }, - "GetDiplomacy": function() { return [-1, 1]; }, - "IsAlly": function() { return false; }, - "IsMutualAlly": function() { return false; }, - "IsNeutral": function() { return false; }, - "IsEnemy": function() { return true; }, "GetDisabledTemplates": function() { return {}; }, "GetDisabledTechnologies": function() { return {}; }, "CanBarter": function() { return false; }, - "GetSpyCostMultiplier": function() { return 1; }, - "HasSharedDropsites": function() { return false; }, - "HasSharedLos": function() { return false; } + "GetSpyCostMultiplier": function() { return 1; } +}); + +AddMock(100, IID_Diplomacy, { + "GetTeam": () => -1, + "IsTeamLocked": () => false, + "GetDiplomacy": () => [-1, 1], + "IsAlly": () => false, + "IsMutualAlly": () => false, + "IsNeutral": () => false, + "IsEnemy": () => true, + "HasSharedDropsites": () => false, + "HasSharedLos": () => false, }); AddMock(100, IID_Identity, { @@ -204,20 +208,23 @@ "GetPanelEntities": function() { return []; }, "IsTrainingBlocked": function() { return false; }, "GetState": function() { return "active"; }, - "GetTeam": function() { return -1; }, - "GetLockTeams": function() {return false; }, "GetCheatsEnabled": function() { return false; }, - "GetDiplomacy": function() { return [-1, 1]; }, - "IsAlly": function() { return true; }, - "IsMutualAlly": function() {return false; }, - "IsNeutral": function() { return false; }, - "IsEnemy": function() { return false; }, "GetDisabledTemplates": function() { return {}; }, "GetDisabledTechnologies": function() { return {}; }, "CanBarter": function() { return false; }, "GetSpyCostMultiplier": function() { return 1; }, - "HasSharedDropsites": function() { return false; }, - "HasSharedLos": function() { return false; } +}); + +AddMock(101, IID_Diplomacy, { + "GetTeam": () => -1, + "IsTeamLocked": () => false, + "GetDiplomacy": () => [-1, 1], + "IsAlly": () => true, + "IsMutualAlly": () => false, + "IsNeutral": () => false, + "IsEnemy": () => false, + "HasSharedDropsites": () => false, + "HasSharedLos": () => false, }); AddMock(101, IID_Identity, { @@ -305,7 +312,7 @@ "trainingBlocked": false, "state": "active", "team": -1, - "teamsLocked": false, + "teamLocked": false, "cheatsEnabled": false, "disabledTemplates": {}, "disabledTechnologies": {}, @@ -356,7 +363,7 @@ "trainingBlocked": false, "state": "active", "team": -1, - "teamsLocked": false, + "teamLocked": false, "cheatsEnabled": false, "disabledTemplates": {}, "disabledTechnologies": {}, @@ -417,7 +424,7 @@ "trainingBlocked": false, "state": "active", "team": -1, - "teamsLocked": false, + "teamLocked": false, "cheatsEnabled": false, "disabledTemplates": {}, "disabledTechnologies": {}, @@ -491,7 +498,7 @@ "trainingBlocked": false, "state": "active", "team": -1, - "teamsLocked": false, + "teamLocked": false, "cheatsEnabled": false, "disabledTemplates": {}, "disabledTechnologies": {}, Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Heal.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Heal.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Heal.js @@ -1,5 +1,6 @@ Engine.LoadHelperScript("ValueModification.js"); Engine.LoadHelperScript("Player.js"); +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/Formation.js"); Engine.LoadComponentScript("interfaces/Heal.js"); Engine.LoadComponentScript("interfaces/Health.js"); @@ -39,11 +40,11 @@ "GetPlayerByID": () => player }); -AddMock(player, IID_Player, { +AddMock(player, IID_Diplomacy, { "IsAlly": (p) => p == player }); -AddMock(otherPlayer, IID_Player, { +AddMock(otherPlayer, IID_Diplomacy, { "IsAlly": (p) => p == player }); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Player.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Player.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Player.js @@ -47,19 +47,6 @@ TS_ASSERT_EQUALS(cmpPlayer.GetPopulationCount(), 0); TS_ASSERT_EQUALS(cmpPlayer.GetPopulationLimit(), 0); -cmpPlayer.SetDiplomacy([-1, 1, 0, 1, -1]); -TS_ASSERT_UNEVAL_EQUALS(cmpPlayer.GetAllies(), [1, 3]); -TS_ASSERT_UNEVAL_EQUALS(cmpPlayer.GetEnemies(), [0, 4]); - -var diplo = cmpPlayer.GetDiplomacy(); -diplo[0] = 1; -TS_ASSERT(cmpPlayer.IsEnemy(0)); - -diplo = [1, 1, 0]; -cmpPlayer.SetDiplomacy(diplo); -diplo[1] = -1; -TS_ASSERT(cmpPlayer.IsAlly(1)); - TS_ASSERT_EQUALS(cmpPlayer.GetSpyCostMultiplier(), 1); TS_ASSERT_UNEVAL_EQUALS(cmpPlayer.GetBarterMultiplier(), { "buy": { Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_TurretHolder.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_TurretHolder.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_TurretHolder.js @@ -1,4 +1,5 @@ Engine.LoadHelperScript("Player.js"); +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/TurretHolder.js"); Engine.LoadComponentScript("interfaces/Turretable.js"); Engine.LoadComponentScript("interfaces/UnitAI.js"); @@ -38,16 +39,14 @@ }); } -AddMock(player, IID_Player, { +AddMock(player, IID_Diplomacy, { "IsAlly": id => id != enemyPlayer, "IsMutualAlly": id => id != enemyPlayer, - "GetPlayerID": () => player }); -AddMock(alliedPlayer, IID_Player, { +AddMock(alliedPlayer, IID_Diplomacy, { "IsAlly": id => true, "IsMutualAlly": id => true, - "GetPlayerID": () => alliedPlayer }); let cmpTurretHolder = ConstructComponent(turretHolderID, "TurretHolder", { Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Turrets.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Turrets.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Turrets.js @@ -1,6 +1,7 @@ Engine.LoadHelperScript("ValueModification.js"); Engine.LoadHelperScript("Player.js"); Engine.LoadHelperScript("Position.js"); +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/Health.js"); Engine.LoadComponentScript("interfaces/Turretable.js"); Engine.LoadComponentScript("interfaces/TurretHolder.js"); @@ -47,16 +48,14 @@ "GetOwner": () => player }); -AddMock(player, IID_Player, { +AddMock(player, IID_Diplomacy, { "IsAlly": id => id != enemyPlayer, "IsMutualAlly": id => id != enemyPlayer, - "GetPlayerID": () => player }); -AddMock(friendlyPlayer, IID_Player, { +AddMock(friendlyPlayer, IID_Diplomacy, { "IsAlly": id => true, "IsMutualAlly": id => true, - "GetPlayerID": () => friendlyPlayer }); AddMock(SYSTEM_ENTITY, IID_PlayerManager, { Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js @@ -5,6 +5,7 @@ Engine.LoadComponentScript("interfaces/Builder.js"); Engine.LoadComponentScript("interfaces/BuildingAI.js"); Engine.LoadComponentScript("interfaces/Capturable.js"); +Engine.LoadComponentScript("interfaces/Diplomacy.js"); Engine.LoadComponentScript("interfaces/Garrisonable.js"); Engine.LoadComponentScript("interfaces/Resistance.js"); Engine.LoadComponentScript("interfaces/Formation.js"); @@ -144,7 +145,7 @@ "GetNumPlayers": function() { return 2; }, }); - AddMock(playerEntity, IID_Player, { + AddMock(playerEntity, IID_Diplomacy, { "IsAlly": function() { return false; }, "IsEnemy": function() { return true; }, "GetEnemies": function() { return [2]; }, @@ -327,7 +328,7 @@ "IsInTargetRange": (ent, target, min, max) => true }); - AddMock(playerEntity, IID_Player, { + AddMock(playerEntity, IID_Diplomacy, { "IsAlly": function() { return false; }, "IsEnemy": function() { return true; }, "GetEnemies": function() { return [2]; }, Index: ps/trunk/binaries/data/mods/public/simulation/helpers/Attack.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/helpers/Attack.js +++ ps/trunk/binaries/data/mods/public/simulation/helpers/Attack.js @@ -218,7 +218,7 @@ AttackHelper.prototype.GetPlayersToDamage = function(attackerOwner, friendlyFire) { if (!friendlyFire) - return QueryPlayerIDInterface(attackerOwner).GetEnemies(); + return QueryPlayerIDInterface(attackerOwner, IID_Diplomacy).GetEnemies(); return Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetAllPlayers(); }; Index: ps/trunk/binaries/data/mods/public/simulation/helpers/Commands.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/helpers/Commands.js +++ ps/trunk/binaries/data/mods/public/simulation/helpers/Commands.js @@ -88,28 +88,29 @@ "diplomacy": function(player, cmd, data) { - let cmpCeasefireManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_CeasefireManager); - if (data.cmpPlayer.GetLockTeams() || - cmpCeasefireManager && cmpCeasefireManager.IsCeasefireActive()) + if (Engine.QueryInterface(SYSTEM_ENTITY, IID_CeasefireManager).IsCeasefireActive()) + return; + + const cmpDiplomacy = QueryPlayerIDInterface(player, IID_Diplomacy); + if (!cmpDiplomacy || cmpDiplomacy.IsTeamLocked()) return; switch(cmd.to) { case "ally": - data.cmpPlayer.SetAlly(cmd.player); + cmpDiplomacy.Ally(cmd.player); break; case "neutral": - data.cmpPlayer.SetNeutral(cmd.player); + cmpDiplomacy.SetNeutral(cmd.player); break; case "enemy": - data.cmpPlayer.SetEnemy(cmd.player); + cmpDiplomacy.SetEnemy(cmd.player); break; default: warn("Invalid command: Could not set "+player+" diplomacy status of player "+cmd.player+" to "+cmd.to); } - var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); - cmpGuiInterface.PushNotification({ + Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface).PushNotification({ "type": "diplomacy", "players": [player], "targetPlayer": cmd.player, Index: ps/trunk/binaries/data/mods/public/simulation/helpers/Player.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/helpers/Player.js +++ ps/trunk/binaries/data/mods/public/simulation/helpers/Player.js @@ -107,9 +107,9 @@ // If diplomacy explicitly defined, use that; otherwise use teams. const diplomacy = getPlayerSetting(i, "Diplomacy"); if (diplomacy !== undefined) - cmpPlayer.SetDiplomacy(diplomacy); + QueryPlayerIDInterface(i, IID_Diplomacy).SetDiplomacy(diplomacy); else - cmpPlayer.SetTeam(getPlayerSetting(i, "Team") ?? -1); + QueryPlayerIDInterface(i, IID_Diplomacy).ChangeTeam(getPlayerSetting(i, "Team") ?? -1); const formations = getPlayerSetting(i, "Formations"); if (formations) @@ -120,11 +120,11 @@ cmpPlayer.SetStartingCamera(startCam.Position, startCam.Rotation); } - // NOTE: We need to do the team locking here, as otherwise - // SetTeam can't ally the players. + // NOTE: We need to do the team locking here, as + // otherwise we can't ally the players above. if (settings.LockTeams) for (let i = 0; i < numPlayers; ++i) - QueryPlayerIDInterface(i).SetLockTeams(true); + QueryPlayerIDInterface(i, IID_Diplomacy).LockTeam(); } function GetPlayerTemplateName(civ) @@ -232,21 +232,8 @@ function IsOwnedByEntityHelper(entity, target, check) { - // Figure out which player controls us - let owner = 0; - let cmpOwnership = Engine.QueryInterface(entity, IID_Ownership); - if (cmpOwnership) - owner = cmpOwnership.GetOwner(); - - // Figure out which player controls the target entity - let targetOwner = 0; - let cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership); - if (cmpOwnershipTarget) - targetOwner = cmpOwnershipTarget.GetOwner(); - - let cmpPlayer = QueryPlayerIDInterface(owner); - - return cmpPlayer && cmpPlayer[check](targetOwner); + const owner = Engine.QueryInterface(entity, IID_Ownership)?.GetOwner() || 0; + return IsOwnedByHelper(owner, target, check); } /** @@ -288,14 +275,9 @@ function IsOwnedByHelper(player, target, check) { - let targetOwner = 0; - let cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership); - if (cmpOwnershipTarget) - targetOwner = cmpOwnershipTarget.GetOwner(); - - let cmpPlayer = QueryPlayerIDInterface(player); - - return cmpPlayer && cmpPlayer[check](targetOwner); + const targetOwner = Engine.QueryInterface(target, IID_Ownership)?.GetOwner() || 0; + const cmpDiplomacy = QueryPlayerIDInterface(player, IID_Diplomacy); + return cmpDiplomacy && cmpDiplomacy[check](targetOwner); } Engine.RegisterGlobal("LoadPlayerSettings", LoadPlayerSettings); Index: ps/trunk/binaries/data/mods/public/simulation/templates/special/players/gaia.xml =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/templates/special/players/gaia.xml +++ ps/trunk/binaries/data/mods/public/simulation/templates/special/players/gaia.xml @@ -1,5 +1,9 @@ + + + + gaia Gaia @@ -7,8 +11,6 @@ true - - 1.0 Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_player.xml =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/templates/template_player.xml +++ ps/trunk/binaries/data/mods/public/simulation/templates/template_player.xml @@ -13,6 +13,10 @@ 0 8 + + unlock_shared_los + unlock_shared_dropsites + 50 @@ -70,8 +74,6 @@ 1.0 - unlock_shared_los - unlock_shared_dropsites 1.0 special/formations/null