Index: binaries/data/mods/public/gamesettings/GameSetting.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/GameSetting.js @@ -0,0 +1,30 @@ +/** + * The game settings are split in subclasses that are only responsible + * for a logical subset of settings. + * These are observables so updates are automated. + */ +class GameSetting extends Observable +{ + /** + * Legacy-support system: reload a setting from whatever is in data. + * Used for maps and persistsettings.json + */ + reloadFromLegacy(data) + { + } + + getLegacySetting(attrib, name) + { + if (!attrib || !attrib.settings || !attrib.settings[name]) + return undefined; + return attrib.settings[name]; + } + + getMapSetting(name) + { + if (!g_NewGameSettings.map.data || !g_NewGameSettings.map.data.settings || + !g_NewGameSettings.map.data.settings[name]) + return undefined; + return g_NewGameSettings.map.data.settings[name]; + } +} Index: binaries/data/mods/public/gamesettings/GameSettings.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/GameSettings.js @@ -0,0 +1,101 @@ +/** + * Data store for game settings. + * Serializes to/from JSON. + */ +class GameSettings +{ + constructor() + { + } + + Init() + { + for (let comp in GameSettings.prototype.Attributes) + { + let name = comp[0].toLowerCase() + comp.substr(1); + this[name] = new GameSettings.prototype.Attributes[comp](); + } + for (let comp in this) + this[comp].Init(); + return this; + } + + LegacySerialize() + { + let attribs = { + "settings": {} + }; + for (let comp in this) + if (this[comp].LegacySerialize) + this[comp].LegacySerialize(attribs); + return attribs; + } + + LegacyDeserialize(attribs) + { + // Settings depend on the map, but some saved settings + // may also be illegal for a given map (and validation is annoying). + // To simplify, deserialize the map first, then settings, then the map again. + this.map.LegacyDeserialize(attribs); + for (let comp in this) + if (this[comp].LegacyDeserialize) + this[comp].LegacyDeserialize(attribs); + /* + try + { + this.map.setType(undefined); + this.map.selectMap(undefined); + } + catch(_) + { + // ignore. + } + this.map.LegacyDeserialize(attribs); + */ + } + + Serialize() + { + let ret = {}; + for (let comp in this) + ret[comp] = this[comp].Serialize(); + return ret; + } + + prepareForLaunch() + { + this.pickRandomItems(); + } + + /** + * Change "random" settings into their proper settings. + */ + pickRandomItems() + { + let picked = true; + while (picked) + { + // Re-pick if any random setting was unrandomised, + // to make sure dependencies are cleared. + // TODO: there's probably a better way to handle this. + picked = false; + for (let comp in this) + if (this[comp].pickRandomItems) + picked |= this[comp].pickRandomItems(); + } + } + + reloadFromLegacy(data) + { + for (let comp in this) + this[comp].reloadFromLegacy(data); + } +} + +Object.defineProperty(GameSettings.prototype, "Attributes", { + "value": {}, + "enumerable": false, + "writable": true, +}); + +var g_NewGameSettings = new GameSettings(); Index: binaries/data/mods/public/gamesettings/Observable.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/Observable.js @@ -0,0 +1,58 @@ +/** + * Observable is a self-proxy to enable opt-in reactive programming. + * Properties of an Observable can be watched, and whenever they are changed + * a callback willl be fired. + */ +class Observable +{ + constructor() + { + // Stores observers that are fired when the value is changed + Object.defineProperty(this, "_changeObserver", { + "value": {}, + "enumerable": false, + }); + // Stores observers that are fired when the value is assigned to, + // even if it isn't changed. + Object.defineProperty(this, "_setObserver", { + "value": {}, + "enumerable": false, + }); + return new Proxy(this, { + "set": (target, key, value) => { + let old; + if (Reflect.has(this, key)) + old = Reflect.get(this, key); + Reflect.set(this, key, value); + this._trigger(this._setObserver, key, old); + if (old === undefined || old !== value) + this._trigger(this._changeObserver, key, old); + return true; + } + }); + } + + _trigger(dict, key, old) + { + if (dict[key]) + for (let watcher of dict[key]) + watcher(key, old); + } + + trigger(key, old) + { + this._trigger(this._setObserver, key, old); + this._trigger(this._changeObserver, key, old); + } + + watch(watcher, props, onlyChange = true) + { + let dic = onlyChange ? this._changeObserver : this._setObserver; + for (let prop of props) + { + if (!dic[prop]) + dic[prop] = []; + dic[prop].push(watcher); + } + } +} Index: binaries/data/mods/public/gamesettings/attributes/Biome.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/Biome.js @@ -0,0 +1,72 @@ +GameSettings.prototype.Attributes.Biome = class extends GameSetting +{ + Init() + { + this.biomes = loadBiomes(); + this.biomeData = {}; + for (let biome of this.biomes) + this.biomeData[biome.Id] = biome; + this.biome = undefined; + // NB: random is always available. + this.available = new Set(this.biomes.map(x => x.Id)); + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + if (!this.biome) + return; + attribs.settings.Biome = this.biome; + } + + Serialize() + { + return { "biome": this.biome }; + } + + Deserialize(data) + { + this.biome = data.biome; + } + + onMapChange() + { + let mapData = g_NewGameSettings.map.data; + if (mapData && mapData.settings && mapData.settings.SupportedBiomes !== undefined) + { + this.available = new Set(this.biomes.filter(biome => mapData.settings.SupportedBiomes.indexOf(biome) !== -1)); + this.biome = "random"; + } + else if (g_NewGameSettings.map.type == "random") + { + this.available = new Set(this.biomes.map(x => x.Id)); + this.biome = "random"; + } + else + { + this.available = new Set(); + this.biome = undefined; + } + } + + setBiome(biome) + { + // TODO: validation. + this.biome = biome; + } + + getData() + { + if (!this.biome) + return undefined; + return this.biomeData[this.biome]; + } + + pickRandomItems() + { + if (this.biome !== "random") + return false; + this.biome = pickRandom(this.available); + return true; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/Ceasefire.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/Ceasefire.js @@ -0,0 +1,47 @@ +GameSettings.prototype.Attributes.Ceasefire = class extends GameSetting +{ + Init() + { + this.value = 0; + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + if (!this.value) + return; + attribs.settings.Ceasefire = this.value; + } + + LegacyDeserialize(attribs) + { + if (!this.getLegacySetting(attribs, "Ceasefire")) + return; + this.value = +this.getLegacySetting(attribs, "Ceasefire"); + } + + Serialize() + { + return { "value": this.value }; + } + + Deserialize(data) + { + this.value = data.value; + } + + onMapChange() + { + if (g_NewGameSettings.map.type != "scenario") + return; + if (!this.getMapSetting("Ceasefire")) + this.value = 0; + else + this.value = +this.getMapSetting("Ceasefire"); + } + + setValue(val) + { + this.value = Math.round(val); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/Cheats.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/Cheats.js @@ -0,0 +1,38 @@ +GameSettings.prototype.Attributes.Cheats = class extends GameSetting +{ + Init() + { + this.enabled = false; + g_NewGameSettings.rating.watch(() => this.maybeUpdate(), ["enabled"]); + } + + LegacySerialize(attribs) + { + attribs.settings.CheatEnabled = this.enabled; + } + + Serialize() + { + return { "enabled": this.enabled }; + } + + Deserialize(data) + { + this.enabled = data.enabled; + } + + _set(enabled) + { + this.enabled = (enabled && !g_NewGameSettings.rating.enabled); + } + + setEnabled(enabled) + { + this._set(enabled); + } + + maybeUpdate() + { + this._set(this.enabled); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/Daytime.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/Daytime.js @@ -0,0 +1,53 @@ +GameSettings.prototype.Attributes.Daytime = class extends GameSetting +{ + Init() + { + this.data = undefined; + this.value = undefined; + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + if (this.value) + attribs.settings.Daytime = this.value; + } + + Serialize() + { + return { "value": this.value }; + } + + Deserialize(data) + { + this.value = data.value; + } + + onMapChange() + { + let mapData = g_NewGameSettings.map.data; + if (!mapData || !mapData.settings || !mapData.settings.Daytime) + { + this.value = undefined; + this.data = undefined; + return; + } + // TODO: validation + this.data = mapData.settings.Daytime; + this.value = "random"; + } + + setValue(val) + { + // TODO: validation. + this.value = val; + } + + pickRandomItems() + { + if (this.value !== "random") + return false; + this.value = pickRandom(this.data).Id; + return true; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/DisableSpies.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/DisableSpies.js @@ -0,0 +1,42 @@ +GameSettings.prototype.Attributes.DisableSpies = class extends GameSetting +{ + Init() + { + this.enabled = false; + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + attribs.settings.DisableSpies = this.enabled; + } + + LegacyDeserialize(attribs) + { + if (!this.getLegacySetting(attribs, "DisableSpies")) + return; + this.value = +this.getLegacySetting(attribs, "DisableSpies"); + } + + Serialize() + { + return { "enabled": this.enabled }; + } + + Deserialize(data) + { + this.enabled = data.enabled; + } + + onMapChange() + { + if (g_NewGameSettings.map.type != "scenario") + return; + this.setEnabled(!!this.getMapSetting("DisableSpies")); + } + + setEnabled(enabled) + { + this.enabled = enabled; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/DisableTreasures.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/DisableTreasures.js @@ -0,0 +1,42 @@ +GameSettings.prototype.Attributes.DisableTreasures = class extends GameSetting +{ + Init() + { + this.enabled = false; + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + attribs.settings.DisableTreasures = this.enabled; + } + + LegacyDeserialize(attribs) + { + if (!this.getLegacySetting(attribs, "DisableTreasures")) + return; + this.value = +this.getLegacySetting(attribs, "DisableTreasures"); + } + + Serialize() + { + return { "enabled": this.enabled }; + } + + Deserialize(data) + { + this.enabled = data.enabled; + } + + onMapChange() + { + if (g_NewGameSettings.map.type != "scenario") + return; + this.setEnabled(!!this.getMapSetting("DisableTreasures")); + } + + setEnabled(enabled) + { + this.enabled = enabled; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/GameSpeed.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/GameSpeed.js @@ -0,0 +1,41 @@ +GameSettings.prototype.Attributes.GameSpeed = class extends GameSetting +{ + Init() + { + this.gameSpeed = 1; + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + attribs.gameSpeed = this.gameSpeed; + } + + LegacyDeserialize(attribs) + { + if (!attribs.gameSpeed) + return; + this.gameSpeed = +attribs.gameSpeed; + } + Serialize() + { + return { "gameSpeed": this.gameSpeed }; + } + + Deserialize(data) + { + this.gameSpeed = data.gameSpeed; + } + + onMapChange() + { + if (!this.getMapSetting("gameSpeed")) + return; + this.setSpeed(+this.getMapSetting("gameSpeed")); + } + + setSpeed(speed) + { + this.speed = speed; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/Landscape.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/Landscape.js @@ -0,0 +1,64 @@ +GameSettings.prototype.Attributes.Landscape = class extends GameSetting +{ + Init() + { + this.data = undefined; + this.value = undefined; + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + if (this.value) + attribs.settings.Landscape = this.value; + } + + Serialize() + { + return { "value": this.value }; + } + + Deserialize(data) + { + this.value = data.value; + } + + onMapChange() + { + if (!this.getMapSetting("Landscape")) + { + this.value = undefined; + this.data = undefined; + return; + } + // TODO: validation + this.data = this.getMapSetting("Landscape"); + this.value = "random"; + } + + setValue(val) + { + // TODO: validation. + this.value = val; + } + + pickRandomItems() + { + if (!this.value || this.value.startsWith("random")) + return false; + + let items = []; + + if (this.value.indexOf("_") !== -1) + { + let subgroup = this.value.substr(this.value.indexOf("_")+1); + subgroup = this.data.find(x => x.Id == subgroup); + items = subgroup.map(x => x.Id); + } + else + items = this.data.map(x => x.Items.map(item => item.Id)); + + this.value = pickRandom(items); + return true; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/LastManStanding.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/LastManStanding.js @@ -0,0 +1,50 @@ +GameSettings.prototype.Attributes.LastManStanding = class extends GameSetting +{ + Init() + { + this.available = !g_NewGameSettings.lockedTeams.enabled; + this.enabled = false; + g_NewGameSettings.lockedTeams.watch(() => this.maybeUpdate(), ["enabled"]); + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + attribs.settings.LastManStanding = this.enabled; + } + + LegacyDeserialize(attribs) + { + if (!this.getLegacySetting(attribs, "LastManStanding")) + return; + this.enabled = !!this.getLegacySetting(attribs, "LastManStanding"); + } + + Serialize() + { + return { "enabled": this.enabled }; + } + + Deserialize(data) + { + this.enabled = data.enabled; + } + + onMapChange() + { + if (g_NewGameSettings.map.type != "scenario") + return; + this.setEnabled(!!this.getMapSetting("LastManStanding")); + } + + setEnabled(enabled) + { + this.available = !g_NewGameSettings.lockedTeams.enabled; + this.enabled = (enabled && this.available); + } + + maybeUpdate() + { + this.setEnabled(this.enabled); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/LockedTeams.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/LockedTeams.js @@ -0,0 +1,42 @@ +GameSettings.prototype.Attributes.LockedTeams = class extends GameSetting +{ + Init() + { + this.enabled = false; + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + attribs.settings.LockTeams = this.enabled; + } + + LegacyDeserialize(attribs) + { + if (!this.getLegacySetting(attribs, "LockTeams")) + return; + this.enabled = !!this.getLegacySetting(attribs, "LockTeams"); + } + + Serialize() + { + return { "enabled": this.enabled }; + } + + Deserialize(data) + { + this.enabled = data.enabled; + } + + onMapChange() + { + if (g_NewGameSettings.map.type != "scenario") + return; + this.setEnabled(!!this.getMapSetting("LockTeams")); + } + + setEnabled(enabled) + { + this.enabled = enabled; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/Map.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/Map.js @@ -0,0 +1,88 @@ +GameSettings.prototype.Attributes.Map = class extends GameSetting +{ + Init() + { + this.watch(() => this.updateMapMetadata(), ["map"]); + this.map = undefined; + this.type = g_MapTypes.Name[g_MapTypes.Default]; + this.script = undefined; + this.randomOptions = []; + } + + LegacySerialize(attribs) + { + attribs.map = this.map; + attribs.mapType = this.type; + if (this.script) + attribs.script = this.script; + + let copy = ["CircularMap", + "StartingTechnologies", + "DisabledTechnologies", + "DisabledTemplates", + "StartingCamera", + "Garrison", + // Copy the map name so that the replay menu doesn't have to load hundreds of map descriptions on init + // Also it allows determining the english mapname from the replay file if the map is not available. + "Name"]; + + for (let property of copy) + if (this.data.settings[property] !== undefined) + attribs.settings[property] = this.data.settings[property]; + } + + LegacyDeserialize(attribs) + { + if (attribs.mapType) + this.setType(attribs.mapType); + + if (!attribs.map) + return; + + this.selectMap(attribs.map); + } + + Serialize() + { + return { "type": this.type, "map": this.map }; + } + + Deserialize(data) + { + // TODO + } + + setType(mapType) + { + this.type = mapType; + } + + selectMap(map) + { + this.data = this.mapCache.getMapData(this.type, map); + this.map = map; + } + + updateMapMetadata() + { + if (this.type == "random" && this.data) + this.script = this.data.settings.Script; + else + this.script = undefined; + } + + pickRandomItems() + { + if (this.map !== "random") + return false; + this.map = pickRandom(this.randomOptions); + return true; + } + + setRandomOptions(options) + { + this.randomOptions = clone(options); + if (this.randomOptions.indexOf("random") !== -1) + this.randomOptions = this.randomOptions.splice(this.randomOptions.indexOf("random"), 1); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/MapExploration.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/MapExploration.js @@ -0,0 +1,54 @@ +GameSettings.prototype.Attributes.MapExploration = class extends GameSetting +{ + Init() + { + this.explored = false; + this.revealed = false; + + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + attribs.settings.RevealMap = this.revealed; + attribs.settings.ExploreMap = this.explored; + } + + LegacyDeserialize(attribs) + { + if (!!this.getLegacySetting(attribs, "ExploreMap")) + this.explored = !!this.getLegacySetting(attribs, "ExploreMap"); + if (!!this.getLegacySetting(attribs, "RevealMap")) + this.revealed = !!this.getLegacySetting(attribs, "RevealMap"); + } + + Serialize() + { + return { "explored": this.explored, "revealed": this.revealed }; + } + + Deserialize(data) + { + // TODO + } + + onMapChange(mapData) + { + if (g_NewGameSettings.map.type != "scenario") + return; + this.setExplored(this.getMapSetting("ExploreMap")); + this.setRevealed(this.getMapSetting("RevealMap")); + } + + setExplored(enabled) + { + this.explored = enabled; + this.revealed = this.revealed && this.explored; + } + + setRevealed(enabled) + { + this.explored = this.explored || enabled; + this.revealed = enabled; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/MapSize.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/MapSize.js @@ -0,0 +1,43 @@ +GameSettings.prototype.Attributes.MapSize = class extends GameSetting +{ + Init() + { + this.setSize(g_MapSizes.Tiles[g_MapSizes.Default]); + g_NewGameSettings.map.watch(() => this.onTypeChange(), ["type"]); + } + + LegacySerialize(attribs) + { + if (g_NewGameSettings.map.type == "random") + attribs.settings.Size = this.size; + } + + LegacyDeserialize(attribs) + { + if (!!this.getLegacySetting(attribs, "Size")) + this.setSize(this.getLegacySetting(attribs, "Size")); + } + + Serialize() + { + if (!this.available) + return null; + return { "size": this.size }; + } + + Deserialize(data) + { + } + + setSize(size) + { + this.available = g_NewGameSettings.map.type == "random"; + this.size = size; + } + + onTypeChange(old) + { + if (g_NewGameSettings.map.type == "random" && old != "random") + this.setSize(g_MapSizes.Tiles[g_MapSizes.Default]); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/MatchID.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/MatchID.js @@ -0,0 +1,20 @@ +GameSettings.prototype.Attributes.MatchID = class extends GameSetting +{ + Init() + { + this.matchID = Engine.GetMatchID(); + } + + LegacySerialize(attribs) + { + attribs.matchID = this.matchID; + } + + Serialize() + { + } + + Deserialize(data) + { + } +}; Index: binaries/data/mods/public/gamesettings/attributes/Nomad.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/Nomad.js @@ -0,0 +1,34 @@ +GameSettings.prototype.Attributes.Nomad = class extends GameSetting +{ + Init() + { + this.enabled = false; + } + + LegacySerialize(attribs) + { + if (g_NewGameSettings.map.type == "random") + attribs.settings.Nomad = this.enabled; + } + + LegacyDeserialize(attribs) + { + if (!!this.getLegacySetting(attribs, "Nomad")) + this.setEnabled(!!this.getLegacySetting(attribs, "Nomad")); + } + + Serialize() + { + return { "enabled": this.enabled }; + } + + Deserialize(data) + { + this.enabled = data.enabled; + } + + setEnabled(enabled) + { + this.enabled = enabled; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/PlayerAI.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/PlayerAI.js @@ -0,0 +1,160 @@ +GameSettings.prototype.Attributes.PlayerAI = class extends GameSetting +{ + Init() + { + // NB: watchers aren't auto-triggered when modifying array elements. + this.values = []; + g_NewGameSettings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]); + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(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].AI = this.values[i].bot; + attribs.settings.PlayerData[i].AIDiff = this.values[i].difficulty; + attribs.settings.PlayerData[i].AIBehavior = this.values[i].behavior; + } + else + attribs.settings.PlayerData[i].AI = false; + } + + LegacyDeserialize(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]) + continue; + if (pData[i].AI) + this.setAI(+i, pData[i].AI); + if (pData[i].AIBehavior) + this.setBehavior(+i, pData[i].AIBehavior); + if (pData[i].AIDiff) + this.setDifficulty(+i, pData[i].AIDiff); + } + } + + Serialize() + { + } + + Deserialize(data) + { + } + + _defaultAI(playerIndex) + { + return { + "bot": g_Settings.PlayerDefaults[playerIndex + 1].AI, + "difficulty": +Engine.ConfigDB_GetValue("user", "gui.gamesetup.aidifficulty"), + "behavior": Engine.ConfigDB_GetValue("user", "gui.gamesetup.aibehavior"), + }; + } + + _resize(nb) + { + while (this.values.length > nb) + this.values.pop(); + while (this.values.length < nb) + this.values.push(this._defaultAI(this.values.length)); + } + + onMapChange() + { + // Reset. + if (g_NewGameSettings.map.type == "scenario") + this._resize(0); + this.maybeUpdate(); + } + + onPlayerAssignmentsChange() + { + this._resize(0); + this.maybeUpdate(); + } + + maybeUpdate() + { + this._resize(g_NewGameSettings.playerCount.nbPlayers); + this.values.forEach((ai, i) => this._set(i, ai)); + this.trigger("values"); + } + + _getMapData(i) + { + let data = g_NewGameSettings.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, ai) + { + if (global["g_PlayerAssignments"]) + for (let guid in g_PlayerAssignments) + if (g_PlayerAssignments[guid].player == playerIndex + 1) + { + this.values[playerIndex] = undefined; + return; + } + if (!ai) + { + this.values[playerIndex] = undefined; + return; + } + this.values[playerIndex] = this._defaultAI(playerIndex); + } + + setAI(playerIndex, ai) + { + if (ai === "undefined") + ai = undefined; + this._set(playerIndex, ai); + this.trigger("values"); + } + + setBehavior(playerIndex, value) + { + if (!this.values[playerIndex]) + this._set(playerIndex); + this.values[playerIndex].behavior = value; + this.trigger("values"); + } + + setDifficulty(playerIndex, value) + { + if (!this.values[playerIndex]) + this._set(playerIndex); + this.values[playerIndex].difficulty = value; + this.trigger("values"); + } + + get(playerIndex) + { + return this.values[playerIndex]; + } + + describe(playerIndex) + { + if (!this.values[playerIndex]) + return ""; + return translateAISettings({ + "AI": this.values[playerIndex].bot, + "AIDiff": this.values[playerIndex].difficulty, + "AIBehavior": this.values[playerIndex].behavior, + }); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/PlayerCiv.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/PlayerCiv.js @@ -0,0 +1,127 @@ +GameSettings.prototype.Attributes.PlayerCiv = class extends GameSetting +{ + Init() + { + // NB: watchers aren't auto-triggered when modifying array elements. + this.values = []; + this.locked = []; + g_NewGameSettings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]); + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(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]; + } + + LegacyDeserialize(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); + } + + Serialize() + { + } + + Deserialize(data) + { + } + + _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 (g_NewGameSettings.map.type == "scenario") + this._resize(0); + this.maybeUpdate(); + } + + maybeUpdate() + { + this._resize(g_NewGameSettings.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(g_CivData).filter(civ => g_CivData[civ].SelectableInGameSetup).map(civ => g_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(g_CivData).filter(civ => + g_CivData[civ].Culture == culture && g_CivData[civ].SelectableInGameSetup)); + + } + if (picked) + this.trigger("values"); + + return picked; + } + + _getMapData(i) + { + let data = g_NewGameSettings.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] = g_NewGameSettings.map.type == "scenario"; + } + } + + setValue(playerIndex, val) + { + this._set(playerIndex, val); + this.trigger("values"); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/PlayerColor.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/PlayerColor.js @@ -0,0 +1,195 @@ +GameSettings.prototype.Attributes.PlayerColor = class extends GameSetting +{ + Init() + { + // TODO: update this + this.defaultColors = g_Settings.PlayerDefaults.slice(1).map(pData => pData.Color); + + // NB: watchers aren't auto-triggered when modifying array elements. + this.values = []; + this.locked = []; + g_NewGameSettings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]); + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(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].Color = this.values[i]; + } + + LegacyDeserialize(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].Color) + this.setColor(i, pData[i].Color); + } + + Serialize() + { + } + + Deserialize(data) + { + } + + _resize(nb) + { + while (this.values.length > nb) + { + this.values.pop(); + this.locked.pop(); + } + while (this.values.length < nb) + { + this.values.push(undefined); + this.locked.push(false); + } + } + + onMapChange() + { + // Reset. + if (g_NewGameSettings.map.type == "scenario") + this._resize(0); + this.maybeUpdate(); + } + + maybeUpdate() + { + this._resize(g_NewGameSettings.playerCount.nbPlayers); + + this._updateAvailable(); + + this.values.forEach((c, i) => this._set(i, c)); + this.trigger("values"); + } + + _set(playerIndex, color) + { + let inUse = this.values.findIndex((otherColor, i) => + color && otherColor && + sameColor(color, otherColor)); + if (inUse !== -1 && inUse !== playerIndex) + { + // Swap colors. + let col = this.values[playerIndex]; + this.values[playerIndex] = undefined; + this._set(inUse, col); + } + if (!color || this.available.indexOf(color) == -1) + { + this.values[playerIndex] = (color && !inUse) ? + this._findClosestColor(color, this.available) : + this._getUnusedColor(); + } + else + this.values[playerIndex] = color; + } + + get(playerIndex) + { + if (playerIndex >= this.values.length) + return undefined; + return this.values[playerIndex]; + } + + setColor(playerIndex, color) + { + this._set(playerIndex, color); + this.trigger("values"); + } + + _getMapData(i) + { + let data = g_NewGameSettings.map.data; + if (!data || !data.settings || !data.settings.PlayerData) + return undefined; + if (data.settings.PlayerData.length <= i) + return undefined; + return data.settings.PlayerData[i].Color; + } + + _updateAvailable() + { + // Step 1: Pick colors that the map specifies, add most unsimilar default colors + // Provide the access to g_MaxPlayers different colors, regardless of current playercount. + let values = []; + for (let i = 0; i < g_MaxPlayers; ++i) + values.push(this._getMapData(i) || + this.defaultColors[i] || this._findFarthestUnusedColor(values)); + + // Step 2: Sort these colors so that the order is most reminiscent of the default colors + let available = []; + for (let i = 0; i < values.length; ++i) + { + let closestColor; + let smallestDistance = Infinity; + for (let color of values) + { + if (available.some(col => sameColor(col, color))) + continue; + + let distance = colorDistance(color, this.defaultColors[i]); + if (distance <= smallestDistance) + { + closestColor = color; + smallestDistance = distance; + } + } + available.push(closestColor); + } + this.available = available; + } + + _findClosestColor(targetColor, colors) + { + let colorDistances = colors.map(color => colorDistance(color, targetColor)); + + let smallestDistance = colorDistances.find( + distance => colorDistances.every(distance2 => distance2 >= distance)); + + return colors.find(color => colorDistance(color, targetColor) == smallestDistance); + } + + _findFarthestUnusedColor(values) + { + let farthestColor; + let farthestDistance = 0; + + for (let defaultColor of this.defaultColors) + { + let smallestDistance = Infinity; + for (let usedColor of values) + { + let distance = colorDistance(usedColor, defaultColor); + if (distance < smallestDistance) + smallestDistance = distance; + } + + if (smallestDistance >= farthestDistance) + { + farthestColor = defaultColor; + farthestDistance = smallestDistance; + } + } + return farthestColor; + } + + _getUnusedColor() + { + return this.available.find(color => { + return this.values.every(otherColor => !otherColor || !sameColor(color, otherColor)); + }); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/PlayerCount.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/PlayerCount.js @@ -0,0 +1,77 @@ +GameSettings.prototype.Attributes.PlayerCount = class extends GameSetting +{ + Init() + { + this.nbPlayers = 1; + g_NewGameSettings.map.watch(() => this.onMapTypeChange(), ["type"]); + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + if (!attribs.settings.PlayerData) + attribs.settings.PlayerData = []; + while (attribs.settings.PlayerData.length < this.nbPlayers) + attribs.settings.PlayerData.push({}); + } + + LegacyDeserialize(attribs) + { + if (!this.getLegacySetting(attribs, "PlayerData")) + return; + let pData = this.getLegacySetting(attribs, "PlayerData"); + if (this.nbPlayers < pData.length) + this.nbPlayers = pData.length; + } + + Serialize() + { + return { "nbPlayers": this.nbPlayers }; + } + + Deserialize(data) + { + this.nbPlayers = data.nbPlayers; + } + + onMapTypeChange(old) + { + if (g_NewGameSettings.map.type == "random" && old != "random") + this.nbPlayers = 2; + } + + onMapChange() + { + if (g_NewGameSettings.map.type == "random") + return; + if (!g_NewGameSettings.map.data || !g_NewGameSettings.map.data.settings || + !g_NewGameSettings.map.data.settings.PlayerData) + return; + this.nbPlayers = g_NewGameSettings.map.data.settings.PlayerData.length; + } + + reloadFromLegacy(data) + { + if (g_NewGameSettings.map.type != "random") + { + this.nbPlayers = g_NewGameSettings.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)); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/PlayerName.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/PlayerName.js @@ -0,0 +1,129 @@ +GameSettings.prototype.Attributes.PlayerName = class extends GameSetting +{ + Init() + { + // NB: watchers aren't auto-triggered when modifying array elements. + this.values = []; + g_NewGameSettings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]); + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(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]; + } + + Serialize() + { + } + + Deserialize(data) + { + } + + _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(); + } + + onPlayerAssignmentsChange() + { + this._resize(0); + this.maybeUpdate(); + } + + maybeUpdate() + { + this._resize(g_NewGameSettings.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]) + continue; + + let ai = g_NewGameSettings.playerAI.values[i]; + if (!ai) + continue; + + let civ = g_NewGameSettings.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(g_CivData[civ].AINames); + + if (!g_IsNetworked) + chosenName = translate(chosenName); + + // 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 = g_NewGameSettings.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) + { + if (global["g_PlayerAssignments"]) + for (let guid in g_PlayerAssignments) + if (g_PlayerAssignments[guid].player == playerIndex + 1) + { + this.values[playerIndex] = g_PlayerAssignments[guid].name; + return; + } + this.values[playerIndex] = this._getMapData(playerIndex); + } +}; + + +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"]; Index: binaries/data/mods/public/gamesettings/attributes/PlayerTeam.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/PlayerTeam.js @@ -0,0 +1,84 @@ +GameSettings.prototype.Attributes.PlayerTeam = class extends GameSetting +{ + Init() + { + // NB: watchers aren't auto-triggered when modifying array elements. + this.values = []; + this.locked = []; + g_NewGameSettings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]); + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(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].Team = this.values[i]; + } + + LegacyDeserialize(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].Team) + this.setValue(i, pData[i].Team); + } + + Serialize() + { + } + + Deserialize(data) + { + } + + _resize(nb) + { + while (this.values.length > nb) + { + this.values.pop(); + this.locked.pop(); + } + while (this.values.length < nb) + { + // -1 is None + this.values.push(-1); + this.locked.push(false); + } + } + + onMapChange() + { + // Reset. + if (g_NewGameSettings.map.type == "scenario") + this._resize(0); + this.maybeUpdate(); + } + + maybeUpdate() + { + this._resize(g_NewGameSettings.playerCount.nbPlayers); + this.values.forEach((c, i) => this._set(i, c)); + this.trigger("values"); + } + + _set(playerIndex, value) + { + this.values[playerIndex] = value; + this.locked[playerIndex] = g_NewGameSettings.map.type == "scenario"; + } + + setValue(playerIndex, val) + { + this._set(playerIndex, val); + this.trigger("values"); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/Population.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/Population.js @@ -0,0 +1,68 @@ +/** + * Combines the worldPopulation and regular population cap. + * At the moment those are incompatible so this makes sense. + */ +GameSettings.prototype.Attributes.Population = class extends GameSetting +{ + Init() + { + this.useWorldPop = false; + this.cap = g_PopulationCapacities.Population[g_PopulationCapacities.Default]; + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + if (this.useWorldPop) + { + attribs.settings.WorldPopulation = this.enabled; + attribs.settings.WorldPopulationCap = this.cap; + } + else + attribs.settings.PopulationCap = this.cap; + } + + LegacyDeserialize(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")); + } + + Serialize() + { + return { "useWorldPop": this.useWorldPop, "cap": this.cap }; + } + + Deserialize(data) + { + this.useWorldPop = data.useWorldPop; + this.cap = data.cap; + } + + onMapChange() + { + if (g_NewGameSettings.map.type != "scenario") + return; + 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 = g_PopulationCapacities.Population[g_PopulationCapacities.Default]; + else if (!this.cap && this.useWorldPop) + this.cap = g_WorldPopulationCapacities.Population[g_WorldPopulationCapacities.Default]; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/Rating.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/Rating.js @@ -0,0 +1,35 @@ +GameSettings.prototype.Attributes.Rating = class extends GameSetting +{ + Init() + { + this.hasXmppClient = Engine.HasXmppClient(); + this.available = false; + this.enabled = false; + } + + LegacySerialize(attribs) + { + attribs.settings.RatingEnabled = this.enabled; + } + + Serialize() + { + return { "enabled": this.enabled }; + } + + Deserialize(data) + { + this.enabled = data.enabled; + } + + setEnabled(enabled) + { + this.enabled = this.available && enabled; + } + + maybeUpdate() + { + this.available = this.hasXmppClient && g_GameAttributes.settings.PlayerData.length == 2; + this.enabled = this.available && this.enabled; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/RegicideGarrison.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/RegicideGarrison.js @@ -0,0 +1,49 @@ +GameSettings.prototype.Attributes.RegicideGarrison = class extends GameSetting +{ + Init() + { + this.setEnabled(false); + g_NewGameSettings.victoryConditions.watch(() => this.maybeUpdate(), ["active"]); + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + if (this.available) + attribs.settings.RegicideGarrison = this.enabled; + } + + LegacyDeserialize(attribs) + { + if (!!this.getLegacySetting(attribs, "RegicideGarrison")) + this.setEnabled(!!this.getLegacySetting(attribs, "RegicideGarrison")); + } + + Serialize() + { + return { "enabled": this.enabled }; + } + + Deserialize(data) + { + this.enabled = data.enabled; + } + + onMapChange() + { + if (g_NewGameSettings.map.type != "scenario") + return; + this.setEnabled(!!this.getMapSetting("RegicideGarrison")); + } + + setEnabled(enabled) + { + this.available = g_NewGameSettings.victoryConditions.active.has("regicide"); + this.enabled = (enabled && this.available); + } + + maybeUpdate() + { + this.setEnabled(this.enabled); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/Relic.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/Relic.js @@ -0,0 +1,81 @@ +GameSettings.prototype.Attributes.Relic = class extends GameSetting +{ + Init() + { + this.available = false; + this.count = 0; + this.duration = 0; + g_NewGameSettings.victoryConditions.watch(() => this.maybeUpdate(), ["active"]); + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + if (this.available) + { + attribs.settings.RelicCount = this.count; + attribs.settings.RelicDuration = this.duration; + } + } + + LegacyDeserialize(attribs) + { + if (!!this.getLegacySetting(attribs, "RelicCount")) + this.setCount(this.getLegacySetting(attribs, "RelicCount")); + if (!!this.getLegacySetting(attribs, "RelicDuration")) + this.setDuration(this.getLegacySetting(attribs, "RelicDuration")); + } + + Serialize() + { + return { "count": this.count, "duration": this.duration }; + } + + Deserialize(data) + { + this.count = data.count; + this.duration = data.duration; + } + + onMapChange() + { + if (g_NewGameSettings.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) + { + let available = this.available; + this.available = g_NewGameSettings.victoryConditions.active.has("capture_the_relic"); + if (!available && this.available) + { + this.count = 2; + this.duration = 20; + } + else + { + this.count = this.available ? Math.max(1, count) : 0; + this.duration = this.available ? duration : 0; + } + } + + 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); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/SeaLevelRise.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/SeaLevelRise.js @@ -0,0 +1,43 @@ +GameSettings.prototype.Attributes.SeaLevelRise = class extends GameSetting +{ + Init() + { + this.min = undefined; + this.max = undefined; + this.value = undefined; + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + if (this.value) + attribs.settings.SeaLevelRiseTime = thiss.value; + } + + Serialize() + { + return { "value": this.value }; + } + + Deserialize(data) + { + this.value = data.value; + } + + onMapChange() + { + if (!this.getMapSetting("SeaLevelRise")) + { + this.value = undefined; + return; + } + this.min = mapData.settings.SeaLevelRise.Min; + this.max = mapData.settings.SeaLevelRise.Max; + this.value = mapData.settings.SeaLevelRise.Default; + } + + setValue(val) + { + this.value = Math.max(this.min, Math.min(this.max, Math.round(val))); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/Seeds.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/Seeds.js @@ -0,0 +1,29 @@ +GameSettings.prototype.Attributes.Seeds = class extends GameSetting +{ + Init() + { + this.seed = 0; + this.AIseed = 0; + } + + LegacySerialize(attribs) + { + // Seed is used for map generation and simulation. + attribs.settings.Seed = this.seed; + attribs.settings.AISeed = this.AIseed; + } + + Serialize() + { + } + + Deserialize(data) + { + } + + pickRandomItems() + { + this.seed = randIntExclusive(0, Math.pow(2, 32)); + this.AIseed = randIntExclusive(0, Math.pow(2, 32)); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/StartingResources.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/StartingResources.js @@ -0,0 +1,44 @@ +GameSettings.prototype.Attributes.StartingResources = class extends GameSetting +{ + Init() + { + this.setResources(g_StartingResources.Resources[g_StartingResources.Default]); + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + attribs.settings.StartingResources = this.resources; + } + + LegacyDeserialize(attribs) + { + if (!!this.getLegacySetting(attribs, "StartingResources")) + this.setResources(this.getLegacySetting(attribs, "StartingResources")); + } + + Serialize() + { + return { "resources": this.resources }; + } + + Deserialize(data) + { + this.resources = data.resources; + } + + onMapChange() + { + if (g_NewGameSettings.map.type != "scenario") + return; + if (!this.getMapSetting("StartingResources")) + this.setResources(g_StartingResources.Resources[g_StartingResources.Default]); + else + this.setResources(this.getMapSetting("StartingResources")); + } + + setResources(res) + { + this.resources = res; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/TeamPlacement.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/TeamPlacement.js @@ -0,0 +1,75 @@ +GameSettings.prototype.Attributes.TeamPlacement = class extends GameSetting +{ + Init() + { + this.available = undefined; + this.value = undefined; + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + if (this.available) + attribs.settings.TeamPlacement = this.value; + } + + Serialize() + { + return { "value": this.value }; + } + + Deserialize(data) + { + this.value = data.value; + } + + onMapChange() + { + if (!this.getMapSetting("TeamPlacements")) + { + this.value = undefined; + this.available = undefined; + return; + } + // TODO: should probably validate that they fit one of the known schemes. + this.available = this.getMapSetting("TeamPlacements"); + this.value = "random"; + } + + setValue(val) + { + this.value = val; + } + + pickRandomItems() + { + if (this.value !== "random") + return false; + this.value = pickRandom(this.available).Id; + return true; + } +}; + + +GameSettings.prototype.Attributes.TeamPlacement.prototype.StartingPositions = [ + { + "Id": "radial", + "Name": translateWithContext("team placement", "Circle"), + "Description": translate("Allied players are grouped and placed with opposing players on one circle spanning the map.") + }, + { + "Id": "line", + "Name": translateWithContext("team placement", "Line"), + "Description": translate("Allied players are placed in a linear pattern."), + }, + { + "Id": "randomGroup", + "Name": translateWithContext("team placement", "Random Group"), + "Description": translate("Allied players are grouped, but otherwise placed randomly on the map."), + }, + { + "Id": "stronghold", + "Name": translateWithContext("team placement", "Stronghold"), + "Description": translate("Allied players are grouped in one random place of the map."), + } +]; Index: binaries/data/mods/public/gamesettings/attributes/TriggerDifficulty.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/TriggerDifficulty.js @@ -0,0 +1,62 @@ +GameSettings.prototype.Attributes.TriggerDifficulty = class extends GameSetting +{ + Init() + { + this.difficulties = loadSettingValuesFile("trigger_difficulties.json"); + this.available = undefined; + this.value = undefined; + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + if (this.available) + attribs.settings.TriggerDifficulty = this.value; + } + + LegacyDeserialize(attribs) + { + if (!!this.getLegacySetting(attribs, "TriggerDifficulty")) + this.setValue(this.getLegacySetting(attribs, "TriggerDifficulty")); + } + + Serialize() + { + return { "value": this.value }; + } + + Deserialize(data) + { + this.value = data.value; + } + + getAvailableSettings() + { + return this.difficulties.filter(x => this.available.indexOf(x.Name) !== -1); + } + + onMapChange() + { + if (!this.getMapSetting("SupportedTriggerDifficulties")) + { + this.value = undefined; + this.available = undefined; + return; + } + // TODO: should probably validate that they fit one of the known schemes. + this.available = mapData.settings.SupportedTriggerDifficulties.Values; + this.value = this.difficulties.find(x => x.Default && this.available.indexOf(x.Name) !== -1).Difficulty; + } + + setValue(val) + { + this.value = val; + } + + getData() + { + if (!this.value) + return undefined; + return this.difficulties[this.value]; + } +}; Index: binaries/data/mods/public/gamesettings/attributes/TriggerScripts.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/TriggerScripts.js @@ -0,0 +1,45 @@ +GameSettings.prototype.Attributes.TriggerScripts = class extends GameSetting +{ + Init() + { + this.victory = new Set(); + this.map = new Set(); + g_NewGameSettings.map.watch(() => this.updateMapScripts(), ["map"]); + g_NewGameSettings.victoryConditions.watch(() => this.updateVictoryScripts(), ["active"]); + } + + LegacySerialize(attribs) + { + attribs.settings.TriggerScripts = Array.from(this.victory).concat(Array.from(this.map)); + } + + Serialize() + { + return { "scripts": Array.from(this.victory).concat(Array.from(this.map)) }; + } + + Deserialize(data) + { + // TODO + } + + updateVictoryScripts() + { + let setting = g_NewGameSettings.victoryConditions; + let scripts = new Set(); + for (let cond of setting.active) + setting.conditions[cond].Scripts.forEach(script => scripts.add(script)); + this.victory = scripts; + } + + updateMapScripts() + { + if (!g_NewGameSettings.map.data || !g_NewGameSettings.map.data.settings || + !g_NewGameSettings.map.data.settings.TriggerScripts) + { + this.map = new Set(); + return; + } + this.map = new Set(g_NewGameSettings.map.data.settings.TriggerScripts); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/VictoryConditions.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/VictoryConditions.js @@ -0,0 +1,103 @@ +GameSettings.prototype.Attributes.VictoryConditions = class extends GameSetting +{ + constructor() + { + super(); + // Set of victory condition names. + this.active = new Set(); + this.disabled = new Set(); + this.conditions = {}; + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + Init() + { + let conditions = loadVictoryConditions(); + for (let cond of conditions) + this.conditions[cond.Name] = cond; + + for (let cond in this.conditions) + if (this.conditions[cond].Default) + this._add(this.conditions[cond].Name); + } + + LegacySerialize(attribs) + { + attribs.settings.VictoryConditions = Array.from(this.active); + } + + LegacyDeserialize(attribs) + { + let legacy = this.getLegacySetting(attribs, "VictoryConditions"); + if (!legacy) + return; + for (let cond of legacy) + this._add(cond); + } + + Serialize() + { + return { "active": Array.from(this.active) }; + } + + Deserialize(data) + { + // TODO: could be optimised. + this.active = new Set(); + for (let cond of data.active) + this._add(cond); + } + + onMapChange() + { + if (g_NewGameSettings.map.type != "scenario") + return; + // If a map specifies victory conditions, replace them all. + this.active = new Set(); + if (!this.getMapSetting("VictoryConditions")) + return; + // TODO: could be optimised. + for (let cond of this.getMapSetting("VictoryConditions")) + this._add(cond); + } + + _reconstruct(active) + { + let disabled = new Set(); + for (let cond of active) + if (this.conditions[cond].DisabledWhenChecked) + this.conditions[cond].DisabledWhenChecked.forEach(x => disabled.add(x)); + return disabled; + } + + _add(name) + { + if (this.disabled.has(name)) + return; + let active = clone(this.active); + active.add(name); + // Assume we want to remove incompatible ones. + if (this.conditions[name].DisabledWhenChecked) + this.conditions[name].DisabledWhenChecked.forEach(x => active.delete(x)); + // TODO: sanity check + this.disabled = this._reconstruct(active); + this.active = active; + } + + _delete(name) + { + let active = clone(this.active); + active.delete(name); + // TODO: sanity check + this.disabled = this._reconstruct(active); + this.active = active; + } + + setEnabled(name, enabled) + { + if (enabled) + this._add(name); + else + this._delete(name); + } +}; Index: binaries/data/mods/public/gamesettings/attributes/Wonder.js =================================================================== --- /dev/null +++ binaries/data/mods/public/gamesettings/attributes/Wonder.js @@ -0,0 +1,54 @@ +GameSettings.prototype.Attributes.Wonder = class extends GameSetting +{ + Init() + { + this.available = false; + this.duration = 0; + g_NewGameSettings.victoryConditions.watch(() => this.maybeUpdate(), ["active"]); + g_NewGameSettings.map.watch(() => this.onMapChange(), ["map"]); + } + + LegacySerialize(attribs) + { + if (this.available) + attribs.settings.WonderDuration = this.duration; + } + + LegacyDeserialize(attribs) + { + if (!!this.getLegacySetting(attribs, "WonderDuration")) + this.setDuration(+this.getLegacySetting(attribs, "WonderDuration")); + } + + Serialize() + { + return { "duration": this.duration }; + } + + Deserialize(data) + { + this.duration = data.duration; + } + + onMapChange() + { + if (g_NewGameSettings.map.type != "scenario") + return; + this.setDuration(+this.getMapSetting("WonderDuration")); + } + + setDuration(duration) + { + let available = this.available; + this.available = g_NewGameSettings.victoryConditions.active.has("wonder"); + if (!available && this.available) + this.duration = 20; + else + this.duration = this.available ? Math.round(duration) : 0; + } + + maybeUpdate() + { + this.setDuration(this.duration); + } +}; Index: binaries/data/mods/public/gui/common/MapCache.js =================================================================== --- binaries/data/mods/public/gui/common/MapCache.js +++ binaries/data/mods/public/gui/common/MapCache.js @@ -12,7 +12,6 @@ { if (!mapPath || mapPath == "random") return undefined; - if (!this.cache[mapPath]) { let mapData = g_Settings.MapTypes.find(type => type.Name == mapType).GetData(mapPath); @@ -62,10 +61,8 @@ return mapData && mapData.settings && translate(mapData.settings.Description) || ""; } - getMapPreview(mapType, mapPath, gameAttributes = undefined) + getMapPreview(mapType, mapPath, filename = undefined) { - let filename = gameAttributes && gameAttributes.settings && gameAttributes.settings.Preview || undefined; - if (!filename) { let mapData = this.getMapData(mapType, mapPath); Index: binaries/data/mods/public/gui/common/gamedescription.js =================================================================== --- binaries/data/mods/public/gui/common/gamedescription.js +++ binaries/data/mods/public/gui/common/gamedescription.js @@ -177,27 +177,23 @@ /** * Sets an additional map label, map preview image and describes the chosen game settings more closely. - * - * Requires g_GameAttributes and g_VictoryConditions. */ function getGameDescription(mapCache) { let titles = []; - if (!g_GameAttributes.settings.VictoryConditions.length) + if (!g_NewGameSettings.victoryConditions.active) titles.push({ "label": translateWithContext("victory condition", "Endless Game"), "value": translate("No winner will be determined, even if everyone is defeated.") }); - for (let victoryCondition of g_VictoryConditions) + for (let Id of g_NewGameSettings.victoryConditions.active) { - if (g_GameAttributes.settings.VictoryConditions.indexOf(victoryCondition.Name) == -1) - continue; - + let victoryCondition = g_NewGameSettings.victoryConditions.conditions[Id]; let title = translateVictoryCondition(victoryCondition.Name); if (victoryCondition.Name == "wonder") { - let wonderDuration = Math.round(g_GameAttributes.settings.WonderDuration); + let wonderDuration = g_NewGameSettings.wonder.duration; title = sprintf( translatePluralWithContext( "victory condition", @@ -211,7 +207,7 @@ let isCaptureTheRelic = victoryCondition.Name == "capture_the_relic"; if (isCaptureTheRelic) { - let relicDuration = Math.round(g_GameAttributes.settings.RelicDuration); + let relicDuration = g_NewGameSettings.relic.duration title = sprintf( translatePluralWithContext( "victory condition", @@ -230,11 +226,11 @@ if (isCaptureTheRelic) titles.push({ "label": translate("Relic Count"), - "value": Math.round(g_GameAttributes.settings.RelicCount) + "value": g_NewGameSettings.relic.count }); if (victoryCondition.Name == "regicide") - if (g_GameAttributes.settings.RegicideGarrison) + if (g_NewGameSettings.regicideGarrison) titles.push({ "label": translate("Hero Garrison"), "value": translate("Heroes can be garrisoned.") @@ -246,14 +242,13 @@ }); } - if (g_GameAttributes.settings.RatingEnabled && - g_GameAttributes.settings.PlayerData.length == 2) + if (g_NewGameSettings.rating.enabled) titles.push({ "label": translate("Rated game"), "value": translate("When the winner of this match is determined, the lobby score will be adapted.") }); - if (g_GameAttributes.settings.LockTeams) + if (g_NewGameSettings.lockedTeams.enabled) titles.push({ "label": translate("Locked Teams"), "value": translate("Players can't change the initial teams.") @@ -264,7 +259,7 @@ "value": translate("Players can make alliances and declare war on allies.") }); - if (g_GameAttributes.settings.LastManStanding) + if (g_NewGameSettings.lastManStanding.enabled) titles.push({ "label": translate("Last Man Standing"), "value": translate("Only one player can win the game. If the remaining players are allies, the game continues until only one remains.") @@ -275,7 +270,7 @@ "value": translate("If one player wins, his or her allies win too. If one group of allies remains, they win.") }); - let ceasefire = Math.round(g_GameAttributes.settings.Ceasefire); + let ceasefire = g_NewGameSettings.ceasefire.value; titles.push({ "label": translate("Ceasefire"), "value": @@ -288,7 +283,7 @@ { "min": ceasefire }) }); - if (g_GameAttributes.map == "random") + if (g_NewGameSettings.map.map == "random") titles.push({ "label": translateWithContext("Map Selection", "Random Map"), "value": translate("Randomly select a map from the list.") @@ -298,23 +293,23 @@ titles.push({ "label": translate("Map Name"), "value": mapCache.translateMapName( - mapCache.getTranslatableMapName(g_GameAttributes.mapType, g_GameAttributes.map, g_GameAttributes)) + mapCache.getTranslatableMapName(g_NewGameSettings.map.type, g_NewGameSettings.map.map, g_NewGameSettings)) }); titles.push({ "label": translate("Map Description"), - "value": mapCache.getTranslatedMapDescription(g_GameAttributes.mapType, g_GameAttributes.map) + "value": mapCache.getTranslatedMapDescription(g_NewGameSettings.map.type, g_NewGameSettings.map.map) }); } titles.push({ "label": translate("Map Type"), - "value": g_MapTypes.Title[g_MapTypes.Name.indexOf(g_GameAttributes.mapType)] + "value": g_MapTypes.Title[g_MapTypes.Name.indexOf(g_NewGameSettings.map.type)] }); - if (g_GameAttributes.mapType == "random") + if (g_NewGameSettings.map.type == "random") { - let mapSize = g_MapSizes.Name[g_MapSizes.Tiles.indexOf(g_GameAttributes.settings.Size)]; + let mapSize = g_MapSizes.Name[g_MapSizes.Tiles.indexOf(g_NewGameSettings.mapSize.size)]; if (mapSize) titles.push({ "label": translate("Map Size"), @@ -322,37 +317,37 @@ }); } - if (g_GameAttributes.settings.Biome) + if (g_NewGameSettings.biome.biome) { - let biome = g_Settings.Biomes.find(b => b.Id == g_GameAttributes.settings.Biome); + let biome = g_NewGameSettings.biome.getData(); titles.push({ "label": biome ? biome.Title : translateWithContext("biome", "Random Biome"), "value": biome ? biome.Description : translate("Randomly select a biome from the list.") }); } - if (g_GameAttributes.settings.TriggerDifficulty !== undefined) + if (g_NewGameSettings.triggerDifficulty.value) { - let triggerDifficulty = g_Settings.TriggerDifficulties.find(difficulty => difficulty.Difficulty == g_GameAttributes.settings.TriggerDifficulty); + let triggerDifficulty = g_NewGameSettings.triggerDifficulty.getData(); titles.push({ "label": triggerDifficulty.Title, "value": triggerDifficulty.Tooltip }); } - if (g_GameAttributes.settings.Nomad !== undefined) + if (g_NewGameSettings.nomad.enabled) titles.push({ - "label": g_GameAttributes.settings.Nomad ? translate("Nomad Mode") : translate("Civic Centers"), + "label": g_NewGameSettings.nomad.enabled ? translate("Nomad Mode") : translate("Civic Centers"), "value": - g_GameAttributes.settings.Nomad ? + g_NewGameSettings.nomad.enabled ? translate("Players start with only few units and have to find a suitable place to build their city.") : translate("Players start with a Civic Center.") }); - if (g_GameAttributes.settings.StartingResources !== undefined) + if (g_NewGameSettings.startingResources.resources) titles.push({ "label": translate("Starting Resources"), - "value": + "value": "toto" /* g_GameAttributes.settings.PlayerData && g_GameAttributes.settings.PlayerData.some(pData => pData && pData.Resources !== undefined) ? translateWithContext("starting resources", "Per Player") : @@ -362,22 +357,22 @@ g_StartingResources.Resources.indexOf( g_GameAttributes.settings.StartingResources)], "amount": g_GameAttributes.settings.StartingResources - }) + })*/ }); - if (g_GameAttributes.settings.PopulationCap !== undefined) + if (!g_NewGameSettings.population.useWorldPop) titles.push({ "label": translate("Population Limit"), - "value": + "value": "toto" /* g_GameAttributes.settings.PlayerData && g_GameAttributes.settings.PlayerData.some(pData => pData && pData.PopulationLimit !== undefined) ? translateWithContext("population limit", "Per Player") : g_PopulationCapacities.Title[ g_PopulationCapacities.Population.indexOf( - g_GameAttributes.settings.PopulationCap)] + g_GameAttributes.settings.PopulationCap)]*/ }); - if (g_GameAttributes.settings.WorldPopulationCap !== undefined) + if (g_NewGameSettings.population.useWorldPop) titles.push({ "label": translate("World Population Cap"), "value": @@ -388,24 +383,24 @@ titles.push({ "label": translate("Treasures"), - "value": g_GameAttributes.settings.DisableTreasures ? + "value": g_NewGameSettings.disableTreasures.enabled ? translateWithContext("treasures", "Disabled") : translateWithContext("treasures", "As defined by the map.") }); titles.push({ "label": translate("Revealed Map"), - "value": g_GameAttributes.settings.RevealMap + "value": g_NewGameSettings.mapExploration.revealed }); titles.push({ "label": translate("Explored Map"), - "value": g_GameAttributes.settings.ExploreMap + "value": g_NewGameSettings.mapExploration.explored }); titles.push({ "label": translate("Cheats"), - "value": g_GameAttributes.settings.CheatsEnabled + "value": g_NewGameSettings.cheats.enabled }); return titles.map(title => sprintf(translate("%(label)s %(details)s"), { @@ -416,6 +411,18 @@ })).join("\n"); } +function translateAISettings(playerData) +{ + if (!playerData.AI) + return ""; + + return sprintf(translate("%(AIdifficulty)s %(AIbehavior)s %(AIname)s"), { + "AIname": translateAIName(playerData.AI), + "AIdifficulty": translateAIDifficulty(playerData.AIDiff), + "AIbehavior": translateAIBehavior(playerData.AIBehavior), + }); +} + /** * Sets the win/defeat icon to indicate current player's state. */ @@ -432,15 +439,3 @@ image.tooltip = translate("Defeated"); } } - -function translateAISettings(playerData) -{ - if (!playerData.AI) - return ""; - - return sprintf(translate("%(AIdifficulty)s %(AIbehavior)s %(AIname)s"), { - "AIname": translateAIName(playerData.AI), - "AIdifficulty": translateAIDifficulty(playerData.AIDiff), - "AIbehavior": translateAIBehavior(playerData.AIBehavior), - }); -} Index: binaries/data/mods/public/gui/gamesetup/Controls/GameSettingsControl.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Controls/GameSettingsControl.js +++ binaries/data/mods/public/gui/gamesetup/Controls/GameSettingsControl.js @@ -19,9 +19,7 @@ this.gameAttributesChangeHandlers = new Set(); this.gameAttributesBatchChangeHandlers = new Set(); this.gameAttributesFinalizeHandlers = new Set(); - this.pickRandomItemsHandlers = new Set(); this.assignPlayerHandlers = new Set(); - this.mapChangeHandlers = new Set(); setupWindow.registerLoadHandler(this.onLoad.bind(this)); setupWindow.registerGetHotloadDataHandler(this.onGetHotloadData.bind(this)); @@ -34,16 +32,6 @@ netMessages.registerNetMessageHandler("gamesetup", this.onGamesetupMessage.bind(this)); } - registerMapChangeHandler(handler) - { - this.mapChangeHandlers.add(handler); - } - - unregisterMapChangeHandler(handler) - { - this.mapChangeHandlers.delete(handler); - } - /** * This message is triggered everytime g_GameAttributes change. * Handlers may subsequently change g_GameAttributes and trigger this message again. @@ -92,59 +80,32 @@ this.assignPlayerHandlers.delete(handler); } - registerPickRandomItemsHandler(handler) - { - this.pickRandomItemsHandlers.add(handler); - } - - unregisterPickRandomItemsHandler(handler) - { - this.pickRandomItemsHandlers.delete(handler); - } - onLoad(initData, hotloadData) { - if (initData && initData.map && initData.mapType) + if (hotloadData) + g_GameAttributes = hotloadData.gameAttributes; + else if (g_IsController && this.gameSettingsFile.enabled) { - Object.defineProperty(this, "autostart", { - "value": true, - "writable": false, - "configurable": false - }); - - // TODO: Fix g_GameAttributes, g_GameAttributes.settings, - // g_GameAttributes.settings.PlayerData object references and - // copy over each attribute individually when receiving - // settings from the server or the local file. - g_GameAttributes = { - "mapType": initData.mapType, - "map": initData.map - }; - - this.updateGameAttributes(); - // Don't launchGame before all Load handlers finished + //g_GameAttributes = this.gameSettingsFile.loadFile(); + g_NewGameSettings.LegacyDeserialize(this.gameSettingsFile.loadFile()); } - else - { - if (hotloadData) - g_GameAttributes = hotloadData.gameAttributes; - else if (g_IsController && this.gameSettingsFile.enabled) - g_GameAttributes = this.gameSettingsFile.loadFile(); - this.updateGameAttributes(); - this.setNetworkGameAttributes(); - } + this.updateGameAttributes(); + this.setNetworkGameAttributes(); } onClose() { if (!this.autostart) + { + warn("here"); this.gameSettingsFile.saveFile(); + } } onGetHotloadData(object) { - object.gameAttributes = g_GameAttributes; + object.gameAttributes = g_NewGameSettings.LegacySerialize(); } onGamesetupMessage(message) @@ -161,61 +122,8 @@ */ updateGameAttributes() { - if (this.depth == 0) - Engine.ProfileStart("updateGameAttributes"); - - if (this.depth >= this.MaxDepth) - { - error("Infinite loop: " + new Error().stack); - Engine.ProfileStop(); - return; - } - - ++this.depth; - - // Basic sanitization - { - if (!g_GameAttributes.settings) - g_GameAttributes.settings = {}; - - if (!g_GameAttributes.settings.PlayerData) - g_GameAttributes.settings.PlayerData = new Array(this.DefaultPlayerCount); - - for (let i = 0; i < g_GameAttributes.settings.PlayerData.length; ++i) - if (!g_GameAttributes.settings.PlayerData[i]) - g_GameAttributes.settings.PlayerData[i] = {}; - } - - // Map change handlers are triggered first, so that GameSettingControls can update their - // gameAttributes model prior to applying that model in their gameAttributesChangeHandler. - if (g_GameAttributes.map && this.previousMap != g_GameAttributes.map && g_GameAttributes.mapType) - { - this.previousMap = g_GameAttributes.map; - // Use a try..catch to avoid completely failing in case of an error - // as this prevents even going back to the main menu. - try - { - let mapData = this.mapCache.getMapData(g_GameAttributes.mapType, g_GameAttributes.map); - for (let handler of this.mapChangeHandlers) - handler(mapData); - } catch(err) { - // Report the error regardless so that the underlying bug gets fixed. - error(err); - error(err.stack); - } - } - - for (let handler of this.gameAttributesChangeHandlers) + for (let handler of this.gameAttributesBatchChangeHandlers) handler(); - - --this.depth; - - if (this.depth == 0) - { - for (let handler of this.gameAttributesBatchChangeHandlers) - handler(); - Engine.ProfileStop(); - } } /** @@ -253,27 +161,15 @@ this.setNetworkGameAttributes(); } - /** - * This function is called everytime a random setting selection was resolved, - * so that subsequent random settings are triggered too, - * for example picking a random biome after picking a random map. - */ - pickRandomItems() - { - for (let handler of this.pickRandomItemsHandlers) - handler(); - } - onLaunchGame() { if (!this.autostart) this.gameSettingsFile.saveFile(); - this.pickRandomItems(); - for (let handler of this.gameAttributesFinalizeHandlers) handler(); + g_NewGameSettings.prepareForLaunch(); this.setNetworkGameAttributes(); } } Index: binaries/data/mods/public/gui/gamesetup/Controls/GameSettingsFile.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Controls/GameSettingsFile.js +++ binaries/data/mods/public/gui/gamesetup/Controls/GameSettingsFile.js @@ -45,7 +45,7 @@ Engine.ProfileStart("savePersistMatchSettingsFile"); Engine.WriteJSONFile(this.filename, { - "attributes": this.enabled ? g_GameAttributes : {}, + "attributes": this.enabled ? g_NewGameSettings.LegacySerialize() : {}, "engine_info": this.engineInfo }); Engine.ProfileStop(); Index: binaries/data/mods/public/gui/gamesetup/Controls/PlayerAssignmentsControl.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Controls/PlayerAssignmentsControl.js +++ binaries/data/mods/public/gui/gamesetup/Controls/PlayerAssignmentsControl.js @@ -79,6 +79,8 @@ updatePlayerAssignments() { Engine.ProfileStart("updatePlayerAssignments"); + g_NewGameSettings.playerName.onPlayerAssignmentsChange(); + g_NewGameSettings.playerAI.onPlayerAssignmentsChange(); for (let handler of this.playerAssignmentsChangeHandlers) handler(); Engine.ProfileStop(); @@ -148,11 +150,11 @@ unassignInvalidPlayers() { if (g_IsNetworked) - for (let playerID = g_GameAttributes.settings.PlayerData.length + 1; playerID <= g_MaxPlayers; ++playerID) + for (let playerID = g_NewGameSettings.playerCount.nbPlayers + 1; playerID <= g_MaxPlayers; ++playerID) // Remove obsolete playerIDs from the servers playerassignments copy Engine.AssignNetworkPlayer(playerID, ""); - else if (g_PlayerAssignments.local.player > g_GameAttributes.settings.PlayerData.length) + else if (g_PlayerAssignments.local.player > g_NewGameSettings.playerCount.nbPlayers) { g_PlayerAssignments.local.player = -1; this.updatePlayerAssignments(); Index: binaries/data/mods/public/gui/gamesetup/Controls/StartGameControl.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Controls/StartGameControl.js +++ binaries/data/mods/public/gui/gamesetup/Controls/StartGameControl.js @@ -34,11 +34,13 @@ for (let handler of this.gameLaunchHandlers) handler(); + Engine.SetRankedGame(g_NewGameSettings.rating.enabled); + if (g_IsNetworked) Engine.StartNetworkGame(); else { - Engine.StartGame(g_GameAttributes, g_PlayerAssignments.local.player); + Engine.StartGame(g_NewGameSettings.LegacySerialize(), g_PlayerAssignments.local.player); this.switchToLoadingPage(); } } @@ -46,7 +48,7 @@ switchToLoadingPage() { Engine.SwitchGuiPage("page_loading.xml", { - "attribs": g_GameAttributes, + "attribs": g_NewGameSettings.LegacySerialize(), "playerAssignments": g_PlayerAssignments }); } Index: binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/AIConfigPage.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/AIConfigPage.js +++ binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/AIConfigPage.js @@ -25,8 +25,7 @@ this.aiConfigPage = Engine.GetGUIObjectByName("aiConfigPage"); Engine.GetGUIObjectByName("aiConfigOkButton").onPress = this.closePage.bind(this); - this.gameSettingsControl.registerGameAttributesBatchChangeHandler( - this.onGameAttributesBatchChange.bind(this)); + g_NewGameSettings.playerAI.watch(() => this.maybeClose(), ["values"]); } registerOpenPageHandler(handler) @@ -49,10 +48,9 @@ this.aiConfigPage.hidden = false; } - onGameAttributesBatchChange() + maybeClose() { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) + if (!g_NewGameSettings.playerAI.get(this.playerIndex)) this.closePage(); } @@ -60,7 +58,7 @@ { this.aiConfigPage.hidden = true; } -} +}; SetupWindowPages.AIConfigPage.prototype.AIGameSettingControlOrder = [ "AISelection", Index: binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/AIDescription.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/AIDescription.js +++ binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/AIDescription.js @@ -6,29 +6,22 @@ this.aiDescription = Engine.GetGUIObjectByName("aiDescription"); - this.gameSettingsControl = setupWindow.controls.gameSettingsControl; - this.gameSettingsControl.registerGameAttributesBatchChangeHandler(this.onGameAttributesBatchChange.bind(this)); - aiConfigPage.registerOpenPageHandler(this.onOpenPage.bind(this)); + + g_NewGameSettings.playerAI.watch(() => this.render(), ["values"]); } onOpenPage(playerIndex) { this.playerIndex = playerIndex; - this.updateSelectedValue(); + this.render(); } - onGameAttributesBatchChange() + render() { - this.updateSelectedValue(); - } - - updateSelectedValue() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) - return; - let AI = g_Settings.AIDescriptions.find(AI => AI.id == pData.AI); + let AI = g_NewGameSettings.playerAI.get(this.playerIndex); + if (!!AI) + AI = g_Settings.AIDescriptions.find(desc => desc.id == AI.bot); this.aiDescription.caption = AI ? AI.data.description : this.NoAIDescription; } } Index: binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/AIGameSettingControl.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/AIGameSettingControl.js +++ binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/AIGameSettingControl.js @@ -1,10 +1,9 @@ class AIGameSettingControlDropdown extends GameSettingControlDropdown { - constructor(...args) + onOpenPage(playerIndex) { - super(...args); - - this.gameSettingsControl.registerAssignPlayerHandler(this.onAssignPlayer.bind(this)); + this.playerIndex = playerIndex; + this.render(); } setControl(aiConfigPage) @@ -25,24 +24,6 @@ this.setHidden(false); } - - onOpenPage(playerIndex) - { - this.playerIndex = playerIndex; - this.updateSelectedValue(); - this.updateVisibility(); - } - - onGameAttributesChange() - { - for (let playerIndex = 0; playerIndex < g_MaxPlayers; ++playerIndex) - this.onGameAttributesChangePlayer(playerIndex); - } - - onGameAttributesBatchChange() - { - this.updateSelectedValue(); - } } AIGameSettingControlDropdown.prototype.Height= 28; Index: binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/Controls/AIBehavior.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/Controls/AIBehavior.js +++ binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/Controls/AIBehavior.js @@ -4,92 +4,26 @@ { super(...args); - this.fixedAIBehavior = []; - this.defaultBehavior = Engine.ConfigDB_GetValue("user", this.ConfigBehavior); + g_NewGameSettings.playerAI.watch(() => this.render(), ["values"]); + } + render() + { this.dropdown.list = g_Settings.AIBehaviors.map(AIBehavior => AIBehavior.Title); this.dropdown.list_data = g_Settings.AIBehaviors.map(AIBehavior => AIBehavior.Name); - } - onAssignPlayer(source, target) - { - if (source && target.AIBehavior) - source.AIBehavior = target.AIBehavior; - - delete target.AIBehavior; - } - - onMapChange(mapData) - { - for (let playerIndex = 0; playerIndex < g_MaxPlayers; ++playerIndex) - { - let mapPData = this.gameSettingsControl.getPlayerData(mapData, playerIndex); - this.fixedAIBehavior[playerIndex] = - mapPData && mapPData.AI ? - (mapPData.AIBehavior !== undefined ? - mapPData.AIBehavior : - g_Settings.PlayerDefaults[playerIndex + 1].AIBehavior) : - undefined; - } - } - - onGameAttributesChangePlayer(playerIndex) - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, playerIndex); - if (!pData) - return; - - if (pData.AI) - { - if (this.fixedAIBehavior[playerIndex] && - (pData.AIBehavior === undefined || - pData.AIBehavior !== this.fixedAIBehavior[playerIndex])) - { - pData.AIBehavior = this.fixedAIBehavior[playerIndex]; - this.gameSettingsControl.updateGameAttributes(); - } - else if (pData.AIDiff !== undefined && - g_Settings.AIDifficulties[pData.AIDiff].Name == "sandbox" && - pData.AIBehavior != "balanced") - { - pData.AIBehavior = "balanced"; - this.gameSettingsControl.updateGameAttributes(); - } - else if (pData.AIBehavior === undefined) - { - pData.AIBehavior = this.defaultBehavior; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (pData.AIBehavior !== undefined) - { - delete pData.AIBehavior; - this.gameSettingsControl.updateGameAttributes(); - } - } - - updateSelectedValue() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - this.setHidden(!pData || !pData.AI || g_Settings.AIDifficulties[pData.AIDiff].Name == "sandbox"); - if (pData && pData.AI && pData.AIDiff !== undefined && pData.AIBehavior !== undefined) - this.setSelectedValue(pData.AIBehavior); + let ai = g_NewGameSettings.playerAI.get(this.playerIndex); + this.setHidden(!ai); + if (!!ai) + this.setSelectedValue(ai.behavior); } onSelectionChange(itemIdx) { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!g_IsController || !pData) - return; - - pData.AIBehavior = g_Settings.AIBehaviors[itemIdx].Name; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.playerAI.setBehavior(this.playerIndex, this.dropdown.list_data[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } -} - -AIGameSettingControls.AIBehavior.prototype.ConfigBehavior = - "gui.gamesetup.aibehavior"; +}; AIGameSettingControls.AIBehavior.prototype.TitleCaption = translate("AI Behavior"); Index: binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/Controls/AIDifficulty.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/Controls/AIDifficulty.js +++ binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/Controls/AIDifficulty.js @@ -4,80 +4,23 @@ { super(...args); - this.fixedAIDiff = []; - this.defaultAIDiff = +Engine.ConfigDB_GetValue("user", this.ConfigDifficulty); + g_NewGameSettings.playerAI.watch(() => this.render(), ["values"]); + } + render() + { this.dropdown.list = g_Settings.AIDifficulties.map(AI => AI.Title); this.dropdown.list_data = g_Settings.AIDifficulties.map((AI, i) => i); - } - onAssignPlayer(source, target) - { - if (source && target.AIDiff !== undefined) - source.AIDiff = target.AIDiff; - - delete target.AIDiff; - } - - onMapChange(mapData) - { - for (let playerIndex = 0; playerIndex < g_MaxPlayers; ++playerIndex) - { - let mapPData = this.gameSettingsControl.getPlayerData(mapData, playerIndex); - this.fixedAIDiff[playerIndex] = - mapPData && mapPData.AI ? - (mapPData.AIDiff !== undefined ? - mapPData.AIDiff : - g_Settings.PlayerDefaults[playerIndex + 1].AIDiff) : - undefined; - } - } - - onGameAttributesChangePlayer(playerIndex) - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, playerIndex); - if (!pData) - return; - - if (pData.AI) - { - if (this.fixedAIDiff[playerIndex] !== undefined && - (pData.AIDiff === undefined || - pData.AIDiff !== this.fixedAIDiff[playerIndex])) - { - pData.AIDiff = this.fixedAIDiff[playerIndex]; - this.gameSettingsControl.updateGameAttributes(); - } - else if (pData.AIDiff === undefined) - { - pData.AIDiff = this.defaultAIDiff; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (pData.AIDiff !== undefined) - { - delete pData.AIDiff; - this.gameSettingsControl.updateGameAttributes(); - } - } - - updateSelectedValue() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - this.setHidden(!pData || !pData.AI); - - if (pData && pData.AIDiff !== undefined) - this.setSelectedValue(pData.AIDiff); + let ai = g_NewGameSettings.playerAI.get(this.playerIndex); + this.setHidden(!ai); + if (!!ai) + this.setSelectedValue(ai.difficulty); } onSelectionChange(itemIdx) { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!g_IsController || !pData) - return; - - pData.AIDiff = itemIdx; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.playerAI.setDifficulty(this.playerIndex, this.dropdown.list_data[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/Controls/AISelection.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/Controls/AISelection.js +++ binaries/data/mods/public/gui/gamesetup/Pages/AIConfigPage/Controls/AISelection.js @@ -4,7 +4,7 @@ { super(...args); - this.fixedAI = []; + g_NewGameSettings.playerAI.watch(() => this.render(), ["values"]); this.values = prepareForDropdown([ this.NoAI, @@ -15,76 +15,29 @@ ]); this.dropdown.list = this.values.Title; - this.dropdown.list_data = this.values.Id.map((v, i) => i); + this.dropdown.list_data = this.values.Id; } - onAssignPlayer(source, target) + render() { - if (source && target.AI) - source.AI = target.AI; - - target.AI = false; - } - - onMapChange(mapData) - { - for (let playerIndex = 0; playerIndex < g_MaxPlayers; ++playerIndex) - { - let mapPData = this.gameSettingsControl.getPlayerData(mapData, playerIndex); - this.fixedAI[playerIndex] = mapPData && mapPData.AI || undefined; - } - } - - onGameAttributesChangePlayer(playerIndex) - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, playerIndex); - if (!pData) - return; - - if (this.fixedAI[playerIndex] && pData.AI !== this.fixedAI[playerIndex]) - { - pData.AI = this.fixedAI[playerIndex]; - this.gameSettingsControl.updateGameAttributes(); - } - else if (pData.AI === undefined) - { - let assignedGUID; - for (let guid in g_PlayerAssignments) - if (g_PlayerAssignments[guid].player == playerIndex + 1) - { - assignedGUID = guid; - break; - } - - pData.AI = assignedGUID ? false : g_Settings.PlayerDefaults[playerIndex + 1].AI; - this.gameSettingsControl.updateGameAttributes(); - } - } - - updateSelectedValue() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData || pData.AI === undefined) - return; - - this.setSelectedValue(this.values.Id.indexOf(pData.AI)); + let ai = g_NewGameSettings.playerAI.get(this.playerIndex); + this.setHidden(!ai); + if (!!ai) + this.setSelectedValue(ai.bot); + else + this.setSelectedValue(undefined); } onSelectionChange(itemIdx) { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) - return; - - pData.AI = this.values.Id[itemIdx]; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.playerAI.setAI(this.playerIndex, this.dropdown.list_data[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } -} +}; AIGameSettingControls.AISelection.prototype.NoAI = { "Title": translateWithContext("ai", "None"), - "Id": false + "Id": undefined }; AIGameSettingControls.AISelection.prototype.TitleCaption = Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/GameSettingControl.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/GameSettingControl.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/GameSettingControl.js @@ -59,9 +59,6 @@ this.setHidden(false); - if (this.onMapChange) - this.gameSettingsControl.registerMapChangeHandler(this.onMapChange.bind(this)); - if (this.onLoad) this.setupWindow.registerLoadHandler(this.onLoad.bind(this)); @@ -74,9 +71,6 @@ if (this.onAssignPlayer && this.playerIndex === 0) this.gameSettingsControl.registerAssignPlayerHandler(this.onAssignPlayer.bind(this)); - if (this.onPickRandomItems) - this.gameSettingsControl.registerPickRandomItemsHandler(this.onPickRandomItems.bind(this)); - if (this.onGameAttributesFinalize) this.gameSettingsControl.registerGameAttributesFinalizeHandler(this.onGameAttributesFinalize.bind(this)); @@ -104,10 +98,6 @@ this.setControlTooltip(tooltip); } - /** - * Do not call functions calling updateVisibility onMapChange but onGameAttributesChange, - * so that changes take effect when increasing the playercount as well. - */ setEnabled(enabled) { this.enabled = enabled; @@ -118,6 +108,8 @@ { this.hidden = hidden; this.updateVisibility(); + // Trigger a layout update to reposition items. + this.gameSettingsControl.updateGameAttributes(); } updateVisibility() @@ -126,8 +118,8 @@ this.hidden || this.playerIndex === undefined && this.category != g_TabCategorySelected || - this.playerIndex !== undefined && - g_GameAttributes.settings && this.playerIndex >= g_GameAttributes.settings.PlayerData.length; + this.playerIndex !== undefined && + this.playerIndex >= g_NewGameSettings.playerCount.nbPlayers; if (this.frame) this.frame.hidden = hidden; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/AIConfigButton.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/AIConfigButton.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/AIConfigButton.js @@ -6,8 +6,10 @@ this.aiConfigButton = Engine.GetGUIObjectByName("aiConfigButton[" + this.playerIndex + "]"); + g_NewGameSettings.playerAI.watch(() => this.render(), ["values"]); // Save little performance by not reallocating every call this.sprintfArgs = {}; + this.render(); } onLoad() @@ -16,15 +18,13 @@ this.aiConfigButton.onPress = aiConfigPage.openPage.bind(aiConfigPage, this.playerIndex); } - onGameAttributesBatchChange() + render() { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) + this.aiConfigButton.hidden = !g_NewGameSettings.playerAI.get(this.playerIndex); + if (this.aiConfigButton.hidden) return; - - this.sprintfArgs.description = translateAISettings(pData); + this.sprintfArgs.description = g_NewGameSettings.playerAI.describe(this.playerIndex); this.aiConfigButton.tooltip = sprintf(this.Tooltip, this.sprintfArgs); - this.aiConfigButton.hidden = !pData.AI; } }; 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 @@ -16,6 +16,9 @@ this.assignedGUID = undefined; this.fixedAI = undefined; + g_NewGameSettings.playerAI.watch(() => this.render(), ["values"]); + this.render(); + this.playerAssignmentsControl.registerClientJoinHandler(this.onClientJoin.bind(this)); } @@ -29,6 +32,7 @@ { if (!hotloadData && !g_IsNetworked) this.onClientJoin("local", g_PlayerAssignments); + this.playerAssignmentsControl.updatePlayerAssignments(); } onClientJoin(newGUID, newAssignments) @@ -36,16 +40,12 @@ if (!g_IsController || this.fixedAI || newAssignments[newGUID].player != -1) return; - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) - return; - // Assign the client (or only buddies if prefered) to a free slot if (newGUID != Engine.GetPlayerGUID()) { let assignOption = Engine.ConfigDB_GetValue("user", this.ConfigAssignPlayers); if (assignOption == "disabled" || - assignOption == "buddies" && g_Buddies.indexOf(splitRatingFromNick(newAssignments[newGUID].name).nick) == -1) + assignOption == "buddies" && g_Buddies.indexOf(splitRatingFromNick(newAssignments[newGUID].name).nick) == -1) return; } @@ -53,9 +53,10 @@ if (newAssignments[guid].player == this.playerIndex + 1) return; - if (pData.AI) + let ai = g_NewGameSettings.playerAI.get(this.playerIndex); + if (ai) { - pData.AI = false; + g_NewGameSettings.playerAI.setAI(this.playerIndex, undefined); this.gameSettingsControl.updateGameAttributes(); this.gameSettingsControl.setNetworkGameAttributes(); } @@ -78,46 +79,26 @@ this.clientItemFactory.createItem.bind(this.clientItemFactory)); this.rebuildList(); - this.updateSelection(); + this.render(); } - onMapChange(mapData) + render() { - let mapPData = this.gameSettingsControl.getPlayerData(mapData, this.playerIndex); - this.fixedAI = mapPData && mapPData.AI || undefined; - } - - onGameAttributesChange() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) + this.setEnabled(true); + if (this.assignedGUID) + { + this.setSelectedValue(this.assignedGUID); return; - - if (this.fixedAI && (pData.AI === undefined || pData.AI != this.fixedAI)) + } + let ai = g_NewGameSettings.playerAI.get(this.playerIndex); + if (ai) { - pData.AI = this.fixedAI; - this.gameSettingsControl.updateGameAttributes(); this.playerAssignmentsControl.unassignClient(this.playerIndex + 1); - } - } - - onGameAttributesBatchChange() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) + this.setSelectedValue(ai.bot); return; + } - this.setEnabled(!this.fixedAI); - this.updateSelection(); - } - - updateSelection() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (pData && this.values) - this.setSelectedValue( - this.values.Value.findIndex((value, i) => - this.values.Handler[i].isSelected(pData, this.assignedGUID, value))); + this.setSelectedValue(undefined); } rebuildList() @@ -130,7 +111,7 @@ ]); this.dropdown.list = this.values.Caption; - this.dropdown.list_data = this.values.Value.map((value, i) => i); + this.dropdown.list_data = this.values.Value; Engine.ProfileStop(); } @@ -181,6 +162,8 @@ let sourcePlayer = g_PlayerAssignments[guidToAssign].player - 1; playerAssignmentsControl.assignPlayer(guidToAssign, playerIndex); gameSettingsControl.assignPlayer(sourcePlayer, playerIndex); + playerAssignmentsControl.updatePlayerAssignments(); + gameSettingsControl.setNetworkGameAttributes(); } isSelected(pData, guid, value) @@ -214,7 +197,7 @@ { playerAssignmentsControl.unassignClient(playerIndex + 1); - g_GameAttributes.settings.PlayerData[playerIndex].AI = value; + g_NewGameSettings.playerAI.setAI(playerIndex, value); gameSettingsControl.updateGameAttributes(); gameSettingsControl.setNetworkGameAttributes(); @@ -250,7 +233,9 @@ { playerAssignmentsControl.unassignClient(playerIndex + 1); - g_GameAttributes.settings.PlayerData[playerIndex].AI = false; + warn("jere"); + g_NewGameSettings.playerAI.setAI(playerIndex, undefined); + gameSettingsControl.updateGameAttributes(); gameSettingsControl.setNetworkGameAttributes(); } Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerCiv.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerCiv.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerCiv.js @@ -4,11 +4,13 @@ { super(...args); - this.fixedCiv = undefined; this.values = prepareForDropdown(this.getItems()); this.dropdown.list = this.values.name; this.dropdown.list_data = this.values.civ; + + g_NewGameSettings.playerCiv.watch(() => this.render(), ["values", "locked"]); + this.render(); } setControl() @@ -22,51 +24,16 @@ this.dropdown.tooltip = this.values && this.values.tooltip[this.dropdown.hovered] || this.Tooltip; } - onMapChange(mapData) - { - let mapPData = this.gameSettingsControl.getPlayerData(mapData, this.playerIndex); - this.fixedCiv = mapPData && mapPData.Civ || undefined; - } - onAssignPlayer(source, target) { if (g_GameAttributes.mapType != "scenario" && source && target) [source.Civ, target.Civ] = [target.Civ, source.Civ]; } - onGameAttributesChange() + render() { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData || !g_GameAttributes.mapType) - return; - - if (this.fixedCiv) - { - if (!pData.Civ || this.fixedCiv != pData.Civ) - { - pData.Civ = this.fixedCiv; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (this.values.civ.indexOf(pData.Civ || undefined) == -1) - { - pData.Civ = - g_GameAttributes.mapType == "scenario" ? - g_Settings.PlayerDefaults[this.playerIndex + 1].Civ : - this.RandomCivId; - - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData || !g_GameAttributes.mapType) - return; - - this.setEnabled(!this.fixedCiv); - this.setSelectedValue(pData.Civ); + this.setEnabled(!g_NewGameSettings.playerCiv.locked[this.playerIndex]); + this.setSelectedValue(g_NewGameSettings.playerCiv.values[this.playerIndex]); } getItems() @@ -101,30 +68,9 @@ onSelectionChange(itemIdx) { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - pData.Civ = this.values.civ[itemIdx]; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.playerCiv.setValue(this.playerIndex, this.values.civ[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } - - onPickRandomItems() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData || pData.Civ != this.RandomCivId) - return; - - // Get a unique array of selectable cultures - let cultures = Object.keys(g_CivData).filter(civ => g_CivData[civ].SelectableInGameSetup).map(civ => g_CivData[civ].Culture); - cultures = cultures.filter((culture, index) => cultures.indexOf(culture) === index); - - // Pick a random civ of a random culture - let culture = pickRandom(cultures); - pData.Civ = pickRandom(Object.keys(g_CivData).filter(civ => - g_CivData[civ].Culture == culture && g_CivData[civ].SelectableInGameSetup)); - - this.gameSettingsControl.updateGameAttributes(); - this.gameSettingsControl.pickRandomItems(); - } }; PlayerSettingControls.PlayerCiv.prototype.Tooltip = Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerColor.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerColor.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerColor.js @@ -4,7 +4,8 @@ { super(...args); - this.defaultColors = g_Settings.PlayerDefaults.slice(1).map(pData => pData.Color); + g_NewGameSettings.playerColor.watch(() => this.render(), ["values", "locked"]); + this.render(); } setControl() @@ -14,92 +15,22 @@ this.playerColorHeading = Engine.GetGUIObjectByName("playerColorHeading"); } - onMapChange(mapData) + render() { - Engine.ProfileStart("updatePlayerColorList"); - let hidden = !g_IsController || g_GameAttributes.mapType == "scenario"; + let hidden = !g_IsController || g_NewGameSettings.map.type == "scenario"; this.dropdown.hidden = hidden; this.playerColorHeading.hidden = hidden; - // Step 1: Pick colors that the map specifies, add most unsimilar default colors - // Provide the access to g_MaxPlayers different colors, regardless of current playercount. - let values = []; - for (let i = 0; i < g_MaxPlayers; ++i) - { - let pData = this.gameSettingsControl.getPlayerData(mapData, i); - values.push(pData && pData.Color || this.findFarthestUnusedColor(values)); - } + if (!g_NewGameSettings.playerColor.values.length) + return; - // Step 2: Sort these colors so that the order is most reminiscent of the default colors - this.values = []; - for (let i = 0; i < g_MaxPlayers; ++i) - { - let closestColor; - let smallestDistance = Infinity; - for (let color of values) - { - if (this.values.some(col => sameColor(col, color))) - continue; - - let distance = colorDistance(color, this.defaultColors[i]); - if (distance <= smallestDistance) - { - closestColor = color; - smallestDistance = distance; - } - } - this.values.push(closestColor); - } + let value = g_NewGameSettings.playerColor.get(this.playerIndex); + this.setSelectedValue(value); + this.playerBackgroundColor.sprite = "color:" + rgbToGuiColor(value, 100); + this.values = g_NewGameSettings.playerColor.available; this.dropdown.list = this.values.map(color => coloredText(this.ColorIcon, rgbToGuiColor(color))); this.dropdown.list_data = this.values.map((color, i) => i); - - // If the map specified a color for this slot, use that - let mapPlayerData = this.gameSettingsControl.getPlayerData(mapData, this.playerIndex); - let playerData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - - if (playerData && mapPlayerData && mapPlayerData.Color && - (!playerData.Color || !sameColor(playerData.Color, mapPlayerData.Color))) - { - playerData.Color = mapPlayerData.Color; - this.gameSettingsControl.updateGameAttributes(); - } - - Engine.ProfileStop(); - } - - onGameAttributesChange() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData || !this.values) - return; - - let inUse = - pData.Color && - g_GameAttributes.settings.PlayerData.some((otherPData, i) => - i < this.playerIndex && - otherPData.Color && - sameColor(pData.Color, otherPData.Color)); - - if (!pData.Color || this.values.indexOf(pData.Color) == -1 || inUse) - { - pData.Color = - (pData.Color && !inUse) ? - this.findClosestColor(pData.Color, this.values) : - this.getUnusedColor(); - - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData || !this.values) - return; - - this.setSelectedValue(this.values.indexOf(pData.Color)); - this.playerBackgroundColor.sprite = "color:" + rgbToGuiColor(pData.Color, 100); } onAssignPlayer(source, target) @@ -110,62 +41,9 @@ onSelectionChange(itemIdx) { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - - // If someone else has that color, give that player the old color - let otherPData = g_GameAttributes.settings.PlayerData.find(data => - sameColor(this.values[itemIdx], data.Color)); - - if (otherPData) - otherPData.Color = pData.Color; - - pData.Color = this.values[itemIdx]; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.playerColor.setColor(this.playerIndex, this.values[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } - - findClosestColor(targetColor, colors) - { - let colorDistances = colors.map(color => colorDistance(color, targetColor)); - - let smallestDistance = colorDistances.find( - distance => colorDistances.every(distance2 => distance2 >= distance)); - - return colors.find(color => colorDistance(color, targetColor) == smallestDistance); - } - - findFarthestUnusedColor(values) - { - let farthestColor; - let farthestDistance = 0; - - for (let defaultColor of this.defaultColors) - { - let smallestDistance = Infinity; - for (let usedColor of values) - { - let distance = colorDistance(usedColor, defaultColor); - if (distance < smallestDistance) - smallestDistance = distance; - } - - if (smallestDistance >= farthestDistance) - { - farthestColor = defaultColor; - farthestDistance = smallestDistance; - } - } - return farthestColor; - } - - getUnusedColor() - { - return this.values.find(color => - g_GameAttributes && - g_GameAttributes.settings && - g_GameAttributes.settings.PlayerData && - g_GameAttributes.settings.PlayerData.every(pData => !pData.Color || !sameColor(color, pData.Color))); - } }; PlayerSettingControls.PlayerColor.prototype.Tooltip = Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerTeam.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerTeam.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/Dropdowns/PlayerTeam.js @@ -16,8 +16,12 @@ "id": i })) ]); + this.dropdown.list = this.values.label; this.dropdown.list_data = this.values.id; + + g_NewGameSettings.playerTeam.watch(() => this.render(), ["values", "locked"]); + this.render(); } setControl() @@ -26,45 +30,15 @@ this.dropdown = Engine.GetGUIObjectByName("playerTeam[" + this.playerIndex + "]"); } - onMapChange(mapData) + render() { - let mapPData = this.gameSettingsControl.getPlayerData(mapData, this.playerIndex); - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - - if (pData && mapPData && mapPData.Team !== undefined) - { - pData.Team = mapPData.Team; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesChange() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) - return; - - if (pData.Team === undefined) - { - pData.Team = this.NoTeamId; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) - return; - - this.setEnabled(g_GameAttributes.mapType != "scenario"); - this.setSelectedValue(pData.Team); + this.setEnabled(g_NewGameSettings.map.type != "scenario"); + this.setSelectedValue(g_NewGameSettings.playerTeam.values[this.playerIndex]); } onSelectionChange(itemIdx) { - g_GameAttributes.settings.PlayerData[this.playerIndex].Team = itemIdx - 1; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.playerTeam.setValue(this.playerIndex, itemIdx - 1); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/PlayerFrame.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/PlayerFrame.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/PlayerFrame.js @@ -12,12 +12,16 @@ size.bottom = this.Height * (this.playerIndex + 1); this.playerFrame.size = size; } + + g_NewGameSettings.playerCount.watch(() => this.render(), ["nbPlayers"]); + this.render(); } - onGameAttributesBatchChange() + render() { - this.playerFrame.hidden = !this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); + this.playerFrame.hidden = this.playerIndex >= g_NewGameSettings.playerCount.nbPlayers; + this.playerAssignmentsControl.unassignInvalidPlayers(); } -} +}; PlayerSettingControls.PlayerFrame.prototype.Height = 32; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/PlayerName.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/PlayerName.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/PlayerName.js @@ -8,44 +8,12 @@ this.playerName = Engine.GetGUIObjectByName("playerName[" + this.playerIndex + "]"); - this.displayedName = undefined; + g_NewGameSettings.playerName.watch(() => this.render(), ["values"]); + this.render(); + this.guid = undefined; } - onMapChange(mapData) - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) - return; - - let mapPData = this.gameSettingsControl.getPlayerData(mapData, this.playerIndex); - pData.Name = mapPData && mapPData.Name || g_Settings.PlayerDefaults[this.playerIndex + 1].Name; - this.gameSettingsControl.updateGameAttributes(); - } - - onGameAttributesChange() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) - return; - - if (!pData.Name) - { - pData.Name = g_Settings.PlayerDefaults[this.playerIndex + 1].Name; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) - return; - - this.displayedName = g_IsNetworked ? pData.Name : translate(pData.Name); - this.rebuild(); - } - onPlayerAssignmentsChange() { this.guid = undefined; @@ -56,66 +24,24 @@ this.guid = guid; break; } - - this.rebuild(); } - rebuild() + render() { - let name = this.displayedName; - if (!name) - return; + let name = g_NewGameSettings.playerName.values[this.playerIndex] || g_Settings.PlayerDefaults[this.playerIndex + 1].Name; if (g_IsNetworked) { let status = this.guid ? g_PlayerAssignments[this.guid].status : this.ReadyTags.length - 1; - name = setStringTags(this.displayedName, this.ReadyTags[status]); + name = setStringTags(name, this.ReadyTags[status]); } this.playerName.caption = name; } - onGameAttributesFinalize() - { - let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex); - if (!pData) - return; - if (g_GameAttributes.mapType != "scenario" && pData.AI) - { - // Pick one of the available botnames for the chosen civ - // Determine botnames - let chosenName = pickRandom(g_CivData[pData.Civ].AINames); - - if (!g_IsNetworked) - chosenName = translate(chosenName); - - // Count how many players use the chosenName - let usedName = g_GameAttributes.settings.PlayerData.filter(otherPData => - otherPData.Name && otherPData.Name.indexOf(chosenName) !== -1).length; - - pData.Name = - usedName ? - sprintf(this.RomanLabel, { - "playerName": chosenName, - "romanNumber": this.RomanNumbers[usedName + 1] - }) : - chosenName; - } - else - // Copy client playernames so they appear in replays - for (let guid in g_PlayerAssignments) - if (g_PlayerAssignments[guid].player == this.playerIndex + 1) - pData.Name = g_PlayerAssignments[guid].name; - } }; -PlayerSettingControls.PlayerName.prototype.RomanLabel = - translate("%(playerName)s %(romanNumber)s"); - -PlayerSettingControls.PlayerName.prototype.RomanNumbers = - [undefined, "I", "II", "III", "IV", "V", "VI", "VII", "VIII"]; - PlayerSettingControls.PlayerName.prototype.ReadyTags = [ { "color": "white", Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/PlayerSettings.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/PlayerSettings.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/PerPlayer/PlayerSettings.js @@ -1,3 +1,4 @@ +/* // TODO: There should be a dialog allowing to specify starting resources and population capacity per player PlayerSettingControls.PlayerSettings = class extends GameSettingControl { @@ -43,3 +44,4 @@ "DisabledTemplates", "StartingCamera" ]; +*/ Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Cheats.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Cheats.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Cheats.js @@ -6,32 +6,26 @@ constructor(...args) { super(...args); - this.setHidden(!g_IsNetworked); + + g_NewGameSettings.cheats.watch(() => this.render(), ["enabled"]); + g_NewGameSettings.rating.watch(() => this.render(), ["enabled"]); } - onGameAttributesChange() + onLoad() { - if (g_GameAttributes.settings.CheatsEnabled === undefined || - g_GameAttributes.settings.CheatsEnabled && g_GameAttributes.settings.RatingEnabled || - !g_GameAttributes.settings.CheatsEnabled && !g_IsNetworked) - { - g_GameAttributes.settings.CheatsEnabled = !g_IsNetworked; - this.gameSettingsControl.updateGameAttributes(); - } + g_NewGameSettings.cheats.setEnabled(!g_IsNetworked); + this.render(); } - onGameAttributesBatchChange() + render() { - this.setChecked(g_GameAttributes.settings.CheatsEnabled); - this.setEnabled(!g_GameAttributes.settings.RatingEnabled); + this.setChecked(g_NewGameSettings.cheats.enabled); + this.setEnabled(g_IsNetworked && !g_NewGameSettings.rating.enabled); } onPress(checked) { - g_GameAttributes.settings.CheatsEnabled = - !g_IsNetworked || - checked && !g_GameAttributes.settings.RatingEnabled; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.cheats.setEnabled(g_IsNetworked || checked); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/ExploredMap.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/ExploredMap.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/ExploredMap.js @@ -1,51 +1,22 @@ GameSettingControls.ExploredMap = class extends GameSettingControlCheckbox { - onMapChange(mapData) + constructor(...args) { - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.ExploreMap !== undefined) - mapValue = mapData.settings.ExploreMap; - - if (mapValue !== undefined && mapValue != g_GameAttributes.settings.ExploreMap) - { - g_GameAttributes.settings.ExploreMap = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesChange() - { - if (!g_GameAttributes.mapType) - return; - - if (g_GameAttributes.settings.ExploreMap === undefined) - { - g_GameAttributes.settings.ExploreMap = !!g_GameAttributes.settings.RevealMap; - this.gameSettingsControl.updateGameAttributes(); - } - else if (g_GameAttributes.settings.RevealMap && - !g_GameAttributes.settings.ExploreMap) - { - g_GameAttributes.settings.ExploreMap = true; - this.gameSettingsControl.updateGameAttributes(); - } + super(...args); + g_NewGameSettings.mapExploration.watch(() => this.render(), ["explored"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesBatchChange() + render() { - if (!g_GameAttributes.mapType) - return; - - this.setChecked(g_GameAttributes.settings.ExploreMap); - this.setEnabled(g_GameAttributes.mapType != "scenario" && !g_GameAttributes.settings.RevealMap); + this.setEnabled(g_NewGameSettings.map.type != "scenario"); + this.setChecked(g_NewGameSettings.mapExploration.explored); } onPress(checked) { - g_GameAttributes.settings.ExploreMap = checked; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.mapExploration.setExplored(checked); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/LastManStanding.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/LastManStanding.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/LastManStanding.js @@ -1,56 +1,23 @@ GameSettingControls.LastManStanding = class extends GameSettingControlCheckbox { - onMapChange(mapData) + constructor(...args) { - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.LastManStanding !== undefined) - mapValue = !mapData.settings.LockTeams && - mapData.settings.LastManStanding; - - if (mapValue !== undefined && mapValue != g_GameAttributes.settings.LastManStanding) - { - g_GameAttributes.settings.LastManStanding = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesChange() - { - if (!g_GameAttributes.mapType) - return; - - this.available = !g_GameAttributes.settings.LockTeams; - if (this.available) - { - if (g_GameAttributes.settings.LastManStanding === undefined) - { - g_GameAttributes.settings.LastManStanding = false; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (g_GameAttributes.settings.LastManStanding !== undefined) - { - delete g_GameAttributes.settings.LastManStanding; - this.gameSettingsControl.updateGameAttributes(); - } + super(...args); + g_NewGameSettings.lastManStanding.watch(() => this.render(), ["enabled", "available"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); } - onGameAttributesBatchChange() + render() { - if (!g_GameAttributes.mapType) - return; - // Always display this, so that players are aware that there is this gamemode - this.setChecked(!!g_GameAttributes.settings.LastManStanding); - this.setEnabled(g_GameAttributes.mapType != "scenario" && !g_GameAttributes.settings.LockTeams); + this.setChecked(g_NewGameSettings.lastManStanding.enabled); + this.setEnabled(g_NewGameSettings.map.type != "scenario" && + g_NewGameSettings.lastManStanding.available); } onPress(checked) { - g_GameAttributes.settings.LastManStanding = checked; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.lastManStanding.setEnabled(checked); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/LockedTeams.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/LockedTeams.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/LockedTeams.js @@ -1,50 +1,27 @@ GameSettingControls.LockedTeams = class extends GameSettingControlCheckbox { - onMapChange(mapData) + constructor(...args) { - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.LockTeams !== undefined) - mapValue = !mapData.settings.LockTeams && - mapData.settings.LastManStanding; - - if (mapValue !== undefined && mapValue != g_GameAttributes.settings.LastManStanding) - { - g_GameAttributes.settings.LastManStanding = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } + super(...args); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + g_NewGameSettings.lockedTeams.watch(() => this.render(), ["enabled"]); + g_NewGameSettings.lockedTeams.setEnabled(GameSettingControls.LockedTeams.DefaultValue); + this.render(); } - onGameAttributesChange() + render() { - if (!g_GameAttributes.mapType) - return; - - if (g_GameAttributes.settings.LockTeams === undefined || - g_GameAttributes.settings.RatingEnabled && !g_GameAttributes.settings.LockTeams) - { - g_GameAttributes.settings.LockTeams = g_IsNetworked; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - if (!g_GameAttributes.mapType) - return; - - this.setChecked(g_GameAttributes.settings.LockTeams); - - this.setEnabled( - g_GameAttributes.mapType != "scenario" && - !g_GameAttributes.settings.RatingEnabled); + this.setEnabled(g_NewGameSettings.map.type != "scenario"); + this.setChecked(g_NewGameSettings.lockedTeams.enabled); + // TODO: is this rating enablable? + /*this.setEnabled( + g_GameAttributes.mapType && g_GameAttributes.mapType != "scenario" && + !g_NewGameSettings.rating.enabled);*/ } onPress(checked) { - g_GameAttributes.settings.LockTeams = checked; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.lockedTeams.setEnabled(checked); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Nomad.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Nomad.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Nomad.js @@ -1,58 +1,22 @@ GameSettingControls.Nomad = class extends GameSettingControlCheckbox { - onMapChange(mapData) + constructor(...args) { - let available = g_GameAttributes.mapType == "random"; - this.setHidden(!available); - if (!available) - return; - - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.Nomad !== undefined) - mapValue = mapData.settings.Nomad; - - if (mapValue !== undefined && mapValue != g_GameAttributes.settings.Nomad) - { - g_GameAttributes.settings.Nomad = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } + super(...args); + g_NewGameSettings.nomad.watch(() => this.render(), ["enabled"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesChange() + render() { - if (!g_GameAttributes.mapType) - return; - - if (g_GameAttributes.mapType == "random") - { - if (g_GameAttributes.settings.Nomad === undefined) - { - g_GameAttributes.settings.Nomad = false; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (g_GameAttributes.settings.Nomad !== undefined) - { - delete g_GameAttributes.settings.Nomad; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - if (!g_GameAttributes.mapType) - return; - - if (g_GameAttributes.mapType == "random") - this.setChecked(g_GameAttributes.settings.Nomad); + this.setHidden(g_NewGameSettings.map.type != "random"); + this.setChecked(g_NewGameSettings.nomad.enabled); } onPress(checked) { - g_GameAttributes.settings.Nomad = checked; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.nomad.setEnabled(checked); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Rating.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Rating.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Rating.js @@ -4,47 +4,21 @@ { super(...args); - this.hasXmppClient = Engine.HasXmppClient(); - this.available = false; + g_NewGameSettings.rating.watch(() => this.render(), ["enabled", "available"]); + this.render(); } - onGameAttributesChange() + render() { - this.available = this.hasXmppClient && g_GameAttributes.settings.PlayerData.length == 2; - if (this.available) - { - if (g_GameAttributes.settings.RatingEnabled === undefined) - { - g_GameAttributes.settings.RatingEnabled = true; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (g_GameAttributes.settings.RatingEnabled !== undefined) - { - delete g_GameAttributes.settings.RatingEnabled; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - this.setHidden(!this.available); - if (this.available) - this.setChecked(g_GameAttributes.settings.RatingEnabled); + this.setHidden(!g_NewGameSettings.rating.available); + this.setChecked(g_NewGameSettings.rating.enabled); } onPress(checked) { - g_GameAttributes.settings.RatingEnabled = checked; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.rating.SetEnabled(checked); this.gameSettingsControl.setNetworkGameAttributes(); } - - onGameAttributesFinalize() - { - if (this.hasXmppClient) - Engine.SetRankedGame(!!g_GameAttributes.settings.RatingEnabled); - } }; GameSettingControls.Rating.prototype.TitleCaption = Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/RegicideGarrison.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/RegicideGarrison.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/RegicideGarrison.js @@ -1,59 +1,24 @@ GameSettingControls.RegicideGarrison = class extends GameSettingControlCheckbox { - onMapChange(mapData) + constructor(...args) { - this.setEnabled(g_GameAttributes.mapType != "scenario"); + super(...args); - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.VictoryConditions && - mapData.settings.VictoryConditions.indexOf(this.RegicideName) != -1 && - mapData.settings.RegicideGarrison !== undefined) - mapValue = mapData.settings.RegicideGarrison; - - if (mapValue !== undefined || !g_GameAttributes.settings || mapValue == g_GameAttributes.settings.RegicideGarrison) - return; - - if (!g_GameAttributes.settings.VictoryConditions) - g_GameAttributes.settings.VictoryConditions = []; - - if (g_GameAttributes.settings.VictoryConditions.indexOf(this.RegicideName) == -1) - g_GameAttributes.settings.VictoryConditions.push(this.RegicideName); - - g_GameAttributes.settings.RegicideGarrison = mapValue; - - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.regicideGarrison.watch(() => this.render(), ["enabled", "available"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesChange() + render() { - if (!g_GameAttributes.settings.VictoryConditions) - return; - - let available = g_GameAttributes.settings.VictoryConditions.indexOf(this.RegicideName) != -1; - this.setHidden(!available); - - if (available) - { - if (g_GameAttributes.settings.RegicideGarrison === undefined) - { - g_GameAttributes.settings.RegicideGarrison = false; - this.gameSettingsControl.updateGameAttributes(); - } - this.setChecked(g_GameAttributes.settings.RegicideGarrison); - } - else if (g_GameAttributes.settings.RegicideGarrison !== undefined) - { - delete g_GameAttributes.settings.RegicideGarrison; - this.gameSettingsControl.updateGameAttributes(); - } + this.setHidden(g_NewGameSettings.map.type == "scenario" || + !g_NewGameSettings.regicideGarrison.available); + this.setChecked(g_NewGameSettings.regicideGarrison.enabled); } onPress(checked) { - g_GameAttributes.settings.RegicideGarrison = checked; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.regicideGarrison.setEnabled(checked); this.gameSettingsControl.setNetworkGameAttributes(); } }; @@ -63,6 +28,3 @@ GameSettingControls.RegicideGarrison.prototype.Tooltip = translate("Toggle whether heroes can be garrisoned."); - -GameSettingControls.RegicideGarrison.prototype.RegicideName = - "regicide"; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/RevealedMap.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/RevealedMap.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/RevealedMap.js @@ -1,46 +1,22 @@ GameSettingControls.RevealedMap = class extends GameSettingControlCheckbox { - onMapChange(mapData) + constructor(...args) { - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.RevealMap !== undefined) - mapValue = mapData.settings.RevealMap; - - if (mapValue !== undefined && mapValue != g_GameAttributes.settings.RevealMap) - { - g_GameAttributes.settings.RevealMap = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - - this.setEnabled(g_GameAttributes.mapType != "scenario"); + super(...args); + g_NewGameSettings.mapExploration.watch(() => this.render(), ["revealed"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesChange() + render() { - if (!g_GameAttributes.mapType) - return; - - if (g_GameAttributes.settings.RevealMap === undefined) - { - g_GameAttributes.settings.RevealMap = false; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - if (!g_GameAttributes.mapType) - return; - - this.setChecked(g_GameAttributes.settings.RevealMap); + this.setEnabled(g_NewGameSettings.map.type != "scenario"); + this.setChecked(g_NewGameSettings.mapExploration.revealed); } onPress(checked) { - g_GameAttributes.settings.RevealMap = checked; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.mapExploration.setRevealed(checked); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Spies.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Spies.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Spies.js @@ -1,40 +1,22 @@ GameSettingControls.Spies = class extends GameSettingControlCheckbox { - onMapChange(mapData) + constructor(...args) { - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.DisableSpies !== undefined) - mapValue = mapData.settings.DisableSpies; - - if (mapValue !== undefined && mapValue != g_GameAttributes.settings.DisableSpies) - { - g_GameAttributes.settings.DisableSpies = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - - this.setEnabled(g_GameAttributes.mapType != "scenario"); - } - - onGameAttributesChange() - { - if (g_GameAttributes.settings.DisableSpies === undefined) - { - g_GameAttributes.settings.DisableSpies = false; - this.gameSettingsControl.updateGameAttributes(); - } + super(...args); + g_NewGameSettings.disableSpies.watch(() => this.render(), ["enabled"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesBatchChange() + render() { - this.setChecked(g_GameAttributes.settings.DisableSpies); + this.setEnabled(g_NewGameSettings.map.type != "scenario"); + this.setChecked(g_NewGameSettings.disableSpies.enabled); } onPress(checked) { - g_GameAttributes.settings.DisableSpies = checked; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.disableSpies.setEnabled(checked); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Treasures.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Treasures.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/Treasures.js @@ -1,40 +1,22 @@ GameSettingControls.Treasures = class extends GameSettingControlCheckbox { - onMapChange(mapData) + constructor(...args) { - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.DisableTreasures !== undefined) - mapValue = mapData.settings.DisableTreasures; - - if (mapValue !== undefined && mapValue != g_GameAttributes.settings.DisableTreasures) - { - g_GameAttributes.settings.DisableTreasures = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - - this.setEnabled(g_GameAttributes.mapType != "scenario"); - } - - onGameAttributesChange() - { - if (g_GameAttributes.settings.DisableTreasures === undefined) - { - g_GameAttributes.settings.DisableTreasures = false; - this.gameSettingsControl.updateGameAttributes(); - } + super(...args); + g_NewGameSettings.disableTreasures.watch(() => this.render(), ["enabled"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesBatchChange() + render() { - this.setChecked(g_GameAttributes.settings.DisableTreasures); + this.setEnabled(g_NewGameSettings.map.type != "scenario"); + this.setChecked(g_NewGameSettings.disableTreasures.enabled); } onPress(checked) { - g_GameAttributes.settings.DisableTreasures = checked; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.disableTreasures.setEnabled(checked); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/WorldPopulation.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/WorldPopulation.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Checkboxes/WorldPopulation.js @@ -1,46 +1,22 @@ GameSettingControls.WorldPopulation = class extends GameSettingControlCheckbox { - onMapChange(mapData) + constructor(...args) { - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.WorldPopulation !== undefined) - mapValue = mapData.settings.WorldPopulation; - - if (mapValue !== undefined && mapValue != g_GameAttributes.settings.WorldPopulation) - { - g_GameAttributes.settings.WorldPopulation = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - - this.setEnabled(g_GameAttributes.mapType != "scenario"); - } - - onGameAttributesChange() - { - if (!g_GameAttributes.mapType) - return; - - if (g_GameAttributes.settings.WorldPopulation !== undefined) - return; - - g_GameAttributes.settings.WorldPopulation = false; - this.gameSettingsControl.updateGameAttributes(); + super(...args); + g_NewGameSettings.population.watch(() => this.render(), ["useWorldPop"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesBatchChange() + render() { - if (!g_GameAttributes.mapType) - return; - - this.setChecked(g_GameAttributes.settings.WorldPopulation); + this.setEnabled(g_NewGameSettings.map.type != "scenario"); + this.setChecked(g_NewGameSettings.population.useWorldPop); } onPress(checked) { - g_GameAttributes.settings.WorldPopulation = checked; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.population.setPopCap(checked); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/Biome.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/Biome.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/Biome.js @@ -4,124 +4,57 @@ { super(...args); - this.values = undefined; - this.biomeValues = undefined; - - this.randomItem = { - "Id": this.RandomBiomeId, - "Title": setStringTags(this.RandomBiome, this.RandomItemTags), - "Autocomplete": this.RandomBiome, - "Description": this.RandomDescription - }; + g_NewGameSettings.biome.watch(() => this.render(), ["biome", "available"]); + this.render(); } onHoverChange() { - this.dropdown.tooltip = - this.values && this.values.Description && this.values.Description[this.dropdown.hovered] || - this.Tooltip; - } - - onMapChange(mapData) - { - let available = g_GameAttributes.mapType == "random" && - mapData && mapData.settings && mapData.settings.SupportedBiomes || undefined; - - this.setHidden(!available); - - if (available) - { - Engine.ProfileStart("updateBiomeList"); - this.biomeValues = - g_Settings.Biomes.filter(this.filterBiome(available)).map(this.createBiomeItem); - - this.values = prepareForDropdown([ - this.randomItem, - ...this.biomeValues - ]); - - this.dropdown.list = this.values.Title; - this.dropdown.list_data = this.values.Id; - Engine.ProfileStop(); - } + if (!this.dropdown.list_data[this.dropdown.hovered]) + this.dropdown.tooltip = ""; + else if (this.dropdown.list_data[this.dropdown.hovered] == "random") + this.dropdown.tooltip = this.RandomDescription; else - this.values = undefined; - + this.dropdown.tooltip = g_NewGameSettings.biome.biomeData[ + this.dropdown.list_data[this.dropdown.hovered] + ].Description; } - onGameAttributesChange() + render() { - if (!g_GameAttributes.mapType || !g_GameAttributes.map) + this.setHidden(!g_NewGameSettings.biome.available.size); + + let values = prepareForDropdown([ + { "Title": translateWithContext("biome", "Random"), "Id": "random" }, + ...g_NewGameSettings.biome.biomes + ]); + + this.dropdown.list = values.Title; + this.dropdown.list_data = values.Id; + + this.setSelectedValue(g_NewGameSettings.biome.biome); + + if (!g_GameAttributes.map) return; - if (this.values) - { - if (this.values.Id.indexOf(g_GameAttributes.settings.Biome || undefined) == -1) - { - g_GameAttributes.settings.Biome = this.RandomBiomeId; - this.gameSettingsControl.updateGameAttributes(); - } + let biomePreviewFile = + basename(g_GameAttributes.map) + "_" + + basename(g_GameAttributes.settings.Biome || "") + ".png"; - let biomePreviewFile = - basename(g_GameAttributes.map) + "_" + - basename(g_GameAttributes.settings.Biome || "") + ".png"; - - if (!g_GameAttributes.settings.Preview || g_GameAttributes.settings.Preview != biomePreviewFile && Engine.TextureExists(this.mapCache.TexturesPath + this.mapCache.PreviewsPath + biomePreviewFile)) - g_GameAttributes.settings.Preview = biomePreviewFile; - - } - else if (g_GameAttributes.settings.Biome) - { - delete g_GameAttributes.settings.Biome; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - if (this.values) - this.setSelectedValue(g_GameAttributes.settings.Biome); - } - - filterBiome(available) - { - if (typeof available == "string") - return biome => biome.Id.startsWith(available); - - return biome => available.indexOf(biome.Id) != -1; - } - - createBiomeItem(biome) - { - return { - "Id": biome.Id, - "Title": biome.Title, - "Autocomplete": biome.Title, - "Description": biome.Description - }; + if (!g_GameAttributes.settings.Preview || g_GameAttributes.settings.Preview != biomePreviewFile && Engine.TextureExists(this.mapCache.TexturesPath + this.mapCache.PreviewsPath + biomePreviewFile)) + g_GameAttributes.settings.Preview = biomePreviewFile; } getAutocompleteEntries() { - return this.values && this.values.Autocomplete; + return g_NewGameSettings.biome.biomes; } onSelectionChange(itemIdx) { - g_GameAttributes.settings.Biome = this.values.Id[itemIdx]; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.biome.setBiome(this.dropdown.list_data[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } - - onPickRandomItems() - { - if (this.values && g_GameAttributes.settings.Biome == this.RandomBiomeId) - { - g_GameAttributes.settings.Biome = pickRandom(this.biomeValues).Id; - this.gameSettingsControl.updateGameAttributes(); - this.gameSettingsControl.pickRandomItems(); - } - } }; GameSettingControls.Biome.prototype.TitleCaption = Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/Daytime.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/Daytime.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/Daytime.js @@ -5,6 +5,8 @@ super(...args); this.values = undefined; + g_NewGameSettings.daytime.watch(() => this.render(), ["value", "data"]); + this.render(); } onHoverChange() @@ -12,65 +14,35 @@ this.dropdown.tooltip = this.values.Description[this.dropdown.hovered] || this.Tooltip; } - onMapChange(mapData) + render() { - if (mapData && mapData.settings && mapData.settings.Daytime) + this.setHidden(!g_NewGameSettings.daytime.data); + if (!g_NewGameSettings.daytime.data) { - this.values = prepareForDropdown([ - { - "Id": "random", - "Name": setStringTags(this.RandomTitle, this.RandomItemTags), - "Description": this.RandomDescription, - "Preview": mapData.settings.Preview - }, - ...mapData.settings.Daytime.map(item => ({ - "Id": item.Id, - "Name": translate(item.Name), - "Description": translate(item.Description), - "Preview": item.Preview - })) - ]); - - this.dropdown.list = this.values.Name; - this.dropdown.list_data = this.values.Id; - } - else - this.values = undefined; - - this.setHidden(!this.values); - } - - onGameAttributesChange() - { - if (!g_GameAttributes.map) + this.gameSettingsControl.updateGameAttributes(); return; + } - if (this.values) - { - if (this.values.Id.indexOf(g_GameAttributes.settings.Daytime || undefined) == -1) + this.values = prepareForDropdown([ { - g_GameAttributes.settings.Daytime = "random"; - this.gameSettingsControl.updateGameAttributes(); - } + "Id": "random", + "Name": setStringTags(this.RandomTitle, this.RandomItemTags), + "Description": this.RandomDescription, + "Preview": g_NewGameSettings.map.data.settings.Preview + }, + ...g_NewGameSettings.daytime.data.map(item => ({ + "Id": item.Id, + "Name": translate(item.Name), + "Description": translate(item.Description), + "Preview": item.Preview + })) + ]); - let preview = this.values.Preview[this.values.Id.indexOf(g_GameAttributes.settings.Daytime)]; - if (!g_GameAttributes.settings.Preview || g_GameAttributes.settings.Preview != preview) - { - g_GameAttributes.settings.Preview = preview; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (g_GameAttributes.settings.Daytime !== undefined) - { - delete g_GameAttributes.settings.Daytime; - this.gameSettingsControl.updateGameAttributes(); - } - } + this.dropdown.list = this.values.Name; + this.dropdown.list_data = this.values.Id; - onGameAttributesBatchChange() - { - if (g_GameAttributes.settings.Daytime) - this.setSelectedValue(g_GameAttributes.settings.Daytime); + this.setSelectedValue(g_NewGameSettings.daytime.value); + this.gameSettingsControl.updateGameAttributes(); } getAutocompleteEntries() @@ -80,21 +52,9 @@ onSelectionChange(itemIdx) { - g_GameAttributes.settings.Daytime = this.values.Id[itemIdx]; - - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.daytime.setValue(this.values.Id[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } - - onPickRandomItems() - { - if (this.values && g_GameAttributes.settings.Daytime == "random") - { - g_GameAttributes.settings.Daytime = pickRandom(this.values.Id.slice(1)); - this.gameSettingsControl.updateGameAttributes(); - this.gameSettingsControl.pickRandomItems(); - } - } }; GameSettingControls.Daytime.prototype.TitleCaption = Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/GameSpeed.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/GameSpeed.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/GameSpeed.js @@ -5,31 +5,17 @@ super(...args); this.previousAllowFastForward = undefined; - } - onMapChange(mapData) - { - let mapValue; - if (mapData && mapData.gameSpeed !== undefined) - mapValue = mapData.gameSpeed; - if (mapValue !== undefined && mapValue != g_GameAttributes.gameSpeed) - { - g_GameAttributes.gameSpeed = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } + g_NewGameSettings.gameSpeed.watch(() => this.render(), ["gameSpeed"]); + this.render(); } onPlayerAssignmentsChange() { - this.update(); + this.render(); } - onGameAttributesChange() - { - this.update(); - } - - update() + render() { let allowFastForward = true; for (let guid in g_PlayerAssignments) @@ -41,32 +27,20 @@ if (this.previousAllowFastForward !== allowFastForward) { - Engine.ProfileStart("updateGameSpeedList"); this.previousAllowFastForward = allowFastForward; - this.values = prepareForDropdown( + let values = prepareForDropdown( g_Settings.GameSpeeds.filter(speed => !speed.FastForward || allowFastForward)); - this.dropdown.list = this.values.Title; - this.dropdown.list_data = this.values.Speed; - Engine.ProfileStop(); + this.dropdown.list = values.Title; + this.dropdown.list_data = values.Speed; } - if (this.values.Speed.indexOf(g_GameAttributes.gameSpeed || undefined) == -1) - { - g_GameAttributes.gameSpeed = this.values.Speed[this.values.Default]; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - this.setSelectedValue(g_GameAttributes.gameSpeed); + this.setSelectedValue(g_NewGameSettings.gameSpeed.gameSpeed); } onSelectionChange(itemIdx) { - g_GameAttributes.gameSpeed = this.values.Speed[itemIdx]; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.gameSpeed.setSpeed(this.dropdown.list_data[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/Landscape.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/Landscape.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/Landscape.js @@ -5,7 +5,8 @@ super(...args); this.values = undefined; - this.mapData = undefined; + g_NewGameSettings.landscape.watch(() => this.render(), ["value", "data"]); + this.render(); } onHoverChange() @@ -13,37 +14,35 @@ this.dropdown.tooltip = this.values.Description[this.dropdown.hovered] || this.Tooltip; } - onMapChange(mapData) + render() { - this.mapData = mapData; - - if (mapData && mapData.settings && mapData.settings.Landscapes) + this.setHidden(!g_NewGameSettings.landscape.data); + if (!g_NewGameSettings.landscape.data) { - let randomItems = []; - for (let item of this.RandomItems) - if (item.Id == "random" || mapData.settings.Landscapes.land && mapData.settings.Landscapes.naval) - randomItems.push({ - "Id": item.Id, - "Name": setStringTags(item.Name, this.RandomItemTags), - "Description": item.Description, - "Preview": mapData.settings.Preview || this.mapCache.DefaultPreview - }); + this.gameSettingsControl.updateGameAttributes(); + return; + } + let randomItems = [{ + "Id": "random", + "Name": translateWithContext("landscape selection", "Random"), + "Description": translateWithContext("landscape selection", "Select a random landscape.") + }]; + let data = g_NewGameSettings.landscape.data; + let items = []; + for (let group of data) + { + randomItems.push(this.translateItem(group)); let sort = (item1, item2) => item1.Name > item2.Name; - - this.values = prepareForDropdown([ - ...randomItems, - ...mapData.settings.Landscapes.land.map(this.translateItem).sort(sort), - ...mapData.settings.Landscapes.naval.map(this.translateItem).sort(sort) - ]); - - this.dropdown.list = this.values.Name; - this.dropdown.list_data = this.values.Id; + items = items.concat(group.Items.map(this.translateItem).sort(sort)); } - else - this.values = undefined; - this.setHidden(!this.values); + this.values = prepareForDropdown(randomItems.concat(items)); + + this.dropdown.list = this.values.Name; + this.dropdown.list_data = this.values.Id; + + this.setSelectedValue(g_NewGameSettings.landscape.value); } translateItem(item) @@ -56,34 +55,6 @@ }; } - onGameAttributesChange() - { - if (this.values) - { - if (this.values.Id.indexOf(g_GameAttributes.settings.Landscape || undefined) == -1) - { - g_GameAttributes.settings.Landscape = "random"; - this.gameSettingsControl.updateGameAttributes(); - } - - let landscapePreview = this.values.Preview[this.values.Id.indexOf(g_GameAttributes.settings.Landscape)]; - if (!g_GameAttributes.settings.Preview || g_GameAttributes.settings.Preview != landscapePreview) - g_GameAttributes.settings.Preview = landscapePreview; - - } - else if (g_GameAttributes.settings.Landscape !== undefined) - { - delete g_GameAttributes.settings.Landscape; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - if (g_GameAttributes.settings.Landscape) - this.setSelectedValue(g_GameAttributes.settings.Landscape); - } - getAutocompleteEntries() { if (!this.values) @@ -99,39 +70,9 @@ onSelectionChange(itemIdx) { - g_GameAttributes.settings.Landscape = this.values.Id[itemIdx]; - - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.landscape.setValue(this.values.Id[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } - - onPickRandomItems() - { - if (!this.mapData) - return; - - let items; - let landscapes = this.mapData.settings.Landscapes; - - switch (g_GameAttributes.settings.Landscape || undefined) - { - case "random": - items = [...landscapes.land, ...landscapes.naval]; - break; - case "random_land": - items = landscapes.land; - break; - case "random_naval": - items = landscapes.naval; - break; - default: - return; - } - - g_GameAttributes.settings.Landscape = pickRandom(items).Id; - this.gameSettingsControl.updateGameAttributes(); - this.gameSettingsControl.pickRandomItems(); - } }; GameSettingControls.Landscape.prototype.TitleCaption = @@ -140,23 +81,4 @@ GameSettingControls.Landscape.prototype.Tooltip = translate("Select one of the landscapes of this map."); -GameSettingControls.Landscape.prototype.RandomItems = -[ - { - "Id": "random", - "Name": translateWithContext("landscape selection", "Random Land or Naval"), - "Description": translateWithContext("landscape selection", "Select a random land or naval map generation.") - }, - { - "Id": "random_land", - "Name": translateWithContext("landscape selection", "Random Land"), - "Description": translateWithContext("landscape selection", "Select a random land map generation.") - }, - { - "Id": "random_naval", - "Name": translateWithContext("landscape selection", "Random Naval"), - "Description": translateWithContext("landscape selection", "Select a random naval map generation.") - } -]; - GameSettingControls.Landscape.prototype.AutocompleteOrder = 0; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapFilter.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapFilter.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapFilter.js @@ -5,7 +5,8 @@ super(...args); this.values = undefined; - this.previousMapType = undefined; + + g_NewGameSettings.map.watch(() => this.checkMapTypeChange(), ["type"]); } onHoverChange() @@ -13,36 +14,17 @@ this.dropdown.tooltip = this.values.Description[this.dropdown.hovered] || this.Tooltip; } - onGameAttributesChange() - { - this.checkMapTypeChange(); - - if (this.values) - { - if (this.values.Name.indexOf(g_GameAttributes.mapFilter || undefined) == -1) - { - g_GameAttributes.mapFilter = this.values.Name[this.values.Default]; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (g_GameAttributes.mapFilter !== undefined) - { - delete g_GameAttributes.mapFilter; - this.gameSettingsControl.updateGameAttributes(); - } - } - checkMapTypeChange() { - if (!g_GameAttributes.mapType || this.previousMapType == g_GameAttributes.mapType) + if (!g_NewGameSettings.map.type) return; Engine.ProfileStart("updateMapFilterList"); - this.previousMapType = g_GameAttributes.mapType; + this.previousMapType = g_NewGameSettings.map.type; let values = prepareForDropdown( this.mapFilters.getAvailableMapFilters( - g_GameAttributes.mapType)); + g_NewGameSettings.map.type)); if (values.Name.length) { @@ -53,16 +35,12 @@ else this.values = undefined; + this.setSelectedValue(g_MapFilter.filter); + this.setHidden(!this.values); Engine.ProfileStop(); } - onGameAttributesBatchChange() - { - if (this.values && g_GameAttributes.mapFilter) - this.setSelectedValue(g_GameAttributes.mapFilter); - } - getAutocompleteEntries() { return this.values && this.values.Title; @@ -70,18 +48,7 @@ onSelectionChange(itemIdx) { - if (this.values) - { - g_GameAttributes.mapFilter = this.values.Name[itemIdx]; - this.gameSettingsControl.updateGameAttributes(); - this.gameSettingsControl.setNetworkGameAttributes(); - } - } - - onGameAttributesFinalize() - { - // This setting is only relevant in the game-setup stage. - delete g_GameAttributes.mapFilter; + g_MapFilter.filter = this.values.Name[itemIdx]; } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapSelection.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapSelection.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapSelection.js @@ -6,8 +6,12 @@ this.values = undefined; - this.previousMapType = undefined; - this.previousMapFilter = undefined; + // TODO: change this? + g_NewGameSettings.map.mapCache = this.gameSettingsControl.mapCache; + g_NewGameSettings.map.watch(() => this.render(), ["map"]); + g_NewGameSettings.map.watch(() => this.updateMapList(), ["type"]); + + g_MapFilter.watch(() => this.updateMapList(), ["filter"]); this.randomItem = { "file": this.RandomMapId, @@ -21,51 +25,28 @@ this.dropdown.tooltip = this.values.description[this.dropdown.hovered] || this.Tooltip; } - onGameAttributesChange() + render() { - if (!g_GameAttributes.mapType || !g_GameAttributes.mapFilter) - return; - - this.updateMapList(); - - if (!this.gameSettingsControl.autostart && - this.values && - this.values.file.indexOf(g_GameAttributes.map || undefined) == -1) - { - g_GameAttributes.map = this.values.file[0]; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - if (g_GameAttributes.map) - this.setSelectedValue(g_GameAttributes.map); + this.setSelectedValue(g_NewGameSettings.map.map); } updateMapList() { - if (this.previousMapType && - this.previousMapType == g_GameAttributes.mapType && - this.previousMapFilter && - this.previousMapFilter == g_GameAttributes.mapFilter) - return; - Engine.ProfileStart("updateMapSelectionList"); - this.previousMapType = g_GameAttributes.mapType; - this.previousMapFilter = g_GameAttributes.mapFilter; + if (!g_NewGameSettings.map.type) + return; { let values = this.mapFilters.getFilteredMaps( - g_GameAttributes.mapType, - g_GameAttributes.mapFilter, + g_NewGameSettings.map.type, + g_MapFilter.filter, false); values.sort(sortNameIgnoreCase); - if (g_GameAttributes.mapType == "random") + if (g_NewGameSettings.map.type == "random") values.unshift(this.randomItem); this.values = prepareForDropdown(values); @@ -73,70 +54,26 @@ this.dropdown.list = this.values.name; this.dropdown.list_data = this.values.file; + + g_NewGameSettings.map.setRandomOptions(this.values.file); + + if (this.values.file.indexOf(g_NewGameSettings.map.map) === -1) + // Reset the selected map. + g_NewGameSettings.map.selectMap(this.values.file[0]); + Engine.ProfileStop(); } onSelectionChange(itemIdx) { - this.selectMap(this.values.file[itemIdx]); + g_NewGameSettings.map.selectMap(this.values.file[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } - /** - * @param mapPath - for example "maps/skirmishes/Acropolis Bay (2)" - */ - selectMap(mapPath) - { - if (g_GameAttributes.map == mapPath) - return; - - Engine.ProfileStart("selectMap"); - - // For scenario map, reset every setting per map selection - // For skirmish and random maps, persist player choices - if (g_GameAttributes.mapType == "scenario") - g_GameAttributes = { - "mapType": g_GameAttributes.mapType, - "mapFilter": g_GameAttributes.mapFilter - }; - - g_GameAttributes.map = mapPath; - this.gameSettingsControl.updateGameAttributes(); - - Engine.ProfileStop(); - } - getAutocompleteEntries() { return this.values.name; } - - onPickRandomItems() - { - if (g_GameAttributes.map == this.RandomMapId) - { - this.selectMap(pickRandom(this.values.file.slice(1))); - this.gameSettingsControl.pickRandomItems(); - } - } - - onGameAttributesFinalize() - { - // Copy map well known properties (and only well known properties) - let mapData = this.mapCache.getMapData(g_GameAttributes.mapType, g_GameAttributes.map); - - if (g_GameAttributes.mapType == "random") - g_GameAttributes.script = mapData.settings.Script; - - g_GameAttributes.settings.TriggerScripts = Array.from(new Set([ - ...(g_GameAttributes.settings.TriggerScripts || []), - ...(mapData.settings.TriggerScripts || []) - ])); - - for (let property of this.MapSettings) - if (mapData.settings[property] !== undefined) - g_GameAttributes.settings[property] = mapData.settings[property]; - } }; GameSettingControls.MapSelection.prototype.TitleCaption = @@ -155,15 +92,3 @@ translate("Pick any of the given maps at random."); GameSettingControls.MapSelection.prototype.AutocompleteOrder = 0; - -GameSettingControls.MapSelection.prototype.MapSettings = [ - "CircularMap", - "StartingTechnologies", - "DisabledTechnologies", - "DisabledTemplates", - "StartingCamera", - "Garrison", - // Copy the map name so that the replay menu doesn't have to load hundreds of map descriptions on init - // Also it allows determining the english mapname from the replay file if the map is not available. - "Name" -]; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapSize.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapSize.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapSize.js @@ -4,10 +4,11 @@ { super(...args); - this.previousMapType = undefined; - this.dropdown.list = g_MapSizes.Name; this.dropdown.list_data = g_MapSizes.Tiles; + + g_NewGameSettings.mapSize.watch(() => this.render(), ["size", "available"]); + this.render(); } onHoverChange() @@ -15,47 +16,11 @@ this.dropdown.tooltip = g_MapSizes.Tooltip[this.dropdown.hovered] || this.Tooltip; } - onMapChange(mapData) + render() { - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.Size !== undefined) - mapValue = mapData.settings.Size; - - if (g_GameAttributes.mapType == "random" && mapValue !== undefined && mapValue != g_GameAttributes.settings.Size) - { - g_GameAttributes.settings.Size = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesChange() - { - if (!g_GameAttributes.mapType || - !g_GameAttributes.settings || - this.previousMapType == g_GameAttributes.mapType) - return; - - this.previousMapType = g_GameAttributes.mapType; - - let available = g_GameAttributes.mapType == "random"; - this.setHidden(!available); - - if (available) - { - if (g_GameAttributes.settings.Size === undefined) - { - g_GameAttributes.settings.Size = g_MapSizes.Tiles[g_MapSizes.Default]; - this.gameSettingsControl.updateGameAttributes(); - } - this.setSelectedValue(g_GameAttributes.settings.Size); - } - else if (g_GameAttributes.settings.Size !== undefined) - { - delete g_GameAttributes.settings.Size; - this.gameSettingsControl.updateGameAttributes(); - } + this.setHidden(!g_NewGameSettings.mapSize.available); + this.setSelectedValue(g_NewGameSettings.mapSize.size); + // TODO: select first entry. } getAutocompleteEntries() @@ -65,8 +30,7 @@ onSelectionChange(itemIdx) { - g_GameAttributes.settings.Size = g_MapSizes.Tiles[itemIdx]; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.mapSize.setSize(g_MapSizes.Tiles[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapType.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapType.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/MapType.js @@ -12,6 +12,10 @@ this.dropdown.list = g_MapTypes.Title; this.dropdown.list_data = g_MapTypes.Name; + + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + g_NewGameSettings.map.setType("scenario"); + this.render(); } onHoverChange() @@ -19,18 +23,9 @@ this.dropdown.tooltip = g_MapTypes.Description[this.dropdown.hovered] || this.Tooltip; } - onGameAttributesChange() + render() { - if (g_MapTypes.Name.indexOf(g_GameAttributes.mapType || undefined) == -1) - { - g_GameAttributes.mapType = g_MapTypes.Name[g_MapTypes.Default]; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - this.setSelectedValue(g_GameAttributes.mapType); + this.setSelectedValue(g_NewGameSettings.map.type); } getAutocompleteEntries() @@ -40,19 +35,7 @@ onSelectionChange(itemIdx) { - let mapType = g_MapTypes.Name[itemIdx]; - - if (g_GameAttributes.mapType == mapType) - return; - - if (mapType == "scenario") - g_GameAttributes = { - "mapFilter": g_GameAttributes.mapFilter - }; - - g_GameAttributes.mapType = mapType; - - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.map.setType(g_MapTypes.Name[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/PlayerCount.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/PlayerCount.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/PlayerCount.js @@ -10,38 +10,22 @@ this.dropdown.list = this.values; this.dropdown.list_data = this.values; - } - - onMapChange(mapData) - { - if (mapData && - mapData.settings && - mapData.settings.PlayerData && - mapData.settings.PlayerData.length != g_GameAttributes.settings.PlayerData.length) - { - this.onSelectionChange(this.values.indexOf(mapData.settings.PlayerData.length)); - } - this.setEnabled(g_GameAttributes.mapType == "random"); + g_NewGameSettings.playerCount.watch(() => this.render(), ["nbPlayers"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesBatchChange() + render() { - this.setSelectedValue(g_GameAttributes.settings.PlayerData.length); + this.setEnabled(g_NewGameSettings.map.type == "random"); + this.setSelectedValue(g_NewGameSettings.playerCount.nbPlayers); } onSelectionChange(itemIdx) { - let length = this.values[itemIdx]; - if (g_GameAttributes.settings.PlayerData.length == length) - return; - - g_GameAttributes.settings.PlayerData.length = length; - - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.playerCount.setNb(this.values[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); - - this.playerAssignmentsControl.unassignInvalidPlayers(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/PopulationCap.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/PopulationCap.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/PopulationCap.js @@ -10,66 +10,38 @@ this.dropdown.list_data = g_PopulationCapacities.Population; this.sprintfArgs = {}; + + g_NewGameSettings.population.watch(() => this.render(), ["useWorldPop", "cap"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onMapChange(mapData) + render() { - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.PopulationCap !== undefined) - mapValue = mapData.settings.PopulationCap; + let isScenario = g_NewGameSettings.map.type == "scenario"; - if (mapValue !== undefined && mapValue != g_GameAttributes.settings.PopulationCap) - { - g_GameAttributes.settings.PopulationCap = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - - let isScenario = g_GameAttributes.mapType == "scenario"; - - this.perPlayer = + this.perPlayer = false; + /* isScenario && mapData && mapData.settings && mapData.settings.PlayerData && mapData.settings.PlayerData.some(pData => pData && pData.PopulationLimit !== undefined); - + */ this.setEnabled(!isScenario && !this.perPlayer); + this.setHidden(g_NewGameSettings.population.useWorldPop); + if (!this.perPlayer) + this.setSelectedValue(g_NewGameSettings.population.cap); if (this.perPlayer) this.label.caption = this.PerPlayerCaption; } - onGameAttributesChange() - { - if (g_GameAttributes.settings.WorldPopulation) - { - this.setHidden(true); - g_GameAttributes.settings.PopulationCap = undefined; - } - else - { - this.setHidden(false); - if (g_GameAttributes.settings.PopulationCap === undefined) - { - g_GameAttributes.settings.PopulationCap = g_PopulationCapacities.Population[g_PopulationCapacities.Default]; - this.gameSettingsControl.updateGameAttributes(); - } - } - } - - onGameAttributesBatchChange() - { - if (!this.perPlayer) - this.setSelectedValue(g_GameAttributes.settings.PopulationCap); - } - onHoverChange() { let tooltip = this.Tooltip; if (this.dropdown.hovered != -1) { let popCap = g_PopulationCapacities.Population[this.dropdown.hovered]; - let players = g_GameAttributes.settings.PlayerData.length; + let players = g_NewGameSettings.playerCount.nbPlayers; if (popCap * players >= this.PopulationCapacityRecommendation) { this.sprintfArgs.players = players; @@ -82,8 +54,7 @@ onSelectionChange(itemIdx) { - g_GameAttributes.settings.PopulationCap = g_PopulationCapacities.Population[itemIdx]; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.population.setPopCap(false, g_PopulationCapacities.Population[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/StartingResources.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/StartingResources.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/StartingResources.js @@ -9,6 +9,10 @@ this.perPlayer = false; this.sprintfArgs = {}; + + g_NewGameSettings.startingResources.watch(() => this.render(), ["resources"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } onHoverChange() @@ -22,49 +26,24 @@ this.dropdown.tooltip = tooltip; } - onMapChange(mapData) + render() { - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.StartingResources !== undefined) - mapValue = mapData.settings.StartingResources; + let isScenario = g_NewGameSettings.map.type == "scenario"; - if (mapValue !== undefined && mapValue != g_GameAttributes.settings.StartingResources) - { - g_GameAttributes.settings.StartingResources = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - - let isScenario = g_GameAttributes.mapType == "scenario"; - - this.perPlayer = + this.perPlayer = false;/* isScenario && mapData && mapData.settings && mapData.settings.PlayerData && mapData.settings.PlayerData.some(pData => pData && pData.Resources !== undefined); - + */ this.setEnabled(!isScenario && !this.perPlayer); + if (!this.perPlayer) + this.setSelectedValue(g_NewGameSettings.startingResources.resources); + if (this.perPlayer) this.label.caption = this.PerPlayerCaption; } - onGameAttributesChange() - { - if (g_GameAttributes.settings.StartingResources === undefined) - { - g_GameAttributes.settings.StartingResources = - g_StartingResources.Resources[g_StartingResources.Default]; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - if (!this.perPlayer) - this.setSelectedValue(g_GameAttributes.settings.StartingResources); - } - getAutocompleteEntries() { return g_StartingResources.Title; @@ -72,8 +51,7 @@ onSelectionChange(itemIdx) { - g_GameAttributes.settings.StartingResources = g_StartingResources.Resources[itemIdx]; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.startingResources.setResources(g_StartingResources.Resources[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/TeamPlacement.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/TeamPlacement.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/TeamPlacement.js @@ -4,6 +4,9 @@ { super(...args); this.values = undefined; + + g_NewGameSettings.teamPlacement.watch(() => this.render(), ["value", "available"]); + this.render(); } onHoverChange() @@ -11,57 +14,33 @@ this.dropdown.tooltip = this.values.Description[this.dropdown.hovered] || this.Tooltip; } - onMapChange(mapData) + render() { - if (mapData && mapData.settings && mapData.settings.TeamPlacements) + this.setHidden(!g_NewGameSettings.teamPlacement.value); + if (!g_NewGameSettings.teamPlacement.value) { - let randomItem = clone(this.RandomItem); - randomItem.Name = setStringTags(randomItem.Name, this.RandomItemTags); - - let patterns = [randomItem]; - - for (let pattern of mapData.settings.TeamPlacements) - patterns.push( - typeof pattern == "string" ? - this.DefaultStartingPositions.find(pObj => pObj.Id == pattern) : - { - "Id": pattern.Id, - "Name": translate(pattern.Name), - "Description": translate(pattern.Description) - }); - - this.values = prepareForDropdown(patterns); - - this.dropdown.list = this.values.Name; - this.dropdown.list_data = this.values.Id; - } - else - this.values = undefined; - } - - onGameAttributesChange() - { - if (this.values) - { - if (this.values.Id.indexOf(g_GameAttributes.settings.TeamPlacement || undefined) == -1) - { - g_GameAttributes.settings.TeamPlacement = this.values.Id[0]; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (g_GameAttributes.settings.TeamPlacement !== undefined) - { - delete g_GameAttributes.settings.TeamPlacement; + // TODO: better rerender. this.gameSettingsControl.updateGameAttributes(); + return; } - } - onGameAttributesBatchChange() - { - this.setHidden(!this.values); + let randomItem = clone(this.RandomItem); + randomItem.Name = setStringTags(randomItem.Name, this.RandomItemTags); - if (this.values) - this.setSelectedValue(g_GameAttributes.settings.TeamPlacement); + let patterns = [randomItem]; + + for (let pattern of g_NewGameSettings.teamPlacement.available) + patterns.push(g_NewGameSettings.teamPlacement.StartingPositions + .find(pObj => pObj.Id == pattern)); + + this.values = prepareForDropdown(patterns); + + this.dropdown.list = this.values.Name; + this.dropdown.list_data = this.values.Id; + + this.setSelectedValue(g_NewGameSettings.teamPlacement.value); + // TODO: better rerender. + this.gameSettingsControl.updateGameAttributes(); } getAutocompleteEntries() @@ -71,20 +50,9 @@ onSelectionChange(itemIdx) { - g_GameAttributes.settings.TeamPlacement = this.values.Id[itemIdx]; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.teamPlacement.setValue(this.values.Id[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } - - onPickRandomItems() - { - if (!this.values || g_GameAttributes.settings.TeamPlacement != "random") - return; - - g_GameAttributes.settings.TeamPlacement = pickRandom(this.values.Id.filter(id => id != "random")); - this.gameSettingsControl.updateGameAttributes(); - this.gameSettingsControl.pickRandomItems(); - } }; GameSettingControls.TeamPlacement.prototype.TitleCaption = @@ -99,27 +67,4 @@ "Description": translateWithContext("team placement", "Select a random team placement pattern when starting the game.") }; -GameSettingControls.TeamPlacement.prototype.DefaultStartingPositions = [ - { - "Id": "radial", - "Name": translateWithContext("team placement", "Circle"), - "Description": translate("Allied players are grouped and placed with opposing players on one circle spanning the map.") - }, - { - "Id": "line", - "Name": translateWithContext("team placement", "Line"), - "Description": translate("Allied players are placed in a linear pattern."), - }, - { - "Id": "randomGroup", - "Name": translateWithContext("team placement", "Random Group"), - "Description": translate("Allied players are grouped, but otherwise placed randomly on the map."), - }, - { - "Id": "stronghold", - "Name": translateWithContext("team placement", "Stronghold"), - "Description": translate("Allied players are grouped in one random place of the map."), - } -]; - GameSettingControls.TeamPlacement.prototype.AutocompleteOrder = 0; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/TriggerDifficulty.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/TriggerDifficulty.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/TriggerDifficulty.js @@ -5,6 +5,8 @@ super(...args); this.values = undefined; + g_NewGameSettings.triggerDifficulty.watch(() => this.render(), ["value", "available"]); + this.render(); } onHoverChange() @@ -14,65 +16,27 @@ this.Tooltip; } - onMapChange(mapData) + render() { - let available = mapData && mapData.settings && mapData.settings.SupportedTriggerDifficulties || undefined; - this.setHidden(!available); - - if (available) + this.setHidden(!g_NewGameSettings.triggerDifficulty.available); + if (!g_NewGameSettings.triggerDifficulty.available) { - Engine.ProfileStart("updateTriggerDifficultyList"); - let values = g_Settings.TriggerDifficulties; - if (Array.isArray(available.Values)) - values = values.filter(diff => available.Values.indexOf(diff.Name) != -1); - - this.values = prepareForDropdown(values); - - this.dropdown.list = this.values.Title; - this.dropdown.list_data = this.values.Difficulty; - - if (mapData.settings.TriggerDifficulty && - this.values.Difficulty.indexOf(mapData.settings.TriggerDifficulty) != -1) - g_GameAttributes.settings.TriggerDifficulty = mapData.settings.TriggerDifficulty; - Engine.ProfileStop(); - } - else - { - this.values = undefined; - this.defaultValue = undefined; - } - } - - onGameAttributesChange() - { - if (!g_GameAttributes.mapType) - return; - - if (this.values) - { - if (this.values.Difficulty.indexOf(g_GameAttributes.settings.TriggerDifficulty || undefined) == -1) - { - g_GameAttributes.settings.TriggerDifficulty = this.values.Difficulty[this.values.Default]; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (g_GameAttributes.settings.TriggerDifficulty !== undefined) - { - delete g_GameAttributes.settings.TriggerDifficulty; this.gameSettingsControl.updateGameAttributes(); + return; } - } - onGameAttributesBatchChange() - { - if (this.values) - this.setSelectedValue(g_GameAttributes.settings.TriggerDifficulty); - } + this.values = prepareForDropdown(g_NewGameSettings.triggerDifficulty.getAvailableSettings()); - onSelectionChange(itemIdx) - { - g_GameAttributes.settings.TriggerDifficulty = this.values.Difficulty[itemIdx]; + this.dropdown.list = this.values.Title; + this.dropdown.list_data = this.values.Difficulty; + + this.setSelectedValue(g_NewGameSettings.triggerDifficulty.value); this.gameSettingsControl.updateGameAttributes(); + } + + onSelectionChange(itemIdx) + { + g_NewGameSettings.triggerDifficulty.setValue(this.values.Difficulty[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/WorldPopulationCap.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/WorldPopulationCap.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Dropdowns/WorldPopulationCap.js @@ -8,46 +8,17 @@ this.dropdown.list_data = g_WorldPopulationCapacities.Population; this.sprintfArgs = {}; - } - - onMapChange(mapData) - { - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.WorldPopulationCap !== undefined) - mapValue = mapData.settings.WorldPopulationCap; - - if (mapValue !== undefined && mapValue != g_GameAttributes.settings.WorldPopulationCap) - { - g_GameAttributes.settings.WorldPopulationCap = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - this.setEnabled(g_GameAttributes.mapType != "scenario"); - } - - onGameAttributesChange() - { - if (g_GameAttributes.settings.WorldPopulation) - { - this.setHidden(false); - if (g_GameAttributes.settings.WorldPopulationCap === undefined) - { - g_GameAttributes.settings.WorldPopulationCap = g_WorldPopulationCapacities.Population[g_WorldPopulationCapacities.Default]; - this.gameSettingsControl.updateGameAttributes(); - } - } - else - { - this.setHidden(true); - g_GameAttributes.settings.WorldPopulationCap = undefined; - } + g_NewGameSettings.population.watch(() => this.render(), ["useWorldPop", "cap"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesBatchChange() + render() { - this.setSelectedValue(g_GameAttributes.settings.WorldPopulationCap); + this.setEnabled(g_NewGameSettings.map.type != "scenario"); + this.setHidden(!g_NewGameSettings.population.useWorldPop); + this.setSelectedValue(g_NewGameSettings.population.cap); } onHoverChange() @@ -67,8 +38,7 @@ onSelectionChange(itemIdx) { - g_GameAttributes.settings.WorldPopulationCap = g_WorldPopulationCapacities.Population[itemIdx]; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.population.setPopCap(true, g_WorldPopulationCapacities.Population[itemIdx]); this.gameSettingsControl.setNetworkGameAttributes(); } }; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Seed.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Seed.js +++ /dev/null @@ -1,12 +0,0 @@ -GameSettingControls.Seed = class extends GameSettingControl -{ - onGameAttributesFinalize() - { - // The matchID is used for identifying rated game reports for the lobby and possibly when sharing replays. - g_GameAttributes.matchID = Engine.GetMatchID(); - - // Seed is used for map generation and simulation. - g_GameAttributes.settings.Seed = randIntExclusive(0, Math.pow(2, 32)); - g_GameAttributes.settings.AISeed = randIntExclusive(0, Math.pow(2, 32)); - } -}; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/Ceasefire.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/Ceasefire.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/Ceasefire.js @@ -5,41 +5,20 @@ super(...args); this.sprintfValue = {}; - } - - onMapChange(mapData) - { - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.Ceasefire !== undefined) - mapValue = mapData.settings.Ceasefire; - if (mapValue !== undefined && mapValue != g_GameAttributes.settings.Ceasefire) - { - g_GameAttributes.settings.Ceasefire = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - - this.setEnabled(g_GameAttributes.mapType != "scenario"); + g_NewGameSettings.ceasefire.watch(() => this.render(), ["value"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesChange() + render() { - if (g_GameAttributes.settings.Ceasefire == undefined) - { - g_GameAttributes.settings.Ceasefire = this.DefaultValue; - this.gameSettingsControl.updateGameAttributes(); - } - } + this.setEnabled(g_NewGameSettings.map.type != "scenario"); - onGameAttributesBatchChange() - { - let value = Math.round(g_GameAttributes.settings.Ceasefire); + let value = Math.round(g_NewGameSettings.ceasefire.value); this.sprintfValue.minutes = value; - this.setSelectedValue( - g_GameAttributes.settings.Ceasefire, + this.setSelectedValue(g_NewGameSettings.ceasefire.value, value == 0 ? this.NoCeasefireCaption : sprintf(this.CeasefireCaption(value), this.sprintfValue)); @@ -47,15 +26,9 @@ onValueChange(value) { - g_GameAttributes.settings.Ceasefire = value; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.ceasefire.setValue(value); this.gameSettingsControl.setNetworkGameAttributes(); } - - onGameAttributesFinalize() - { - g_GameAttributes.settings.Ceasefire = Math.round(g_GameAttributes.settings.Ceasefire); - } }; GameSettingControls.Ceasefire.prototype.TitleCaption = Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/RelicCount.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/RelicCount.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/RelicCount.js @@ -6,81 +6,32 @@ this.sprintfValue = {}; this.available = false; - } - - onMapChange(mapData) - { - this.setEnabled(g_GameAttributes.mapType != "scenario"); - - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.VictoryConditions && - mapData.settings.VictoryConditions.indexOf(this.NameCaptureTheRelic) != -1 && - mapData.settings.RelicCount !== undefined) - mapValue = mapData.settings.RelicCount; - - if (mapValue === undefined || mapValue == g_GameAttributes.settings.RelicCount) - return; - - if (!g_GameAttributes.settings.VictoryConditions) - g_GameAttributes.settings.VictoryConditions = []; - - if (g_GameAttributes.settings.VictoryConditions.indexOf(this.NameCaptureTheRelic) == -1) - g_GameAttributes.settings.VictoryConditions.push(this.NameCaptureTheRelic); - g_GameAttributes.settings.RelicCount = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - - onGameAttributesChange() - { - if (!g_GameAttributes.settings.VictoryConditions) - return; - - this.available = g_GameAttributes.settings.VictoryConditions.indexOf(this.NameCaptureTheRelic) != -1; - - if (this.available) - { - if (g_GameAttributes.settings.RelicCount === undefined) - { - g_GameAttributes.settings.RelicCount = this.DefaultValue; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (g_GameAttributes.settings.RelicCount !== undefined) - { - delete g_GameAttributes.settings.RelicCount; - this.gameSettingsControl.updateGameAttributes(); - } + g_NewGameSettings.relic.watch(() => this.render(), ["count", "available"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesBatchChange() + render() { - this.setHidden(!this.available); + this.setHidden(!g_NewGameSettings.relic.available); + this.setEnabled(g_NewGameSettings.map.type != "scenario"); - if (this.available) + if (g_NewGameSettings.relic.available) { - let value = Math.round(g_GameAttributes.settings.RelicCount); + let value = g_NewGameSettings.relic.count; this.sprintfValue.number = value; this.setSelectedValue( - g_GameAttributes.settings.RelicCount, + g_NewGameSettings.relic.count, value == 0 ? this.InstantVictory : sprintf(this.CaptionRelicCount(value), this.sprintfValue)); } } onValueChange(value) { - g_GameAttributes.settings.RelicCount = value; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.relic.setCount(value); this.gameSettingsControl.setNetworkGameAttributes(); } - - onGameAttributesFinalize() - { - if (this.available) - g_GameAttributes.settings.RelicCount = Math.round(g_GameAttributes.settings.RelicCount); - } }; GameSettingControls.RelicCount.prototype.TitleCaption = @@ -98,5 +49,3 @@ GameSettingControls.RelicCount.prototype.MinValue = 1; GameSettingControls.RelicCount.prototype.MaxValue = Object.keys(g_CivData).length; - -GameSettingControls.RelicCount.prototype.DefaultValue = 2; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/RelicDuration.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/RelicDuration.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/RelicDuration.js @@ -6,81 +6,32 @@ this.sprintfValue = {}; this.available = false; - } - - onMapChange(mapData) - { - this.setEnabled(g_GameAttributes.mapType != "scenario"); - - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.VictoryConditions && - mapData.settings.VictoryConditions.indexOf(this.NameCaptureTheRelic) != -1 && - mapData.settings.RelicDuration !== undefined) - mapValue = mapData.settings.RelicDuration; - - if (mapValue === undefined || mapValue == g_GameAttributes.settings.RelicDuration) - return; - - if (!g_GameAttributes.settings.VictoryConditions) - g_GameAttributes.settings.VictoryConditions = []; - - if (g_GameAttributes.settings.VictoryConditions.indexOf(this.NameCaptureTheRelic) == -1) - g_GameAttributes.settings.VictoryConditions.push(this.NameCaptureTheRelic); - g_GameAttributes.settings.RelicDuration = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - - onGameAttributesChange() - { - if (!g_GameAttributes.settings.VictoryConditions) - return; - - this.available = g_GameAttributes.settings.VictoryConditions.indexOf(this.NameCaptureTheRelic) != -1; - - if (this.available) - { - if (g_GameAttributes.settings.RelicDuration === undefined) - { - g_GameAttributes.settings.RelicDuration = this.DefaultValue; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (g_GameAttributes.settings.RelicDuration !== undefined) - { - delete g_GameAttributes.settings.RelicDuration; - this.gameSettingsControl.updateGameAttributes(); - } + g_NewGameSettings.relic.watch(() => this.render(), ["duration", "available"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesBatchChange() + render() { - this.setHidden(!this.available); + this.setHidden(!g_NewGameSettings.relic.available); + this.setEnabled(g_NewGameSettings.map.type != "scenario"); - if (this.available) + if (g_NewGameSettings.relic.available) { - let value = Math.round(g_GameAttributes.settings.RelicDuration); + let value = g_NewGameSettings.relic.duration; this.sprintfValue.min = value; this.setSelectedValue( - g_GameAttributes.settings.RelicDuration, + g_NewGameSettings.relic.duration, value == 0 ? this.InstantVictory : sprintf(this.CaptionVictoryTime(value), this.sprintfValue)); } } onValueChange(value) { - g_GameAttributes.settings.RelicDuration = value; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.relic.setDuration(value); this.gameSettingsControl.setNetworkGameAttributes(); } - - onGameAttributesFinalize() - { - if (this.available) - g_GameAttributes.settings.RelicDuration = Math.round(g_GameAttributes.settings.RelicDuration); - } }; GameSettingControls.RelicDuration.prototype.TitleCaption = @@ -101,5 +52,3 @@ GameSettingControls.RelicDuration.prototype.MinValue = 0; GameSettingControls.RelicDuration.prototype.MaxValue = 60; - -GameSettingControls.RelicDuration.prototype.DefaultValue = 20; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/SeaLevelRiseTime.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/SeaLevelRiseTime.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/SeaLevelRiseTime.js @@ -6,67 +6,29 @@ this.values = undefined; this.sprintfValue = {}; - } - - onMapChange(mapData) - { - this.values = - mapData && - mapData.settings && - mapData.settings.SeaLevelRise || undefined; - - if (this.values) - { - this.slider.min_value = this.values.Min; - this.slider.max_value = this.values.Max; - } - this.setHidden(!this.values); - this.setEnabled(g_GameAttributes.mapType != "scenario"); - } - - onGameAttributesChange() - { - if (this.values) - { - if (g_GameAttributes.settings.SeaLevelRiseTime === undefined) - { - g_GameAttributes.settings.SeaLevelRiseTime = this.values.Default; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (g_GameAttributes.settings.SeaLevelRiseTime !== undefined) - { - delete g_GameAttributes.settings.SeaLevelRiseTime; - this.gameSettingsControl.updateGameAttributes(); - } + g_NewGameSettings.seaLevelRise.watch(() => this.render(), ["value"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesBatchChange() + render() { - if (!this.values) - return; + this.setHidden(g_NewGameSettings.seaLevelRise.value === undefined); + this.setEnabled(g_NewGameSettings.map.type != "scenario"); - let value = Math.round(g_GameAttributes.settings.SeaLevelRiseTime); + let value = g_NewGameSettings.seaLevelRise.value; this.sprintfValue.minutes = value; this.setSelectedValue( - g_GameAttributes.settings.SeaLevelRiseTime, - sprintf(this.SeaLevelRiseTimeCaption(value), this.sprintfValue)); + value, sprintf(this.SeaLevelRiseTimeCaption(value), this.sprintfValue)); } onValueChange(value) { - g_GameAttributes.settings.SeaLevelRiseTime = value; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.seaLevelRise.setValue(value); this.gameSettingsControl.setNetworkGameAttributes(); } - - onGameAttributesFinalize() - { - if (this.values) - g_GameAttributes.settings.SeaLevelRiseTime = Math.round(g_GameAttributes.settings.SeaLevelRiseTime); - } }; GameSettingControls.SeaLevelRiseTime.prototype.TitleCaption = Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/WonderDuration.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/WonderDuration.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/WonderDuration.js @@ -6,82 +6,32 @@ this.sprintfValue = {}; this.available = false; - } - - onMapChange(mapData) - { - this.setEnabled(g_GameAttributes.mapType != "scenario"); - - let mapValue; - if (mapData && - mapData.settings && - mapData.settings.VictoryConditions && - mapData.settings.VictoryConditions.indexOf(this.NameWonderVictory) != -1 && - mapData.settings.WonderDuration !== undefined) - mapValue = mapData.settings.WonderDuration; - - if (mapValue === undefined || mapValue == g_GameAttributes.settings.WonderDuration) - return; - - if (!g_GameAttributes.settings.VictoryConditions) - g_GameAttributes.settings.VictoryConditions = []; - - if (g_GameAttributes.settings.VictoryConditions.indexOf(this.NameWonderVictory) == -1) - g_GameAttributes.settings.VictoryConditions.push(this.NameWonderVictory); - - g_GameAttributes.settings.WonderDuration = mapValue; - this.gameSettingsControl.updateGameAttributes(); - } - - onGameAttributesChange() - { - if (!g_GameAttributes.settings.VictoryConditions) - return; - - this.available = g_GameAttributes.settings.VictoryConditions.indexOf(this.NameWonderVictory) != -1; - - if (this.available) - { - if (g_GameAttributes.settings.WonderDuration === undefined) - { - g_GameAttributes.settings.WonderDuration = this.DefaultValue; - this.gameSettingsControl.updateGameAttributes(); - } - } - else if (g_GameAttributes.settings.WonderDuration !== undefined) - { - delete g_GameAttributes.settings.WonderDuration; - this.gameSettingsControl.updateGameAttributes(); - } + g_NewGameSettings.wonder.watch(() => this.render(), ["duration", "available"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onGameAttributesBatchChange() + render() { - this.setHidden(!this.available); + this.setHidden(!g_NewGameSettings.wonder.available); + this.setEnabled(g_NewGameSettings.map.type != "scenario"); - if (this.available) + if (g_NewGameSettings.wonder.available) { - let value = Math.round(g_GameAttributes.settings.WonderDuration); + let value = g_NewGameSettings.wonder.duration; this.sprintfValue.min = value; this.setSelectedValue( - g_GameAttributes.settings.WonderDuration, + g_NewGameSettings.wonder.duration, value == 0 ? this.InstantVictory : sprintf(this.CaptionVictoryTime(value), this.sprintfValue)); } } onValueChange(value) { - g_GameAttributes.settings.WonderDuration = value; - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.wonder.setDuration(value); this.gameSettingsControl.setNetworkGameAttributes(); } - - onGameAttributesFinalize() - { - if (this.available) - g_GameAttributes.settings.WonderDuration = Math.round(g_GameAttributes.settings.WonderDuration); - } }; GameSettingControls.WonderDuration.prototype.TitleCaption = @@ -90,9 +40,6 @@ GameSettingControls.WonderDuration.prototype.Tooltip = translate("Minutes until the player has achieved Wonder Victory"); -GameSettingControls.WonderDuration.prototype.NameWonderVictory = - "wonder"; - GameSettingControls.WonderDuration.prototype.CaptionVictoryTime = min => translatePluralWithContext("victory duration", "%(min)s minute", "%(min)s minutes", min); Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/VictoryConditionCheckbox.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/VictoryConditionCheckbox.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/VictoryConditionCheckbox.js @@ -7,99 +7,25 @@ { super(...args); - this.victoryCondition = victoryCondition; + this.victoryCondition = victoryCondition.Name; + this.setTitle(victoryCondition.Title); + this.setTooltip(victoryCondition.Description); - this.setTitle(this.victoryCondition.Title); - this.setTooltip(this.victoryCondition.Description); + g_NewGameSettings.victoryConditions.watch(() => this.render(), ["active"]); + g_NewGameSettings.map.watch(() => this.render(), ["type"]); + this.render(); } - onMapChange(mapData) + render() { - let mapIndex = - mapData && - mapData.settings && - mapData.settings.VictoryConditions && - mapData.settings.VictoryConditions.indexOf(this.victoryCondition.Name); - - if (mapIndex === undefined) - return; - - let index = - g_GameAttributes.settings && - g_GameAttributes.settings.VictoryConditions && - g_GameAttributes.settings.VictoryConditions.indexOf(this.victoryCondition.Name); - - if (index !== undefined && (mapIndex == -1) == (index == -1)) - return; - - if (!g_GameAttributes.settings.VictoryConditions) - g_GameAttributes.settings.VictoryConditions = []; - - if (mapIndex == -1) - { - if (index !== undefined) - g_GameAttributes.settings.VictoryConditions.splice(index, 1); - } - else - g_GameAttributes.settings.VictoryConditions.push(this.victoryCondition.Name); - - this.gameSettingsControl.updateGameAttributes(); - } - - onGameAttributesChange() - { - if (!g_GameAttributes.settings.VictoryConditions) - { - g_GameAttributes.settings.VictoryConditions = []; - for (let victoryCondition of g_VictoryConditions) - if (victoryCondition.Default) - g_GameAttributes.settings.VictoryConditions.push(victoryCondition.Name); - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - this.setEnabled( - g_GameAttributes.mapType != "scenario" && - (!this.victoryCondition.DisabledWhenChecked || - this.victoryCondition.DisabledWhenChecked.every(name => - g_GameAttributes.settings.VictoryConditions.indexOf(name) == -1))); - - this.setChecked(g_GameAttributes.settings.VictoryConditions.indexOf(this.victoryCondition.Name) != -1); + this.setEnabled(g_NewGameSettings.map.type != "scenario" && + !g_NewGameSettings.victoryConditions.disabled.has(this.victoryCondition)); + this.setChecked(g_NewGameSettings.victoryConditions.active.has(this.victoryCondition)); } onPress(checked) { - let victoryCondition = new Set(g_GameAttributes.settings.VictoryConditions); - - if (checked) - { - victoryCondition.add(this.victoryCondition.Name); - - if (this.victoryCondition.ChangeOnChecked) - for (let name in this.victoryCondition.ChangeOnChecked) - if (this.victoryCondition.ChangeOnChecked[name]) - victoryCondition.add(name); - else - victoryCondition.delete(name); - } - else - victoryCondition.delete(this.victoryCondition.Name); - - g_GameAttributes.settings.VictoryConditions = Array.from(victoryCondition); - this.gameSettingsControl.updateGameAttributes(); + g_NewGameSettings.victoryConditions.setEnabled(this.victoryCondition, checked); this.gameSettingsControl.setNetworkGameAttributes(); } - - onGameAttributesFinalize() - { - if (!g_GameAttributes.settings.TriggerScripts) - g_GameAttributes.settings.TriggerScripts = []; - - if (g_GameAttributes.settings.VictoryConditions.indexOf(this.victoryCondition.Name) != -1) - for (let script of this.victoryCondition.Scripts) - if (g_GameAttributes.settings.TriggerScripts.indexOf(script) == -1) - g_GameAttributes.settings.TriggerScripts.push(script); - } } Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/GameSettingWarning.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/GameSettingWarning.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/GameSettingWarning.js @@ -14,11 +14,11 @@ onGameAttributesBatchChange() { let caption = - g_GameAttributes.settings.CheatsEnabled ? + g_NewGameSettings.cheats.enabled ? this.CheatsEnabled : - g_GameAttributes.settings.RatingEnabled ? - this.RatingEnabled : - ""; + g_NewGameSettings.rating.enabled ? + this.RatingEnabled : + ""; this.gameSettingWarning.caption = caption; this.gameSettingWarning.hidden = !caption; Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/MapPreview.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/MapPreview.js +++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/MapPreview.js @@ -8,29 +8,18 @@ this.mapInfoName = Engine.GetGUIObjectByName("mapInfoName"); this.mapPreview = Engine.GetGUIObjectByName("mapPreview"); - this.gameSettingsControl.registerMapChangeHandler(this.onMapChange.bind(this)); - this.gameSettingsControl.registerGameAttributesBatchChangeHandler(this.onGameAttributesBatchChange.bind(this)); + g_NewGameSettings.map.watch(() => this.render(), ["map"]); + g_NewGameSettings.biome.watch(() => this.render(), ["biome"]); + g_NewGameSettings.landscape.watch(() => this.render(), ["value"]); + g_NewGameSettings.daytime.watch(() => this.render(), ["value"]); } - onMapChange(mapData) + render() { - let preview = mapData && mapData.settings && mapData.settings.Preview; - if (!g_GameAttributes.settings.Preview || g_GameAttributes.settings.Preview != preview) - { - g_GameAttributes.settings.Preview = preview; - this.gameSettingsControl.updateGameAttributes(); - } - } - - onGameAttributesBatchChange() - { - if (!g_GameAttributes.map || !g_GameAttributes.mapType) - return; - this.mapInfoName.caption = this.mapCache.translateMapName( - this.mapCache.getTranslatableMapName(g_GameAttributes.mapType, g_GameAttributes.map)); + this.mapCache.getTranslatableMapName(g_NewGameSettings.map.type, g_NewGameSettings.map.map)); this.mapPreview.sprite = - this.mapCache.getMapPreview(g_GameAttributes.mapType, g_GameAttributes.map, g_GameAttributes); + this.mapCache.getMapPreview(g_NewGameSettings.map.type, g_NewGameSettings.map.map); } } Index: binaries/data/mods/public/gui/gamesetup/gamesetup.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/gamesetup.js +++ binaries/data/mods/public/gui/gamesetup/gamesetup.js @@ -33,6 +33,12 @@ */ var g_PlayerAssignments = {}; +/** + * Active map filters. + */ +var g_MapFilter = new Observable(); +g_MapFilter.filter = "default"; + /** * This instance owns all handlers that control the two synchronized states g_GameAttributes and g_PlayerAssignments. */ @@ -42,6 +48,8 @@ function init(initData, hotloadData) { + g_NewGameSettings.Init(); + g_SetupWindow = new SetupWindow(initData, hotloadData); } Index: binaries/data/mods/public/gui/gamesetup/gamesetup.xml =================================================================== --- binaries/data/mods/public/gui/gamesetup/gamesetup.xml +++ binaries/data/mods/public/gui/gamesetup/gamesetup.xml @@ -1,11 +1,17 @@ +