diff --git a/art/textures/ui/campaigns/grand_strategy/art/banner.png b/art/textures/ui/campaigns/grand_strategy/art/banner.png new file mode 100644 index 0000000..1a13e76 Binary files /dev/null and b/art/textures/ui/campaigns/grand_strategy/art/banner.png differ diff --git a/gui/campaigns/grand_strategy/game/GameData.js b/gui/campaigns/grand_strategy/game/GameData.js index 58a11a1..b9295aa 100644 --- a/gui/campaigns/grand_strategy/game/GameData.js +++ b/gui/campaigns/grand_strategy/game/GameData.js @@ -11,6 +11,8 @@ class GameData this.provinces = {}; this.tribes = {}; + this.difficulty = "medium"; + this.playerTribe = undefined; this.playerHero = undefined; @@ -45,6 +47,7 @@ class GameData "turn": this.turn, "playerTribe": this.playerTribe, "playerHero": this.playerHero.Serialize(), + "difficulty": this.difficulty, "tribes": tribes, "provinces": pv, "events": pastEvents @@ -71,6 +74,9 @@ class GameData this.playerHero = new Hero(); this.playerHero.Deserialize(data.playerHero); + if (data.difficulty) + this.difficulty = data.difficulty; + this.pastTurnEvents = []; for (const evs of data.events) { @@ -87,10 +93,10 @@ class GameData this.turnEvents = this.pastTurnEvents[this.pastTurnEvents.length - 1]; } - static createNewGame(playerData) + static createNewGame(playerData, difficulty) { g_GameData = new GameData(); - g_GameData.initialiseGame(playerData); + g_GameData.initialiseGame(playerData, difficulty); return g_GameData; } @@ -118,7 +124,7 @@ class GameData CampaignRun.getCurrentRun().save(); } - initialiseGame(playerData) + initialiseGame(playerData, difficulty) { this.parseHistory(); @@ -144,6 +150,8 @@ class GameData this.provinces[prov].setOwner(code); } + this.difficulty = difficulty; + this.save(); } @@ -228,7 +236,7 @@ class GameData let aiID = 1 - playerID; gameSettings.playerAI.set(aiID, { "bot": "petra", - "difficulty": playerIsAttacker ? province.garrison / 2 : 5 - province.garrison / 2, + "difficulty": this.getAIDifficulty(province.garrison, playerIsAttacker), "behavior": "random", }); gameSettings.playerCiv.setValue(0, this.tribes[attackerTribe].civ); @@ -253,6 +261,13 @@ class GameData }); } + getAIDifficulty(garrison, playerIsAttacker) + { + const max = this.difficulty === "easy" ? 2 : this.difficulty == "medium" ? 4 : 5; + const min = this.difficulty === "easy" ? 0 : this.difficulty == "medium" ? 2 : 3; + return Math.max(min, Math.min(max, playerIsAttacker ? min + garrison : max - garrison)); + } + changeGarrison(provinceCode, delta) { this.provinces[provinceCode].garrison = Math.max(0, Math.min(10, @@ -301,11 +316,16 @@ class GameData let tribe = this.tribes[code]; let targets = new Set(); for (let prov of tribe.controlledProvinces) - for (let pot of g_GameData.provinces[prov].getLinks()) + { + const pv = g_GameData.provinces[prov]; + if (pv.garrison < 2) + pv.garrison++; + for (let pot of pv.getLinks()) { - if (g_GameData.provinces[pot].ownerTribe !== code) + if (pv.ownerTribe !== code) targets.add(pot); } + } if (randBool(0.5) && targets.size) { diff --git a/gui/campaigns/grand_strategy/init/InitPage.js b/gui/campaigns/grand_strategy/init/InitPage.js index b4ab59d..b2d91aa 100644 --- a/gui/campaigns/grand_strategy/init/InitPage.js +++ b/gui/campaigns/grand_strategy/init/InitPage.js @@ -15,7 +15,7 @@ class InitPage desc += "\nWelcome to 0 A.D.'s Grand Strategy campaign, where you will take control of a country through the eyes of a Hero character. Fortify your lands, conquer your neighbors, and lead your civilization to victory."; Engine.GetGUIObjectByName("campaignDescription").caption = desc; - Engine.GetGUIObjectByName("campaignImage").sprite = "color:0 0 0"; + Engine.GetGUIObjectByName("campaignImage").sprite = "stretched:campaigns/grand_strategy/art/banner.png"; Engine.GetGUIObjectByName("playerSettings").caption = "Customize your civilization"; @@ -47,6 +47,13 @@ class InitPage this.difficultySelect.list = ["Easy", "Medium", "Hard"]; this.difficultySelect.list_data = ["easy", "medium", "hard"]; this.difficultySelect.selected = 0; + this.difficultySelect.onHoverChange = () => { + this.difficultySelect.tooltip = [ + "AI players will range from Sandbox to Easy difficulty", + "AI players will range from Easy to Hard difficulty", + "AI players will range from Medium to Very Hard difficulty", + ]?.[this.difficultySelect.hovered] ?? ""; + }; this.customHeroName = false; this.customTribeName = false; @@ -141,10 +148,11 @@ class InitPage "width": 450, "height": 200, "title": "Start Campaign?", - "message": sprintf("You have chosen to start a campaign as the %(tribe)s of the %(civ)s.\nConfirm?", + "message": sprintf("You have chosen to start a campaign as a %(civ)s tribe called the ā€œ%(tribe)sā€, in %(prov)s.\nConfirm?", { "tribe": this.tribeName.caption, "civ": this.civSelect.list[this.civSelect.selected], + "prov": this.provinceSelect.list[this.provinceSelect.selected], }), "buttonCaptions": ["No", "Yes"], }, @@ -155,10 +163,12 @@ class InitPage { // Writes g_GameData GameData.createNewGame({ - "civ": this.civSelect.list_data[this.civSelect.selected], - "tribeName": this.tribeName.caption, - "startProvince": this.provinceSelect.list_data[this.provinceSelect.selected], - }); + "civ": this.civSelect.list_data[this.civSelect.selected], + "tribeName": this.tribeName.caption, + "startProvince": this.provinceSelect.list_data[this.provinceSelect.selected], + }, + this.difficultySelect.list_data[this.difficultySelect.selected] + ); Engine.SwitchGuiPage("campaigns/grand_strategy/page.xml", { "filename": CampaignRun.getCurrentRunFilename() });