Changeset View
Standalone View
binaries/data/mods/public/gui/campaign/simple_campaign/mainmenu.js
- This file was added.
var g_SelectedLevel; | |||||
elexis: Good that campaigns can come with custom GUi pages.
Maybe simple -> default.
Interface ->… | |||||
wraitiiAuthorUnsubmitted Not Done Inline ActionsI'm not sure we want the list interface to be the default one. I had an AOE-2 like campaign map in mind for the default. wraitii: I'm not sure we want the list interface to be the default one. I had an AOE-2 like campaign map… | |||||
Not Done Inline Actionsvar g_SelectedLevel; since the linter complains about = undefined being unneeded. (null has a use case once its meaning differs from the default undefined.) elexis: `var g_SelectedLevel;` since the linter complains about `= undefined` being unneeded. (`null`… | |||||
var g_SavedGamesMetadata = []; | |||||
function init(data) | |||||
{ | |||||
if (!data) | |||||
{ | |||||
warn("Loading campaign menu without a campaign loaded"); | |||||
return; | |||||
} | |||||
g_CampaignID = data.ID; | |||||
g_CampaignTemplate = data.template; | |||||
g_CampaignSaveFilename = data.save; | |||||
g_CampaignState = data.data; | |||||
generateLevelList(); | |||||
selectionChanged(); | |||||
Engine.GetGUIObjectByName("mapPreview").sprite = "cropped:" + 400/512 + "," + 300/512 + ":session/icons/mappreview/nopreview.png"; | |||||
elexisUnsubmitted Not Done Inline ActionssetMapPreviewImage elexis: setMapPreviewImage | |||||
let gameSelection = Engine.GetGUIObjectByName("gameSelection"); | |||||
let savedGames = Engine.GetSavedGames().sort(sortDecreasingDate).filter(game => game.metadata.initAttributes && game.metadata.initAttributes.campaignData && game.metadata.initAttributes.campaignData.ID == g_CampaignID); | |||||
gameSelection.enabled = !!savedGames.length; | |||||
if (!savedGames.length) | |||||
{ | |||||
gameSelection.list = [translate("No saved games found")]; | |||||
gameSelection.selected = -1; | |||||
return; | |||||
} | |||||
// Get current game version and loaded mods | |||||
let engineInfo = Engine.GetEngineInfo(); | |||||
g_SavedGamesMetadata = savedGames.map(game => game.metadata); | |||||
gameSelection.list = savedGames.map(game => generateCampaignLabel(game.metadata, engineInfo)); | |||||
gameSelection.list_data = savedGames.map(game => game.id); | |||||
saveSelectionChanged(); | |||||
} | |||||
function generateLevelList() | |||||
{ | |||||
let selection = Engine.GetGUIObjectByName("levelSelection"); | |||||
let list = []; | |||||
for (let key in g_CampaignTemplate.Levels) | |||||
{ | |||||
let level = g_CampaignTemplate.Levels[key]; | |||||
if (!("ShowUnavailable" in g_CampaignTemplate) || !g_CampaignTemplate.ShowUnavailable && !meetsRequirements(level)) | |||||
continue; | |||||
let status = ""; | |||||
let name = level.Name; | |||||
if (!meetsRequirements(level)) | |||||
{ | |||||
status = translate("not unlocked yet"); | |||||
name = "[color=\"gray\"]" + name + "[/color]"; | |||||
elexisUnsubmitted Not Done Inline ActionssetStringTags(caption, { "color": "gray" }) elexis: `setStringTags(caption, { "color": "gray" })` | |||||
} | |||||
Done Inline Actionstranslate elexis: translate | |||||
list.push({ "ID": key, "name": name, "status": status }); | |||||
} | |||||
list.sort((a, b) => g_CampaignTemplate.Order.indexOf(a.ID) - g_CampaignTemplate.Order.indexOf(b.ID)); | |||||
list = prepareForDropdown(list); | |||||
selection.selected = -1; | |||||
selection.list_name = list.name || []; | |||||
selection.list_status = list.status || []; | |||||
// These must be changed last or things crash. | |||||
selection.list = list.ID || []; | |||||
selection.list_data = list.ID || []; | |||||
} | |||||
function displayLevelDetails(levelID) | |||||
Done Inline Actionslist and list_data come from the inherited CList whereas the other list_column name ones come from COList. elexis: list and list_data come from the inherited CList whereas the other list_column name ones come… | |||||
{ | |||||
let level = g_CampaignTemplate.Levels[levelID]; | |||||
Engine.GetGUIObjectByName("scenarioName").caption = translate(level.Name); | |||||
Engine.GetGUIObjectByName("scenarioDesc").caption = translate(level.Description); | |||||
setMapPreviewImage("mapPreview", level.Preview); | |||||
Done Inline Actionsforgot that setMapPreviewImage fallbacks on its own. wraitii: forgot that setMapPreviewImage fallbacks on its own. | |||||
g_SelectedLevel = levelID; | |||||
if (!meetsRequirements(level)) | |||||
{ | |||||
Engine.GetGUIObjectByName("startButton").enabled = false; | |||||
return; | |||||
} | |||||
Engine.GetGUIObjectByName("startButton").enabled = true; | |||||
elexisUnsubmitted Not Done Inline ActionsEngine.GetGUIObjectByName("startButton").enabled = meetsRequirements(level); elexis: Engine.GetGUIObjectByName("startButton").enabled = meetsRequirements(level); | |||||
} | |||||
function selectionChanged() | |||||
{ | |||||
let selection = Engine.GetGUIObjectByName("levelSelection"); | |||||
if (selection.selected === -1) | |||||
{ | |||||
Engine.GetGUIObjectByName("startButton").enabled = false; | |||||
Engine.GetGUIObjectByName("startButton").hidden = false; | |||||
Engine.GetGUIObjectByName("loadSavedButton").hidden = true; | |||||
return; | |||||
} | |||||
Engine.GetGUIObjectByName("loadSavedButton").hidden = true; | |||||
Engine.GetGUIObjectByName("startButton").hidden = false; | |||||
elexisUnsubmitted Not Done Inline Actionssame as above elexis: same as above | |||||
let selec = Engine.GetGUIObjectByName("gameSelection"); | |||||
selec.selected = -1; | |||||
elexisUnsubmitted Not Done Inline Actionslet gameSelection = Engine.GetGUIObjectByName("gameSelection"); (makes it easier to keep track of GUIObjects if the variable names correlate with the GUIObject names globally) elexis: let gameSelection = Engine.GetGUIObjectByName("gameSelection"); (makes it easier to keep track… | |||||
displayLevelDetails(selection.list[selection.selected]); | |||||
} | |||||
function saveSelectionChanged() | |||||
{ | |||||
let metadata = g_SavedGamesMetadata[Engine.GetGUIObjectByName("gameSelection").selected]; | |||||
if (!metadata) | |||||
return; | |||||
// fetch campaign scenario metadata if present. | |||||
let scenarioID = metadata.initAttributes.campaignData.level; | |||||
let selection = Engine.GetGUIObjectByName("levelSelection"); | |||||
selection.selected = -1; | |||||
for (let level of selection.list_data) | |||||
if (level == scenarioID) | |||||
{ | |||||
displayLevelDetails(level); | |||||
break; | |||||
} | |||||
elexisUnsubmitted Not Done Inline ActionsWould have proposed Array function find, but why does it loop at all? elexis: Would have proposed Array function `find`, but why does it loop at all? | |||||
Engine.GetGUIObjectByName("loadSavedButton").hidden = false; | |||||
Engine.GetGUIObjectByName("startButton").hidden = true; | |||||
} | |||||
function generateCampaignLabel(metadata, engineInfo) | |||||
{ | |||||
let dateTimeString = Engine.FormatMillisecondsIntoDateStringLocal(metadata.time*1000, translate("yyyy-MM-dd HH:mm:ss")); | |||||
elexisUnsubmitted Not Done Inline ActionsgenerateSavegameDateString to avoid duplication that is patched by some temple diff elexis: `generateSavegameDateString` to avoid duplication that is patched by some temple diff | |||||
let dateString = sprintf(translate("\\[%(date)s]"), { "date": dateTimeString }); | |||||
if (engineInfo) | |||||
{ | |||||
if (!isCompatibleSavegame(metadata, engineInfo) || !hasSameEngineVersion(metadata, engineInfo)) | |||||
dateString = "[color=\"red\"]" + dateString + "[/color]"; | |||||
else if (!hasSameMods(metadata, engineInfo)) | |||||
dateString = "[color=\"orange\"]" + dateString + "[/color]"; | |||||
elexisUnsubmitted Not Done Inline ActionsShould be red as well. (Also in the future we should not just state theyre incompatible but provide an auto-launch of the needed mods if they exist) elexis: Should be red as well. (Also in the future we should not just state theyre incompatible but… | |||||
} | |||||
return sprintf( | |||||
Done Inline Actionsdelete, can be beautified later elexis: delete, can be beautified later | |||||
metadata.description ? | |||||
translate("%(dateString)s %(level)s - %(description)s") : | |||||
translate("%(dateString)s %(level)s"), | |||||
{ | |||||
"dateString": dateString, | |||||
"level": metadata.initAttributes.campaignData.template.Levels[metadata.initAttributes.campaignData.level].Name, | |||||
"description": metadata.description || "" | |||||
} | |||||
); | |||||
elexisUnsubmitted Not Done Inline ActionsgenerateSavegameLabel. (Reveals a bit how the patch was written) elexis: `generateSavegameLabel`. (Reveals a bit how the patch was written) | |||||
} | |||||
function exitCampaignMode(exitGame = false) | |||||
{ | |||||
saveCurrentCampaign(); | |||||
if (exitGame) | |||||
{ | |||||
messageBox( | |||||
400, 200, | |||||
translate("Are you sure you want to quit 0 A.D.?"), | |||||
elexisUnsubmitted Not Done Inline ActionsApplication exit is in the main menu, not in every menu elexis: Application exit is in the main menu, not in every menu | |||||
translate("Confirmation"), | |||||
[translate("No"), translate("Yes")], | |||||
[null, Engine.Exit] | |||||
); | |||||
return; | |||||
} | |||||
Engine.SwitchGuiPage("page_pregame.xml", {}); | |||||
} | |||||
function startSelectedLevel() | |||||
{ | |||||
Engine.SwitchGuiPage("page_gamesetup.xml", { | |||||
"type": "offline", | |||||
elexisUnsubmitted Not Done Inline Actionstype was removed recently. Going through the gamesetup is healthy as it avoids 10 gamesetup rewrites. elexis: `type` was removed recently.
Going through the gamesetup is healthy as it avoids 10 gamesetup… | |||||
"autostart": g_CampaignTemplate.Levels[g_SelectedLevel].Map, | |||||
"campaignData": { | |||||
"ID": g_CampaignID, | |||||
"template": g_CampaignTemplate, | |||||
"save": g_CampaignSaveFilename, | |||||
"data": g_CampaignState, | |||||
"level": g_SelectedLevel | |||||
} | |||||
}); | |||||
} | |||||
Not Done Inline ActionsIt's a design question when to save things. Not sure if saving should be enforced in some cases, it sounds better to only save the campaign state when requested by the user. elexis: It's a design question when to save things. Not sure if saving should be enforced in some cases… | |||||
Not Done Inline ActionsA dialog asking whether the player would like to save would be nice; though just always saving works just as well for the simple interface. leper: A dialog asking whether the player would like to save would be nice; though just always saving… | |||||
Not Done Inline Actionsrephrase the TODO comment then elexis: rephrase the TODO comment then |
Good that campaigns can come with custom GUi pages.
Maybe simple -> default.
Interface -> GUIPage?