Index: ps/trunk/binaries/data/mods/public/gui/autostart/autostart.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/autostart/autostart.js (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/autostart/autostart.js (revision 25077) @@ -0,0 +1,17 @@ +function init(initData) +{ + let settings = new GameSettings().init(); + settings.fromInitAttributes(initData); + let assignments = { + "local": { + "player": 1, + "name": Engine.ConfigDB_GetValue("user", "playername.singleplayer") || Engine.GetSystemUsername() + } + }; + settings.launchGame(assignments); + + Engine.SwitchGuiPage("page_loading.xml", { + "attribs": settings.toInitAttributes(), + "playerAssignments": assignments + }); +} Property changes on: ps/trunk/binaries/data/mods/public/gui/autostart/autostart.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/PlayerName.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/PlayerName.js (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/PlayerName.js (revision 25077) @@ -0,0 +1,114 @@ +/** + * Stores in-game names for all players. + * + * NB: the regular gamesetup has a particular handling of this setting. + * The names are loaded from the map, but the GUI also show playernames + * and forces them when starting the game. + * This is therefore just handling map-defined names & AI random bot names. + */ +GameSettings.prototype.Attributes.PlayerName = class PlayerName extends GameSetting +{ + init() + { + // NB: watchers aren't auto-triggered when modifying array elements. + this.values = []; + this.settings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]); + this.settings.map.watch(() => this.onMapChange(), ["map"]); + } + + toInitAttributes(attribs) + { + if (!attribs.settings.PlayerData) + attribs.settings.PlayerData = []; + while (attribs.settings.PlayerData.length < this.values.length) + attribs.settings.PlayerData.push({}); + for (let i in this.values) + if (this.values[i]) + attribs.settings.PlayerData[i].Name = this.values[i]; + } + + _resize(nb) + { + while (this.values.length > nb) + this.values.pop(); + while (this.values.length < nb) + this.values.push(undefined); + } + + onMapChange() + { + // Reset. + this._resize(0); + this.maybeUpdate(); + } + + maybeUpdate() + { + this._resize(this.settings.playerCount.nbPlayers); + this.values.forEach((_, i) => this._set(i)); + this.trigger("values"); + } + + /** + * Pick bot names. + */ + pickRandomItems() + { + let picked = false; + for (let i in this.values) + { + if (!!this.values[i] && + this.values[i] !== g_Settings.PlayerDefaults[+i + 1].Name) + continue; + + let ai = this.settings.playerAI.values[i]; + if (!ai) + continue; + + let civ = this.settings.playerCiv.values[i]; + if (!civ || civ == "random") + continue; + + picked = true; + // Pick one of the available botnames for the chosen civ + // Determine botnames + let chosenName = pickRandom(this.settings.civData[civ].AINames); + + // Count how many players use the chosenName + let usedName = this.values.filter(oName => oName && oName.indexOf(chosenName) !== -1).length; + + this.values[i] = + usedName ? + sprintf(this.RomanLabel, { + "playerName": chosenName, + "romanNumber": this.RomanNumbers[usedName + 1] + }) : + chosenName; + } + if (picked) + this.trigger("values"); + return picked; + } + + _getMapData(i) + { + let data = this.settings.map.data; + if (!data || !data.settings || !data.settings.PlayerData) + return undefined; + if (data.settings.PlayerData.length <= i) + return undefined; + return data.settings.PlayerData[i].Name; + } + + _set(playerIndex) + { + this.values[playerIndex] = this._getMapData(playerIndex) || g_Settings && g_Settings.PlayerDefaults[playerIndex + 1].Name || ""; + } +}; + + +GameSettings.prototype.Attributes.PlayerName.prototype.RomanLabel = + translate("%(playerName)s %(romanNumber)s"); + +GameSettings.prototype.Attributes.PlayerName.prototype.RomanNumbers = + [undefined, "I", "II", "III", "IV", "V", "VI", "VII", "VIII"]; Property changes on: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/PlayerName.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Rating.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Rating.js (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Rating.js (revision 25077) @@ -0,0 +1,36 @@ +GameSettings.prototype.Attributes.Rating = class Rating extends GameSetting +{ + init() + { + this.hasXmppClient = Engine.HasXmppClient(); + this.settings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]); + this.maybeUpdate(); + } + + toInitAttributes(attribs) + { + if (this.available) + attribs.settings.RatingEnabled = this.enabled; + } + + fromInitAttributes(attribs) + { + if (this.getLegacySetting(attribs, "RatingEnabled")) + { + this.available = this.hasXmppClient && this.settings.playerCount.nbPlayers === 2; + this.enabled = this.available && !!this.getLegacySetting(attribs, "RatingEnabled"); + } + } + + setEnabled(enabled) + { + this.enabled = this.available && enabled; + } + + maybeUpdate() + { + // This setting is activated by default if it's possible. + this.available = this.hasXmppClient && this.settings.playerCount.nbPlayers === 2; + this.enabled = this.available; + } +}; Property changes on: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Rating.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/SeaLevelRise.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/SeaLevelRise.js (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/SeaLevelRise.js (revision 25077) @@ -0,0 +1,43 @@ +GameSettings.prototype.Attributes.SeaLevelRise = class SeaLevelRise extends GameSetting +{ + init() + { + this.min = undefined; + this.max = undefined; + this.value = undefined; + this.settings.map.watch(() => this.onMapChange(), ["map"]); + } + + toInitAttributes(attribs) + { + if (this.value) + attribs.settings.SeaLevelRiseTime = this.value; + } + + fromInitAttributes(attribs) + { + if (!!this.getLegacySetting(attribs, "SeaLevelRiseTime")) + this.setValue(this.getLegacySetting(attribs, "SeaLevelRiseTime")); + } + + onMapChange() + { + if (!this.getMapSetting("SeaLevelRise")) + { + this.value = undefined; + return; + } + let mapData = this.settings.map.data; + this.min = mapData.settings.SeaLevelRise.Min; + this.max = mapData.settings.SeaLevelRise.Max; + this.value = mapData.settings.SeaLevelRise.Default; + } + + setValue(val) + { + if (!this.getMapSetting("SeaLevelRise")) + this.value = undefined; + else + this.value = Math.max(this.min, Math.min(this.max, Math.round(val))); + } +}; Property changes on: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/SeaLevelRise.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/MapName.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/MapName.js (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/MapName.js (revision 25077) @@ -0,0 +1,36 @@ +/** + * Map name. + * This is usually just the regular map name, but can be overwritten. + */ +GameSettings.prototype.Attributes.MapName = class MapName extends GameSetting +{ + init() + { + } + + toInitAttributes(attribs) + { + if (this.value) + attribs.settings.Name = this.value; + else + { + // Copy from the map data by default - this helps make InitAttributes self-sufficient, + // which is nice for replays / saved games. + // Fallback to the map name to avoid 'undefined' errors. + attribs.settings.Name = this.settings.map?.data?.settings?.Name || this.settings.map.map; + } + } + + fromInitAttributes(attribs) + { + // Ser/Deser from a different attribute name as a poor man's not-persisted-setting. + // TODO: split this off more properly. + if (attribs.mapName) + this.value = attribs.mapName; + } + + set(name) + { + this.value = name; + } +}; Property changes on: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/MapName.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/MapSize.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/MapSize.js (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/MapSize.js (revision 25077) @@ -0,0 +1,35 @@ +GameSettings.prototype.Attributes.MapSize = class MapSize extends GameSetting +{ + init() + { + this.defaultValue = this.getDefaultValue("MapSizes", "Tiles") || 256; + this.setSize(this.defaultValue); + this.settings.map.watch(() => this.onTypeChange(), ["type"]); + } + + toInitAttributes(attribs) + { + if (this.settings.map.type === "random") + attribs.settings.Size = this.size; + } + + fromInitAttributes(attribs) + { + if (!!this.getLegacySetting(attribs, "Size")) + this.setSize(this.getLegacySetting(attribs, "Size")); + } + + setSize(size) + { + this.available = this.settings.map.type === "random"; + this.size = size; + } + + onTypeChange(old) + { + if (this.settings.map.type === "random" && old !== "random") + this.setSize(this.defaultValue); + else if (this.settings.map.type !== "random") + this.available = false; + } +}; Property changes on: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/MapSize.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Nomad.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Nomad.js (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Nomad.js (revision 25077) @@ -0,0 +1,23 @@ +GameSettings.prototype.Attributes.Nomad = class Nomad extends GameSetting +{ + init() + { + this.enabled = false; + } + + toInitAttributes(attribs) + { + if (this.settings.map.type == "random") + attribs.settings.Nomad = this.enabled; + } + + fromInitAttributes(attribs) + { + this.setEnabled(!!this.getLegacySetting(attribs, "Nomad")); + } + + setEnabled(enabled) + { + this.enabled = enabled; + } +}; Property changes on: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Nomad.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/PlayerCiv.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/PlayerCiv.js (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/PlayerCiv.js (revision 25077) @@ -0,0 +1,133 @@ +/** + * Stores civ settings for all players. + */ +GameSettings.prototype.Attributes.PlayerCiv = class PlayerCiv extends GameSetting +{ + init() + { + // NB: watchers aren't auto-triggered when modifying array elements. + this.values = []; + this.locked = []; + this.settings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]); + this.settings.map.watch(() => this.onMapChange(), ["map"]); + } + + toInitAttributes(attribs) + { + if (!attribs.settings.PlayerData) + attribs.settings.PlayerData = []; + while (attribs.settings.PlayerData.length < this.values.length) + attribs.settings.PlayerData.push({}); + for (let i in this.values) + if (this.values[i]) + attribs.settings.PlayerData[i].Civ = this.values[i]; + } + + fromInitAttributes(attribs) + { + if (!this.getLegacySetting(attribs, "PlayerData")) + return; + let pData = this.getLegacySetting(attribs, "PlayerData"); + if (this.values.length < pData.length) + this._resize(pData.length); + for (let i in pData) + if (pData[i] && pData[i].Civ) + this.setValue(i, pData[i].Civ); + } + + _resize(nb) + { + while (this.values.length > nb) + { + this.values.pop(); + this.locked.pop(); + } + while (this.values.length < nb) + { + this.values.push("random"); + this.locked.push(false); + } + } + + onMapChange() + { + // Reset. + if (this.settings.map.type == "scenario" || + this.getMapSetting("PlayerData") && + this.getMapSetting("PlayerData").some(data => data && data.Civ)) + { + this._resize(0); + this.maybeUpdate(); + } + } + + maybeUpdate() + { + this._resize(this.settings.playerCount.nbPlayers); + this.values.forEach((c, i) => this._set(i, c)); + this.trigger("values"); + } + + pickRandomItems() + { + // Get a unique array of selectable cultures + let cultures = Object.keys(this.settings.civData).filter(civ => this.settings.civData[civ].SelectableInGameSetup).map(civ => this.settings.civData[civ].Culture); + cultures = cultures.filter((culture, index) => cultures.indexOf(culture) === index); + + let picked = false; + for (let i in this.values) + { + if (this.values[i] != "random") + continue; + picked = true; + + // Pick a random civ of a random culture + let culture = pickRandom(cultures); + this.values[i] = pickRandom(Object.keys(this.settings.civData).filter(civ => + this.settings.civData[civ].Culture == culture && this.settings.civData[civ].SelectableInGameSetup)); + + } + if (picked) + this.trigger("values"); + + return picked; + } + + _getMapData(i) + { + let data = this.settings.map.data; + if (!data || !data.settings || !data.settings.PlayerData) + return undefined; + if (data.settings.PlayerData.length <= i) + return undefined; + return data.settings.PlayerData[i].Civ; + } + + _set(playerIndex, value) + { + let map = this._getMapData(playerIndex); + if (!!map) + { + this.values[playerIndex] = map; + this.locked[playerIndex] = true; + } + else + { + this.values[playerIndex] = value; + this.locked[playerIndex] = this.settings.map.type == "scenario"; + } + } + + setValue(playerIndex, val) + { + this._set(playerIndex, val); + this.trigger("values"); + } + + swap(sourceIndex, targetIndex) + { + [this.values[sourceIndex], this.values[targetIndex]] = [this.values[targetIndex], this.values[sourceIndex]]; + [this.locked[sourceIndex], this.locked[targetIndex]] = [this.locked[targetIndex], this.locked[sourceIndex]]; + this.trigger("values"); + } +}; Property changes on: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/PlayerCiv.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/PlayerCount.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/PlayerCount.js (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/PlayerCount.js (revision 25077) @@ -0,0 +1,67 @@ +GameSettings.prototype.Attributes.PlayerCount = class PlayerCount extends GameSetting +{ + init() + { + this.nbPlayers = 1; + this.settings.map.watch(() => this.onMapTypeChange(), ["type"]); + this.settings.map.watch(() => this.onMapChange(), ["map"]); + } + + toInitAttributes(attribs) + { + if (!attribs.settings.PlayerData) + attribs.settings.PlayerData = []; + while (attribs.settings.PlayerData.length < this.nbPlayers) + attribs.settings.PlayerData.push({}); + } + + fromInitAttributes(attribs) + { + if (!this.getLegacySetting(attribs, "PlayerData")) + return; + let pData = this.getLegacySetting(attribs, "PlayerData"); + if (this.nbPlayers !== pData.length) + this.nbPlayers = pData.length; + } + + onMapTypeChange(old) + { + if (this.settings.map.type == "random" && old != "random") + this.nbPlayers = 2; + } + + onMapChange() + { + if (this.settings.map.type == "random") + return; + if (!this.settings.map.data || !this.settings.map.data.settings || + !this.settings.map.data.settings.PlayerData) + return; + this.nbPlayers = this.settings.map.data.settings.PlayerData.length; + } + + reloadFromLegacy(data) + { + if (this.settings.map.type != "random") + { + this.nbPlayers = this.settings.map.data.settings.PlayerData.length; + return; + } + if (!data || !data.settings || data.settings.PlayerData === undefined) + return; + this.nbPlayers = data.settings.PlayerData.length; + } + + /** + * @param index - Player Index, 0 is 'player 1' since GAIA isn't there. + */ + get(index) + { + return this.data[index]; + } + + setNb(nb) + { + this.nbPlayers = Math.max(1, Math.min(g_MaxPlayers, nb)); + } +}; Property changes on: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/PlayerCount.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Population.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Population.js (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Population.js (revision 25077) @@ -0,0 +1,75 @@ +/** + * Combines the worldPopulation and regular population cap. + * At the moment those are incompatible so this makes sense. + * TODO: Should there be a dialog allowing per-player pop limits? + */ +GameSettings.prototype.Attributes.Population = class Population extends GameSetting +{ + init() + { + this.popDefault = this.getDefaultValue("PopulationCapacities", "Population") || 200; + this.worldPopDefault = this.getDefaultValue("WorldPopulationCapacities", "Population") || 800; + + this.perPlayer = false; + this.useWorldPop = false; + this.cap = this.popDefault; + this.settings.map.watch(() => this.onMapChange(), ["map"]); + } + + toInitAttributes(attribs) + { + if (this.perPlayer) + { + if (!attribs.settings.PlayerData) + attribs.settings.PlayerData = []; + while (attribs.settings.PlayerData.length < this.perPlayer.length) + attribs.settings.PlayerData.push({}); + for (let i in this.perPlayer) + if (this.perPlayer[i]) + attribs.settings.PlayerData[i].PopulationLimit = this.perPlayer[i]; + } + if (this.useWorldPop) + { + attribs.settings.WorldPopulation = true; + attribs.settings.WorldPopulationCap = this.cap; + } + else + attribs.settings.PopulationCap = this.cap; + } + + fromInitAttributes(attribs) + { + if (!!this.getLegacySetting(attribs, "WorldPopulation")) + this.setPopCap(true, this.getLegacySetting(attribs, "WorldPopulationCap")); + else if (!!this.getLegacySetting(attribs, "PopulationCap")) + this.setPopCap(false, this.getLegacySetting(attribs, "PopulationCap")); + } + + onMapChange() + { + this.perPlayer = undefined; + if (this.settings.map.type != "scenario") + return; + if (this.getMapSetting("PlayerData")?.some(data => data.PopulationLimit)) + this.perPlayer = this.getMapSetting("PlayerData").map(data => data.PopulationLimit || undefined); + else if (this.getMapSetting("WorldPopulation")) + this.setPopCap(true, +this.getMapSetting("WorldPopulationCap")); + else + this.setPopCap(false, +this.getMapSetting("PopulationCap")); + } + + setPopCap(worldPop, cap = undefined) + { + if (worldPop != this.useWorldPop) + this.cap = undefined; + + this.useWorldPop = worldPop; + + if (!!cap) + this.cap = cap; + else if (!this.cap && !this.useWorldPop) + this.cap = this.popDefault; + else if (!this.cap && this.useWorldPop) + this.cap = this.worldPopDefault; + } +}; Property changes on: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Population.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Relic.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Relic.js (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Relic.js (revision 25077) @@ -0,0 +1,62 @@ +GameSettings.prototype.Attributes.Relic = class Relic extends GameSetting +{ + init() + { + this.available = false; + this.count = 0; + this.duration = 0; + this.settings.victoryConditions.watch(() => this.maybeUpdate(), ["active"]); + this.settings.map.watch(() => this.onMapChange(), ["map"]); + } + + toInitAttributes(attribs) + { + // For consistency, only save this if the victory condition is active. + if (this.available) + { + attribs.settings.RelicCount = this.count; + attribs.settings.RelicDuration = this.duration; + } + } + + fromInitAttributes(attribs) + { + if (!!this.getLegacySetting(attribs, "RelicCount")) + this.setCount(this.getLegacySetting(attribs, "RelicCount")); + if (!!this.getLegacySetting(attribs, "RelicDuration")) + this.setDuration(this.getLegacySetting(attribs, "RelicDuration")); + } + + onMapChange() + { + if (this.settings.map.type != "scenario") + return; + // TODO: probably should sync the victory condition. + if (!this.getMapSetting("RelicCount")) + this.available = false; + else + this._set(+this.getMapSetting("RelicCount"), +this.getMapSetting("RelicDuration")); + } + + _set(count, duration) + { + this.available = this.settings.victoryConditions.active.has("capture_the_relic"); + this.count = Math.max(1, count); + this.duration = duration; + } + + setCount(val) + { + this._set(Math.round(val), this.duration); + } + + setDuration(val) + { + this._set(this.count, Math.round(val)); + } + + maybeUpdate() + { + this._set(this.count, this.duration); + } +}; Property changes on: ps/trunk/binaries/data/mods/public/gui/gamesettings/attributes/Relic.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: ps/trunk/binaries/data/mods/public/gui/autostart/autostart.xml =================================================================== --- ps/trunk/binaries/data/mods/public/gui/autostart/autostart.xml (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/autostart/autostart.xml (revision 25077) @@ -0,0 +1,8 @@ + + +