Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerAssignment.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerAssignment.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerAssignment.js @@ -7,6 +7,7 @@ this.clientItemFactory = new PlayerAssignmentItem.Client(); this.aiItemFactory = new PlayerAssignmentItem.AI(); this.unassignedItem = new PlayerAssignmentItem.Unassigned().createItem(); + this.removedItem = new PlayerAssignmentItem.Removed().createItem(); this.aiItems = g_Settings.AIDescriptions.filter(ai => !ai.data.hidden).map( @@ -126,7 +127,8 @@ this.values = prepareForDropdown([ ...this.playerItems, ...this.aiItems, - this.unassignedItem + this.unassignedItem, + this.removedItem ]); this.dropdown.list = this.values.Caption; @@ -215,6 +217,7 @@ playerAssignmentsControl.unassignClient(playerIndex + 1); g_GameAttributes.settings.PlayerData[playerIndex].AI = value; + g_GameAttributes.settings.PlayerData[playerIndex].Removed = false; gameSettingsControl.updateGameAttributes(); gameSettingsControl.setNetworkGameAttributes(); @@ -222,7 +225,7 @@ isSelected(pData, guid, value) { - return !guid && pData.AI && pData.AI == value; + return !guid && !pData.Removed && pData.AI && pData.AI == value; } }; @@ -251,13 +254,14 @@ playerAssignmentsControl.unassignClient(playerIndex + 1); g_GameAttributes.settings.PlayerData[playerIndex].AI = false; + g_GameAttributes.settings.PlayerData[playerIndex].Removed = false; gameSettingsControl.updateGameAttributes(); gameSettingsControl.setNetworkGameAttributes(); } isSelected(pData, guid, value) { - return !guid && !pData.AI; + return !guid && !pData.Removed && !pData.AI; } }; @@ -267,3 +271,40 @@ PlayerAssignmentItem.Unassigned.prototype.Tags = { "color": "140 140 140" }; } + +{ + + PlayerAssignmentItem.Removed = class + { + createItem() + { + return { + "Handler": this, + "Value": undefined, + "Autocomplete": this.Label, + "Caption": setStringTags(this.Label, this.Tags) + }; + } + + onSelectionChange(gameSettingsControl, playerAssignmentsControl, playerIndex) + { + playerAssignmentsControl.unassignClient(playerIndex + 1); + g_GameAttributes.settings.PlayerData[playerIndex].AI = false; + g_GameAttributes.settings.PlayerData[playerIndex].Removed = true; + gameSettingsControl.updateGameAttributes(); + gameSettingsControl.setNetworkGameAttributes(); + } + + isSelected(pData, guid, value) + { + return !guid && pData.Removed && !pData.AI; + } + }; + + + PlayerAssignmentItem.Removed.prototype.Label = + translate("Removed"); + + PlayerAssignmentItem.Removed.prototype.Tags = + { "color": "255 140 140" }; +} Index: binaries/data/mods/public/maps/random/rmgen-common/player.js =================================================================== --- binaries/data/mods/public/maps/random/rmgen-common/player.js +++ binaries/data/mods/public/maps/random/rmgen-common/player.js @@ -108,6 +108,10 @@ */ function placeCivDefaultStartingEntities(position, playerID, wallType, dist = 6, orientation = BUILDING_ORIENTATION) { + // Removed players should have no entities. + if (!!g_MapSettings.PlayerData[playerID].Removed) + return; + placeStartingEntities(position, playerID, getStartingEntities(playerID), dist, orientation); placeStartingWalls(position, playerID, wallType, orientation); } Index: binaries/data/mods/public/simulation/components/Player.js =================================================================== --- binaries/data/mods/public/simulation/components/Player.js +++ binaries/data/mods/public/simulation/components/Player.js @@ -71,6 +71,7 @@ this.startCam = undefined; this.controlAllUnits = false; this.isAI = false; + this.isRemoved = false; this.cheatsEnabled = false; this.panelEntities = []; this.resourceNames = {}; @@ -663,6 +664,16 @@ this.isAI = flag; }; +Player.prototype.SetRemoved = function(flag) +{ + this.isRemoved = flag; +}; + +Player.prototype.IsRemoved = function() +{ + return this.isRemoved; +}; + Player.prototype.IsAI = function() { return this.isAI; Index: binaries/data/mods/public/simulation/components/SkirmishReplacer.js =================================================================== --- binaries/data/mods/public/simulation/components/SkirmishReplacer.js +++ binaries/data/mods/public/simulation/components/SkirmishReplacer.js @@ -48,7 +48,7 @@ else templateName = ""; - if (!templateName || civ == "gaia") + if (!templateName || civ == "gaia" || cmpPlayer.IsRemoved()) { Engine.DestroyEntity(this.entity); return; Index: binaries/data/mods/public/simulation/helpers/InitGame.js =================================================================== --- binaries/data/mods/public/simulation/helpers/InitGame.js +++ binaries/data/mods/public/simulation/helpers/InitGame.js @@ -2,8 +2,22 @@ * Called when the map has been loaded, but before the simulation has started. * Only called when a new game is started, not when loading a saved game. */ -function PreInitGame() +function PreInitGame(settings) { + // No settings when loading a map in Atlas, so do nothing. + if (settings) + { + for (let i = 0; i < settings.PlayerData.length; ++i) + { + if (!settings.PlayerData[i]) + continue; + + let cmpPlayer = QueryPlayerIDInterface(i); + if (!!settings.PlayerData[i].Removed) + cmpPlayer.SetRemoved(true); + } + } + // We need to replace skirmish "default" entities with real ones. // This needs to happen before AI initialization (in InitGame). // And we need to flush destroyed entities otherwise the AI gets the wrong game state in Index: source/simulation2/Simulation2.cpp =================================================================== --- source/simulation2/Simulation2.cpp +++ source/simulation2/Simulation2.cpp @@ -734,7 +734,11 @@ { ScriptRequest rq(GetScriptInterface()); JS::RootedValue global(rq.cx, rq.globalValue()); - GetScriptInterface().CallFunctionVoid(global, "PreInitGame"); + JS::RootedValue settings(rq.cx); + JS::RootedValue tmpInitAttributes(rq.cx, GetInitAttributes()); + GetScriptInterface().GetProperty(tmpInitAttributes, "settings", &settings); + + GetScriptInterface().CallFunctionVoid(global, "PreInitGame", settings); } void CSimulation2::InitGame()