Index: binaries/data/mods/public/gui/autostart/autostart.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/autostart/autostart.js
@@ -0,0 +1,57 @@
+class Autostart
+{
+ constructor(data)
+ {
+ this.data = data;
+
+ let mapCache = new MapCache();
+ this.settings = new GameSettings();
+ this.settings.Init();
+ this.settings.map.mapCache = mapCache;
+ this.settings.LegacyDeserialize(data);
+
+ this.player = 1;
+ }
+
+ getGameAttributes()
+ {
+ let ret = this.settings.LegacySerialize();
+ // TODO: this overwrites some things which are legitimately game settings.
+ for (let key in this.data)
+ ret[key] = this.data[key];
+ warn(uneval(ret));
+ return ret;
+ }
+
+ startGame()
+ {
+ this.settings.prepareForLaunch();
+
+ // TODO: this doesn't actually work,
+ // because it doesn't listen to the net "start" message.
+ if (Engine.HasNetClient())
+ {
+ Engine.SetNetworkGameAttributes(this.getGameAttributes());
+ Engine.SetRankedGame(this.settings.rating.enabled);
+ Engine.StartNetworkGame();
+ }
+ else
+ {
+ Engine.StartGame(this.getGameAttributes(), this.player);
+ this.switchToLoadingPage();
+ }
+ }
+
+ switchToLoadingPage()
+ {
+ Engine.SwitchGuiPage("page_loading.xml", {
+ "attribs": this.settings.LegacySerialize(),
+ "playerAssignments": {
+ "local": {
+ "name": "autostart",
+ "player": this.player
+ }
+ }
+ });
+ }
+}
Index: binaries/data/mods/public/gui/autostart/autostart.xml
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/autostart/autostart.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
Index: binaries/data/mods/public/gui/autostart/page_autostart.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/autostart/page_autostart.js
@@ -0,0 +1,19 @@
+var g_Autostart;
+
+const g_MapSizes = prepareForDropdown(g_Settings && g_Settings.MapSizes);
+const g_MapTypes = prepareForDropdown(g_Settings && g_Settings.MapTypes);
+const g_PopulationCapacities = prepareForDropdown(g_Settings && g_Settings.PopulationCapacities);
+const g_WorldPopulationCapacities = prepareForDropdown(g_Settings && g_Settings.WorldPopulationCapacities);
+const g_StartingResources = prepareForDropdown(g_Settings && g_Settings.StartingResources);
+const g_VictoryConditions = g_Settings && g_Settings.VictoryConditions;
+
+const g_CivData = loadCivData(false, false);
+const g_IsNetworked = Engine.HasNetClient();
+const g_IsController = !g_IsNetworked || Engine.HasNetServer();
+
+
+function init(data)
+{
+ g_Autostart = new Autostart(data);
+ g_Autostart.startGame();
+}
Index: binaries/data/mods/public/gui/autostart/page_autostart.xml
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/autostart/page_autostart.xml
@@ -0,0 +1,4 @@
+
+
+ autostart/autostart.xml
+
Index: binaries/data/mods/public/gui/campaigns/default_menu/CampaignMenu.js
===================================================================
--- binaries/data/mods/public/gui/campaigns/default_menu/CampaignMenu.js
+++ binaries/data/mods/public/gui/campaigns/default_menu/CampaignMenu.js
@@ -39,10 +39,9 @@
let level = this.getSelectedLevelData();
if (!meetsRequirements(this.run, level))
return;
- Engine.SwitchGuiPage("page_gamesetup.xml", {
+ Engine.SwitchGuiPage("autostart/page_autostart.xml", {
"mapType": level.MapType,
"map": "maps/" + level.Map,
- "autostart": true,
"campaignData": {
"run": this.run.filename,
"levelID": this.levelSelection.list_data[this.selectedLevel],
Index: binaries/data/mods/public/gui/common/Observable.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/common/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 will 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/gui/common/gamedescription.js
===================================================================
--- binaries/data/mods/public/gui/common/gamedescription.js
+++ binaries/data/mods/public/gui/common/gamedescription.js
@@ -176,28 +176,24 @@
}
/**
- * Sets an additional map label, map preview image and describes the chosen game settings more closely.
- *
- * Requires g_GameAttributes and g_VictoryConditions.
+ * Describes the chosen game settings more closely.
*/
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.enabled)
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,90 +317,86 @@
});
}
- 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":
- g_GameAttributes.settings.PlayerData &&
- g_GameAttributes.settings.PlayerData.some(pData => pData && pData.Resources !== undefined) ?
- translateWithContext("starting resources", "Per Player") :
- sprintf(translate("%(startingResourcesTitle)s (%(amount)s)"), {
- "startingResourcesTitle":
- g_StartingResources.Title[
- g_StartingResources.Resources.indexOf(
- g_GameAttributes.settings.StartingResources)],
- "amount": g_GameAttributes.settings.StartingResources
- })
+ "value": g_NewGameSettings.startingResources.perPlayer ?
+ translateWithContext("starting resources", "Per Player") :
+ sprintf(translate("%(startingResourcesTitle)s (%(amount)s)"), {
+ "startingResourcesTitle":
+ g_StartingResources.Title[
+ g_StartingResources.Resources.indexOf(
+ g_NewGameSettings.startingResources.resources)],
+ "amount": g_NewGameSettings.startingResources.resources
+ })
});
- if (g_GameAttributes.settings.PopulationCap !== undefined)
+ if (!g_NewGameSettings.population.useWorldPop)
titles.push({
"label": translate("Population Limit"),
- "value":
- 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)]
+ "value": g_NewGameSettings.population.perPlayer ?
+ translateWithContext("population limit", "Per Player") :
+ g_PopulationCapacities.Title[
+ g_PopulationCapacities.Population.indexOf(
+ g_NewGameSettings.population.cap)]
});
- if (g_GameAttributes.settings.WorldPopulationCap !== undefined)
+ if (g_NewGameSettings.population.useWorldPop)
titles.push({
"label": translate("World Population Cap"),
"value":
g_WorldPopulationCapacities.Title[
g_WorldPopulationCapacities.Population.indexOf(
- g_GameAttributes.settings.WorldPopulationCap)]
+ g_NewGameSettings.population.cap)]
});
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
- });
-
titles.push({
"label": translate("Explored Map"),
- "value": g_GameAttributes.settings.ExploreMap
+ "value": g_NewGameSettings.mapExploration.explored
+ });
+
+ titles.push({
+ "label": translate("Revealed Map"),
+ "value": g_NewGameSettings.mapExploration.revealed
});
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 +407,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 +435,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/gamesettings/GameSetting.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/GameSetting.js
@@ -0,0 +1,28 @@
+/**
+ * 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
+{
+ constructor(settings)
+ {
+ super();
+ this.settings = settings;
+ }
+
+ getLegacySetting(attrib, name)
+ {
+ if (!attrib || !attrib.settings || attrib.settings[name] === undefined)
+ return undefined;
+ return attrib.settings[name];
+ }
+
+ getMapSetting(name)
+ {
+ if (!this.settings.map.data || !this.settings.map.data.settings ||
+ this.settings.map.data.settings[name] === undefined)
+ return undefined;
+ return this.settings.map.data.settings[name];
+ }
+}
Index: binaries/data/mods/public/gui/gamesettings/GameSettings.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/GameSettings.js
@@ -0,0 +1,88 @@
+/**
+ * Data store for game settings.
+ * Serializes to/from JSON.
+ */
+class GameSettings
+{
+ Init()
+ {
+ for (let comp in GameSettings.prototype.Attributes)
+ {
+ let name = comp[0].toLowerCase() + comp.substr(1);
+ this[name] = new GameSettings.prototype.Attributes[comp](this);
+ }
+ for (let comp in this)
+ this[comp].Init();
+ return this;
+ }
+
+ /**
+ * Serialize the settings into a g_GameAttributes-compatible format.
+ * This is currently also used for hotloading and MP sync,
+ * so it should be equivalent to the non-serialized state.
+ * TODO: does it make sense to serialize differently?
+ */
+ LegacySerialize()
+ {
+ let attribs = {
+ "settings": {}
+ };
+ for (let comp in this)
+ if (this[comp].LegacySerialize)
+ this[comp].LegacySerialize(attribs);
+ return attribs;
+ }
+
+ /**
+ * Deserialize from a g_GameAttributes-compatible format.
+ * TODO: this could/should maybe support partial deserialization,
+ * which means MP might actually send only the bits that change.
+ */
+ LegacyDeserialize(attribs)
+ {
+ // Settings depend on the map, but some settings
+ // may also be illegal for a given map.
+ // It would be good to validate, but just bulk-accept at the moment.
+ // Deserialize the map first as that leads to requirements in other areas.
+ this.map.LegacyDeserialize(attribs);
+ for (let comp in this)
+ if (this[comp].LegacyDeserialize)
+ this[comp].LegacyDeserialize(attribs);
+ }
+
+ /**
+ * Call this before starting the game.
+ */
+ prepareForLaunch()
+ {
+ this.pickRandomItems();
+ }
+
+ /**
+ * Change "random" settings into their proper settings.
+ */
+ pickRandomItems()
+ {
+ let components = Object.keys(this);
+ let i = 0;
+ while (components.length && i < 100)
+ {
+ // Re-pick if any random setting was unrandomised,
+ // to make sure dependencies are cleared.
+ // TODO: there's probably a better way to handle this.
+ components = components.filter(comp => this[comp].pickRandomItems ?
+ !!this[comp].pickRandomItems() : false);
+ ++i;
+ }
+ if (i === 100)
+ {
+ throw new Error("Infinite loop picking random items, remains : " + uneval(components));
+ }
+ }
+}
+
+Object.defineProperty(GameSettings.prototype, "Attributes", {
+ "value": {},
+ "enumerable": false,
+ "writable": true,
+});
Index: binaries/data/mods/public/gui/gamesettings/attributes/Biome.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/Biome.js
@@ -0,0 +1,75 @@
+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));
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (!this.biome)
+ return;
+ attribs.settings.Biome = this.biome;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (!this.getLegacySetting(attribs, "Biome"))
+ this.biome = undefined;
+ else
+ this.biome = this.getLegacySetting(attribs, "Biome");
+ }
+
+ onMapChange()
+ {
+ let mapData = this.settings.map.data;
+ if (mapData && mapData.settings && mapData.settings.SupportedBiomes !== undefined)
+ {
+ this.available = new Set(this.biomes.filter(biome => biome.Id.indexOf(mapData.settings.SupportedBiomes) !== -1)
+ .map(biome => biome.Id));
+ this.biome = "random";
+ }
+ else
+ {
+ this.available = new Set();
+ this.biome = undefined;
+ }
+ }
+
+ setBiome(biome)
+ {
+ // TODO: validation.
+ this.biome = biome;
+ }
+
+ getAvailableBiomeData()
+ {
+ return Array.from(this.available).map(biome => this.biomeData[biome]);
+ }
+
+ getData()
+ {
+ if (!this.biome)
+ return undefined;
+ return this.biomeData[this.biome];
+ }
+
+ pickRandomItems()
+ {
+ // If the map is random, we need to wait until it selects to know if we need to pick a biome.
+ if (this.settings.map.map === "random")
+ return true;
+
+ if (this.biome !== "random")
+ return false;
+ this.biome = pickRandom(this.available);
+ return true;
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/Ceasefire.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/Ceasefire.js
@@ -0,0 +1,38 @@
+GameSettings.prototype.Attributes.Ceasefire = class extends GameSetting
+{
+ Init()
+ {
+ this.value = 0;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (!this.value)
+ return;
+ attribs.settings.Ceasefire = this.value;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (!this.getLegacySetting(attribs, "Ceasefire"))
+ this.value = 0;
+ else
+ this.value = +this.getLegacySetting(attribs, "Ceasefire");
+ }
+
+ onMapChange()
+ {
+ if (this.settings.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/gui/gamesettings/attributes/Cheats.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/Cheats.js
@@ -0,0 +1,33 @@
+GameSettings.prototype.Attributes.Cheats = class extends GameSetting
+{
+ Init()
+ {
+ this.enabled = false;
+ this.settings.rating.watch(() => this.maybeUpdate(), ["enabled"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ attribs.settings.CheatsEnabled = this.enabled;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ this.enabled = !!this.getLegacySetting(attribs, "CheatsEnabled");
+ }
+
+ _set(enabled)
+ {
+ this.enabled = (enabled && !this.settings.rating.enabled);
+ }
+
+ setEnabled(enabled)
+ {
+ this._set(enabled);
+ }
+
+ maybeUpdate()
+ {
+ this._set(this.enabled);
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/Daytime.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/Daytime.js
@@ -0,0 +1,51 @@
+GameSettings.prototype.Attributes.Daytime = class extends GameSetting
+{
+ Init()
+ {
+ this.data = undefined;
+ this.value = undefined;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.value)
+ attribs.settings.Daytime = this.value;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (!this.getLegacySetting(attribs, "Daytime"))
+ this.setValue(undefined);
+ else
+ this.setValue(this.getLegacySetting(attribs, "Daytime"));
+ }
+
+ onMapChange()
+ {
+ let mapData = this.settings.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/gui/gamesettings/attributes/DisableSpies.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/DisableSpies.js
@@ -0,0 +1,30 @@
+GameSettings.prototype.Attributes.DisableSpies = class extends GameSetting
+{
+ Init()
+ {
+ this.enabled = false;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ attribs.settings.DisableSpies = this.enabled;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ this.enabled = !!this.getLegacySetting(attribs, "DisableSpies");
+ }
+
+ onMapChange()
+ {
+ if (this.settings.map.type != "scenario")
+ return;
+ this.setEnabled(!!this.getMapSetting("DisableSpies"));
+ }
+
+ setEnabled(enabled)
+ {
+ this.enabled = enabled;
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/DisableTreasures.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/DisableTreasures.js
@@ -0,0 +1,30 @@
+GameSettings.prototype.Attributes.DisableTreasures = class extends GameSetting
+{
+ Init()
+ {
+ this.enabled = false;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ attribs.settings.DisableTreasures = this.enabled;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ this.enabled = !!this.getLegacySetting(attribs, "DisableTreasures");
+ }
+
+ onMapChange()
+ {
+ if (this.settings.map.type != "scenario")
+ return;
+ this.setEnabled(!!this.getMapSetting("DisableTreasures"));
+ }
+
+ setEnabled(enabled)
+ {
+ this.enabled = enabled;
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/DisabledTechnologies.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/DisabledTechnologies.js
@@ -0,0 +1,39 @@
+/**
+ * TODO: does this need a GUI setting?
+ * Also TODO: would probably be better to let maps implement custom modifiers.
+ */
+GameSettings.prototype.Attributes.DisabledTechnologies = class extends GameSetting
+{
+ Init()
+ {
+ this.value = undefined;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.value)
+ attribs.settings.DisabledTechnologies = this.value;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (!this.getLegacySetting(attribs, "DisabledTechnologies"))
+ this.setValue(undefined);
+ else
+ this.setValue(this.getLegacySetting(attribs, "DisabledTechnologies"));
+ }
+
+ onMapChange()
+ {
+ if (!this.getMapSetting("DisabledTechnologies"))
+ this.setValue(undefined);
+ else
+ this.setValue(this.getMapSetting("DisabledTechnologies"));
+ }
+
+ setValue(val)
+ {
+ this.value = val;
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/DisabledTemplates.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/DisabledTemplates.js
@@ -0,0 +1,39 @@
+/**
+ * TODO: does this need a GUI setting?
+ * Also TODO: would probably be better to let maps implement custom modifiers.
+ */
+GameSettings.prototype.Attributes.DisabledTemplates = class extends GameSetting
+{
+ Init()
+ {
+ this.value = undefined;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.value)
+ attribs.settings.DisabledTemplates = this.value;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (!this.getLegacySetting(attribs, "DisabledTemplates"))
+ this.setValue(undefined);
+ else
+ this.setValue(this.getLegacySetting(attribs, "DisabledTemplates"));
+ }
+
+ onMapChange()
+ {
+ if (!this.getMapSetting("DisabledTemplates"))
+ this.setValue(undefined);
+ else
+ this.setValue(this.getMapSetting("DisabledTemplates"));
+ }
+
+ setValue(val)
+ {
+ this.value = val;
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/GameSpeed.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/GameSpeed.js
@@ -0,0 +1,32 @@
+GameSettings.prototype.Attributes.GameSpeed = class extends GameSetting
+{
+ Init()
+ {
+ this.gameSpeed = 1;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ attribs.gameSpeed = this.gameSpeed;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (!attribs.gameSpeed)
+ return;
+ this.gameSpeed = +attribs.gameSpeed;
+ }
+
+ onMapChange()
+ {
+ if (!this.getMapSetting("gameSpeed"))
+ return;
+ this.setSpeed(+this.getMapSetting("gameSpeed"));
+ }
+
+ setSpeed(speed)
+ {
+ this.gameSpeed = speed;
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/Landscape.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/Landscape.js
@@ -0,0 +1,73 @@
+GameSettings.prototype.Attributes.Landscape = class extends GameSetting
+{
+ Init()
+ {
+ this.data = undefined;
+ this.value = undefined;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.value)
+ attribs.settings.Landscape = this.value;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (!this.getLegacySetting(attribs, "Landscape"))
+ this.setValue(undefined);
+ else
+ this.setValue(this.getLegacySetting(attribs, "Landscape"));
+ }
+
+ onMapChange()
+ {
+ if (!this.getMapSetting("Landscapes"))
+ {
+ this.value = undefined;
+ this.data = undefined;
+ return;
+ }
+ // TODO: validation
+ this.data = this.getMapSetting("Landscapes");
+ this.value = "random";
+ }
+
+ setValue(val)
+ {
+ // TODO: validation.
+ this.value = val;
+ }
+
+ getPreviewFilename()
+ {
+ if (!this.value)
+ return undefined;
+ for (let group of this.data)
+ for (let item of group.Items)
+ if (item.Id == this.value)
+ return item.Preview;
+ return undefined;
+ }
+
+ 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/gui/gamesettings/attributes/LastManStanding.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/LastManStanding.js
@@ -0,0 +1,38 @@
+GameSettings.prototype.Attributes.LastManStanding = class extends GameSetting
+{
+ Init()
+ {
+ this.available = !this.settings.lockedTeams.enabled;
+ this.enabled = false;
+ this.settings.lockedTeams.watch(() => this.maybeUpdate(), ["enabled"]);
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ attribs.settings.LastManStanding = this.enabled;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ this.enabled = !!this.getLegacySetting(attribs, "LastManStanding");
+ }
+
+ onMapChange()
+ {
+ if (this.settings.map.type != "scenario")
+ return;
+ this.setEnabled(!!this.getMapSetting("LastManStanding"));
+ }
+
+ setEnabled(enabled)
+ {
+ this.available = !this.settings.lockedTeams.enabled;
+ this.enabled = (enabled && this.available);
+ }
+
+ maybeUpdate()
+ {
+ this.setEnabled(this.enabled);
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/LockedTeams.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/LockedTeams.js
@@ -0,0 +1,30 @@
+GameSettings.prototype.Attributes.LockedTeams = class extends GameSetting
+{
+ Init()
+ {
+ this.enabled = false;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ attribs.settings.LockTeams = this.enabled;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ this.enabled = !!this.getLegacySetting(attribs, "LockTeams");
+ }
+
+ onMapChange()
+ {
+ if (this.settings.map.type != "scenario")
+ return;
+ this.setEnabled(!!this.getMapSetting("LockTeams"));
+ }
+
+ setEnabled(enabled)
+ {
+ this.enabled = enabled;
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/Map.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/Map.js
@@ -0,0 +1,81 @@
+GameSettings.prototype.Attributes.Map = class extends GameSetting
+{
+ Init()
+ {
+ this.watch(() => this.updateMapMetadata(), ["map"]);
+ this.map = undefined;
+ this.type = undefined;
+ this.script = undefined;
+ this.randomOptions = [];
+ }
+
+ LegacySerialize(attribs)
+ {
+ attribs.map = this.map;
+ attribs.mapType = this.type;
+ if (this.script)
+ attribs.script = this.script;
+
+ if (!this.data)
+ return;
+
+ // Some map attributes cannot be changed but are required
+ // copy them explicitly.
+ let copy = ["CircularMap",
+ "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.
+ // TODO: this should probably be moved out of settings and into the core engine bit.
+ "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);
+ }
+
+ 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.selectMap(pickRandom(this.randomOptions));
+ return true;
+ }
+
+ setRandomOptions(options)
+ {
+ this.randomOptions = clone(options);
+ if (this.randomOptions.indexOf("random") !== -1)
+ this.randomOptions.splice(this.randomOptions.indexOf("random"), 1);
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/MapExploration.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/MapExploration.js
@@ -0,0 +1,42 @@
+GameSettings.prototype.Attributes.MapExploration = class extends GameSetting
+{
+ Init()
+ {
+ this.explored = false;
+ this.revealed = false;
+
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ attribs.settings.RevealMap = this.revealed;
+ attribs.settings.ExploreMap = this.explored;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ this.explored = !!this.getLegacySetting(attribs, "ExploreMap");
+ this.revealed = !!this.getLegacySetting(attribs, "RevealMap");
+ }
+
+ onMapChange(mapData)
+ {
+ if (this.settings.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/gui/gamesettings/attributes/MapSize.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/MapSize.js
@@ -0,0 +1,34 @@
+GameSettings.prototype.Attributes.MapSize = class extends GameSetting
+{
+ Init()
+ {
+ this.setSize(g_MapSizes.Tiles[g_MapSizes.Default]);
+ this.settings.map.watch(() => this.onTypeChange(), ["type"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.settings.map.type === "random")
+ attribs.settings.Size = this.size;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (!!this.getLegacySetting(attribs, "Size"))
+ this.setSize(this.getLegacySetting(attribs, "Size"));
+ }
+
+ setSize(size)
+ {
+ this.available = this.settings.map.type === "random";
+ this.size = size;
+ }
+
+ onTypeChange(old)
+ {
+ if (this.settings.map.type === "random" && old !== "random")
+ this.setSize(g_MapSizes.Tiles[g_MapSizes.Default]);
+ else if (this.settings.map.type !== "random")
+ this.available = false;
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/MatchID.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/MatchID.js
@@ -0,0 +1,17 @@
+GameSettings.prototype.Attributes.MatchID = class extends GameSetting
+{
+ Init()
+ {
+ this.matchID = Engine.GetMatchID();
+ }
+
+ LegacySerialize(attribs)
+ {
+ attribs.matchID = this.matchID;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ this.matchID = attribs.matchID || undefined;
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/Nomad.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/Nomad.js
@@ -0,0 +1,23 @@
+GameSettings.prototype.Attributes.Nomad = class extends GameSetting
+{
+ Init()
+ {
+ this.enabled = false;
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.settings.map.type == "random")
+ attribs.settings.Nomad = this.enabled;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ this.setEnabled(!!this.getLegacySetting(attribs, "Nomad"));
+ }
+
+ setEnabled(enabled)
+ {
+ this.enabled = enabled;
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/PlayerAI.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/PlayerAI.js
@@ -0,0 +1,127 @@
+/**
+ * Stores AI settings for all players.
+ * Note that tby default, this does not assign AI
+ * unless an AI bot is explicitly specified.
+ * This is because:
+ * - the regular GameSetup does that on its own
+ * - this makes campaign/autostart scenarios easier to handle.
+ * - cleans the code here.
+ */
+GameSettings.prototype.Attributes.PlayerAI = class extends GameSetting
+{
+ Init()
+ {
+ // NB: watchers aren't auto-triggered when modifying array elements.
+ this.values = [];
+ this.settings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (!attribs.settings.PlayerData)
+ attribs.settings.PlayerData = [];
+ while (attribs.settings.PlayerData.length < this.values.length)
+ attribs.settings.PlayerData.push({});
+ for (let i = 0; i < this.values.length; ++i)
+ 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)
+ {
+ // Also covers the "" case.
+ if (!pData[i] || !pData[i].AI)
+ {
+ this.set(+i, undefined);
+ continue;
+ }
+ this.set(+i, {
+ "bot": pData[i].AI,
+ "difficulty": pData[i].AIDiff || +Engine.ConfigDB_GetValue("user", "gui.gamesetup.aidifficulty"),
+ "behavior": pData[i].AIBehavior || 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(undefined);
+ }
+
+ maybeUpdate()
+ {
+ this._resize(this.settings.playerCount.nbPlayers);
+ this.trigger("values");
+ }
+
+ swap(sourceIndex, targetIndex)
+ {
+ [this.values[sourceIndex], this.values[targetIndex]] = [this.values[targetIndex], this.values[sourceIndex]];
+ this.trigger("values");
+ }
+
+ set(playerIndex, botSettings)
+ {
+ this.values[playerIndex] = botSettings;
+ this.trigger("values");
+ }
+
+ setAI(playerIndex, ai)
+ {
+ let old = this.values[playerIndex] ? this.values[playerIndex].bot : undefined;
+ if (!ai)
+ this.values[playerIndex] = undefined;
+ else
+ this.values[playerIndex].bot = ai;
+ if (old !== (this.values[playerIndex] ? this.values[playerIndex].bot : undefined))
+ this.trigger("values");
+ }
+
+ setBehavior(playerIndex, value)
+ {
+ if (!this.values[playerIndex])
+ return;
+ this.values[playerIndex].behavior = value;
+ this.trigger("values");
+ }
+
+ setDifficulty(playerIndex, value)
+ {
+ if (!this.values[playerIndex])
+ return;
+ 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/gui/gamesettings/attributes/PlayerCiv.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/PlayerCiv.js
@@ -0,0 +1,129 @@
+/**
+ * Stores civ settings for all players.
+ */
+GameSettings.prototype.Attributes.PlayerCiv = class extends GameSetting
+{
+ Init()
+ {
+ // NB: watchers aren't auto-triggered when modifying array elements.
+ this.values = [];
+ this.locked = [];
+ this.settings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]);
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ 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);
+ }
+
+ _resize(nb)
+ {
+ while (this.values.length > nb)
+ {
+ this.values.pop();
+ this.locked.pop();
+ }
+ while (this.values.length < nb)
+ {
+ this.values.push("random");
+ this.locked.push(false);
+ }
+ }
+
+ onMapChange()
+ {
+ // Reset.
+ if (this.settings.map.type == "scenario")
+ this._resize(0);
+ this.maybeUpdate();
+ }
+
+ maybeUpdate()
+ {
+ this._resize(this.settings.playerCount.nbPlayers);
+ this.values.forEach((c, i) => this._set(i, c));
+ this.trigger("values");
+ }
+
+ pickRandomItems()
+ {
+ // Get a unique array of selectable cultures
+ let cultures = Object.keys(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 = this.settings.map.data;
+ if (!data || !data.settings || !data.settings.PlayerData)
+ return undefined;
+ if (data.settings.PlayerData.length <= i)
+ return undefined;
+ return data.settings.PlayerData[i].Civ;
+ }
+
+ _set(playerIndex, value)
+ {
+ let map = this._getMapData(playerIndex);
+ if (!!map)
+ {
+ this.values[playerIndex] = map;
+ this.locked[playerIndex] = true;
+ }
+ else
+ {
+ this.values[playerIndex] = value;
+ this.locked[playerIndex] = this.settings.map.type == "scenario";
+ }
+ }
+
+ setValue(playerIndex, val)
+ {
+ this._set(playerIndex, val);
+ this.trigger("values");
+ }
+
+ swap(sourceIndex, targetIndex)
+ {
+ [this.values[sourceIndex], this.values[targetIndex]] = [this.values[targetIndex], this.values[sourceIndex]];
+ [this.locked[sourceIndex], this.locked[targetIndex]] = [this.locked[targetIndex], this.locked[sourceIndex]];
+ this.trigger("values");
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/PlayerColor.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/PlayerColor.js
@@ -0,0 +1,180 @@
+/**
+ * Stores player color for all players.
+ */
+ GameSettings.prototype.Attributes.PlayerColor = class extends GameSetting
+{
+ Init()
+ {
+ // TODO: update this
+ this.defaultColors = g_Settings.PlayerDefaults.slice(1).map(pData => pData.Color);
+
+ this.watch(() => this.maybeUpdate(), ["available"]);
+ this.settings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]);
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+
+ // NB: watchers aren't auto-triggered when modifying array elements.
+ this.values = [];
+ this.locked = [];
+ this._updateAvailable();
+ }
+
+ 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);
+ }
+
+ _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 (this.settings.map.type == "scenario" ||
+ this.getMapSetting("PlayerData") &&
+ this.getMapSetting("PlayerData").some(data => data && data.Color))
+ this._resize(0);
+ this._updateAvailable();
+ this.maybeUpdate();
+ }
+
+ maybeUpdate()
+ {
+ this._resize(this.settings.playerCount.nbPlayers);
+
+ 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 ?
+ 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");
+ }
+
+ swap(sourceIndex, targetIndex)
+ {
+ [this.values[sourceIndex], this.values[targetIndex]] = [this.values[targetIndex], this.values[sourceIndex]];
+ [this.locked[sourceIndex], this.locked[targetIndex]] = [this.locked[targetIndex], this.locked[sourceIndex]];
+ this.trigger("values");
+ }
+
+ _getMapData(i)
+ {
+ let data = this.settings.map.data;
+ if (!data || !data.settings || !data.settings.PlayerData)
+ return undefined;
+ if (data.settings.PlayerData.length <= i)
+ return undefined;
+ return data.settings.PlayerData[i].Color;
+ }
+
+ _updateAvailable()
+ {
+ // 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));
+ this.available = values;
+ }
+
+ _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/gui/gamesettings/attributes/PlayerCount.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/PlayerCount.js
@@ -0,0 +1,67 @@
+GameSettings.prototype.Attributes.PlayerCount = class extends GameSetting
+{
+ Init()
+ {
+ this.nbPlayers = 1;
+ this.settings.map.watch(() => this.onMapTypeChange(), ["type"]);
+ this.settings.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;
+ }
+
+ onMapTypeChange(old)
+ {
+ if (this.settings.map.type == "random" && old != "random")
+ this.nbPlayers = 2;
+ }
+
+ onMapChange()
+ {
+ if (this.settings.map.type == "random")
+ return;
+ if (!this.settings.map.data || !this.settings.map.data.settings ||
+ !this.settings.map.data.settings.PlayerData)
+ return;
+ this.nbPlayers = this.settings.map.data.settings.PlayerData.length;
+ }
+
+ reloadFromLegacy(data)
+ {
+ if (this.settings.map.type != "random")
+ {
+ this.nbPlayers = this.settings.map.data.settings.PlayerData.length;
+ return;
+ }
+ if (!data || !data.settings || data.settings.PlayerData === undefined)
+ return;
+ this.nbPlayers = data.settings.PlayerData.length;
+ }
+
+ /**
+ * @param index - Player Index, 0 is 'player 1' since GAIA isn't there.
+ */
+ get(index)
+ {
+ return this.data[index];
+ }
+
+ setNb(nb)
+ {
+ this.nbPlayers = Math.max(1, Math.min(g_MaxPlayers, nb));
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/PlayerName.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/PlayerName.js
@@ -0,0 +1,117 @@
+/**
+ * Stores in-game names for all players.
+ *
+ * NB: the regular gamesetup has a particular handling of this setting.
+ * The names are loaded from the map, but the GUI also show playernames
+ * and forces them when starting the game.
+ * This is therefore just handling map-defined names & AI random bot names.
+ */
+GameSettings.prototype.Attributes.PlayerName = class extends GameSetting
+{
+ Init()
+ {
+ // NB: watchers aren't auto-triggered when modifying array elements.
+ this.values = [];
+ this.settings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]);
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ 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];
+ }
+
+ _resize(nb)
+ {
+ while (this.values.length > nb)
+ this.values.pop();
+ while (this.values.length < nb)
+ this.values.push(undefined);
+ }
+
+ onMapChange()
+ {
+ // Reset.
+ this._resize(0);
+ this.maybeUpdate();
+ }
+
+ maybeUpdate()
+ {
+ this._resize(this.settings.playerCount.nbPlayers);
+ this.values.forEach((_, i) => this._set(i));
+ this.trigger("values");
+ }
+
+ /**
+ * Pick bot names.
+ */
+ pickRandomItems()
+ {
+ let picked = false;
+ for (let i in this.values)
+ {
+ if (!!this.values[i] &&
+ this.values[i] !== g_Settings.PlayerDefaults[+i + 1].Name)
+ continue;
+
+ let ai = this.settings.playerAI.values[i];
+ if (!ai)
+ continue;
+
+ let civ = this.settings.playerCiv.values[i];
+ if (!civ || civ == "random")
+ continue;
+
+ picked = true;
+ // Pick one of the available botnames for the chosen civ
+ // Determine botnames
+ let chosenName = pickRandom(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 = this.settings.map.data;
+ if (!data || !data.settings || !data.settings.PlayerData)
+ return undefined;
+ if (data.settings.PlayerData.length <= i)
+ return undefined;
+ return data.settings.PlayerData[i].Name;
+ }
+
+ _set(playerIndex)
+ {
+ this.values[playerIndex] = this._getMapData(playerIndex) || g_Settings && g_Settings.PlayerDefaults[playerIndex + 1].Name || "";
+ }
+};
+
+
+GameSettings.prototype.Attributes.PlayerName.prototype.RomanLabel =
+ translate("%(playerName)s %(romanNumber)s");
+
+GameSettings.prototype.Attributes.PlayerName.prototype.RomanNumbers =
+ [undefined, "I", "II", "III", "IV", "V", "VI", "VII", "VIII"];
Index: binaries/data/mods/public/gui/gamesettings/attributes/PlayerTeam.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/PlayerTeam.js
@@ -0,0 +1,79 @@
+/**
+ * Stores team settings for all players.
+ */
+GameSettings.prototype.Attributes.PlayerTeam = class extends GameSetting
+{
+ Init()
+ {
+ // NB: watchers aren't auto-triggered when modifying array elements.
+ this.values = [];
+ this.locked = [];
+ this.settings.playerCount.watch(() => this.maybeUpdate(), ["nbPlayers"]);
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ 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] !== undefined)
+ 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 !== undefined)
+ this.setValue(i, pData[i].Team);
+ }
+
+ _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 (this.settings.map.type == "scenario")
+ this._resize(0);
+ this.maybeUpdate();
+ }
+
+ maybeUpdate()
+ {
+ this._resize(this.settings.playerCount.nbPlayers);
+ this.values.forEach((c, i) => this._set(i, c));
+ this.trigger("values");
+ }
+
+ _set(playerIndex, value)
+ {
+ this.values[playerIndex] = value;
+ this.locked[playerIndex] = this.settings.map.type == "scenario";
+ }
+
+ setValue(playerIndex, val)
+ {
+ this._set(playerIndex, val);
+ this.trigger("values");
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/Population.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/Population.js
@@ -0,0 +1,73 @@
+/**
+ * Combines the worldPopulation and regular population cap.
+ * At the moment those are incompatible so this makes sense.
+ * TODO: Should there be a dialog allowing per-player pop limits?
+ */
+GameSettings.prototype.Attributes.Population = class extends GameSetting
+{
+ Init()
+ {
+ this.perPlayer = false;
+ this.useWorldPop = false;
+ this.cap = g_PopulationCapacities.Population[g_PopulationCapacities.Default];
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.perPlayer)
+ {
+ if (!attribs.settings.PlayerData)
+ attribs.settings.PlayerData = [];
+ while (attribs.settings.PlayerData.length < this.perPlayer.length)
+ attribs.settings.PlayerData.push({});
+ for (let i in this.perPlayer)
+ if (this.perPlayer[i])
+ attribs.settings.PlayerData[i].PopulationLimit = this.perPlayer[i];
+ }
+ if (this.useWorldPop)
+ {
+ attribs.settings.WorldPopulation = true;
+ attribs.settings.WorldPopulationCap = this.cap;
+ }
+ else
+ attribs.settings.PopulationCap = this.cap;
+ }
+
+ 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"));
+ }
+
+ onMapChange()
+ {
+ this.perPlayer = undefined;
+ if (this.settings.map.type != "scenario")
+ return;
+ if (!!this.getMapSetting("PlayerData") &&
+ this.getMapSetting("PlayerData").some(data => data.PopulationLimit))
+ this.perPlayer = this.getMapSetting("PlayerData").map(data => data.PopulationLimit || undefined);
+ else if (this.getMapSetting("WorldPopulation"))
+ this.setPopCap(true, +this.getMapSetting("WorldPopulationCap"));
+ else
+ this.setPopCap(false, +this.getMapSetting("PopulationCap"));
+ }
+
+ setPopCap(worldPop, cap = undefined)
+ {
+ if (worldPop != this.useWorldPop)
+ this.cap = undefined;
+
+ this.useWorldPop = worldPop;
+
+ if (!!cap)
+ this.cap = cap;
+ else if (!this.cap && !this.useWorldPop)
+ this.cap = 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/gui/gamesettings/attributes/Rating.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/Rating.js
@@ -0,0 +1,30 @@
+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;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ this.enabled = !!this.getLegacySetting(attribs, "RatingEnabled");
+ }
+
+ 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/gui/gamesettings/attributes/RegicideGarrison.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/RegicideGarrison.js
@@ -0,0 +1,37 @@
+GameSettings.prototype.Attributes.RegicideGarrison = class extends GameSetting
+{
+ Init()
+ {
+ this.setEnabled(false);
+ this.settings.victoryConditions.watch(() => this.maybeUpdate(), ["active"]);
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ attribs.settings.RegicideGarrison = this.enabled;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ this.enabled = !!this.getLegacySetting(attribs, "RegicideGarrison");
+ }
+
+ onMapChange()
+ {
+ if (this.settings.map.type != "scenario")
+ return;
+ this.setEnabled(!!this.getMapSetting("RegicideGarrison"));
+ }
+
+ setEnabled(enabled)
+ {
+ this.available = this.settings.victoryConditions.active.has("regicide");
+ this.enabled = (enabled && this.available);
+ }
+
+ maybeUpdate()
+ {
+ this.setEnabled(this.enabled);
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/Relic.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/Relic.js
@@ -0,0 +1,62 @@
+GameSettings.prototype.Attributes.Relic = class extends GameSetting
+{
+ Init()
+ {
+ this.available = false;
+ this.count = 0;
+ this.duration = 0;
+ this.settings.victoryConditions.watch(() => this.maybeUpdate(), ["active"]);
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ // For consistency, only save this if the victory condition is active.
+ if (this.available)
+ {
+ attribs.settings.RelicCount = this.count;
+ attribs.settings.RelicDuration = this.duration;
+ }
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (!!this.getLegacySetting(attribs, "RelicCount"))
+ this.setCount(this.getLegacySetting(attribs, "RelicCount"));
+ if (!!this.getLegacySetting(attribs, "RelicDuration"))
+ this.setDuration(this.getLegacySetting(attribs, "RelicDuration"));
+ }
+
+ onMapChange()
+ {
+ if (this.settings.map.type != "scenario")
+ return;
+ // TODO: probably should sync the victory condition.
+ if (!this.getMapSetting("RelicCount"))
+ this.available = false;
+ else
+ this._set(+this.getMapSetting("RelicCount"), +this.getMapSetting("RelicDuration"));
+ }
+
+ _set(count, duration)
+ {
+ this.available = this.settings.victoryConditions.active.has("capture_the_relic");
+ this.count = Math.max(1, count);
+ this.duration = duration;
+ }
+
+ setCount(val)
+ {
+ this._set(Math.round(val), this.duration);
+ }
+
+ setDuration(val)
+ {
+ this._set(this.count, Math.round(val));
+ }
+
+ maybeUpdate()
+ {
+ this._set(this.count, this.duration);
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/SeaLevelRise.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/SeaLevelRise.js
@@ -0,0 +1,40 @@
+GameSettings.prototype.Attributes.SeaLevelRise = class extends GameSetting
+{
+ Init()
+ {
+ this.min = undefined;
+ this.max = undefined;
+ this.value = undefined;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.value)
+ attribs.settings.SeaLevelRiseTime = this.value;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (!!this.getLegacySetting(attribs, "SeaLevelRiseTime"))
+ this.value = this.getLegacySetting(attribs, "SeaLevelRiseTime");
+ }
+
+ onMapChange()
+ {
+ if (!this.getMapSetting("SeaLevelRise"))
+ {
+ this.value = undefined;
+ return;
+ }
+ let mapData = this.settings.map.data;
+ this.min = mapData.settings.SeaLevelRise.Min;
+ this.max = mapData.settings.SeaLevelRise.Max;
+ this.value = mapData.settings.SeaLevelRise.Default;
+ }
+
+ setValue(val)
+ {
+ this.value = Math.max(this.min, Math.min(this.max, Math.round(val)));
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/Seeds.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/Seeds.js
@@ -0,0 +1,30 @@
+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;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ // Seed is used for map generation and simulation.
+ if (this.getLegacySetting(attribs, "Seed") !== undefined)
+ this.seed = this.getLegacySetting(attribs, "Seed");
+ if (this.getLegacySetting(attribs, "AISeed") !== undefined)
+ this.AIseed = this.getLegacySetting(attribs, "AISeed");
+ }
+
+ pickRandomItems()
+ {
+ this.seed = randIntExclusive(0, Math.pow(2, 32));
+ this.AIseed = randIntExclusive(0, Math.pow(2, 32));
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/StartingResources.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/StartingResources.js
@@ -0,0 +1,52 @@
+/**
+ * TODO: There should be a dialog allowing to specify starting resources per player
+ */
+GameSettings.prototype.Attributes.StartingResources = class extends GameSetting
+{
+ Init()
+ {
+ this.perPlayer = undefined;
+ this.setResources(g_StartingResources.Resources[g_StartingResources.Default]);
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.perPlayer)
+ {
+ if (!attribs.settings.PlayerData)
+ attribs.settings.PlayerData = [];
+ while (attribs.settings.PlayerData.length < this.perPlayer.length)
+ attribs.settings.PlayerData.push({});
+ for (let i in this.perPlayer)
+ if (this.perPlayer[i])
+ attribs.settings.PlayerData[i].Resources = this.perPlayer[i];
+ }
+ attribs.settings.StartingResources = this.resources;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (this.getLegacySetting(attribs, "StartingResources") !== undefined)
+ this.setResources(this.getLegacySetting(attribs, "StartingResources"));
+ }
+
+ onMapChange()
+ {
+ this.perPlayer = undefined;
+ if (this.settings.map.type != "scenario")
+ return;
+ if (!!this.getMapSetting("PlayerData") &&
+ this.getMapSetting("PlayerData").some(data => data.Resources))
+ this.perPlayer = this.getMapSetting("PlayerData").map(data => data.Resources || undefined);
+ else 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/gui/gamesettings/attributes/StartingTechnologies.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/StartingTechnologies.js
@@ -0,0 +1,38 @@
+/**
+ * TODO: this doesn't have a GUI setting.
+ */
+GameSettings.prototype.Attributes.StartingTechnologies = class extends GameSetting
+{
+ Init()
+ {
+ this.value = undefined;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.value)
+ attribs.settings.StartingTechnologies = this.value;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (!this.getLegacySetting(attribs, "StartingTechnologies"))
+ this.setValue(undefined);
+ else
+ this.setValue(this.getLegacySetting(attribs, "StartingTechnologies"));
+ }
+
+ onMapChange()
+ {
+ if (!this.getMapSetting("StartingTechnologies"))
+ this.setValue(undefined);
+ else
+ this.setValue(this.getMapSetting("StartingTechnologies"));
+ }
+
+ setValue(val)
+ {
+ this.value = val;
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/TeamPlacement.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/TeamPlacement.js
@@ -0,0 +1,71 @@
+GameSettings.prototype.Attributes.TeamPlacement = class extends GameSetting
+{
+ Init()
+ {
+ this.available = undefined;
+ this.value = undefined;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.value)
+ attribs.settings.TeamPlacement = this.value;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (!!this.getLegacySetting(attribs, "TeamPlacement"))
+ this.value = this.getLegacySetting(attribs, "TeamPlacement");
+ }
+
+ 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/gui/gamesettings/attributes/TriggerDifficulty.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/TriggerDifficulty.js
@@ -0,0 +1,52 @@
+GameSettings.prototype.Attributes.TriggerDifficulty = class extends GameSetting
+{
+ Init()
+ {
+ this.difficulties = loadSettingValuesFile("trigger_difficulties.json");
+ this.available = undefined;
+ this.value = undefined;
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.available)
+ attribs.settings.TriggerDifficulty = this.value;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (this.getLegacySetting(attribs, "TriggerDifficulty") !== undefined)
+ this.setValue(this.getLegacySetting(attribs, "TriggerDifficulty"));
+ }
+
+ 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 = this.getMapSetting("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 - 1];
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/TriggerScripts.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/TriggerScripts.js
@@ -0,0 +1,39 @@
+GameSettings.prototype.Attributes.TriggerScripts = class extends GameSetting
+{
+ Init()
+ {
+ this.victory = new Set();
+ this.map = new Set();
+ this.settings.map.watch(() => this.updateMapScripts(), ["map"]);
+ this.settings.victoryConditions.watch(() => this.updateVictoryScripts(), ["active"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ attribs.settings.TriggerScripts = Array.from(this.victory).concat(Array.from(this.map));
+ }
+
+ /**
+ * Exceptionally, this setting has no Deserialize: it's entirely determined from other settings.
+ */
+
+ updateVictoryScripts()
+ {
+ let setting = this.settings.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 (!this.settings.map.data || !this.settings.map.data.settings ||
+ !this.settings.map.data.settings.TriggerScripts)
+ {
+ this.map = new Set();
+ return;
+ }
+ this.map = new Set(this.settings.map.data.settings.TriggerScripts);
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/VictoryConditions.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/VictoryConditions.js
@@ -0,0 +1,93 @@
+GameSettings.prototype.Attributes.VictoryConditions = class extends GameSetting
+{
+ constructor(settings)
+ {
+ super(settings);
+ // Set of victory condition names.
+ this.active = new Set();
+ this.disabled = new Set();
+ this.conditions = {};
+ }
+
+ Init()
+ {
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+
+ 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)
+ {
+ this.active = new Set();
+ this.disabled = new Set();
+ let legacy = this.getLegacySetting(attribs, "VictoryConditions");
+ if (legacy)
+ for (let cond of legacy)
+ this._add(cond);
+ }
+
+ onMapChange()
+ {
+ if (this.settings.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);
+ }
+
+ _reconstructDisabled(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._reconstructDisabled(active);
+ this.active = active;
+ }
+
+ _delete(name)
+ {
+ let active = clone(this.active);
+ active.delete(name);
+ // TODO: sanity check
+ this.disabled = this._reconstructDisabled(active);
+ this.active = active;
+ }
+
+ setEnabled(name, enabled)
+ {
+ if (enabled)
+ this._add(name);
+ else
+ this._delete(name);
+ }
+};
Index: binaries/data/mods/public/gui/gamesettings/attributes/Wonder.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesettings/attributes/Wonder.js
@@ -0,0 +1,40 @@
+GameSettings.prototype.Attributes.Wonder = class extends GameSetting
+{
+ Init()
+ {
+ this.available = false;
+ this.duration = 0;
+ this.settings.victoryConditions.watch(() => this.maybeUpdate(), ["active"]);
+ this.settings.map.watch(() => this.onMapChange(), ["map"]);
+ }
+
+ LegacySerialize(attribs)
+ {
+ if (this.available)
+ attribs.settings.WonderDuration = this.duration;
+ }
+
+ LegacyDeserialize(attribs)
+ {
+ if (this.getLegacySetting(attribs, "WonderDuration") !== undefined)
+ this.setDuration(+this.getLegacySetting(attribs, "WonderDuration"));
+ }
+
+ onMapChange()
+ {
+ if (this.settings.map.type != "scenario")
+ return;
+ this.setDuration(+this.getMapSetting("WonderDuration"));
+ }
+
+ setDuration(duration)
+ {
+ this.available = this.settings.victoryConditions.active.has("wonder");
+ this.duration = Math.round(duration);
+ }
+
+ maybeUpdate()
+ {
+ this.setDuration(this.duration);
+ }
+};
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
@@ -1,6 +1,5 @@
/**
- * This class provides a property independent interface to g_GameAttributes events.
- * Classes may use this interface in order to react to changing g_GameAttributes.
+ * 'Controller' for the GUI handling of gamesettings.
*/
class GameSettingsControl
{
@@ -10,18 +9,12 @@
this.mapCache = mapCache;
this.gameSettingsFile = new GameSettingsFile(this);
- this.previousMap = undefined;
- this.depth = 0;
-
- // This property may be read from publicly
- this.autostart = false;
+ this.guiData = new GameSettingsGuiData();
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,33 +27,9 @@
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.
- */
- registerGameAttributesChangeHandler(handler)
- {
- this.gameAttributesChangeHandlers.add(handler);
- }
-
- unregisterGameAttributesChangeHandler(handler)
- {
- this.gameAttributesChangeHandlers.delete(handler);
- }
-
- /**
- * This message is triggered after g_GameAttributes changed and recursed gameAttributesChangeHandlers finished.
- * The use case for this is to update GUI objects which do not change g_GameAttributes but only display the attributes.
+ * This message is triggered when any game setting changes, though
+ * not necessarily for each individual change.
*/
registerGameAttributesBatchChangeHandler(handler)
{
@@ -72,16 +41,6 @@
this.gameAttributesBatchChangeHandlers.delete(handler);
}
- registerGameAttributesFinalizeHandler(handler)
- {
- this.gameAttributesFinalizeHandlers.add(handler);
- }
-
- unregisterGameAttributesFinalizeHandler(handler)
- {
- this.gameAttributesFinalizeHandlers.delete(handler);
- }
-
registerAssignPlayerHandler(handler)
{
this.assignPlayerHandlers.add(handler);
@@ -92,46 +51,15 @@
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 (initData.autostart)
- Object.defineProperty(this, "autostart", {
- "value": true,
- "writable": false,
- "configurable": false
- });
+ if (hotloadData)
+ this.parseSettings(hotloadData.gameAttributes);
+ else if (g_IsController && this.gameSettingsFile.enabled)
+ this.parseSettings(this.gameSettingsFile.loadFile());
- // 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 = initData;
-
- this.updateGameAttributes();
- // Don't launchGame before all Load handlers finished
- }
- 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()
@@ -142,16 +70,35 @@
onGetHotloadData(object)
{
- object.gameAttributes = g_GameAttributes;
+ object.gameAttributes = this.getSettings();
}
onGamesetupMessage(message)
{
- if (!message.data)
+ if (!message.data || g_IsController)
return;
- g_GameAttributes = message.data;
- this.updateGameAttributes();
+ this.parseSettings(message.data);
+ }
+
+ /**
+ * Returns the game settings, augmented by GUI-specific data.
+ */
+ getSettings()
+ {
+ let ret = g_NewGameSettings.LegacySerialize();
+ ret.guiData = this.guiData.Serialize();
+ return ret;
+ }
+
+ /**
+ * Parse the following settings.
+ */
+ parseSettings(settings)
+ {
+ if (settings.guiData)
+ this.guiData.Deserialize(settings.guiData);
+ g_NewGameSettings.LegacyDeserialize(settings);
}
/**
@@ -159,61 +106,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();
- }
}
/**
@@ -227,49 +121,23 @@
*/
setNetworkGameAttributes()
{
+ for (let handler of this.gameAttributesBatchChangeHandlers)
+ handler();
+
if (g_IsNetworked && this.timer === undefined)
this.timer = setTimeout(this.setNetworkGameAttributesImmediately.bind(this), this.Timeout);
}
setNetworkGameAttributesImmediately()
{
- delete this.timer;
- if (g_IsNetworked)
- Engine.SetNetworkGameAttributes(g_GameAttributes);
- }
-
- getPlayerData(gameAttributes, playerIndex)
- {
- return gameAttributes &&
- gameAttributes.settings &&
- gameAttributes.settings.PlayerData &&
- gameAttributes.settings.PlayerData[playerIndex] || undefined;
- }
-
- assignPlayer(sourcePlayerIndex, playerIndex)
- {
- if (playerIndex == -1)
- return;
-
- let target = this.getPlayerData(g_GameAttributes, playerIndex);
- let source = this.getPlayerData(g_GameAttributes, sourcePlayerIndex);
-
- for (let handler of this.assignPlayerHandlers)
- handler(source, target);
-
- this.updateGameAttributes();
- 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();
+ if (this.timer)
+ {
+ clearTimeout(this.timer);
+ delete this.timer;
+ }
+
+ if (g_IsNetworked && g_IsController)
+ Engine.SetNetworkGameAttributes(this.getSettings());
}
onLaunchGame()
@@ -277,23 +145,20 @@
if (!this.autostart)
this.gameSettingsFile.saveFile();
- this.pickRandomItems();
-
for (let handler of this.gameAttributesFinalizeHandlers)
handler();
+ g_NewGameSettings.prepareForLaunch();
+ // Replace player names with the real players.
+ for (let guid in g_PlayerAssignments)
+ if (g_PlayerAssignments[guid].player !== -1)
+ g_NewGameSettings.playerName.values[g_PlayerAssignments[guid].player -1] = g_PlayerAssignments[guid].name;
this.setNetworkGameAttributesImmediately();
}
}
-GameSettingsControl.prototype.MaxDepth = 512;
/**
* Wait (at most) this many milliseconds before sending network messages.
*/
GameSettingsControl.prototype.Timeout = 400;
-
-/**
- * This number is used when selecting the random map type, which doesn't provide PlayerData.
- */
-GameSettingsControl.prototype.DefaultPlayerCount = 4;
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
@@ -9,6 +9,8 @@
this.GameAttributesFileMultiplayer :
this.GameAttributesFileSingleplayer;
+ this.gameSettingsControl = GameSettingsControl;
+
this.engineInfo = Engine.GetEngineInfo();
this.enabled = Engine.ConfigDB_GetValue("user", this.ConfigName) == "true";
}
@@ -45,7 +47,7 @@
Engine.ProfileStart("savePersistMatchSettingsFile");
Engine.WriteJSONFile(this.filename, {
- "attributes": this.enabled ? g_GameAttributes : {},
+ "attributes": this.enabled ? this.gameSettingsControl.getSettings() : {},
"engine_info": this.engineInfo
});
Engine.ProfileStop();
Index: binaries/data/mods/public/gui/gamesetup/Controls/GuiData.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/gamesetup/Controls/GuiData.js
@@ -0,0 +1,27 @@
+/**
+ * This class contains GUI-specific gamesetting data.
+ */
+class GameSettingsGuiData
+{
+ constructor()
+ {
+ this.mapFilter = new Observable();
+ this.mapFilter.filter = "default";
+ }
+
+ /**
+ * Serialize for network transmission or settings persistence.
+ */
+ Serialize()
+ {
+ return {
+ "mapFilter": this.mapFilter.filter
+ }
+ }
+
+ Deserialize(data)
+ {
+ this.mapFilter.filter = data.mapFilter;
+ }
+
+}
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
@@ -25,6 +25,8 @@
};
}
+ g_NewGameSettings.playerCount.watch(() => this.unassignInvalidPlayers(), ["nbPlayers"]);
+
setupWindow.registerLoadHandler(this.onLoad.bind(this));
setupWindow.registerGetHotloadDataHandler(this.onGetHotloadData.bind(this));
netMessages.registerNetMessageHandler("players", this.onPlayerAssignmentMessage.bind(this));
@@ -104,19 +106,18 @@
g_PlayerAssignments = newAssignments;
this.updatePlayerAssignments();
// Send at most one gameRegisterStanza after all handlers run in case a
- // joining observer has been assigned to a playerslot.
+ // joining observer has been assigned to a playerslot.
this.gameRegisterStanza.sendImmediately?.();
}
assignClient(guid, playerIndex)
{
+ g_NewGameSettings.playerAI.setAI(playerIndex - 1, undefined);
if (g_IsNetworked)
Engine.AssignNetworkPlayer(playerIndex, guid);
- else
- {
+ if (g_PlayerAssignments[guid])
g_PlayerAssignments[guid].player = playerIndex;
- this.updatePlayerAssignments();
- }
+ this.updatePlayerAssignments();
}
/**
@@ -125,17 +126,15 @@
assignPlayer(guidToAssign, playerIndex)
{
if (g_PlayerAssignments[guidToAssign].player != -1)
+ {
for (let guid in g_PlayerAssignments)
if (g_PlayerAssignments[guid].player == playerIndex + 1)
{
this.assignClient(guid, g_PlayerAssignments[guidToAssign].player);
break;
}
-
+ }
this.assignClient(guidToAssign, playerIndex + 1);
-
- if (!g_IsNetworked)
- this.updatePlayerAssignments();
}
unassignClient(playerID)
@@ -152,11 +151,10 @@
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/NetMessages/GameRegisterStanza.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/NetMessages/GameRegisterStanza.js
+++ binaries/data/mods/public/gui/gamesetup/NetMessages/GameRegisterStanza.js
@@ -20,11 +20,15 @@
// Events
setupWindow.registerClosePageHandler(this.onClosePage.bind(this));
- gameSettingsControl.registerGameAttributesBatchChangeHandler(this.onGameAttributesBatchChange.bind(this));
netMessages.registerNetMessageHandler("start", this.onGameStart.bind(this));
+
+ g_NewGameSettings.map.watch(() => this.onSettingsChange(), ["map", "type"]);
+ g_NewGameSettings.mapSize.watch(() => this.onSettingsChange(), ["size"]);
+ g_NewGameSettings.victoryConditions.watch(() => this.onSettingsChange(), ["active"]);
+ g_NewGameSettings.playerCount.watch(() => this.onSettingsChange(), ["nbPlayers"]);
}
- onGameAttributesBatchChange()
+ onSettingsChange()
{
if (this.lastStanza)
this.sendDelayed();
@@ -83,13 +87,13 @@
let stanza = {
"name": this.serverName,
"hostUsername": Engine.LobbyGetNick(),
- "mapName": g_GameAttributes.map,
- "niceMapName": this.mapCache.getTranslatableMapName(g_GameAttributes.mapType, g_GameAttributes.map),
- "mapSize": g_GameAttributes.mapType == "random" ? g_GameAttributes.settings.Size : "Default",
- "mapType": g_GameAttributes.mapType,
- "victoryConditions": g_GameAttributes.settings.VictoryConditions.join(","),
+ "mapName": g_NewGameSettings.map.map,
+ "niceMapName": this.mapCache.getTranslatableMapName(g_NewGameSettings.map.type, g_NewGameSettings.map.map),
+ "mapSize": g_NewGameSettings.map.type == "random" ? g_NewGameSettings.mapSize.size : "Default",
+ "mapType": g_NewGameSettings.map.type,
+ "victoryConditions": Array.from(g_NewGameSettings.victoryConditions.active).join(","),
"nbp": clients.connectedPlayers,
- "maxnbp": g_GameAttributes.settings.PlayerData.length,
+ "maxnbp": g_NewGameSettings.playerCount.nbPlayers,
"players": clients.list,
"mods": this.mods,
"hasPassword": this.hasPassword || ""
@@ -107,7 +111,6 @@
/**
* Send a list of playernames and distinct between players and observers.
* Don't send teams, AIs or anything else until the game was started.
- * The playerData format from g_GameAttributes is kept to reuse the GUI function presenting the data.
*/
formatClientsForStanza()
{
@@ -118,7 +121,7 @@
{
let pData = { "Name": g_PlayerAssignments[guid].name };
- if (g_GameAttributes.settings.PlayerData[g_PlayerAssignments[guid].player - 1])
+ if (g_PlayerAssignments[guid].player <= g_NewGameSettings.playerCount.nbPlayers)
++connectedPlayers;
else
pData.Team = "observer";
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
@@ -2,29 +2,17 @@
* The GameSettingControl is an abstract class that is inherited by game-setting control classes specific to a GUI-object type,
* such as the GameSettingControlCheckbox or GameSettingControlDropdown.
*
- * These classes are abstract classes too and are implemented by each handler class specific to one logical setting of g_GameAttributes.
- * The purpose of these classes is to control precisely one logical setting of g_GameAttributes.
- * Having one class per logical setting allows to handle each setting without making a restriction as to how the property should be written to g_GameAttributes or g_PlayerAssignments.
+ * The purpose of these classes is to control one logical game setting.
* The base classes allow implementing that while avoiding duplication.
*
- * A GameSettingControl may depend on and read from other g_GameAttribute values,
- * but the class instance is to be the sole instance writing to its setting value in g_GameAttributes and
- * shall not write to setting values of other logical settings.
+ * GameSettingControl classes watch for g_newGameSettings property changes,
+ * and re-render accordingly. They also trigger changes in g_newGameSettings.
*
- * The derived classes shall not make assumptions on the validity of g_GameAttributes,
- * sanitize or delete their value if it is incompatible.
- *
- * A class should only write values to g_GameAttributes that it itself has confirmed to be accurate.
- * This means that handlers may not copy an entire object or array of values, for example on mapchange.
- * This avoids writing a setting value to g_GameAttributes that is not tracked and deleted when it becomes invalid.
- *
- * Since GameSettingControls shall be able to subscribe to g_GameAttributes changes,
- * it is an obligation of the derived GameSettingControl class to broadcast the GameAttributesChange event each time it changes g_GameAttributes.
+ * The GameSettingControl classes are responsible for triggering network synchronisation,
+ * and for updating the whole gamesetup layout when necessary.
*/
class GameSettingControl
{
- // The constructor and inherited constructors shall not modify game attributes,
- // since all GameSettingControl shall be able to subscribe to any game-setting change.
constructor(gameSettingControlManager, category, playerIndex, setupWindow)
{
// Store arguments
@@ -59,27 +47,12 @@
this.setHidden(false);
- if (this.onMapChange)
- this.gameSettingsControl.registerMapChangeHandler(this.onMapChange.bind(this));
-
if (this.onLoad)
this.setupWindow.registerLoadHandler(this.onLoad.bind(this));
- if (this.onGameAttributesChange)
- this.gameSettingsControl.registerGameAttributesChangeHandler(this.onGameAttributesChange.bind(this));
-
if (this.onGameAttributesBatchChange)
this.gameSettingsControl.registerGameAttributesBatchChangeHandler(this.onGameAttributesBatchChange.bind(this));
- 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));
-
if (this.onPlayerAssignmentsChange)
this.playerAssignmentsControl.registerPlayerAssignmentsChangeHandler(this.onPlayerAssignmentsChange.bind(this));
}
@@ -104,10 +77,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 +87,8 @@
{
this.hidden = hidden;
this.updateVisibility();
+ // Trigger a layout update to reposition items.
+ this.gameSettingsControl.updateGameAttributes();
}
updateVisibility()
@@ -126,8 +97,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
@@ -1,3 +1,9 @@
+/**
+ * Warning: this class handles more than most other GUI controls.
+ * Indeed, the logic of how to handle player assignments is here,
+ * as that is not really a GUI-agnostic concern
+ * (campaigns and other autostarting scripts should handle that themselves).
+ */
PlayerSettingControls.PlayerAssignment = class extends GameSettingControlDropdown
{
constructor(...args)
@@ -16,6 +22,10 @@
this.assignedGUID = undefined;
this.fixedAI = undefined;
+ g_NewGameSettings.playerAI.watch(() => this.render(), ["values"]);
+ g_NewGameSettings.playerCount.watch((_, oldNb) => this.OnPlayerNbChange(oldNb), ["nbPlayers"]);
+ this.render();
+
this.playerAssignmentsControl.registerClientJoinHandler(this.onClientJoin.bind(this));
}
@@ -29,6 +39,24 @@
{
if (!hotloadData && !g_IsNetworked)
this.onClientJoin("local", g_PlayerAssignments);
+ this.playerAssignmentsControl.updatePlayerAssignments();
+ this.OnPlayerNbChange(0);
+ }
+
+ OnPlayerNbChange(oldNb)
+ {
+ let isPlayerSlot = Object.values(g_PlayerAssignments).some(x => x.player === this.playerIndex + 1);
+ if (!isPlayerSlot && !g_NewGameSettings.playerAI.get(this.playerIndex) &&
+ this.playerIndex >= oldNb && this.playerIndex < g_NewGameSettings.playerCount.nbPlayers)
+ {
+ // Add AIs to unused slots by default.
+ // TODO: we could save the settings in case the player lowers, then re-raises the # of players.
+ g_NewGameSettings.playerAI.set(this.playerIndex, {
+ "bot": g_Settings.PlayerDefaults[this.playerIndex + 1].AI,
+ "difficulty": +Engine.ConfigDB_GetValue("user", "gui.gamesetup.aidifficulty"),
+ "behavior": Engine.ConfigDB_GetValue("user", "gui.gamesetup.aibehavior"),
+ });
+ }
}
onClientJoin(newGUID, newAssignments)
@@ -36,16 +64,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,13 +77,6 @@
if (newAssignments[guid].player == this.playerIndex + 1)
return;
- if (pData.AI)
- {
- pData.AI = false;
- this.gameSettingsControl.updateGameAttributes();
- this.gameSettingsControl.setNetworkGameAttributes();
- }
-
newAssignments[newGUID].player = this.playerIndex + 1;
this.playerAssignmentsControl.assignClient(newGUID, this.playerIndex + 1);
}
@@ -78,46 +95,25 @@
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)
- return;
-
- if (this.fixedAI && (pData.AI === undefined || pData.AI != this.fixedAI))
+ this.setEnabled(true);
+ if (this.assignedGUID)
{
- pData.AI = this.fixedAI;
- this.gameSettingsControl.updateGameAttributes();
- this.playerAssignmentsControl.unassignClient(this.playerIndex + 1);
+ this.setSelectedValue(this.assignedGUID);
+ return;
}
- }
-
- onGameAttributesBatchChange()
- {
- let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex);
- if (!pData)
+ let ai = g_NewGameSettings.playerAI.get(this.playerIndex);
+ if (ai)
+ {
+ 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 +126,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();
}
@@ -179,8 +175,21 @@
onSelectionChange(gameSettingsControl, playerAssignmentsControl, playerIndex, guidToAssign)
{
let sourcePlayer = g_PlayerAssignments[guidToAssign].player - 1;
+
+ let ai = g_NewGameSettings.playerAI.get(playerIndex);
+ let isPlayerSlot = Object.values(g_PlayerAssignments).some(x => x.player === playerIndex + 1);
+ if (ai)
+ // If the target was an AI, swap so AI settings are kept.
+ g_NewGameSettings.playerAI.swap(sourcePlayer, playerIndex);
+ else if (isPlayerSlot)
+ {
+ // If the target was a player, swap civ/color
+ g_NewGameSettings.playerCiv.swap(sourcePlayer, playerIndex);
+ g_NewGameSettings.playerColor.swap(sourcePlayer, playerIndex);
+ }
+
playerAssignmentsControl.assignPlayer(guidToAssign, playerIndex);
- gameSettingsControl.assignPlayer(sourcePlayer, playerIndex);
+ gameSettingsControl.setNetworkGameAttributes();
}
isSelected(pData, guid, value)
@@ -214,7 +223,11 @@
{
playerAssignmentsControl.unassignClient(playerIndex + 1);
- g_GameAttributes.settings.PlayerData[playerIndex].AI = value;
+ g_NewGameSettings.playerAI.set(playerIndex, {
+ "bot": value,
+ "difficulty": +Engine.ConfigDB_GetValue("user", "gui.gamesetup.aidifficulty"),
+ "behavior": Engine.ConfigDB_GetValue("user", "gui.gamesetup.aibehavior"),
+ });
gameSettingsControl.updateGameAttributes();
gameSettingsControl.setNetworkGameAttributes();
@@ -250,7 +263,8 @@
{
playerAssignmentsControl.unassignClient(playerIndex + 1);
- g_GameAttributes.settings.PlayerData[playerIndex].AI = false;
+ 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,10 @@
this.dropdown.tooltip = this.values && this.values.tooltip[this.dropdown.hovered] || this.Tooltip;
}
- onMapChange(mapData)
+ render()
{
- 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()
- {
- 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 +62,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,158 +15,29 @@
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)
- {
- if (g_GameAttributes.mapType != "scenario" && source && target)
- [source.Color, target.Color] = [target.Color, source.Color];
}
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,15 @@
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;
}
-}
+};
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
@@ -7,43 +7,10 @@
super(...args);
this.playerName = Engine.GetGUIObjectByName("playerName[" + this.playerIndex + "]");
+ g_NewGameSettings.playerCount.watch(() => this.render(), ["nbPlayers"]);
- this.displayedName = undefined;
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();
+ this.render();
}
onPlayerAssignmentsChange()
@@ -57,65 +24,24 @@
break;
}
- this.rebuild();
+ this.render();
}
- rebuild()
+ render()
{
- let name = this.displayedName;
- if (!name)
- return;
+ let name = this.guid ? g_PlayerAssignments[this.guid].name :
+ g_NewGameSettings.playerName.values[this.playerIndex];
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
+++ /dev/null
@@ -1,45 +0,0 @@
-// TODO: There should be a dialog allowing to specify starting resources and population capacity per player
-PlayerSettingControls.PlayerSettings = class extends GameSettingControl
-{
- onMapChange(mapData)
- {
- let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex);
- if (!pData)
- return;
-
- let mapPData = this.gameSettingsControl.getPlayerData(mapData, this.playerIndex);
- let isScenario = mapPData && g_GameAttributes.mapType == "scenario";
-
- if (isScenario && mapPData.Resources)
- pData.Resources = mapPData.Resources;
- else
- delete pData.Resources;
-
- if (isScenario && mapPData.PopulationLimit)
- pData.PopulationLimit = mapPData.PopulationLimit;
- else
- delete pData.PopulationLimit;
- }
-
- onGameAttributesFinalize()
- {
- // Copy map well known properties (and only well known properties)
- let mapData = this.mapCache.getMapData(g_GameAttributes.mapType, g_GameAttributes.map);
-
- let pData = this.gameSettingsControl.getPlayerData(g_GameAttributes, this.playerIndex);
- let mapPData = this.gameSettingsControl.getPlayerData(mapData, this.playerIndex);
- if (!pData || !mapPData)
- return;
-
- for (let property of this.MapSettings)
- if (mapPData[property] !== undefined)
- pData[property] = mapPData[property];
- }
-};
-
-PlayerSettingControls.PlayerSettings.prototype.MapSettings = [
- "StartingTechnologies",
- "DisabledTechnologies",
- "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,23 @@
GameSettingControls.Spies = class extends GameSettingControlCheckbox
{
- onMapChange(mapData)
+ constructor(...args)
{
- let mapValue;
- if (mapData &&
- mapData.settings &&
- mapData.settings.DisableSpies !== undefined)
- mapValue = mapData.settings.DisableSpies;
+ super(...args);
- 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();
- }
+ 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,50 @@
{
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)
- return;
+ this.setHidden(!g_NewGameSettings.biome.available.size);
- if (this.values)
- {
- if (this.values.Id.indexOf(g_GameAttributes.settings.Biome || undefined) == -1)
+ let values = prepareForDropdown([
{
- g_GameAttributes.settings.Biome = this.RandomBiomeId;
- this.gameSettingsControl.updateGameAttributes();
- }
+ "Title": setStringTags(this.RandomBiome, this.RandomItemTags),
+ "Id": "random"
+ },
+ ...g_NewGameSettings.biome.getAvailableBiomeData()
+ ]);
- let biomePreviewFile =
- basename(g_GameAttributes.map) + "_" +
- basename(g_GameAttributes.settings.Biome || "") + ".png";
+ this.dropdown.list = values.Title;
+ this.dropdown.list_data = values.Id;
- 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
- };
+ this.setSelectedValue(g_NewGameSettings.biome.biome);
}
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,34 @@
this.dropdown.tooltip = this.values.Description[this.dropdown.hovered] || this.Tooltip;
}
- onMapChange(mapData)
+ render()
{
- this.mapData = mapData;
+ this.setHidden(!g_NewGameSettings.landscape.data);
+ if (!g_NewGameSettings.landscape.data)
+ return;
- if (mapData && mapData.settings && mapData.settings.Landscapes)
+ let randomItems = [{
+ "Id": "random",
+ "Name": setStringTags(translateWithContext("landscape selection", "Random"), this.RandomItemTags),
+ "Description": translateWithContext("landscape selection", "Select a random landscape.")
+ }];
+ let data = g_NewGameSettings.landscape.data;
+ let items = [];
+ for (let group of 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
- });
-
+ let itemTag = this.translateItem(group);
+ itemTag.Name = setStringTags(itemTag.Name, this.RandomItemTags);
+ randomItems.push(itemTag);
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 +54,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 +69,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 +80,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,14 @@
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;
-
let values = prepareForDropdown(
this.mapFilters.getAvailableMapFilters(
- g_GameAttributes.mapType));
+ g_NewGameSettings.map.type));
if (values.Name.length)
{
@@ -53,14 +32,15 @@
else
this.values = undefined;
+ if (this.values && this.values.Name.indexOf(this.gameSettingsControl.guiData.mapFilter.filter) === -1)
+ {
+ this.gameSettingsControl.guiData.mapFilter.filter = this.values.Name[this.values.Default];
+ this.gameSettingsControl.setNetworkGameAttributes();
+ }
+ // Index may have changed, reset.
+ this.setSelectedValue(this.gameSettingsControl.guiData.mapFilter.filter);
+
this.setHidden(!this.values);
- Engine.ProfileStop();
- }
-
- onGameAttributesBatchChange()
- {
- if (this.values && g_GameAttributes.mapFilter)
- this.setSelectedValue(g_GameAttributes.mapFilter);
}
getAutocompleteEntries()
@@ -70,18 +50,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;
+ this.gameSettingsControl.guiData.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"]);
+
+ this.gameSettingsControl.guiData.mapFilter.watch(() => this.updateMapList(), ["filter"]);
this.randomItem = {
"file": this.RandomMapId,
@@ -21,51 +25,34 @@
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)
+ // Can happen with bad matchsettings
+ if (this.values.file.indexOf(g_NewGameSettings.map.map) === -1)
{
- g_GameAttributes.map = this.values.file[0];
- this.gameSettingsControl.updateGameAttributes();
+ g_NewGameSettings.map.selectMap(this.values.file[this.values.Default]);
+ return;
}
- }
-
- 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,
+ this.gameSettingsControl.guiData.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 +60,31 @@
this.dropdown.list = this.values.name;
this.dropdown.list_data = this.values.file;
+
+ g_NewGameSettings.map.setRandomOptions(this.values.file);
+
+ // Reset the selected map.
+ if (this.values.file.indexOf(g_NewGameSettings.map.map) === -1)
+ {
+ g_NewGameSettings.map.selectMap(this.values.file[this.values.Default]);
+ this.gameSettingsControl.setNetworkGameAttributes();
+ }
+ // The index may have changed: reset.
+ this.setSelectedValue(g_NewGameSettings.map.map);
+
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 +103,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
@@ -6,6 +6,9 @@
this.dropdown.list = g_MapSizes.Name;
this.dropdown.list_data = g_MapSizes.Tiles;
+
+ g_NewGameSettings.mapSize.watch(() => this.render(), ["size", "available"]);
+ this.render();
}
onHoverChange()
@@ -13,44 +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)
- return;
-
- 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()
@@ -60,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,17 @@
this.dropdown.list = g_MapTypes.Title;
this.dropdown.list_data = g_MapTypes.Name;
+
+ g_NewGameSettings.map.watch(() => this.render(), ["type"]);
+ this.render();
+ }
+
+ onLoad()
+ {
+ // Select a default map type if none are currently chosen.
+ // This in cascade will select a default filter and a default map.
+ if (!g_NewGameSettings.map.type)
+ g_NewGameSettings.map.setType(g_MapTypes.Name[g_MapTypes.Default]);
}
onHoverChange()
@@ -19,18 +30,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 +42,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
@@ -7,8 +7,11 @@
this.dropdown.list = g_StartingResources.Title;
this.dropdown.list_data = g_StartingResources.Resources;
- this.perPlayer = false;
this.sprintfArgs = {};
+
+ g_NewGameSettings.startingResources.watch(() => this.render(), ["resources"]);
+ g_NewGameSettings.map.watch(() => this.render(), ["type"]);
+ this.render();
}
onHoverChange()
@@ -22,47 +25,10 @@
this.dropdown.tooltip = tooltip;
}
- onMapChange(mapData)
+ render()
{
- let mapValue;
- if (mapData &&
- mapData.settings &&
- mapData.settings.StartingResources !== undefined)
- mapValue = mapData.settings.StartingResources;
-
- if (mapValue !== undefined && mapValue != g_GameAttributes.settings.StartingResources)
- {
- g_GameAttributes.settings.StartingResources = mapValue;
- this.gameSettingsControl.updateGameAttributes();
- }
-
- let isScenario = g_GameAttributes.mapType == "scenario";
-
- this.perPlayer =
- 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.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);
+ this.setEnabled(g_NewGameSettings.map.type != "scenario");
+ this.setSelectedValue(g_NewGameSettings.startingResources.resources);
}
getAutocompleteEntries()
@@ -72,8 +38,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();
}
};
@@ -87,7 +52,4 @@
GameSettingControls.StartingResources.prototype.HoverTooltip =
translate("Initial amount of each resource: %(resources)s.");
-GameSettingControls.StartingResources.prototype.PerPlayerCaption =
- translateWithContext("starting resources", "Per Player");
-
GameSettingControls.StartingResources.prototype.AutocompleteOrder = 0;
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/Buttons/ResetCivsButton.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/Buttons/ResetCivsButton.js
+++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/Buttons/ResetCivsButton.js
@@ -3,26 +3,23 @@
constructor(setupWindow)
{
this.gameSettingsControl = setupWindow.controls.gameSettingsControl;
- this.gameSettingsControl.registerGameAttributesBatchChangeHandler(this.onGameAttributesBatchChange.bind(this));
this.civResetButton = Engine.GetGUIObjectByName("civResetButton");
this.civResetButton.tooltip = this.Tooltip;
this.civResetButton.onPress = this.onPress.bind(this);
+
+ g_NewGameSettings.map.watch(() => this.render(), ["type"]);
}
- onGameAttributesBatchChange()
+ render()
{
- if (g_GameAttributes.mapType)
- this.civResetButton.hidden = g_GameAttributes.mapType == "scenario" || !g_IsController;
+ this.civResetButton.hidden = g_NewGameSettings.map.type == "scenario" || !g_IsController;
}
onPress()
{
- if (!g_GameAttributes.settings || !g_GameAttributes.settings.PlayerData)
- return;
-
- for (let pData of g_GameAttributes.settings.PlayerData)
- pData.Civ = this.RandomCivId;
+ for (let i = 0; i < g_NewGameSettings.playerCount.nbPlayers; ++i)
+ g_NewGameSettings.playerCiv.setValue(i, "random");
this.gameSettingsControl.updateGameAttributes();
this.gameSettingsControl.setNetworkGameAttributes();
@@ -31,6 +28,3 @@
ResetCivsButton.prototype.Tooltip =
translate("Reset any civilizations that have been selected to the default (random).");
-
-ResetCivsButton.prototype.RandomCivId =
- "random";
Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/Buttons/ResetTeamsButton.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/Buttons/ResetTeamsButton.js
+++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/Buttons/ResetTeamsButton.js
@@ -3,28 +3,23 @@
constructor(setupWindow)
{
this.gameSettingsControl = setupWindow.controls.gameSettingsControl;
- this.gameSettingsControl.registerGameAttributesBatchChangeHandler(this.onGameAttributesBatchChange.bind(this));
this.teamResetButton = Engine.GetGUIObjectByName("teamResetButton");
this.teamResetButton.tooltip = this.Tooltip;
this.teamResetButton.onPress = this.onPress.bind(this);
+
+ g_NewGameSettings.map.watch(() => this.render(), ["type"]);
}
- onGameAttributesBatchChange()
+ render()
{
- if (!g_GameAttributes.mapType)
- return;
-
- this.teamResetButton.hidden = g_GameAttributes.mapType == "scenario" || !g_IsController;
+ this.teamResetButton.hidden = g_NewGameSettings.map.type == "scenario" || !g_IsController;
}
onPress()
{
- if (!g_GameAttributes.settings || !g_GameAttributes.settings.PlayerData)
- return;
-
- for (let pData of g_GameAttributes.settings.PlayerData)
- pData.Team = -1;
+ for (let i = 0; i < g_NewGameSettings.playerCount.nbPlayers; ++i)
+ g_NewGameSettings.playerTeam.setValue(i, -1);
this.gameSettingsControl.updateGameAttributes();
this.gameSettingsControl.setNetworkGameAttributes();
Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/Chat/ChatMessages/ClientChat.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/Chat/ChatMessages/ClientChat.js
+++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/Chat/ChatMessages/ClientChat.js
@@ -30,7 +30,7 @@
let color = "white";
if (playerID > 0)
{
- color = g_GameAttributes.settings.PlayerData[playerID - 1].Color;
+ color = g_NewGameSettings.playerColor.values[playerID - 1];
// Enlighten playercolor to improve readability
let [h, s, l] = rgbToHsl(color.r, color.g, color.b);
Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/GameDescription.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/GameDescription.js
+++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/Panels/GameDescription.js
@@ -7,8 +7,32 @@
this.gameDescriptionFrame = Engine.GetGUIObjectByName("gameDescriptionFrame");
this.gameDescription = Engine.GetGUIObjectByName("gameDescription");
- setupWindow.controls.gameSettingsControl.registerGameAttributesBatchChangeHandler(this.onGameAttributesBatchChange.bind(this));
gameSettingTabs.registerTabsResizeHandler(this.onTabsResize.bind(this));
+ this.registerWatchers();
+ this.updateGameDescription();
+ }
+
+ registerWatchers()
+ {
+ let update = () => this.updateGameDescription();
+ g_NewGameSettings.biome.watch(update, ["biome"]);
+ g_NewGameSettings.ceasefire.watch(update, ["value"]);
+ g_NewGameSettings.cheats.watch(update, ["enabled"]);
+ g_NewGameSettings.disableTreasures.watch(update, ["enabled"]);
+ g_NewGameSettings.lastManStanding.watch(update, ["enabled"]);
+ g_NewGameSettings.lockedTeams.watch(update, ["enabled"]);
+ g_NewGameSettings.map.watch(update, ["map", "type"]);
+ g_NewGameSettings.mapExploration.watch(update, ["explored"]);
+ g_NewGameSettings.mapExploration.watch(update, ["revealed"]);
+ g_NewGameSettings.nomad.watch(update, ["enabled"]);
+ g_NewGameSettings.population.watch(update, ["perPlayer", "cap", "useWorldPop"]);
+ g_NewGameSettings.rating.watch(update, ["enabled"]);
+ g_NewGameSettings.regicideGarrison.watch(update, ["enabled"]);
+ g_NewGameSettings.relic.watch(update, ["count", "duration"]);
+ g_NewGameSettings.startingResources.watch(update, ["perPlayer", "resources"]);
+ g_NewGameSettings.triggerDifficulty.watch(update, ["value"]);
+ g_NewGameSettings.victoryConditions.watch(update, ["active"]);
+ g_NewGameSettings.wonder.watch(update, ["duration"]);
}
onTabsResize(settingsTabButtonsFrame)
@@ -18,7 +42,7 @@
this.gameDescriptionFrame.size = size;
}
- onGameAttributesBatchChange()
+ updateGameDescription()
{
this.gameDescription.caption = getGameDescription(this.mapCache);
}
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
@@ -7,18 +7,20 @@
this.gameSettingWarning = Engine.GetGUIObjectByName("gameSettingWarning");
- setupWindow.controls.gameSettingsControl.registerGameAttributesBatchChangeHandler(this.onGameAttributesBatchChange.bind(this));
cancelButton.registerCancelButtonResizeHandler(this.onCancelButtonResize.bind(this));
+
+ g_NewGameSettings.cheats.watch(() => this.onSettingsChange(), ["enabled"]);
+ g_NewGameSettings.rating.watch(() => this.onSettingsChange(), ["enabled"]);
}
- onGameAttributesBatchChange()
+ onSettingsChange()
{
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
@@ -11,8 +11,10 @@
this.mapPreview.onMouseLeftPress = this.onPress.bind(this); // TODO: Why does onPress not work? CGUI.cpp seems to support it
this.mapPreview.tooltip = this.Tooltip;
- 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"]);
}
onPress()
@@ -20,26 +22,45 @@
this.setupWindow.pages.MapBrowserPage.openPage();
}
- onMapChange(mapData)
+ getPreviewForSubtype(basepath, subtype)
{
- let preview = mapData && mapData.settings && mapData.settings.Preview;
- if (!g_GameAttributes.settings.Preview || g_GameAttributes.settings.Preview != preview)
+ if (!subtype)
+ return undefined;
+ let substr = subtype.substr(subtype.lastIndexOf("/") + 1);
+ let path = basepath + "_" + substr + ".png";
+ if (this.mapCache.previewExists(path))
+ return this.mapCache.getMapPreview(g_NewGameSettings.map.type,
+ g_NewGameSettings.map.map, path);
+ return undefined;
+ }
+
+ getLandscapePreview()
+ {
+ let filename = g_NewGameSettings.landscape.getPreviewFilename();
+ if (!filename)
+ return undefined;
+ return this.mapCache.getMapPreview(g_NewGameSettings.map.type,
+ g_NewGameSettings.map.map, filename);
+ }
+
+ render()
+ {
+ if (!g_NewGameSettings.map.map)
{
- g_GameAttributes.settings.Preview = preview;
- this.gameSettingsControl.updateGameAttributes();
- }
- }
-
- onGameAttributesBatchChange()
- {
- if (!g_GameAttributes.map || !g_GameAttributes.mapType)
+ this.mapInfoName.caption = translate("No selected map");
+ this.mapPreview.sprite = this.mapCache.getMapPreview();
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));
+ let mapPath = basename(g_NewGameSettings.map.map);
this.mapPreview.sprite =
- this.mapCache.getMapPreview(g_GameAttributes.mapType, g_GameAttributes.map, g_GameAttributes);
+ this.getPreviewForSubtype(mapPath, g_NewGameSettings.biome.biome) ||
+ this.getLandscapePreview() ||
+ this.getPreviewForSubtype(mapPath, g_NewGameSettings.daytime.value) ||
+ this.mapCache.getMapPreview(g_NewGameSettings.map.type, g_NewGameSettings.map.map);
}
}
Index: binaries/data/mods/public/gui/gamesetup/Pages/MapBrowserPage/MapBrowserPage.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/Pages/MapBrowserPage/MapBrowserPage.js
+++ binaries/data/mods/public/gui/gamesetup/Pages/MapBrowserPage/MapBrowserPage.js
@@ -4,12 +4,38 @@
{
super(setupWindow.controls.mapCache, setupWindow.controls.mapFilters, setupWindow);
this.mapBrowserPage.hidden = true;
+
+ this.gameSettingsControl = setupWindow.controls.gameSettingsControl;
+ }
+
+ onSubmitMapSelection(map, type, filter)
+ {
+ if (!g_IsController)
+ return;
+
+ if (type)
+ g_NewGameSettings.map.setType(type);
+
+ if (filter)
+ this.gameSettingsControl.guiData.mapFilter.filter = filter;
+
+ if (map)
+ g_NewGameSettings.map.selectMap(map);
+
+ this.gameSettingsControl.setNetworkGameAttributes();
}
openPage()
{
super.openPage();
+ this.controls.MapFiltering.select(
+ this.gameSettingsControl.guiData.mapFilter.filter,
+ g_NewGameSettings.map.type || g_MapTypes.Name[g_MapTypes.Default]
+ );
+ if (g_NewGameSettings.map.map)
+ this.gridBrowser.select(g_NewGameSettings.map.map);
+
this.mapBrowserPage.hidden = false;
}
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
@@ -25,7 +25,7 @@
/**
* Central data storing all settings relevant to the map generation and simulation.
*/
-var g_GameAttributes = {};
+var g_NewGameSettings = new GameSettings();
/**
* Remembers which clients are assigned to which player slots and whether they are ready.
@@ -42,6 +42,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
@@ -3,10 +3,13 @@
+
+
+