Changeset View
Standalone View
binaries/data/mods/public/maps/tutorials/starting_economy_walkthrough.js
- This file was added.
Property | Old Value | New Value |
---|---|---|
svn:eol-style | null | native \ No newline at end of property |
let goals = [ | |||||
{ | |||||
elexis: I really like the architecture of this file, invites to contribute! | |||||
"instructions": markForTranslation("This tutorial will teach you how to develop your economy. You usually start with a bunch of units and a civic center at the 'Village Phase' and your goal is to make your empire develop, evolving to 'Town Phase' and then 'City Phase'.\nSelect your building, the civic center, by clicking on it. Its selection ring will be highlighted with the color of your civilization."), | |||||
}, | |||||
Not Done Inline ActionsThat + there splits the string and will make string extraction fail. leper: That + there splits the string and will make string extraction fail. | |||||
Not Done Inline Actionsok. I will replace it by only (long) string for each paragraph, and adding a new markForTranslation for each paragraph. mimo: ok. I will replace it by only (long) string for each paragraph, and adding a new… | |||||
Not Done Inline ActionsIf you have multiple markForTranslation calls that are concatenated in this file it will break actually displaying translated messages, as the string passed to the gui will not be found, as only a prefix of it is actually translated. I am aware that having such long strings is somewhat ugly, but that is the only thing we can actually use without rewriting lots of unrelated code. leper: If you have multiple `markForTranslation` calls that are concatenated in this file it will… | |||||
{ | |||||
"instructions": markForTranslation("The civic center production panel appears on the bottom right, with icons representing the different options: a grey icon means that the corresponding item is not yet available and a red icon means that you don't have enough resources for it. You can hover the mouse over the icons to see what is needed in both cases.\nThe top line displays the units that can be trained in this building, while the bottom line displays the technologies that can be researched. Hover your mouse over the icon II of the bottom line: the tooltip will indicate that we have to build some structures and we need food and wood resources to go to 'Town Phase'."), | |||||
}, | |||||
{ | |||||
Not Done Inline Actions"Hover your mouse over" seems more natural than "pass the mouse over". scythetwirler: "Hover your mouse over" seems more natural than "pass the mouse over". | |||||
"instructions": markForTranslation("This tutorial will show you how to gather resources and build structures. But first, you can toggle between full screen and windowed mode using Alt+Enter. Pick the setting that you feel more comfortable with.\n"), | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("At this point, Food and Wood are the most important resources for expanding your civilization, so let's get started with food gathering. Females have higher food gathering rates on fields and berries than men, thus select all of them and then right-click on the grapes (just near your civic center, on the south-east) when you see a fruit cursor.\nTo select the females, you can either select them at once with the mouse (which will select all units inside the selection rectangle) or click on one of them and then add the other ones by shift-clicking each of them or double-click on one of them (which will select all visible units of the same kind): try these 3 ways before tasking them to gather the grapes. Selected units are highlighted by a ring in the player color ring highlighted, and you can click on an empty point to reset the selection."), | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type == "gather" && msg.cmd.target && | |||||
Not Done Inline ActionsWhy does this start with a \n? leper: Why does this start with a `\n`? | |||||
Not Done Inline Actionsyes, should rather be at the end of the previous comment. mimo: yes, should rather be at the end of the previous comment. | |||||
TriggerHelper.GetResourceType(msg.cmd.target).specific == "fruit") | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Let's now gather some wood with your citizen soldiers; Select them and right-click on the nearest tree, you should see a tree cursor."), | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type == "gather" && msg.cmd.target && | |||||
TriggerHelper.GetResourceType(msg.cmd.target).specific == "tree") | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Cavalry are good for hunting. You can start targeting chicken. Select your cavalry and right-click on some chiken when you see a meat cursor."), | |||||
scythetwirlerUnsubmitted Not Done Inline Actionschiken -> chicken. scythetwirler: chiken -> chicken.
when you see a meat cursor -> "Your cursor will turn into a meat icon when… | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type == "gather" && msg.cmd.target && | |||||
TriggerHelper.GetResourceType(msg.cmd.target).specific == "meat") | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("All your units are now gathering resources. It is time to learn how to produce more units.\nBut first, let's see how to set a rally-point to automatically designate a task upon completion of training. We want to send the newly trained units to gather wood on the group of trees to the south of the civic center. To do so, select the civic center by clicking on it and then right-click on one of the trees.\nRally-Points are indicated by a small flag at the end of the blue line."), | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type != "set-rallypoint" || !msg.cmd.data || | |||||
!msg.cmd.data.command || msg.cmd.data.command != "gather" || | |||||
!msg.cmd.data.resourceType || msg.cmd.data.resourceType.specific != "tree") | |||||
{ | |||||
this.WarningMessage(markForTranslation("Select the civic center, then pass the mouse over the tree and Right-click when you see a wood icon.")); | |||||
return; | |||||
} | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Now that the rally-point is setup, we can produce a few additional units.\nAs soldiers are better than females at wood gathering, select the civic center and shift-click on the second unit icon, the hoplites (shift-clicking allows to produce a batch of five units)."), | |||||
"OnTrainingQueued": function(msg) | |||||
{ | |||||
if (msg.unitTemplate != "units/athen_infantry_spearman_b" || +msg.count == 1) | |||||
{ | |||||
let entity = msg.trainerEntity; | |||||
let cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); | |||||
cmpProductionQueue.ResetQueue(); | |||||
let txt = +msg.count == 1 ? | |||||
markForTranslation("Do not forget to shift-click to produce several units.") : | |||||
markForTranslation("Shift-click on the HOPLITE icon."); | |||||
this.WarningMessage(txt); | |||||
return; | |||||
} | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Let's wait for the units to be trained.\nWhile waiting, look at the top panel: you see there your amount of resources, and see them increase when a worker brings them back to the civic center. That's an important concept to keep in mind: gathered resources have to be brought back to a dropsite to be accounted, and your should always try to minimize the distance to improve your gathering rate."), | |||||
"OnTrainingFinished": function(msg) | |||||
{ | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("The new units automatically go to the trees and start gathering wood.\nBut as they have to bring it back to the civic center to deposit it, their gathering rate suffer from the distance. To fix that, we can build a storehouse close to the trees. To do so, select your five new soldiers and look for the construction panel on the bottom right, then click on the storehouse icon, move the mouse as near as possible to the trees you want to collect and click on a valid place to build the dropsite.\nInvalid (obstructed) positions are indicated in red."), | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type == "construct" && msg.cmd.template == "structures/athen_storehouse") | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("As soon as the foundation is placed, the builders start its construction."), | |||||
"OnStructureBuilt": function(msg) | |||||
{ | |||||
let cmpResourceDropsite = Engine.QueryInterface(msg.building, IID_ResourceDropsite); | |||||
if (cmpResourceDropsite && cmpResourceDropsite.AcceptsType("wood")) | |||||
this.NextGoal(); | |||||
}, | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("And when the construction finishes, the units automatically switch to wood gathering.\nLet's train some females workers to gather more food. Select the civic center and shift-click on the female icon."), | |||||
"OnTrainingQueued": function(msg) | |||||
{ | |||||
if (msg.unitTemplate != "units/athen_support_female_citizen" || +msg.count == 1) | |||||
{ | |||||
let entity = msg.trainerEntity; | |||||
let cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); | |||||
cmpProductionQueue.ResetQueue(); | |||||
let txt = +msg.count == 1 ? | |||||
markForTranslation("Do not forget to shift-click to produce several units.") : | |||||
markForTranslation("Shift-click on the HOPLITE icon."); | |||||
this.WarningMessage(txt); | |||||
return; | |||||
} | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Let's wait for the units to be trained.\nIn the meantime, as we don't want to send them gathering wood, we should remove the current rally-point of the civic center. For that purpose, right-click on the civic center when it is selected (and the flag icon indicating the rally-point is crossed)."), | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type == "unset-rallypoint") | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("The units should be ready soon now.\nIn the meantime, let's have a look at your population count on the top panel (the fifth item, after the resources). You should always keep an eye on it. It indicates your current population (including those being trained) and the limit allowed."), | |||||
"OnTrainingFinished": function(msg) | |||||
{ | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Now that the units are ready, let's build two houses.\nIndeed, as you have nearly reached the population limit, you must increase it by building some new structures if you want to train more units. The one with a good ratio of additional population over cost and which is available already in the first phase is the house."), | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Select two of your newly created women and ask them to build these houses in the empty space on the east of the civic center. For that purpose, 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). You may need to click on an empty space to get rid of the house cursor.\nReminder: to select only two females, click on the first one and then shift-click on the second one to add it to the selection."), | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type == "construct" && msg.cmd.template == "structures/athen_house" && | |||||
++this.count == 2) | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Now we will see how to build fields which produce an unlimited food resource.\nBut to minimize the path done by our farmers to bring back the food to a dropsite, we will first build a farm."), | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Select the three remaining (idle) women and ask them to build a farmstead in the center of the large open area in the west of the civic center.\nWe will need room around to build fields and, in addition, we can see some goats on the west side so having a food dropsite not far will be useful.\nIf you try to select the three idle women by grabing them, there is a high chance that one additional gatherers are included in your selection rectangle. To prevent that, press the 'i' key while grabing: only idle units are then selected. And if during your grabing you select the cavalry which may now be idle, you can remove it by pressing the control key while clicking on its icon in the selection panel (bottom centre)."), | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type == "construct" && msg.cmd.template == "structures/athen_farmstead") | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("When the farmstead will be built, its builders will automatically look for food around, going 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."), | |||||
"OnStructureBuilt": function(msg) | |||||
{ | |||||
if (TriggerHelper.EntityHasClass(msg.building, "House") && ++this.count == 2) | |||||
this.NextGoal(); | |||||
}, | |||||
}, | |||||
{ | |||||
"name": "buildField", | |||||
"instructions": markForTranslation("When both houses are built, select your two females and ask them to build a field as close as possible to the farmstead (farms are a dropsite for all food)."), | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type == "construct" && msg.cmd.template == "structures/athen_field") | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("When the field is built, the builders will automatically start gathering it.\nThe cavalry should have slaughtered all chicken by now. Select it and right-click on one of the goats in the west to start slaughtering them."), | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type == "gather" && msg.cmd.target && | |||||
TriggerHelper.GetResourceType(msg.cmd.target).specific == "meat") | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("A field can have up to five farmers working on it. To add some new one, select again the civic center and setup a rally-point on a field by right-clicking on it. As long as the field is not yet build, new workers sent by a rally-point will help building it, while they will gather it when built."), | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type != "set-rallypoint" || !msg.cmd.data || !msg.cmd.data.command || | |||||
msg.cmd.data.command != "build" || !msg.cmd.data.target || | |||||
!TriggerHelper.EntityHasClass(msg.cmd.data.target, "Field")) | |||||
{ | |||||
this.WarningMessage(markForTranslation("Select the civic center and right-click on the field.")); | |||||
return; | |||||
} | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Now click three times on the female icon in the bottom right panel to train three additional farmers."), | |||||
"OnTrainingQueued": function(msg) | |||||
{ | |||||
if (msg.unitTemplate != "units/athen_support_female_citizen" || +msg.count != 1) | |||||
{ | |||||
let entity = msg.trainerEntity; | |||||
let cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); | |||||
cmpProductionQueue.ResetQueue(); | |||||
let txt = +msg.count == 1 ? | |||||
markForTranslation("Do a simple click to produce only one unit.") : | |||||
markForTranslation("Click on the FEMALE icon."); | |||||
this.WarningMessage(txt); | |||||
return; | |||||
} | |||||
if (++this.count < 3) | |||||
return; | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("You can increase the gather rates of your workers by researching new technologies available in some buildings.\n" + | |||||
"The farming rate for example can be improved in the farmstead. Select it and look at its production panel on the bottom right. You see there several researchable technologies. Pass the mouse over them to see what their costs and effects are and click on the one you want to research."), | |||||
"OnResearchQueued": function(msg) | |||||
{ | |||||
if (msg.technologyTemplate && TriggerHelper.EntityHasClass(msg.researcherEntity, "Farmstead")) | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Select again the civic center and pass the mouse over the 'Town Phase' icon to see what is still needed.\nWe now have enough resources, but one structure is missing. Although this is an economic tutorial, it is nonetheless useful to be prepared for defense in case of attack, so let's build barracks.\nSelect four of your soldiers and ask them to build one barracks: as before, start selecting the soldiers, click on the barracks icon in the production panel and then click in an empty space not far from your civic center where you want to build."), | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type == "construct" && msg.cmd.template == "structures/athen_barracks") | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Let's wait for the barracks to be built. As this construction is lengthy, you can add two soldiers to build it faster. To do so, select again your civic center, setup a rally-point on the barracks foundation by right-clicking on it (you should see a hammer icon), and then produce two more builders by clicking twice on the hoplite icon."), | |||||
"OnStructureBuilt": function(msg) | |||||
{ | |||||
if (TriggerHelper.EntityHasClass(msg.building, "Barracks")) | |||||
this.NextGoal(); | |||||
}, | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("You should now be able to go to 'Town Phase'. Select the civic center and click on the tech icon."), | |||||
"OnResearchQueued": function(msg) | |||||
{ | |||||
if (msg.technologyTemplate && TriggerHelper.EntityHasClass(msg.researcherEntity, "CivilCentre")) | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("In later phase, you need usually stone and metal to build bigger structures and train better soldiers. So while waiting for the research to be done, you will send half of your idle soldiers (those having built the barracks) to gather rock and the other half to gather metal.\nSo we could select two of them and click on the rock mine on the west of the civic center (a stone cursor is shown when you pass the mouse over it while your soldiers are selected). But remember these soldiers were gathering wood, so they may still carry some wood which would be lost when starting to gather something else."), | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("Thus we will ask them to deposit their wood in the civic center along the way. For that, we will queue orders with shift-click: select your soldiers, shift-click on the civic center to deposit their wood and then shift-click on the stone mine to gather it.\nFinally same thing with the remaining soldiers and the metal mine: select the remaining idle soldiers, shift-click on the civic center and then shift-click on the metal mine also on the west."), | |||||
"OnPlayerCommand": function(msg) | |||||
{ | |||||
if (msg.cmd.type == "gather" && msg.cmd.target && | |||||
TriggerHelper.GetResourceType(msg.cmd.target).generic == "stone" && | |||||
++this.count == 3) | |||||
this.NextGoal(); | |||||
if (msg.cmd.type == "gather" && msg.cmd.target && | |||||
TriggerHelper.GetResourceType(msg.cmd.target).generic == "metal" && | |||||
++this.count == 3) | |||||
this.NextGoal(); | |||||
}, | |||||
"OnResearchFinished": function(msg) | |||||
{ | |||||
if (msg.tech == "phase_town_athen" && ++this.count == 3) | |||||
this.NextGoal(); | |||||
} | |||||
}, | |||||
{ | |||||
"instructions": markForTranslation("This is the end of the walkthrough. This should give you a good idea of how to start up a nice economy rapidly.") | |||||
} | |||||
]; | |||||
Trigger.prototype.goals = goals; | |||||
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); | |||||
Not Done Inline ActionsSame here, why is this part of the prototype instead of just being a normal member? leper: Same here, why is this part of the prototype instead of just being a normal member? | |||||
cmpTrigger.RegisterTrigger("OnInitGame", "InitTutorial", { "enabled": true }); | |||||
Not Done Inline Actions(Note to myself: D195) elexis: (Note to myself: D195) |
I really like the architecture of this file, invites to contribute!