1
0
forked from 0ad/0ad

Allow switching to the gamesetup from the campaign screen

This allows switching to the gamesetup, with a harcoded map, from the
campaign screen. Lets player sets up a few things (e.g. their civ &
favorite AI), which can be convenient for some simple campaigns that
lack options.

Differential Revision: https://code.wildfiregames.com/D4039
This was SVN commit r25636.
This commit is contained in:
wraitii 2021-06-02 17:37:29 +00:00
parent 48ea6ee7d2
commit c012888e2a
8 changed files with 154 additions and 30 deletions

View File

@ -36,11 +36,11 @@ class CampaignMenu extends AutoWatcher
startScenario()
{
let level = this.getSelectedLevelData();
const level = this.getSelectedLevelData();
if (!meetsRequirements(this.run, level))
return;
let settings = {
const settings = {
"mapType": level.MapType,
"map": "maps/" + level.Map,
"settings": {
@ -52,20 +52,44 @@ class CampaignMenu extends AutoWatcher
"data": this.run.data
}
};
let assignments = {
const assignments = {
"local": {
"player": 1,
"name": Engine.ConfigDB_GetValue("user", "playername.singleplayer") || Engine.GetSystemUsername()
}
};
let gameSettings = new GameSettings().init();
const gameSettings = new GameSettings().init();
gameSettings.fromInitAttributes(settings);
if (level.Preview)
gameSettings.mapPreview.setCustom("cropped:" + 400/512 + "," + 300/512 + ":" + level.Preview);
gameSettings.mapName.set(this.getLevelName(level));
// TODO: level description should also be passed, ideally.
if (level.useGameSetup)
{
// Setup some default AI on the non-human players.
for (let i = 1; i < gameSettings.playerCount.nbPlayers; ++i)
gameSettings.playerAI.set(i, {
"bot": g_Settings.PlayerDefaults[i + 1].AI,
"difficulty": +Engine.ConfigDB_GetValue("user", "gui.gamesetup.aidifficulty"),
"behavior": Engine.ConfigDB_GetValue("user", "gui.gamesetup.aibehavior"),
});
const attributes = gameSettings.toInitAttributes();
attributes.guiData = {
"lockSettings": {
"map": true,
},
};
Engine.SwitchGuiPage("page_gamesetup.xml", {
"gameSettings": attributes,
});
return;
}
gameSettings.launchGame(assignments);
Engine.SwitchGuiPage("page_loading.xml", {
"attribs": gameSettings.toInitAttributes(),

View File

@ -23,6 +23,7 @@ class GameSettingsController
this.updateLayoutHandlers = new Set();
this.settingsChangeHandlers = new Set();
this.loadingChangeHandlers = new Set();
this.settingsLoadedHandlers = new Set();
setupWindow.registerLoadHandler(this.onLoad.bind(this));
setupWindow.registerGetHotloadDataHandler(this.onGetHotloadData.bind(this));
@ -66,23 +67,35 @@ class GameSettingsController
this.loadingChangeHandlers.add(handler);
}
/**
* @param handler will be called when the initial settings have been loaded.
*/
registerSettingsLoadedHandler(handler)
{
this.settingsLoadedHandlers.add(handler);
}
onLoad(initData, hotloadData)
{
if (hotloadData)
this.parseSettings(hotloadData.initAttributes);
else if (g_IsController && this.persistentMatchSettings.enabled)
else if (g_IsController && (initData?.gameSettings || this.persistentMatchSettings.enabled))
{
let settings = this.persistentMatchSettings.loadFile();
// Allow opting-in to persistence when sending initial data (though default off)
if (initData?.gameSettings)
this.persistentMatchSettings.enabled = !!initData.gameSettings?.usePersistence;
const settings = initData?.gameSettings || this.persistentMatchSettings.loadFile();
if (settings)
{
this.parseSettings(settings);
// If the new settings led to AI & players conflict, remove the AI.
for (let guid in g_PlayerAssignments)
if (g_PlayerAssignments[guid].player !== -1 &&
g_GameSettings.playerAI.get(g_PlayerAssignments[guid].player - 1))
g_GameSettings.playerAI.set(g_PlayerAssignments[guid].player - 1, undefined);
}
}
// If the new settings led to AI & players conflict, remove the AI.
for (const guid in g_PlayerAssignments)
if (g_PlayerAssignments[guid].player !== -1 &&
g_GameSettings.playerAI.get(g_PlayerAssignments[guid].player - 1))
g_GameSettings.playerAI.set(g_PlayerAssignments[guid].player - 1, undefined);
for (const handler of this.settingsLoadedHandlers)
handler();
this.updateLayout();
this.setNetworkInitAttributes();

View File

@ -8,6 +8,10 @@ class GameSettingsGuiData
{
this.mapFilter = new Observable();
this.mapFilter.filter = "default";
// Mark some settings as unmodifiable even if they normally would be.
// TODO: increase support for this feature.
this.lockSettings = {};
}
/**
@ -15,14 +19,17 @@ class GameSettingsGuiData
*/
Serialize()
{
let ret = {
"mapFilter": this.mapFilter.filter,
const ret = {
"mapFilter": this.mapFilter.filter
};
if (Object.keys(this.lockSettings).length)
ret.lockSettings = this.lockSettings;
return ret;
}
Deserialize(data)
{
this.mapFilter.filter = data.mapFilter;
this.lockSettings = data?.lockSettings || {};
}
}

View File

@ -50,6 +50,9 @@ class GameSettingControl /* extends Profilable /* Uncomment to profile controls
if (this.onLoad)
this.setupWindow.registerLoadHandler(this.onLoad.bind(this));
if (this.onSettingsLoaded)
this.gameSettingsController.registerSettingsLoadedHandler(this.onSettingsLoaded.bind(this));
if (this.onPlayerAssignmentsChange)
this.playerAssignmentsController.registerPlayerAssignmentsChangeHandler(this.onPlayerAssignmentsChange.bind(this));
}

View File

@ -8,6 +8,16 @@ GameSettingControls.MapBrowser = class MapBrowser extends GameSettingControlButt
Engine.SetGlobalHotkey(this.HotkeyConfig, "Press", this.onPress.bind(this));
}
onSettingsLoaded()
{
if (this.gameSettingsController.guiData.lockSettings?.map)
{
this.setEnabled(false);
this.setHidden(true);
return;
}
}
setControlHidden()
{
this.button.hidden = false;

View File

@ -6,8 +6,19 @@ GameSettingControls.MapFilter = class MapFilter extends GameSettingControlDropdo
this.values = undefined;
this.gameSettingsController.guiData.mapFilter.watch(() => this.render(), ["filter"]);
g_GameSettings.map.watch(() => this.checkMapTypeChange(), ["type"]);
}
onSettingsLoaded()
{
if (this.gameSettingsController.guiData.lockSettings?.map)
this.setEnabled(false);
else
{
this.gameSettingsController.guiData.mapFilter.watch(() => this.render(), ["filter"]);
g_GameSettings.map.watch(() => this.checkMapTypeChange(), ["type"]);
this.checkMapTypeChange();
}
this.render();
}
onHoverChange()
@ -43,6 +54,13 @@ GameSettingControls.MapFilter = class MapFilter extends GameSettingControlDropdo
render()
{
if (!this.enabled)
{
if (!this.hidden)
this.setHidden(true);
return;
}
// Index may have changed, reset.
this.setSelectedValue(this.gameSettingsController.guiData.mapFilter.filter);
this.setHidden(!this.values);

View File

@ -6,11 +6,6 @@ GameSettingControls.MapSelection = class MapSelection extends GameSettingControl
this.values = undefined;
g_GameSettings.map.watch(() => this.render(), ["map"]);
g_GameSettings.map.watch(() => this.updateMapList(), ["type"]);
this.gameSettingsController.guiData.mapFilter.watch(() => this.updateMapList(), ["filter"]);
this.randomItem = {
"file": this.RandomMapId,
"name": setStringTags(this.RandomMapCaption, this.RandomItemTags),
@ -18,6 +13,35 @@ GameSettingControls.MapSelection = class MapSelection extends GameSettingControl
};
}
onSettingsLoaded()
{
if (this.gameSettingsController.guiData.lockSettings?.map)
{
if (!g_GameSettings.map)
{
error("Map setting locked but no map is selected");
throw new Error();
}
this.setTitle(translate("Map"));
this.setEnabled(false);
// Watch only for map change.
g_GameSettings.map.watch(() => this.render(), ["map"]);
}
else
{
g_GameSettings.map.watch(() => this.render(), ["map"]);
g_GameSettings.map.watch(() => this.updateMapList(), ["type"]);
this.gameSettingsController.guiData.mapFilter.watch(() => this.updateMapList(), ["filter"]);
this.updateMapList();
}
this.render();
}
onHoverChange()
{
this.dropdown.tooltip = this.values.description[this.dropdown.hovered] || this.Tooltip;
@ -25,12 +49,23 @@ GameSettingControls.MapSelection = class MapSelection extends GameSettingControl
render()
{
// Can happen with bad matchsettings
if (!this.enabled)
{
const mapData = this.mapCache.getMapData(g_GameSettings.map.mapType, g_GameSettings.map.map);
this.label.caption = g_GameSettings.mapName.value || mapData.settings.Name;
return;
}
if (!this.values)
return;
// We can end up with incorrect map selection when dependent settings change.
if (this.values.file.indexOf(g_GameSettings.map.map) === -1)
{
g_GameSettings.map.selectMap(this.values.file[this.values.Default]);
return;
}
this.setSelectedValue(g_GameSettings.map.map);
}

View File

@ -13,16 +13,23 @@ GameSettingControls.MapType = class MapType extends GameSettingControlDropdown
this.dropdown.list = g_MapTypes.Title;
this.dropdown.list_data = g_MapTypes.Name;
g_GameSettings.map.watch(() => this.render(), ["type"]);
this.render();
}
onLoad()
onSettingsLoaded()
{
// Select a default map type if none are currently chosen.
// This in cascade will select a default filter and a default map.
if (!g_GameSettings.map.type)
g_GameSettings.map.setType(g_MapTypes.Name[g_MapTypes.Default]);
if (this.gameSettingsController.guiData.lockSettings?.map)
this.setEnabled(false);
else
{
g_GameSettings.map.watch(() => this.render(), ["type"]);
// Select a default map type if none are currently chosen.
// This in cascade will select a default filter and a default map.
if (!g_GameSettings.map.type)
g_GameSettings.map.setType(g_MapTypes.Name[g_MapTypes.Default]);
}
this.render();
}
onHoverChange()
@ -32,6 +39,13 @@ GameSettingControls.MapType = class MapType extends GameSettingControlDropdown
render()
{
if (!this.enabled)
{
if (!this.hidden)
this.setHidden(true);
return;
}
this.setSelectedValue(g_GameSettings.map.type);
}