1-- RST
2-- worker_help.lua
3-- ---------------
4--
5-- This script returns a formatted entry for the ingame worker help.
6-- Pass the internal tribe name and worker name to the coroutine to select the
7-- worker type.
8
9include "tribes/scripting/help/format_help.lua"
10
11--  =======================================================
12--  ************* Main worker help functions *************
13--  =======================================================
14
15-- RST
16-- .. function:: worker_help_producers_string(worker_description)
17--
18--    Displays the buildings that can produce the worker
19--
20--    :arg tribe: the worker's tribe from C++.
21--    :arg worker_description: the worker_description from C++.
22--    :returns: Info about buildings that produce this worker
23--
24function worker_help_producers_string(tribe, worker_description)
25   local result = ""
26   for i, building in ipairs(tribe.buildings) do
27      if (building.type_name == "productionsite") then
28         local recruits_this = false;
29         for j, output in ipairs(building.output_worker_types) do
30            if (output.name == worker_description.name) then
31               recruits_this = true;
32               break;
33            end
34         end
35
36         if (recruits_this) then
37            -- TRANSLATORS: Worker Encyclopedia: A building recruiting a worker
38            result = result .. h2(_"Producer")
39            result = result .. dependencies({building, worker_description}, building.descname)
40
41            -- Find out which programs in the building recruit this worker if any
42            local producing_programs = {}
43            for j, program_name in ipairs(building.production_programs) do
44               for worker, amount in pairs(building:recruited_workers(program_name)) do
45                  if (worker_description.name == worker) then
46                     table.insert(producing_programs, program_name)
47                  end
48               end
49            end
50
51            -- Now collect all workers recruited by the filtered programs
52            local recruited_workers_strings = {}
53            local recruited_workers_counters = {}
54            for j, program_name in ipairs(producing_programs) do
55               local recruited_workers_amount = {}
56               recruited_workers_counters[program_name] = 0
57               for worker, amount in pairs(building:recruited_workers(program_name)) do
58                  if (recruited_workers_amount[worker] == nil) then
59                     recruited_workers_amount[worker] = 0
60                  end
61                  recruited_workers_amount[worker] = recruited_workers_amount[worker] + amount
62                  recruited_workers_counters[program_name] = recruited_workers_counters[program_name] + amount
63               end
64               local produced_wares_string = ""
65               for ware, amount in pairs(recruited_workers_amount) do
66               local ware_descr = wl.Game():get_worker_description(ware)
67                  produced_wares_string = produced_wares_string
68                     .. help_ware_amount_line(ware_descr, amount)
69               end
70               recruited_workers_strings[program_name] = produced_wares_string
71            end
72
73            -- Now collect the consumed wares for each filtered program and print the program info
74            for j, program_name in ipairs(producing_programs) do
75               result = result .. help_consumed_wares_workers(tribe, building, program_name)
76               if (recruited_workers_counters[program_name] > 0) then
77                  if (recruited_workers_counters[program_name] == 1) then
78                     -- TRANSLATORS: Worker Encyclopedia: 1 worker recruited by a productionsite
79                     result = result .. h3(_"Worker recruited:")
80                  else
81                     -- TRANSLATORS: Worker Encyclopedia: More than 1 worker recruited by a productionsite
82                     result = result .. h3(_"Workers recruited:")
83                  end
84                  result = result .. recruited_workers_strings[program_name]
85               end
86            end
87         end
88      end
89   end
90   return result
91end
92
93
94-- RST
95-- .. function:: worker_help_employers_string(worker_description)
96--
97--    Displays the buildings where the worker can work
98--
99--    :arg worker_description: the worker_description from C++.
100--    :returns: Info about buildings that use this worker
101--
102function worker_help_employers_string(worker_description)
103   local result = ""
104
105   if (#worker_description.employers > 0) then
106      local normal = {}
107      local additional = {}
108
109      if (#worker_description.employers == 1) then
110      -- TRANSLATORS: Worker Encyclopedia: Heading for 1 building where a worker can work
111      -- TRANSLATORS: You can also translate this as 'workplace'
112         result = result .. h2(pgettext("workerhelp_one_building", "Works at"))
113      else
114      -- TRANSLATORS: Worker Encyclopedia: A list of more than 1 building where a worker can work
115      -- TRANSLATORS: You can also translate this as 'workplaces'
116         result = result .. h2(pgettext("workerhelp_multiple_buildings", "Works at"))
117      end
118      for i, building in ipairs(worker_description.employers) do
119         result = result .. dependencies({worker_description, building}, building.descname)
120         normal[building.descname] = true
121      end
122      building = worker_description.employers[1]
123         if #building.working_positions > 1 and worker_description.name ~= building.working_positions[1].name then
124            for i, build in ipairs(building.working_positions[1].employers) do
125               if not normal[build.descname] then
126                  table.insert(additional, build)
127               end
128            end
129            if #additional == 1 then
130               -- Translators: Worker Encyclopedia: Heading above a list 1 building where a worker may work instead of a less experienced worker
131               -- TRANSLATORS: You can also translate this as 'additional workplace'
132               result = result .. h2(pgettext("workerhelp_one_building", "Can also work at"))
133            else
134               -- Translators: Worker Encyclopedia: Heading above a list of buildings where a worker may work instead of a less experienced worker
135               -- TRANSLATORS: You can also translate this as 'additional workplaces'
136               result = result .. h2(pgettext("workerhelp_multiple_buildings", "Can also work at"))
137            end
138            for i, build in ipairs(additional) do
139               result = result .. dependencies({worker_description, build}, build.descname)
140            end
141         end
142   end
143   return result
144end
145
146
147-- RST
148-- .. function:: worker_help_string(worker_description)
149--
150--    Displays the worker with a helptext, an image and the tool used
151--
152--    :arg tribe: The :class:`LuaTribeDescription` for the tribe
153--                that we are displaying this help for.
154
155--    :arg worker_description: the worker_description from C++.
156--
157--    :returns: Help string for the worker
158--
159function worker_help_string(tribe, worker_description)
160   include(worker_description.helptext_script)
161
162   local result = h2(_"Purpose") ..
163      li_image(worker_description.icon_name, worker_helptext())
164
165   if (worker_description.buildable) then
166      -- Get the tools for the workers.
167      local toolnames = {}
168      for j, buildcost in ipairs(worker_description.buildcost) do
169         if (buildcost ~= nil and tribe:has_ware(buildcost)) then
170            toolnames[#toolnames + 1] = buildcost
171         end
172      end
173
174      if (#toolnames > 0) then
175         local tool_string = help_tool_string(tribe, toolnames, 1)
176         -- TRANSLATORS: Tribal Encyclopedia: Heading for which tool a worker uses
177         result = result .. h2(_"Worker uses") .. tool_string
178      end
179   else
180      result = result .. worker_help_producers_string(tribe, worker_description)
181   end
182
183   result = result .. worker_help_employers_string(worker_description)
184
185   -- TODO(GunChleoc): Add "enhanced from" info in one_tribe branch
186   local becomes_description = worker_description.becomes
187   if (becomes_description) then
188
189      result = result .. help_worker_experience(worker_description, becomes_description)
190   end
191   -- Soldier properties
192   if (worker_description.type_name == "soldier") then
193      -- TRANSLATORS: Soldier levels
194      result = result .. h2(_"Levels")
195
196      result = result .. h3(_"Health")
197      result = result ..
198         li(
199            -- TRANSLATORS: Soldier health / defense / evade points. A 5 digit number.
200            (_"Starts at %1% points."):bformat(worker_description.base_health)) ..
201         li(
202            -- TRANSLATORS: Soldier health / attack defense / evade points
203            ngettext("Increased by %1% point for each level.", "Increased by %1% points for each level.", worker_description.health_incr_per_level):bformat(worker_description.health_incr_per_level)) ..
204         li(
205            -- TRANSLATORS: Soldier health / attack defense / evade level
206            ngettext("The maximum level is %1%.", "The maximum level is %1%.", worker_description.max_health_level):bformat(worker_description.max_health_level))
207
208      result = result .. h3(_"Attack")
209      result = result ..
210      -- TRANSLATORS: Points are 4 digit numbers.
211         li(_"A random value between %1% and %2% points is added to each attack."):bformat(worker_description.base_min_attack, worker_description.base_max_attack) ..
212
213         li(
214            ngettext("Increased by %1% point for each level.", "Increased by %1% points for each level.", worker_description.attack_incr_per_level):bformat(worker_description.attack_incr_per_level)) ..
215         li(
216            ngettext("The maximum level is %1%.", "The maximum level is %1%.", worker_description.max_attack_level):bformat(worker_description.max_attack_level))
217
218      result = result .. h3(_"Defense")
219      if (worker_description.max_defense_level > 0) then
220         result = result ..
221            li(
222               (_"Starts at %d%%."):bformat(worker_description.base_defense)) ..
223            li(
224               (_"Increased by %d%% for each level."):bformat(worker_description.defense_incr_per_level)) ..
225            li(
226               ngettext("The maximum level is %1%.", "The maximum level is %1%.", worker_description.max_defense_level):bformat(worker_description.max_defense_level))
227      else
228         result = result ..
229            li(
230               (_"Starts at %d%%."):bformat(worker_description.base_defense)) ..
231            li(_"This soldier cannot be trained in defense.")
232      end
233
234      result = result .. h3(_"Evade")
235      result = result ..
236         li(
237            (_"Starts at %d%%."):bformat(worker_description.base_evade)) ..
238         li(
239            (_"Increased by %d%% for each level."):bformat(worker_description.evade_incr_per_level)) ..
240         li(
241            ngettext("The maximum level is %1%.", "The maximum level is %1%.", worker_description.max_evade_level):bformat(worker_description.max_evade_level))
242   end
243   return result
244end
245
246
247return {
248   func = function(tribename, workername)
249      set_textdomain("tribes_encyclopedia")
250      local tribe = wl.Game():get_tribe_description(tribename)
251      local worker_description = wl.Game():get_worker_description(workername)
252      return {
253         title = worker_description.descname,
254         text = worker_help_string(tribe, worker_description)
255      }
256   end
257}
258