diff --git a/binaries/data/mods/public/simulation/components/Player.js b/binaries/data/mods/public/simulation/components/Player.js index 29d4fe272a..27041b2cf7 100644 --- a/binaries/data/mods/public/simulation/components/Player.js +++ b/binaries/data/mods/public/simulation/components/Player.js @@ -22,11 +22,12 @@ Player.prototype.Init = function() 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.state = "active"; // game state - one of "active", "defeated", "won" - this.diplomacy = []; // array of diplomatic stances for this player with respect to other players (including self) + this.diplomacy = []; // array of diplomatic stances for this player with respect to other players (including gaia and self) this.conquestCriticalEntitiesCount = 0; // number of owned units with ConquestCritical class this.phase = "village"; this.startCam = undefined; this.controlAllUnits = false; + this.isAI = false; }; Player.prototype.SetPlayerID = function(id) @@ -235,56 +236,90 @@ Player.prototype.SetPhase = function(p) Player.prototype.GetStartingCameraPos = function() { return this.startCam.position; -} +}; Player.prototype.GetStartingCameraRot = function() { return this.startCam.rotation; -} +}; Player.prototype.SetStartingCamera = function(pos, rot) { this.startCam = {"position": pos, "rotation": rot}; -} +}; Player.prototype.HasStartingCamera = function() { return (this.startCam !== undefined); -} +}; Player.prototype.SetControlAllUnits = function(c) { this.controlAllUnits = c; -} +}; Player.prototype.CanControlAllUnits = function() { return this.controlAllUnits; -} +}; + +Player.prototype.SetAI = function(flag) +{ + this.isAI = flag; +}; + +Player.prototype.IsAI = function() +{ + return this.isAI; +}; + +Player.prototype.SetAlly = function(id) +{ + if (id >= 0 && id != this.playerID) + { + this.diplomacy[id] = 1; + } +}; /** * Check if given player is our ally */ Player.prototype.IsAlly = function(id) { - return (id >= 0 && (id == this.playerID || this.diplomacy[id] > 0)); -} + return (id >= 0 && id < this.diplomacy.length && (id == this.playerID || this.diplomacy[id] > 0)); +}; + +Player.prototype.SetEnemy = function(id) +{ + if (id >= 0 && id != this.playerID) + { + this.diplomacy[id] = -1; + } +}; /** * Check if given player is our enemy */ Player.prototype.IsEnemy = function(id) { - return (id >= 0 && id != this.playerID && this.diplomacy[id] < 0); -} + return (id >= 0 && id < this.diplomacy.length && id != this.playerID && this.diplomacy[id] < 0); +}; + +Player.prototype.SetNeutral = function(id) +{ + if (id >= 0 && id != this.playerID) + { + this.diplomacy[id] = 0; + } +}; /** * Check if given player is neutral */ Player.prototype.IsNeutral = function(id) { - return (id >= 0 && id != this.playerID && this.diplomacy[id] == 0); -} + return (id >= 0 && id < this.diplomacy.length && id != this.playerID && this.diplomacy[id] == 0); +}; /** * Keep track of population effects of all entities that @@ -345,6 +380,6 @@ Player.prototype.OnPlayerDefeated = function() var cmpOwnership = Engine.QueryInterface(entity, IID_Ownership); cmpOwnership.SetOwner(0); } -} +}; Engine.RegisterComponentType(IID_Player, "Player", Player); diff --git a/binaries/data/mods/public/simulation/components/PlayerManager.js b/binaries/data/mods/public/simulation/components/PlayerManager.js index 4be71ae5c8..3a05d8f8e8 100644 --- a/binaries/data/mods/public/simulation/components/PlayerManager.js +++ b/binaries/data/mods/public/simulation/components/PlayerManager.js @@ -3,13 +3,6 @@ function PlayerManager() {} PlayerManager.prototype.Schema = ""; -// Diplomatic stance constants -PlayerManager.prototype.Diplomacy = { - "ENEMY" : -1, - "NEUTRAL" : 0, - "ALLY" : 1 -}; - PlayerManager.prototype.Init = function() { this.playerEntities = []; // list of player entity IDs diff --git a/binaries/data/mods/public/simulation/helpers/Commands.js b/binaries/data/mods/public/simulation/helpers/Commands.js index 08d72d0408..9049fc0488 100644 --- a/binaries/data/mods/public/simulation/helpers/Commands.js +++ b/binaries/data/mods/public/simulation/helpers/Commands.js @@ -143,45 +143,44 @@ function ProcessCommand(player, cmd) cmpPosition.JumpTo(cmd.x, cmd.z); cmpPosition.SetYRotation(cmd.angle); - // Check whether it's obstructed by other entities or invalid terrain - var cmpBuildRestrictions = Engine.QueryInterface(ent, IID_BuildRestrictions); - if (!cmpBuildRestrictions || !cmpBuildRestrictions.CheckPlacement(player)) + // TODO: Build restrctions disabled for AI since it lacks a mechanism for checking most of them + if (!cmpPlayer.IsAI()) { - var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); - cmpGuiInterface.PushNotification({ "player": player, "message": "Building site was obstructed" }); + // Check whether it's obstructed by other entities or invalid terrain + var cmpBuildRestrictions = Engine.QueryInterface(ent, IID_BuildRestrictions); + if (!cmpBuildRestrictions || !cmpBuildRestrictions.CheckPlacement(player)) + { + var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); + cmpGuiInterface.PushNotification({ "player": player, "message": "Building site was obstructed" }); - // Remove the foundation because the construction was aborted - Engine.DestroyEntity(ent); - break; - } - - // Check build limits - var cmpBuildLimits = QueryPlayerIDInterface(player, IID_BuildLimits); - if (!cmpBuildLimits || !cmpBuildLimits.AllowedToBuild(cmpBuildRestrictions.GetCategory())) - { - // TODO: The UI should tell the user they can't build this (but we still need this check) + // Remove the foundation because the construction was aborted + Engine.DestroyEntity(ent); + break; + } - // Remove the foundation because the construction was aborted - Engine.DestroyEntity(ent); - break; + // Check build limits + var cmpBuildLimits = QueryPlayerIDInterface(player, IID_BuildLimits); + if (!cmpBuildLimits || !cmpBuildLimits.AllowedToBuild(cmpBuildRestrictions.GetCategory())) + { + // TODO: The UI should tell the user they can't build this (but we still need this check) + + // Remove the foundation because the construction was aborted + Engine.DestroyEntity(ent); + break; + } + + // Check whether it's in a visible region + var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); + var visible = (cmpRangeManager.GetLosVisibility(ent, player) == "visible"); + if (!visible) + { + // TODO: report error to player (the building site was not visible) + print("Building site was not visible\n"); + + Engine.DestroyEntity(ent); + break; + } } - - /* TODO: the AI isn't smart enough to explore before building, so we'll - * just disable the requirement that the location is visible. Should we - * fix that, or let players build in fog too, or something? - - // Check whether it's in a visible region - var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - var visible = (cmpRangeManager.GetLosVisibility(ent, player) == "visible"); - if (!visible) - { - // TODO: report error to player (the building site was not visible) - print("Building site was not visible\n"); - - Engine.DestroyEntity(ent); - break; - } - */ var cmpCost = Engine.QueryInterface(ent, IID_Cost); if (!cmpPlayer.TrySubtractResources(cmpCost.GetResourceCosts())) diff --git a/binaries/data/mods/public/simulation/helpers/Player.js b/binaries/data/mods/public/simulation/helpers/Player.js index 45d20ac3f8..a08bbe964d 100644 --- a/binaries/data/mods/public/simulation/helpers/Player.js +++ b/binaries/data/mods/public/simulation/helpers/Player.js @@ -25,7 +25,7 @@ function LoadPlayerSettings(settings) var numPlayers = 8; if (settings.PlayerData) - { //Get number of players including gaia + { // Get number of players including gaia numPlayers = settings.PlayerData.length + 1; } else @@ -35,36 +35,6 @@ function LoadPlayerSettings(settings) // Get player manager var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); - - var teams = []; - var diplomacy = []; - - // Build team + diplomacy data - for (var i = 0; i < numPlayers; ++i) - { - diplomacy[i] = cmpPlayerMan.Diplomacy.ENEMY; - - // Skip gaia - if (i > 0) - { - var pData = settings.PlayerData ? settings.PlayerData[i-1] : {}; - var pDefs = playerDefaults ? playerDefaults[i] : {}; - var team = getSetting(pData, pDefs, "Team"); - - // If team defined, add player to the team - if (team !== undefined && team != -1) - { - if (!teams[team]) - { - teams[team] = [i]; - } - else - { - teams[team].push(i); - } - } - } - } for (var i = 0; i < numPlayers; ++i) { @@ -72,13 +42,13 @@ function LoadPlayerSettings(settings) var entID = Engine.AddEntity("special/player"); // Retrieve entity - var player = Engine.QueryInterface(entID, IID_Player); - if (!player) + var cmpPlayer = Engine.QueryInterface(entID, IID_Player); + if (!cmpPlayer) { throw("Player.js: Error creating player entity "+i); } - player.SetPlayerID(i); + cmpPlayer.SetPlayerID(i); var pDefs = playerDefaults ? playerDefaults[i] : {}; @@ -88,63 +58,66 @@ function LoadPlayerSettings(settings) var pData = settings.PlayerData ? settings.PlayerData[i-1] : {}; // Copy player data - player.SetName(getSetting(pData, pDefs, "Name")); - player.SetCiv(getSetting(pData, pDefs, "Civ")); + cmpPlayer.SetName(getSetting(pData, pDefs, "Name")); + cmpPlayer.SetCiv(getSetting(pData, pDefs, "Civ")); + cmpPlayer.SetAI(pData.AI && pData.AI != ""); var colour = getSetting(pData, pDefs, "Colour"); - player.SetColour(colour.r, colour.g, colour.b); + cmpPlayer.SetColour(colour.r, colour.g, colour.b); if (getSetting(pData, pDefs, "PopulationLimit") !== undefined) { - player.SetMaxPopulation(getSetting(pData, pDefs, "PopulationLimit")); + cmpPlayer.SetMaxPopulation(getSetting(pData, pDefs, "PopulationLimit")); } if (getSetting(pData, pDefs, "Resources") !== undefined) { - player.SetResourceCounts(getSetting(pData, pDefs, "Resources")); + cmpPlayer.SetResourceCounts(getSetting(pData, pDefs, "Resources")); } - var team = getSetting(pData, pDefs, "Team"); - - //If diplomacy array exists use that, otherwise use team data or default diplomacy + // If diplomacy explicitly defined, use that; otherwise use teams if (getSetting(pData, pDefs, "Diplomacy") !== undefined) { - player.SetDiplomacy(getSetting(pData, pDefs, "Diplomacy")); - } - else if (team !== undefined && team != -1) - { - //Team exists, copy default diplomacy - var teamDiplomacy = []; - for (var p in diplomacy) - { - teamDiplomacy[p] = diplomacy[p]; - } - // Set teammates to allies - var myTeam = teams[team]; - for (var n in myTeam) - { - teamDiplomacy[myTeam[n]] = cmpPlayerMan.Diplomacy.ALLY; //Set ally - } - - player.SetDiplomacy(teamDiplomacy); + cmpPlayer.SetDiplomacy(getSetting(pData, pDefs, "Diplomacy")); } else - { //Set default - player.SetDiplomacy(diplomacy); + { + var myTeam = getSetting(pData, pDefs, "Team"); + for (var j = 0; j < numPlayers; ++j) + { + // Check if player is on same team + if (j > 0) + { + var theirTeam = getSetting(settings.PlayerData[j-1], playerDefaults[j], "Team"); + if (myTeam !== undefined && myTeam != -1 + && theirTeam !== undefined && theirTeam != -1 + && myTeam == theirTeam) + { + cmpPlayer.SetAlly(j); + continue; + } + } + // Gaia, different team, or no team defined + cmpPlayer.SetEnemy(j); + } } var startCam = getSetting(pData, pDefs, "StartingCamera"); if (startCam !== undefined) { - player.SetStartingCamera(startCam.Position, startCam.Rotation); + cmpPlayer.SetStartingCamera(startCam.Position, startCam.Rotation); } } else { // Copy gaia data from defaults - player.SetName(pDefs.Name); - player.SetCiv(pDefs.Civ); - player.SetColour(pDefs.Colour.r, pDefs.Colour.g, pDefs.Colour.b); - player.SetDiplomacy(diplomacy); + cmpPlayer.SetName(pDefs.Name); + cmpPlayer.SetCiv(pDefs.Civ); + cmpPlayer.SetColour(pDefs.Colour.r, pDefs.Colour.g, pDefs.Colour.b); + + for (var j = 0; j < numPlayers; ++j) + { // Gaia is everyone's enemy + cmpPlayer.SetEnemy(j); + } } // Add player to player manager @@ -219,7 +192,6 @@ function IsOwnedByAllyOfEntity(entity, target) if (cmpOwnershipTarget) targetOwner = cmpOwnershipTarget.GetOwner(); - // Get our diplomacy array var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); var cmpPlayer = Engine.QueryInterface(cmpPlayerMan.GetPlayerByID(owner), IID_Player); @@ -250,7 +222,6 @@ function IsOwnedByAllyOfPlayer(player, target) if (cmpOwnershipTarget) targetOwner = cmpOwnershipTarget.GetOwner(); - // Get our diplomacy array var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); var cmpPlayer = Engine.QueryInterface(cmpPlayerMan.GetPlayerByID(player), IID_Player); @@ -272,7 +243,6 @@ function IsOwnedByEnemyOfPlayer(player, target) if (cmpOwnershipTarget) targetOwner = cmpOwnershipTarget.GetOwner(); - // Get our diplomacy array var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); var cmpPlayer = Engine.QueryInterface(cmpPlayerMan.GetPlayerByID(player), IID_Player);