Index: binaries/data/mods/public/maps/scripts/Tutorial.js =================================================================== --- binaries/data/mods/public/maps/scripts/Tutorial.js +++ binaries/data/mods/public/maps/scripts/Tutorial.js @@ -3,6 +3,7 @@ this.count = 0; this.index = 0; this.fullText = ""; + this.foundations = []; // Used to follow the constructions required this.tutorialEvents = []; // Register needed triggers @@ -16,6 +17,8 @@ { if (typeof goal[key] !== "function" || this.tutorialEvents.indexOf(key) != -1) continue; + if (key === "IsDone") + continue; let action = key + "Trigger"; this.RegisterTrigger(key, action, { "enabled": false }); this.tutorialEvents.push(key); @@ -32,10 +35,14 @@ let goal = this.tutorialGoals[this.index]; let needDelay = true; let readyButton = false; + + Trigger.prototype.IsDone = goal.IsDone ? goal.IsDone : () => false; + let goalAlreadyDone = this.IsDone(); + for (let event of this.tutorialEvents) { let action = event + "Trigger"; - if (goal[event]) + if (!goalAlreadyDone && goal[event]) { Trigger.prototype[action] = goal[event]; this.EnableTrigger(event, action); @@ -54,7 +61,7 @@ { this.EnableTrigger("OnPlayerCommand", "OnPlayerCommandTrigger"); Trigger.prototype.OnPlayerCommandTrigger = function(msg) - { + { if (msg.cmd.type == "dialog-answer" && msg.cmd.tutorial && msg.cmd.tutorial == "ready") this.NextGoal(); }; Index: binaries/data/mods/public/maps/tutorials/starting_economy_walkthrough.js =================================================================== --- binaries/data/mods/public/maps/tutorials/starting_economy_walkthrough.js +++ binaries/data/mods/public/maps/tutorials/starting_economy_walkthrough.js @@ -122,10 +122,21 @@ { if (msg.cmd.type == "unset-rallypoint") this.NextGoal(); + }, + "OnTrainingFinished": function(msg) + { + this.nextGoalDone = true; } }, { "instructions": markForTranslation("The units should be ready soon.\nIn the meantime, direct your attention to your population count on the top panel. It is the fifth item from the left, after the resources. It would be prudent to keep an eye on it. It indicates your current population (including those being trained) and the current population limit, which is determined by your built structures."), + "IsDone": function(msg) + { + if (!this.nextGoalDone) + return false; + this.nextGoalDone = false; + return true; + }, "OnTrainingFinished": function(msg) { this.NextGoal(); @@ -138,8 +149,10 @@ "instructions": markForTranslation("Select two of your newly trained Female Citizens and ask them to build these houses in the empty space to the east of the Civic Center. To do so, after selecting the Female Citizens, click on the house icon in the bottom right panel and shift-click on the position in the map where you want to build the first house followed by a shift-click on the position of the second house (when giving orders, shift-click put the order in the queue and the units will automatically switch to the next order in their queue when they finish their work). Press Escape to get rid of the house cursor so you don't spam houses all over the map.\nReminder: to select only two Female Citizens, click on the first one and then shift-click on the second one to add her to the selection."), "OnPlayerCommand": function(msg) { - if (msg.cmd.type == "construct" && msg.cmd.template == "structures/athen_house" && - ++this.count == 2) + if (msg.cmd.type == "repair" && msg.cmd.target && Engine.QueryInterface(+msg.cmd.target, IID_Foundation) && + TriggerHelper.EntityHasClass(+msg.cmd.target, "House")) + this.foundations.push(+msg.cmd.target); + if (this.foundations.filter(e => TriggerHelper.EntityHasClass(e, "House")).length > 1) this.NextGoal(); } }, @@ -156,11 +169,18 @@ }, { "instructions": markForTranslation("When the farmstead construction is finished, its builders will automatically look for food, and in this case, they will go after the nearby goats.\nBut your house builders will only look for something else to build and, if nothing found, become idle. Let's wait for them to build the houses."), + "IsDone": function() + { + return !this.foundations.filter(e => TriggerHelper.EntityHasClass(e, "House")).length; + }, "OnStructureBuilt": function(msg) { - if (TriggerHelper.EntityHasClass(msg.building, "House") && ++this.count == 2) + // We need to remove this foundation as it will be effectively destroyed only on the next turn + if (this.foundations.indexOf(+msg.from) != -1) + this.foundations.splice(this.foundations.indexOf(+msg.from), 1); + if (this.IsDone()) this.NextGoal(); - }, + } }, { "name": "buildField", @@ -172,7 +192,7 @@ } }, { - "instructions": markForTranslation("When the field is constructed, the builders will automatically start gathering it.\nThe cavalry unit should have slaughtered all chicken by now. Select it and right-click on one of the goats in the west to start hunting them for food."), + "instructions": markForTranslation("When the field is constructed, the builders will automatically start gathering it.\nThe cavalry unit should have slaughtered all chicken by now. Select it and explore the south-west area: there is a lake with some camels around. Move your cavalry by right-clicking on the point you want to go, and when you see a herd of camels, right-click on one of to start hunting for food."), "OnPlayerCommand": function(msg) { if (msg.cmd.type == "gather" && msg.cmd.target && @@ -203,8 +223,8 @@ let entity = msg.trainerEntity; let cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); cmpProductionQueue.ResetQueue(); - let txt = +msg.count == 1 ? - markForTranslation("Do a simple left-click to produce a single unit.") : + let txt = +msg.count != 1 ? + markForTranslation("Do not shift-click to produce a single unit.") : markForTranslation("Click on the FEMALE CITIZEN icon."); this.WarningMessage(txt); return; Index: binaries/data/mods/public/simulation/components/Trigger.js =================================================================== --- binaries/data/mods/public/simulation/components/Trigger.js +++ binaries/data/mods/public/simulation/components/Trigger.js @@ -229,7 +229,7 @@ Trigger.prototype.OnGlobalConstructionFinished = function(msg) { - this.CallEvent("StructureBuilt", { "building": msg.newentity }); + this.CallEvent("StructureBuilt", { "building": msg.newentity, "from": msg.entity }); }; Trigger.prototype.OnGlobalTrainingFinished = function(msg)