Index: binaries/data/mods/public/campaigns/new_maps.json
===================================================================
--- binaries/data/mods/public/campaigns/new_maps.json
+++ binaries/data/mods/public/campaigns/new_maps.json
@@ -123,5 +123,6 @@
"syria_2p",
"white_cliffs_of_dover_5p"
],
- "ShowUnavailable": true
+ "ShowUnavailable": true,
+ "Difficulty": "PerLevel"
}
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
@@ -12,6 +12,8 @@
this.run = campaignRun;
+ this.difficulty = new CampaignDifficulty(this.run);
+
this.selectedLevel = -1;
this.levelSelection = Engine.GetGUIObjectByName("levelSelection");
this.levelSelection.onSelectionChange = () => { this.selectedLevel = this.levelSelection.selected; };
@@ -28,14 +30,25 @@
this._ready = true;
}
- goBackToMainMenu()
+ saveRun()
{
+ if (this.difficulty.isPerLevel())
+ this.difficulty.serialize();
this.run.save();
+ }
+
+ goBackToMainMenu()
+ {
+ this.saveRun();
Engine.SwitchGuiPage("page_pregame.xml", {});
}
startScenario()
{
+ // Save some settings
+ if (this.difficulty.isPerLevel())
+ this.saveRun();
+
const level = this.getSelectedLevelData();
if (!meetsRequirements(this.run, level))
return;
@@ -69,7 +82,7 @@
{
const bot = {
"bot": g_Settings.PlayerDefaults[i + 1].AI,
- "difficulty": +Engine.ConfigDB_GetValue("user", "gui.gamesetup.aidifficulty"),
+ "difficulty": this.difficulty.getAIDifficulty(),
"behavior": Engine.ConfigDB_GetValue("user", "gui.gamesetup.aibehavior"),
};
if (typeof level.AI === "string")
@@ -78,6 +91,17 @@
}
}
+ const triggerDiffs = gameSettings.triggerDifficulty.getAvailableSettings();
+ if (triggerDiffs.length)
+ {
+ const diff = this.difficulty.getTriggerDifficulty();
+ if (triggerDiffs.filter(x => x.Difficulty === diff).length > 0)
+ gameSettings.triggerDifficulty.setValue(diff);
+ else
+ // TODO: should match closest, ideally.
+ gameSettings.triggerDifficulty.setValue(triggerDiffs.find(x => x.Default).Difficulty);
+ }
+
if (level.Preview)
gameSettings.mapPreview.setCustom("cropped:" + 400/512 + "," + 300/512 + ":" + level.Preview);
gameSettings.mapName.set(this.getLevelName(level));
@@ -163,6 +187,16 @@
displayLevelDetails()
{
+ // Render the difficulty & adjust the size of the description box if needed.
+ const scenarioInfoSize = Engine.GetGUIObjectByName("scenarioInfoBox").size;
+
+ const diffObject = this.difficulty.render();
+ if (diffObject.hidden)
+ scenarioInfoSize.bottom = 0;
+ else
+ scenarioInfoSize.bottom = Engine.GetGUIObjectByName("campaignSettings").size.top;
+ Engine.GetGUIObjectByName("scenarioInfoBox").size = scenarioInfoSize;
+
if (this.selectedLevel === -1)
{
Engine.GetGUIObjectByName("startButton").enabled = false;
@@ -170,11 +204,11 @@
return;
}
- let level = this.getSelectedLevelData();
+ const level = this.getSelectedLevelData();
Engine.GetGUIObjectByName("scenarioName").caption = this.getLevelName(level);
Engine.GetGUIObjectByName("scenarioDesc").caption = this.getLevelDescription(level);
- Engine.GetGUIObjectByName('levelPreviewBox').sprite = this.getLevelPreview(level);
+ Engine.GetGUIObjectByName("levelPreviewBox").sprite = this.getLevelPreview(level);
Engine.GetGUIObjectByName("startButton").enabled = meetsRequirements(this.run, level);
Engine.GetGUIObjectByName("startButton").hidden = false;
Index: binaries/data/mods/public/gui/campaigns/default_menu/CampaignMenu.xml
===================================================================
--- binaries/data/mods/public/gui/campaigns/default_menu/CampaignMenu.xml
+++ binaries/data/mods/public/gui/campaigns/default_menu/CampaignMenu.xml
@@ -40,7 +40,7 @@
-
+
+
+
+
+
+
+
+
Index: binaries/data/mods/public/gui/campaigns/default_menu/Difficulty.js
===================================================================
--- /dev/null
+++ binaries/data/mods/public/gui/campaigns/default_menu/Difficulty.js
@@ -0,0 +1,89 @@
+/**
+ * Split off for easier moddability - combines AI & trigger difficulties.
+ */
+var g_CampaignDifficulties = [
+ {
+ "name": "Very easy",
+ "aidiff": 1,
+ "triggerdiff": 1
+ },
+ {
+ "name": "Easy",
+ "aidiff": 2,
+ "triggerdiff": 2
+ },
+ {
+ "name": "Medium",
+ "aidiff": 3,
+ "triggerdiff": 3
+ },
+ {
+ "name": "Hard",
+ "aidiff": 4,
+ "triggerdiff": 4
+ },
+ {
+ "name": "Very hard",
+ "aidiff": 5,
+ "triggerdiff": 5
+ }
+];
+
+class CampaignDifficulty
+{
+ constructor(run)
+ {
+ this.run = run;
+ this.perLevel = this.run.template?.Difficulty === "PerLevel";
+
+ this.difficulty = this.run?.data?.difficulty ?? 2; // Defaults to 'Medium'.
+
+ this.object = Engine.GetGUIObjectByName("perLevelDifficulty");
+ this.label = Engine.GetGUIObjectByName("perLevelDifficultyLabel");
+ this.input = Engine.GetGUIObjectByName("perLevelDifficultyInput");
+
+ this.input.onSelectionChange = () => {
+ this.difficulty = this.input.selected;
+ };
+ }
+
+ isPerLevel()
+ {
+ return this.perLevel;
+ }
+
+ serialize()
+ {
+ this.run.data.difficulty = this.difficulty;
+ }
+
+ getAIDifficulty()
+ {
+ if (this.input.selected !== -1)
+ return g_CampaignDifficulties[this.input.list_data[this.input.selected]].aidiff;
+ return 3; // Defaults to medium.
+ }
+
+ getTriggerDifficulty()
+ {
+ if (this.input.selected !== -1)
+ return g_CampaignDifficulties[this.input.list_data[this.input.selected]].triggerdiff;
+ return 3; // Defaults to medium.
+ }
+
+ render()
+ {
+ if (!this.isPerLevel())
+ {
+ this.object.hidden = true;
+ return this.object;
+ }
+ this.object.hidden = false;
+ this.label.caption = translate("Difficulty");
+ this.input.list = g_CampaignDifficulties.map(x => x.name);
+ this.input.list_data = g_CampaignDifficulties.map((_, i) => i);
+ if (this.input.selected === -1 && this.difficulty < this.input.list.length)
+ this.input.selected = this.difficulty;
+ return this.object;
+ }
+}
Index: binaries/data/mods/public/gui/gamesettings/attributes/TriggerDifficulty.js
===================================================================
--- binaries/data/mods/public/gui/gamesettings/attributes/TriggerDifficulty.js
+++ binaries/data/mods/public/gui/gamesettings/attributes/TriggerDifficulty.js
@@ -22,7 +22,7 @@
getAvailableSettings()
{
- return this.difficulties.filter(x => this.available.indexOf(x.Name) !== -1);
+ return this.difficulties.filter(x => this.available && this.available.indexOf(x.Name) !== -1);
}
onMapChange()
@@ -40,6 +40,7 @@
setValue(val)
{
+ // TODO: should probably validate that they fit one of the known schemes.
this.value = val;
}