1 /*
2 * Copyright (C) 2006-2020 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19
20 #include "scripting/lua_map.h"
21
22 #include "base/log.h"
23 #include "base/macros.h"
24 #include "base/wexception.h"
25 #include "economy/input_queue.h"
26 #include "logic/map_objects/checkstep.h"
27 #include "logic/map_objects/findimmovable.h"
28 #include "logic/map_objects/immovable.h"
29 #include "logic/map_objects/terrain_affinity.h"
30 #include "logic/map_objects/tribes/carrier.h"
31 #include "logic/map_objects/tribes/market.h"
32 #include "logic/map_objects/tribes/ship.h"
33 #include "logic/map_objects/tribes/soldier.h"
34 #include "logic/map_objects/tribes/tribe_basic_info.h"
35 #include "logic/map_objects/tribes/tribes.h"
36 #include "logic/map_objects/tribes/warelist.h"
37 #include "logic/map_objects/world/editor_category.h"
38 #include "logic/map_objects/world/resource_description.h"
39 #include "logic/map_objects/world/terrain_description.h"
40 #include "logic/map_objects/world/world.h"
41 #include "logic/maphollowregion.h"
42 #include "logic/mapregion.h"
43 #include "logic/player.h"
44 #include "logic/widelands_geometry.h"
45 #include "scripting/factory.h"
46 #include "scripting/globals.h"
47 #include "scripting/lua_errors.h"
48 #include "scripting/lua_game.h"
49 #include "wui/mapviewpixelfunctions.h"
50
51 using namespace Widelands;
52
53 namespace LuaMaps {
54
55 /* RST
56 :mod:`wl.map`
57 =============
58
59 .. module:: wl.map
60 :synopsis: Provides access to Fields and Objects on the map
61
62 .. moduleauthor:: The Widelands development team
63
64 .. currentmodule:: wl.map
65
66 */
67
68 namespace {
69
70 // Checks if a field has the desired caps
check_has_caps(lua_State * L,const std::string & query,const FCoords & f,const NodeCaps & caps,const Widelands::Map & map)71 bool check_has_caps(lua_State* L,
72 const std::string& query,
73 const FCoords& f,
74 const NodeCaps& caps,
75 const Widelands::Map& map) {
76 if (query == "walkable") {
77 return caps & MOVECAPS_WALK;
78 }
79 if (query == "swimmable") {
80 return caps & MOVECAPS_SWIM;
81 }
82 if (query == "small") {
83 return caps & BUILDCAPS_SMALL;
84 }
85 if (query == "medium") {
86 return caps & BUILDCAPS_MEDIUM;
87 }
88 if (query == "big") {
89 return (caps & BUILDCAPS_BIG) == BUILDCAPS_BIG;
90 }
91 if (query == "port") {
92 return (caps & BUILDCAPS_PORT) && map.is_port_space(f);
93 }
94 if (query == "mine") {
95 return caps & BUILDCAPS_MINE;
96 }
97 if (query == "flag") {
98 return caps & BUILDCAPS_FLAG;
99 }
100 report_error(L, "Unknown caps queried: %s!", query.c_str());
101 }
102
103 // Pushes a lua table with (name, count) pairs for the given 'ware_amount_container' on the
104 // stack. The 'type' needs to be WARE or WORKER. Returns 1.
wares_or_workers_map_to_lua(lua_State * L,const Buildcost & ware_amount_map,MapObjectType type)105 int wares_or_workers_map_to_lua(lua_State* L,
106 const Buildcost& ware_amount_map,
107 MapObjectType type) {
108 lua_newtable(L);
109 for (const auto& ware_amount : ware_amount_map) {
110 switch (type) {
111 case MapObjectType::WORKER:
112 lua_pushstring(L, get_egbase(L).tribes().get_worker_descr(ware_amount.first)->name());
113 break;
114 case MapObjectType::WARE:
115 lua_pushstring(L, get_egbase(L).tribes().get_ware_descr(ware_amount.first)->name());
116 break;
117 default:
118 throw wexception("wares_or_workers_map_to_lua needs a ware or worker");
119 }
120 lua_pushuint32(L, ware_amount.second);
121 lua_settable(L, -3);
122 }
123 return 1;
124 }
125
126 // Pushes a lua table of tables with food ware names on the stack. Returns 1.
127 // Resulting table will look e.g. like {{"barbarians_bread"}, {"fish", "meat"}}
food_list_to_lua(lua_State * L,const std::vector<std::vector<std::string>> & table)128 int food_list_to_lua(lua_State* L, const std::vector<std::vector<std::string>>& table) {
129 lua_newtable(L);
130 int counter = 0;
131 for (const std::vector<std::string>& foodlist : table) {
132 lua_pushuint32(L, ++counter);
133 lua_newtable(L);
134 int counter2 = 0;
135 for (const std::string& foodname : foodlist) {
136 lua_pushuint32(L, ++counter2);
137 lua_pushstring(L, foodname);
138 lua_settable(L, -3);
139 }
140 lua_settable(L, -3);
141 }
142 return 1;
143 }
144
145 struct SoldierMapDescr {
SoldierMapDescrLuaMaps::__anon101ba5a60111::SoldierMapDescr146 SoldierMapDescr(uint8_t init_health,
147 uint8_t init_attack,
148 uint8_t init_defense,
149 uint8_t init_evade)
150 : health(init_health), attack(init_attack), defense(init_defense), evade(init_evade) {
151 }
SoldierMapDescrLuaMaps::__anon101ba5a60111::SoldierMapDescr152 SoldierMapDescr() : health(0), attack(0), defense(0), evade(0) {
153 }
154
155 uint8_t health;
156 uint8_t attack;
157 uint8_t defense;
158 uint8_t evade;
159
operator <LuaMaps::__anon101ba5a60111::SoldierMapDescr160 bool operator<(const SoldierMapDescr& ot) const {
161 bool equal_health = health == ot.health;
162 bool equal_attack = attack == ot.attack;
163 bool equal_defense = defense == ot.defense;
164 if (equal_health && equal_attack && equal_defense) {
165 return evade < ot.evade;
166 }
167 if (equal_health && equal_attack) {
168 return defense < ot.defense;
169 }
170 if (equal_health) {
171 return attack < ot.attack;
172 }
173 return health < ot.health;
174 }
operator ==LuaMaps::__anon101ba5a60111::SoldierMapDescr175 bool operator==(const SoldierMapDescr& ot) const {
176 if (health == ot.health && attack == ot.attack && defense == ot.defense &&
177 evade == ot.evade) {
178 return true;
179 }
180 return false;
181 }
182 };
183
184 using SoldiersMap = std::map<SoldierMapDescr, Widelands::Quantity>;
185 using WaresWorkersMap = std::map<Widelands::DescriptionIndex, Widelands::Quantity>;
186 using SoldierAmount = std::pair<SoldierMapDescr, Widelands::Quantity>;
187 using WorkerAmount = std::pair<Widelands::DescriptionIndex, Widelands::Quantity>;
188 using PlrInfluence = std::pair<Widelands::PlayerNumber, Widelands::MilitaryInfluence>;
189 using WaresSet = std::set<Widelands::DescriptionIndex>;
190 using InputSet = std::set<std::pair<Widelands::DescriptionIndex, Widelands::WareWorker>>;
191 using WorkersSet = std::set<Widelands::DescriptionIndex>;
192 using SoldiersList = std::vector<Widelands::Soldier*>;
193
194 // Versions of the above macros which accept wares and workers
parse_get_input_arguments(lua_State * L,const TribeDescr & tribe,bool * return_number)195 InputSet parse_get_input_arguments(lua_State* L, const TribeDescr& tribe, bool* return_number) {
196 /* takes either "all", a name or an array of names */
197 int32_t nargs = lua_gettop(L);
198 if (nargs != 2) {
199 report_error(L, "Wrong number of arguments to get_inputs!");
200 }
201 *return_number = false;
202 InputSet rv;
203 if (lua_isstring(L, 2)) {
204 std::string what = luaL_checkstring(L, -1);
205 if (what == "all") {
206 for (const DescriptionIndex& i : tribe.wares()) {
207 rv.insert(std::make_pair(i, wwWARE));
208 }
209 for (const DescriptionIndex& i : tribe.workers()) {
210 rv.insert(std::make_pair(i, wwWORKER));
211 }
212 } else {
213 /* Only one item requested */
214 DescriptionIndex index = tribe.ware_index(what);
215 if (tribe.has_ware(index)) {
216 rv.insert(std::make_pair(index, wwWARE));
217 *return_number = true;
218 } else {
219 index = tribe.worker_index(what);
220 if (tribe.has_worker(index)) {
221 rv.insert(std::make_pair(index, wwWORKER));
222 *return_number = true;
223 } else {
224 report_error(L, "Invalid input: <%s>", what.c_str());
225 }
226 }
227 }
228 } else {
229 /* array of names */
230 luaL_checktype(L, 2, LUA_TTABLE);
231 lua_pushnil(L);
232 while (lua_next(L, 2) != 0) {
233 std::string what = luaL_checkstring(L, -1);
234 DescriptionIndex index = tribe.ware_index(what);
235 if (tribe.has_ware(index)) {
236 rv.insert(std::make_pair(index, wwWARE));
237 } else {
238 index = tribe.worker_index(what);
239 if (tribe.has_worker(index)) {
240 rv.insert(std::make_pair(index, wwWORKER));
241 } else {
242 report_error(L, "Invalid input: <%s>", what.c_str());
243 }
244 }
245 lua_pop(L, 1);
246 }
247 }
248 return rv;
249 }
250
parse_set_input_arguments(lua_State * L,const TribeDescr & tribe)251 InputMap parse_set_input_arguments(lua_State* L, const TribeDescr& tribe) {
252 int32_t nargs = lua_gettop(L);
253 if (nargs != 2 && nargs != 3) {
254 report_error(L, "Wrong number of arguments to set_inputs!");
255 }
256 InputMap rv;
257 if (nargs == 3) {
258 /* name amount */
259 std::string what = luaL_checkstring(L, 2);
260 DescriptionIndex index = tribe.ware_index(what);
261 if (tribe.has_ware(index)) {
262 rv.insert(std::make_pair(std::make_pair(index, wwWARE), luaL_checkuint32(L, 3)));
263 } else {
264 index = tribe.worker_index(what);
265 if (tribe.has_worker(index)) {
266 rv.insert(std::make_pair(std::make_pair(index, wwWORKER), luaL_checkuint32(L, 3)));
267 } else {
268 report_error(L, "Invalid input: <%s>", what.c_str());
269 }
270 }
271 } else {
272 /* array of (name, count) */
273 luaL_checktype(L, 2, LUA_TTABLE);
274 lua_pushnil(L);
275 while (lua_next(L, 2) != 0) {
276 std::string what = luaL_checkstring(L, -2);
277 DescriptionIndex index = tribe.ware_index(what);
278 if (tribe.has_ware(index)) {
279 rv.insert(std::make_pair(std::make_pair(index, wwWARE), luaL_checkuint32(L, -1)));
280 } else {
281 index = tribe.worker_index(what);
282 if (tribe.has_worker(index)) {
283 rv.insert(std::make_pair(std::make_pair(index, wwWORKER), luaL_checkuint32(L, -1)));
284 } else {
285 report_error(L, "Invalid input: <%s>", what.c_str());
286 }
287 }
288 lua_pop(L, 1);
289 }
290 }
291 return rv;
292 }
293
count_wares_on_flag_(Flag & f,const Tribes & tribes)294 WaresWorkersMap count_wares_on_flag_(Flag& f, const Tribes& tribes) {
295 WaresWorkersMap rv;
296
297 for (const WareInstance* ware : f.get_wares()) {
298 DescriptionIndex i = tribes.ware_index(ware->descr().name());
299 if (!rv.count(i)) {
300 rv.insert(Widelands::WareAmount(i, 1));
301 } else {
302 ++rv[i];
303 }
304 }
305 return rv;
306 }
307
308 // Sort functor to sort the owners claiming a field by their influence.
sort_claimers(const PlrInfluence & first,const PlrInfluence & second)309 static int sort_claimers(const PlrInfluence& first, const PlrInfluence& second) {
310 return first.second > second.second;
311 }
312
313 // Return the valid workers for a Road.
get_valid_workers_for(const RoadBase & r)314 WaresWorkersMap get_valid_workers_for(const RoadBase& r) {
315 WaresWorkersMap valid_workers;
316 if (r.descr().type() == MapObjectType::WATERWAY) {
317 valid_workers.insert(WorkerAmount(r.owner().tribe().ferry(), 1));
318 } else {
319 valid_workers.insert(WorkerAmount(r.owner().tribe().carrier(), 1));
320 upcast(const Road, road, &r);
321 assert(road);
322 if (road->is_busy()) {
323 valid_workers.insert(WorkerAmount(r.owner().tribe().carrier2(), 1));
324 }
325 }
326
327 return valid_workers;
328 }
329
330 // Returns the valid workers allowed in 'pi'.
get_valid_workers_for(const ProductionSite & ps)331 WaresWorkersMap get_valid_workers_for(const ProductionSite& ps) {
332 WaresWorkersMap rv;
333 for (const auto& item : ps.descr().working_positions()) {
334 rv.insert(WorkerAmount(item.first, item.second));
335 }
336 return rv;
337 }
338
339 // Translate the given Workers map into a (string, count) Lua table.
workers_map_to_lua(lua_State * L,const WaresWorkersMap & valid_workers)340 int workers_map_to_lua(lua_State* L, const WaresWorkersMap& valid_workers) {
341 lua_newtable(L);
342 for (const WaresWorkersMap::value_type& item : valid_workers) {
343 lua_pushstring(L, get_egbase(L).tribes().get_worker_descr(item.first)->name());
344 lua_pushuint32(L, item.second);
345 lua_rawset(L, -3);
346 }
347 return 1;
348 }
349
350 // Does most of the work of get_workers for player immovables (buildings and roads mainly).
do_get_workers(lua_State * L,const PlayerImmovable & pi,const WaresWorkersMap & valid_workers)351 int do_get_workers(lua_State* L, const PlayerImmovable& pi, const WaresWorkersMap& valid_workers) {
352 const TribeDescr& tribe = pi.owner().tribe();
353
354 DescriptionIndex worker_index = INVALID_INDEX;
355 std::vector<DescriptionIndex> workers_list;
356
357 RequestedWareWorker parse_output =
358 parse_wares_workers_list(L, tribe, &worker_index, &workers_list, false);
359
360 // c_workers is map (index:count) of all workers at the immovable
361 WaresWorkersMap c_workers;
362 for (const Worker* w : pi.get_workers()) {
363 DescriptionIndex i = tribe.worker_index(w->descr().name());
364 if (!c_workers.count(i)) {
365 c_workers.insert(WorkerAmount(i, 1));
366 } else {
367 ++c_workers[i];
368 }
369 }
370
371 // We return quantity for asked worker
372 if (worker_index != INVALID_INDEX) {
373 if (c_workers.count(worker_index)) {
374 lua_pushuint32(L, c_workers[worker_index]);
375 } else {
376 lua_pushuint32(L, 0);
377 }
378 } else {
379 // or array of worker:quantity
380 if (parse_output == RequestedWareWorker::kAll) { // 'all' was required, otherwise we return
381 // only asked workers
382 workers_list.clear();
383 for (const WaresWorkersMap::value_type& v : valid_workers) {
384 workers_list.push_back(v.first);
385 }
386 }
387 lua_newtable(L);
388 for (const DescriptionIndex& i : workers_list) {
389 Widelands::Quantity cnt = 0;
390 if (c_workers.count(i)) {
391 cnt = c_workers[i];
392 }
393 lua_pushstring(L, tribe.get_worker_descr(i)->name());
394 lua_pushuint32(L, cnt);
395 lua_settable(L, -3);
396 }
397 }
398 return 1;
399 }
400
401 // Does most of the work of set_workers for player immovables (buildings and roads mainly).
402 template <typename T>
do_set_workers(lua_State * L,PlayerImmovable * pi,const WaresWorkersMap & valid_workers)403 int do_set_workers(lua_State* L, PlayerImmovable* pi, const WaresWorkersMap& valid_workers) {
404 EditorGameBase& egbase = get_egbase(L);
405 const TribeDescr& tribe = pi->owner().tribe();
406
407 // setpoints is map of index:quantity
408 InputMap setpoints;
409 parse_wares_workers_counted(L, tribe, &setpoints, false);
410
411 // c_workers is actual statistics, the map index:quantity
412 WaresWorkersMap c_workers;
413 for (const Worker* w : pi->get_workers()) {
414 DescriptionIndex i = tribe.worker_index(w->descr().name());
415 if (!valid_workers.count(i)) {
416 // Ignore workers that will be consumed as inputs
417 continue;
418 }
419 if (!c_workers.count(i)) {
420 c_workers.insert(WorkerAmount(i, 1));
421 } else {
422 ++c_workers[i];
423 }
424 if (!setpoints.count(std::make_pair(i, Widelands::WareWorker::wwWORKER))) {
425 setpoints.insert(std::make_pair(std::make_pair(i, Widelands::WareWorker::wwWORKER), 0));
426 }
427 }
428
429 // The idea is to change as little as possible
430 for (const auto& sp : setpoints) {
431 const Widelands::DescriptionIndex& index = sp.first.first;
432 const WorkerDescr* wdes = tribe.get_worker_descr(index);
433 if (sp.second != 0 && !valid_workers.count(index)) {
434 report_error(L, "<%s> can't be employed here!", wdes->name().c_str());
435 }
436
437 Widelands::Quantity cur = 0;
438 WaresWorkersMap::iterator i = c_workers.find(index);
439 if (i != c_workers.end()) {
440 cur = i->second;
441 }
442
443 int d = sp.second - cur;
444 if (d < 0) {
445 while (d) {
446 for (const Worker* w : pi->get_workers()) {
447 if (tribe.worker_index(w->descr().name()) == index) {
448 const_cast<Worker*>(w)->remove(egbase);
449 ++d;
450 break;
451 }
452 }
453 }
454 } else if (d > 0) {
455 for (; d; --d) {
456 if (T::create_new_worker(*pi, egbase, wdes)) {
457 report_error(L, "No space left for this worker");
458 }
459 }
460 }
461 }
462 return 0;
463 }
464
465 // Unpacks the Lua table of the form {health, attack, defense, evade} at the stack index
466 // 'table_index' into a SoldierMapDescr struct.
467 SoldierMapDescr
unbox_lua_soldier_description(lua_State * L,int table_index,const SoldierDescr & sd)468 unbox_lua_soldier_description(lua_State* L, int table_index, const SoldierDescr& sd) {
469 SoldierMapDescr soldier_descr;
470
471 lua_pushuint32(L, 1);
472 lua_rawget(L, table_index);
473 soldier_descr.health = luaL_checkuint32(L, -1);
474 lua_pop(L, 1);
475 if (soldier_descr.health > sd.get_max_health_level()) {
476 report_error(L, "health level (%i) > max health level (%i)", soldier_descr.health,
477 sd.get_max_health_level());
478 }
479
480 lua_pushuint32(L, 2);
481 lua_rawget(L, table_index);
482 soldier_descr.attack = luaL_checkuint32(L, -1);
483 lua_pop(L, 1);
484 if (soldier_descr.attack > sd.get_max_attack_level()) {
485 report_error(L, "attack level (%i) > max attack level (%i)", soldier_descr.attack,
486 sd.get_max_attack_level());
487 }
488
489 lua_pushuint32(L, 3);
490 lua_rawget(L, table_index);
491 soldier_descr.defense = luaL_checkuint32(L, -1);
492 lua_pop(L, 1);
493 if (soldier_descr.defense > sd.get_max_defense_level()) {
494 report_error(L, "defense level (%i) > max defense level (%i)", soldier_descr.defense,
495 sd.get_max_defense_level());
496 }
497
498 lua_pushuint32(L, 4);
499 lua_rawget(L, table_index);
500 soldier_descr.evade = luaL_checkuint32(L, -1);
501 lua_pop(L, 1);
502 if (soldier_descr.evade > sd.get_max_evade_level()) {
503 report_error(L, "evade level (%i) > max evade level (%i)", soldier_descr.evade,
504 sd.get_max_evade_level());
505 }
506
507 return soldier_descr;
508 }
509
510 // Parser the arguments of set_soldiers() into a setpoint. See the
511 // documentation in HasSoldiers to understand the valid arguments.
parse_set_soldiers_arguments(lua_State * L,const SoldierDescr & soldier_descr)512 SoldiersMap parse_set_soldiers_arguments(lua_State* L, const SoldierDescr& soldier_descr) {
513 SoldiersMap rv;
514 if (lua_gettop(L) > 2) {
515 // STACK: cls, descr, count
516 const Widelands::Quantity count = luaL_checkuint32(L, 3);
517 const SoldierMapDescr d = unbox_lua_soldier_description(L, 2, soldier_descr);
518 rv.insert(SoldierAmount(d, count));
519 } else {
520 lua_pushnil(L);
521 while (lua_next(L, 2) != 0) {
522 const SoldierMapDescr d = unbox_lua_soldier_description(L, 3, soldier_descr);
523 const Widelands::Quantity count = luaL_checkuint32(L, -1);
524 rv.insert(SoldierAmount(d, count));
525 lua_pop(L, 1);
526 }
527 }
528 return rv;
529 }
530
531 // Does most of the work of get_soldiers for buildings.
do_get_soldiers(lua_State * L,const Widelands::SoldierControl & sc,const TribeDescr & tribe)532 int do_get_soldiers(lua_State* L, const Widelands::SoldierControl& sc, const TribeDescr& tribe) {
533 if (lua_gettop(L) != 2) {
534 report_error(L, "Invalid arguments!");
535 }
536
537 const SoldiersList soldiers = sc.stationed_soldiers();
538 if (lua_isstring(L, -1)) {
539 if (std::string(luaL_checkstring(L, -1)) != "all") {
540 report_error(L, "Invalid arguments!");
541 }
542
543 // Return All Soldiers
544 SoldiersMap hist;
545 for (const Soldier* s : soldiers) {
546 SoldierMapDescr sd(s->get_health_level(), s->get_attack_level(), s->get_defense_level(),
547 s->get_evade_level());
548
549 SoldiersMap::iterator i = hist.find(sd);
550 if (i == hist.end()) {
551 hist[sd] = 1;
552 } else {
553 ++i->second;
554 }
555 }
556
557 // Get this to Lua.
558 lua_newtable(L);
559 for (const SoldiersMap::value_type& i : hist) {
560 lua_createtable(L, 4, 0);
561 #define PUSHLEVEL(idx, name) \
562 lua_pushuint32(L, idx); \
563 lua_pushuint32(L, i.first.name); \
564 lua_rawset(L, -3);
565 PUSHLEVEL(1, health)
566 PUSHLEVEL(2, attack)
567 PUSHLEVEL(3, defense)
568 PUSHLEVEL(4, evade)
569 #undef PUSHLEVEL
570
571 lua_pushuint32(L, i.second);
572 lua_rawset(L, -3);
573 }
574 } else {
575 const SoldierDescr& soldier_descr =
576 dynamic_cast<const SoldierDescr&>(*tribe.get_worker_descr(tribe.soldier()));
577
578 // Only return the number of those requested
579 const SoldierMapDescr wanted = unbox_lua_soldier_description(L, 2, soldier_descr);
580 Widelands::Quantity rv = 0;
581 for (const Soldier* s : soldiers) {
582 SoldierMapDescr sd(s->get_health_level(), s->get_attack_level(), s->get_defense_level(),
583 s->get_evade_level());
584 if (sd == wanted) {
585 ++rv;
586 }
587 }
588 lua_pushuint32(L, rv);
589 }
590 return 1;
591 }
592
593 // Does most of the work of set_soldiers for buildings.
do_set_soldiers(lua_State * L,const Coords & building_position,SoldierControl * sc,Player * owner)594 int do_set_soldiers(lua_State* L,
595 const Coords& building_position,
596 SoldierControl* sc,
597 Player* owner) {
598 assert(sc != nullptr);
599 assert(owner != nullptr);
600
601 const TribeDescr& tribe = owner->tribe();
602 const SoldierDescr& soldier_descr = // soldiers
603 dynamic_cast<const SoldierDescr&>(*tribe.get_worker_descr(tribe.soldier()));
604 SoldiersMap setpoints = parse_set_soldiers_arguments(L, soldier_descr);
605
606 // Get information about current soldiers
607 const std::vector<Soldier*> curs = sc->stationed_soldiers();
608 SoldiersMap hist;
609 for (const Soldier* s : curs) {
610 SoldierMapDescr sd(s->get_health_level(), s->get_attack_level(), s->get_defense_level(),
611 s->get_evade_level());
612
613 SoldiersMap::iterator i = hist.find(sd);
614 if (i == hist.end()) {
615 hist[sd] = 1;
616 } else {
617 ++i->second;
618 }
619 if (!setpoints.count(sd)) {
620 setpoints[sd] = 0;
621 }
622 }
623
624 // Now adjust them
625 EditorGameBase& egbase = get_egbase(L);
626 for (const SoldiersMap::value_type& sp : setpoints) {
627 Widelands::Quantity cur = 0;
628 SoldiersMap::iterator i = hist.find(sp.first);
629 if (i != hist.end()) {
630 cur = i->second;
631 }
632
633 int d = sp.second - cur;
634 if (d < 0) {
635 while (d) {
636 for (Soldier* s : sc->stationed_soldiers()) {
637 SoldierMapDescr is(s->get_health_level(), s->get_attack_level(),
638 s->get_defense_level(), s->get_evade_level());
639
640 if (is == sp.first) {
641 sc->outcorporate_soldier(*s);
642 s->remove(egbase);
643 ++d;
644 break;
645 }
646 }
647 }
648 } else if (d > 0) {
649 for (; d; --d) {
650 Soldier& soldier = dynamic_cast<Soldier&>(
651 soldier_descr.create(egbase, owner, nullptr, building_position));
652 soldier.set_level(sp.first.health, sp.first.attack, sp.first.defense, sp.first.evade);
653 if (sc->incorporate_soldier(egbase, soldier)) {
654 soldier.remove(egbase);
655 report_error(L, "No space left for soldier!");
656 }
657 }
658 }
659 }
660 return 0;
661 }
662
663 // Parses a table of name/count pairs as given from Lua.
parse_wares_workers(lua_State * L,int table_index,const TribeDescr & tribe,InputMap * ware_workers_list,bool is_ware)664 void parse_wares_workers(lua_State* L,
665 int table_index,
666 const TribeDescr& tribe,
667 InputMap* ware_workers_list,
668 bool is_ware) {
669 luaL_checktype(L, table_index, LUA_TTABLE);
670 lua_pushnil(L);
671 while (lua_next(L, table_index) != 0) {
672 if (is_ware) {
673 if (tribe.ware_index(luaL_checkstring(L, -2)) == INVALID_INDEX) {
674 report_error(L, "Illegal ware %s", luaL_checkstring(L, -2));
675 }
676 ware_workers_list->insert(
677 std::make_pair(std::make_pair(tribe.ware_index(luaL_checkstring(L, -2)),
678 Widelands::WareWorker::wwWARE),
679 luaL_checkuint32(L, -1)));
680 } else {
681 if (tribe.worker_index(luaL_checkstring(L, -2)) == INVALID_INDEX) {
682 report_error(L, "Illegal worker %s", luaL_checkstring(L, -2));
683 }
684 ware_workers_list->insert(
685 std::make_pair(std::make_pair(tribe.worker_index(luaL_checkstring(L, -2)),
686 Widelands::WareWorker::wwWORKER),
687 luaL_checkuint32(L, -1)));
688 }
689 lua_pop(L, 1);
690 }
691 }
692
693 BillOfMaterials
parse_wares_as_bill_of_material(lua_State * L,int table_index,const TribeDescr & tribe)694 parse_wares_as_bill_of_material(lua_State* L, int table_index, const TribeDescr& tribe) {
695 InputMap input_map;
696 parse_wares_workers(L, table_index, tribe, &input_map, true /* is_ware */);
697 BillOfMaterials result;
698 for (const auto& pair : input_map) {
699 result.push_back(std::make_pair(pair.first.first, pair.second));
700 }
701 return result;
702 }
703
get_tribe_descr(lua_State * L,const std::string & tribename)704 const Widelands::TribeDescr& get_tribe_descr(lua_State* L, const std::string& tribename) {
705 if (!Widelands::tribe_exists(tribename)) {
706 report_error(L, "Tribe '%s' does not exist", tribename.c_str());
707 }
708 const Tribes& tribes = get_egbase(L).tribes();
709 return *tribes.get_tribe_descr(tribes.tribe_index(tribename));
710 }
711
712 } // namespace
713
714 /*
715 * Upcast the given map object description to a higher type and hand this
716 * to Lua. We use this so that scripters always work with the highest class
717 * object available.
718 */
719 #define CAST_TO_LUA(klass, lua_klass) \
720 to_lua<lua_klass>(L, new lua_klass(static_cast<const klass*>(descr)))
upcasted_map_object_descr_to_lua(lua_State * L,const MapObjectDescr * const descr)721 int upcasted_map_object_descr_to_lua(lua_State* L, const MapObjectDescr* const descr) {
722 assert(descr != nullptr);
723
724 if (descr->type() >= MapObjectType::BUILDING) {
725 switch (descr->type()) {
726 case MapObjectType::CONSTRUCTIONSITE:
727 return CAST_TO_LUA(ConstructionSiteDescr, LuaConstructionSiteDescription);
728 case MapObjectType::DISMANTLESITE:
729 return CAST_TO_LUA(DismantleSiteDescr, LuaDismantleSiteDescription);
730 case MapObjectType::PRODUCTIONSITE:
731 return CAST_TO_LUA(ProductionSiteDescr, LuaProductionSiteDescription);
732 case MapObjectType::MILITARYSITE:
733 return CAST_TO_LUA(MilitarySiteDescr, LuaMilitarySiteDescription);
734 case MapObjectType::WAREHOUSE:
735 return CAST_TO_LUA(WarehouseDescr, LuaWarehouseDescription);
736 case MapObjectType::MARKET:
737 return CAST_TO_LUA(MarketDescr, LuaMarketDescription);
738 case MapObjectType::TRAININGSITE:
739 return CAST_TO_LUA(TrainingSiteDescr, LuaTrainingSiteDescription);
740 default:
741 return CAST_TO_LUA(BuildingDescr, LuaBuildingDescription);
742 }
743 } else {
744 switch (descr->type()) {
745 case MapObjectType::WARE:
746 return CAST_TO_LUA(WareDescr, LuaWareDescription);
747 case MapObjectType::WORKER:
748 return CAST_TO_LUA(WorkerDescr, LuaWorkerDescription);
749 case MapObjectType::CARRIER:
750 return CAST_TO_LUA(WorkerDescr, LuaWorkerDescription);
751 case MapObjectType::FERRY:
752 return CAST_TO_LUA(WorkerDescr, LuaWorkerDescription);
753 case MapObjectType::SOLDIER:
754 return CAST_TO_LUA(SoldierDescr, LuaSoldierDescription);
755 case MapObjectType::IMMOVABLE:
756 return CAST_TO_LUA(ImmovableDescr, LuaImmovableDescription);
757 default:
758 return CAST_TO_LUA(MapObjectDescr, LuaMapObjectDescription);
759 }
760 }
761 }
762 #undef CAST_TO_LUA
763
764 /*
765 * Upcast the given map object to a higher type and hand this to
766 * Lua. We use this so that scripters always work with the highest class
767 * object available.
768 */
769 #define CAST_TO_LUA(k) to_lua<Lua##k>(L, new Lua##k(*static_cast<k*>(mo)))
upcasted_map_object_to_lua(lua_State * L,MapObject * mo)770 int upcasted_map_object_to_lua(lua_State* L, MapObject* mo) {
771 if (!mo) {
772 return 0;
773 }
774
775 switch (mo->descr().type()) {
776 case MapObjectType::CRITTER:
777 return CAST_TO_LUA(Bob);
778 case MapObjectType::SHIP:
779 return CAST_TO_LUA(Ship);
780 case MapObjectType::WORKER:
781 return CAST_TO_LUA(Worker);
782 case MapObjectType::CARRIER:
783 // TODO(sirver): not yet implemented
784 return CAST_TO_LUA(Worker);
785 case MapObjectType::FERRY:
786 // TODO(Nordfriese): not yet implemented
787 return CAST_TO_LUA(Worker);
788 case MapObjectType::SOLDIER:
789 return CAST_TO_LUA(Soldier);
790
791 case MapObjectType::IMMOVABLE:
792 return CAST_TO_LUA(BaseImmovable);
793
794 case MapObjectType::FLAG:
795 return CAST_TO_LUA(Flag);
796 case MapObjectType::ROAD:
797 return CAST_TO_LUA(Road);
798 case MapObjectType::WATERWAY:
799 // TODO(Nordfriese): not yet implemented
800 return CAST_TO_LUA(Road);
801 case MapObjectType::ROADBASE:
802 // TODO(Nordfriese): not yet implemented
803 return CAST_TO_LUA(Road);
804 case MapObjectType::PORTDOCK:
805 return CAST_TO_LUA(PortDock);
806
807 case MapObjectType::BUILDING:
808 return CAST_TO_LUA(Building);
809 case MapObjectType::CONSTRUCTIONSITE:
810 return CAST_TO_LUA(ConstructionSite);
811 case MapObjectType::DISMANTLESITE:
812 // TODO(sirver): not yet implemented.
813 return CAST_TO_LUA(Building);
814 case MapObjectType::WAREHOUSE:
815 return CAST_TO_LUA(Warehouse);
816 case MapObjectType::MARKET:
817 return CAST_TO_LUA(Market);
818 case MapObjectType::PRODUCTIONSITE:
819 return CAST_TO_LUA(ProductionSite);
820 case MapObjectType::MILITARYSITE:
821 return CAST_TO_LUA(MilitarySite);
822 case MapObjectType::TRAININGSITE:
823 return CAST_TO_LUA(TrainingSite);
824 case MapObjectType::MAPOBJECT:
825 case MapObjectType::BATTLE:
826 case MapObjectType::BOB:
827 case MapObjectType::SHIP_FLEET:
828 case MapObjectType::FERRY_FLEET:
829 case MapObjectType::WARE:
830 throw LuaError((boost::format("upcasted_map_object_to_lua: Unknown %i") %
831 static_cast<int>(mo->descr().type()))
832 .str());
833 }
834 NEVER_HERE();
835 }
836
837 // This is used for get_ware/workers functions, when argument can be
838 // 'all', single ware/worker, or array of ware/workers
parse_wares_workers_list(lua_State * L,const TribeDescr & tribe,Widelands::DescriptionIndex * single_item,std::vector<Widelands::DescriptionIndex> * item_list,bool is_ware)839 RequestedWareWorker parse_wares_workers_list(lua_State* L,
840 const TribeDescr& tribe,
841 Widelands::DescriptionIndex* single_item,
842 std::vector<Widelands::DescriptionIndex>* item_list,
843 bool is_ware) {
844 RequestedWareWorker result = RequestedWareWorker::kUndefined;
845 int32_t nargs = lua_gettop(L);
846 if (nargs != 2) {
847 report_error(L, "One argument is required for produced_wares_count()");
848 }
849
850 /* If we have single string as an argument */
851 if (lua_isstring(L, 2)) {
852
853 std::string what = luaL_checkstring(L, -1);
854 if (what != "all") {
855 result = RequestedWareWorker::kSingle;
856 // This is name of ware/worker
857 if (is_ware) {
858 *single_item = tribe.ware_index(what);
859 } else {
860 *single_item = tribe.worker_index(what);
861 }
862 if (*single_item == INVALID_INDEX) {
863 report_error(L, "Unrecognized ware/worker %s", what.c_str());
864 }
865 } else {
866 // we collect all wares/workers and push it to item_list
867 result = RequestedWareWorker::kAll;
868 if (is_ware) {
869 for (auto idx : tribe.wares()) {
870 item_list->push_back(idx);
871 }
872 } else {
873 for (auto idx : tribe.workers()) {
874 item_list->push_back(idx);
875 }
876 }
877 }
878 } else {
879 result = RequestedWareWorker::kList;
880 /* we got array of names, and so fill the indexes into item_list */
881 luaL_checktype(L, 2, LUA_TTABLE);
882 lua_pushnil(L);
883 while (lua_next(L, 2) != 0) {
884 std::string what = luaL_checkstring(L, -1);
885 lua_pop(L, 1);
886 if (is_ware) {
887 item_list->push_back(tribe.ware_index(what));
888 } else {
889 item_list->push_back(tribe.worker_index(what));
890 }
891 if (item_list->back() == INVALID_INDEX) {
892 report_error(L, "Unrecognized ware %s", what.c_str());
893 }
894 }
895 }
896 assert((*single_item == INVALID_INDEX) != item_list->empty());
897 return result;
898 }
899
900 // Very similar to above function, but expects numbers for every received ware/worker
parse_wares_workers_counted(lua_State * L,const TribeDescr & tribe,InputMap * ware_workers_list,bool is_ware)901 RequestedWareWorker parse_wares_workers_counted(lua_State* L,
902 const TribeDescr& tribe,
903 InputMap* ware_workers_list,
904 bool is_ware) {
905 RequestedWareWorker result = RequestedWareWorker::kUndefined;
906 int32_t nargs = lua_gettop(L);
907 if (nargs != 2 && nargs != 3) {
908 report_error(L, "Wrong number of arguments to set ware/worker method!");
909 }
910
911 // We either received, two items string,int:
912 if (nargs == 3) {
913 result = RequestedWareWorker::kSingle;
914 if (is_ware) {
915 if (tribe.ware_index(luaL_checkstring(L, 2)) == INVALID_INDEX) {
916 report_error(L, "Illegal ware %s", luaL_checkstring(L, 2));
917 }
918 ware_workers_list->insert(std::make_pair(
919 std::make_pair(tribe.ware_index(luaL_checkstring(L, 2)), Widelands::WareWorker::wwWARE),
920 luaL_checkuint32(L, 3)));
921 } else {
922 if (tribe.worker_index(luaL_checkstring(L, 2)) == INVALID_INDEX) {
923 report_error(L, "Illegal worker %s", luaL_checkstring(L, 2));
924 }
925 ware_workers_list->insert(
926 std::make_pair(std::make_pair(tribe.worker_index(luaL_checkstring(L, 2)),
927 Widelands::WareWorker::wwWORKER),
928 luaL_checkuint32(L, 3)));
929 }
930 } else {
931 result = RequestedWareWorker::kList;
932 // or we got a table with name:quantity
933 parse_wares_workers(L, 2, tribe, ware_workers_list, is_ware);
934 }
935 return result;
936 }
937
938 #undef CAST_TO_LUA
939
940 /*
941 * ========================================================================
942 * MODULE CLASSES
943 * ========================================================================
944 */
945
946 /* RST
947 Module Interfaces
948 ^^^^^^^^^^^^^^^^^
949
950 */
951
952 /* RST
953 HasWares
954 --------
955
956 .. class:: HasWares
957
958 HasWares is an interface that most :class:`PlayerImmovable` objects
959 that can contain wares implement. This is at the time of this writing
960 :class:`~wl.map.Flag` and :class:`~wl.map.Warehouse`.
961 */
962
963 /* RST
964 .. method:: get_wares(which)
965
966 Gets the number of wares that currently reside here.
967
968 :arg which: can be either of
969
970 * the string :const:`all`.
971 In this case the function will return a
972 :class:`table` of (ware name,amount) pairs that gives information
973 about all ware information available for this object.
974 * a ware name.
975 In this case a single integer is returned. No check is made
976 if this ware makes sense for this location, you can for example ask a
977 :const:`lumberjacks_hut` for the number of :const:`granite` he has
978 and he will return 0.
979 * an :class:`array` of ware names.
980 In this case a :class:`table` of
981 (ware name,amount) pairs is returned where only the requested wares
982 are listed. All other entries are :const:`nil`.
983
984 :returns: :class:`integer` or :class:`table`
985 */
986
987 /* RST
988 .. method:: set_wares(which[, amount])
989
990 Sets the wares available in this location. Either takes two arguments,
991 a ware name and an amount to set it to. Or it takes a table of
992 (ware name, amount) pairs. Wares are created and added to an economy out
993 of thin air.
994
995 :arg which: name of ware or (ware_name, amount) table
996 :type which: :class:`string` or :class:`table`
997 :arg amount: this many units will be available after the call
998 :type amount: :class:`integer`
999 */
1000
1001 /* RST
1002 .. attribute:: valid_wares
1003
1004 (RO) A :class:`table` of (ware_name, count) if storage is somehow
1005 constrained in this location. For example for a
1006 :class:`~wl.map.ProductionSite` this is the information what wares
1007 and how much can be stored as inputs. For unconstrained storage (like
1008 :class:`~wl.map.Warehouse`) this is :const:`nil`.
1009
1010 You can use this to quickly fill a building:
1011
1012 .. code-block:: lua
1013
1014 if b.valid_wares then b:set_wares(b.valid_wares) end
1015 */
1016
1017 /* RST
1018 HasInputs
1019 ---------
1020
1021 .. class:: HasInputs
1022
1023 HasInputs is an interface that some :class:`PlayerImmovable` objects
1024 implement. At the time of this writing these are
1025 :class:`~wl.map.ProductionSite` and :class:`~wl.map.TrainingSite`.
1026 This interface is similar to :class:`HasWares` but additionally allows
1027 to set workers as inputs. These workers are consumed by the production
1028 or trainings programm.
1029 */
1030
1031 /* RST
1032 .. method:: get_inputs(which)
1033
1034 Gets the number of wares and workers that currently reside here
1035 for consumption.
1036
1037 :arg which: can be either of
1038
1039 * the string :const:`all`.
1040 In this case the function will return a
1041 :class:`table` of (ware/worker name,amount) pairs that gives
1042 information about all ware information available for this object.
1043 * a ware or worker name.
1044 In this case a single integer is returned. No check is made
1045 if this ware/worker makes sense for this location, you can for example ask a
1046 :const:`lumberjacks_hut` for the number of :const:`granite` he has
1047 and he will return 0.
1048 * an :class:`array` of ware and worker names.
1049 In this case a :class:`table` of
1050 (ware/worker name,amount) pairs is returned where only the requested
1051 wares/workers are listed. All other entries are :const:`nil`.
1052
1053 :returns: :class:`integer` or :class:`table`
1054 */
1055
1056 /* RST
1057 .. method:: set_inputs(which[, amount])
1058
1059 Sets the wares/workers available in this location which will
1060 be consumed by the production/training programm. Either takes two arguments,
1061 a ware/worker name and an amount to set it to. Or it takes a table of
1062 (ware/worker name, amount) pairs. Wares are created and added to an
1063 economy out of thin air.
1064
1065 :arg which: name of ware/worker or (ware/worker name, amount) table
1066 :type which: :class:`string` or :class:`table`
1067 :arg amount: this many units will be available after the call
1068 :type amount: :class:`integer`
1069 */
1070
1071 /* RST
1072 .. attribute:: valid_inputs
1073
1074 (RO) A :class:`table` of (ware/worker name, count) which describes how
1075 many wares/workers can be stored here for consumption. For example for a
1076 :class:`~wl.map.ProductionSite` this is the information what wares/workers
1077 and can be stored in which amount as inputs.
1078
1079 You can use this to quickly fill a building:
1080
1081 .. code-block:: lua
1082
1083 if b.valid_inputs then b:set_inputs(b.valid_inputs) end
1084 */
1085
1086 /* RST
1087 HasWorkers
1088 ----------
1089
1090 .. class:: HasWorkers
1091
1092 Analogon to :class:`HasWares`, but for Workers. Supported at the time
1093 of this writing by :class:`~wl.map.Road`, :class:`~wl.map.Warehouse`
1094 and :class:`~wl.map.ProductionSite`. In the case of ProductionSites,
1095 these methods allow access to the workers which do the work instead of
1096 workers which are consumed as accessed by the methods of :class:`HasInputs`.
1097 */
1098
1099 /* RST
1100 .. method:: get_workers(which)
1101
1102 Similar to :meth:`HasWares.get_wares`.
1103 */
1104
1105 /* RST
1106 .. method:: set_workers(which[, amount])
1107
1108 Similar to :meth:`HasWares.set_wares`.
1109 */
1110
1111 /* RST
1112 .. attribute:: valid_workers
1113
1114 (RO) Similar to :attr:`HasWares.valid_wares` but for workers in this
1115 location.
1116 */
1117
1118 /* RST
1119 HasSoldiers
1120 ------------
1121
1122 .. class:: HasSoldiers
1123
1124 Analogon to :class:`HasWorkers`, but for Soldiers. Due to differences in
1125 Soldiers and implementation details in Lua this class has a slightly
1126 different interface than :class:`HasWorkers`. Supported at the time of this
1127 writing by :class:`~wl.map.Warehouse`, :class:`~wl.map.MilitarySite` and
1128 :class:`~wl.map.TrainingSite`.
1129 */
1130
1131 /* RST
1132 .. method:: get_soldiers(descr)
1133
1134 Gets information about the soldiers in a location.
1135
1136 :arg descr: can be either of
1137
1138 * a soldier description.
1139 Returns an :class:`integer` which is the number of soldiers of this
1140 kind in this building.
1141
1142 A soldier description is a :class:`array` that contains the level for
1143 health, attack, defense and evade (in this order). A usage example:
1144
1145 .. code-block:: lua
1146
1147 w:get_soldiers({0,0,0,0})
1148
1149 would return the number of soldiers of level 0 in this location.
1150
1151 * the string :const:`all`.
1152 In this case a :class:`table` of (soldier descriptions, count) is
1153 returned. Note that the following will not work, because Lua indexes
1154 tables by identity:
1155
1156 .. code-block:: lua
1157
1158 w:set_soldiers({0,0,0,0}, 100)
1159 w:get_soldiers({0,0,0,0}) -- works, returns 100
1160 w:get_soldiers("all")[{0,0,0,0}] -- works not, this is nil
1161
1162 -- Following is a working way to check for a {0,0,0,0} soldier
1163 for descr,count in pairs(w:get_soldiers("all")) do
1164 if descr[1] == 0 and descr[2] == 0 and
1165 descr[3] == 0 and descr[4] == 0 then
1166 print(count)
1167 end
1168 end
1169
1170 :returns: Number of soldiers that match descr or the :class:`table`
1171 containing all soldiers
1172 :rtype: :class:`integer` or :class:`table`.
1173 */
1174
1175 /* RST
1176 .. method:: set_soldiers(which[, amount])
1177
1178 Analogous to :meth:`HasWorkers.set_workers`, but for soldiers. Instead of
1179 a name a :class:`array` is used to define the soldier. See
1180 :meth:`get_soldiers` for an example.
1181
1182 Usage example:
1183
1184 .. code-block:: lua
1185
1186 l:set_soldiers({0,0,0,0}, 100)
1187
1188 would add 100 level 0 soldiers. While
1189
1190 .. code-block:: lua
1191
1192 l:set_soldiers({
1193 [{0,0,0,0}] = 10,
1194 [{1,2,3,4}] = 5,
1195 })
1196
1197 would add 10 level 0 soldier and 5 soldiers with hit point level 1,
1198 attack level 2, defense level 3 and evade level 4 (as long as this is
1199 legal for the players tribe).
1200
1201 :arg which: either a table of (description, count) pairs or one
1202 description. In that case amount has to be specified as well.
1203 :type which: :class:`table` or :class:`array`.
1204 */
1205
1206 /* RST
1207 .. attribute:: max_soldiers
1208
1209 (RO) The maximum number of soldiers that can be inside this building at
1210 one time. If it is not constrained, like for :class:`~wl.map.Warehouse`
1211 this will be :const:`nil`.
1212 */
1213
1214 /* RST
1215 Module Classes
1216 ^^^^^^^^^^^^^^
1217
1218 */
1219
1220 /* RST
1221 Map
1222 ---
1223
1224 .. class:: Map
1225
1226 Access to the map and its objects. You cannot instantiate this directly,
1227 instead access it via :attr:`wl.Game.map`.
1228 */
1229 const char LuaMap::className[] = "Map";
1230 const MethodType<LuaMap> LuaMap::Methods[] = {
1231 METHOD(LuaMap, count_conquerable_fields),
1232 METHOD(LuaMap, count_terrestrial_fields),
1233 METHOD(LuaMap, count_owned_valuable_fields),
1234 METHOD(LuaMap, place_immovable),
1235 METHOD(LuaMap, get_field),
1236 METHOD(LuaMap, recalculate),
1237 METHOD(LuaMap, recalculate_seafaring),
1238 METHOD(LuaMap, set_port_space),
1239 METHOD(LuaMap, sea_route_exists),
1240 METHOD(LuaMap, find_ocean_fields),
1241 {nullptr, nullptr},
1242 };
1243 const PropertyType<LuaMap> LuaMap::Properties[] = {
1244 PROP_RO(LuaMap, allows_seafaring), PROP_RO(LuaMap, number_of_port_spaces),
1245 PROP_RO(LuaMap, port_spaces), PROP_RO(LuaMap, width),
1246 PROP_RO(LuaMap, height), PROP_RO(LuaMap, player_slots),
1247 {nullptr, nullptr, nullptr},
1248 };
1249
__persist(lua_State *)1250 void LuaMap::__persist(lua_State* /* L */) {
1251 }
1252
__unpersist(lua_State *)1253 void LuaMap::__unpersist(lua_State* /* L */) {
1254 }
1255
1256 /*
1257 ==========================================================
1258 PROPERTIES
1259 ==========================================================
1260 */
1261 /* RST
1262 .. attribute:: allows_seafaring
1263
1264 (RO) Whether the map currently allows seafaring.
1265
1266 :returns: True if there are at least two port spaces that can be reached from each other.
1267 */
get_allows_seafaring(lua_State * L)1268 int LuaMap::get_allows_seafaring(lua_State* L) {
1269 lua_pushboolean(L, get_egbase(L).map().allows_seafaring());
1270 return 1;
1271 }
1272 /* RST
1273 .. attribute:: number_of_port_spaces
1274
1275 (RO) The amount of port spaces on the map.
1276
1277 :returns: An integer with the number of port spaces.
1278 */
get_number_of_port_spaces(lua_State * L)1279 int LuaMap::get_number_of_port_spaces(lua_State* L) {
1280 lua_pushuint32(L, get_egbase(L).map().get_port_spaces().size());
1281 return 1;
1282 }
1283
1284 /* RST
1285 .. attribute:: port_spaces
1286
1287 (RO) A list of coordinates for all port spaces on the map.
1288
1289 :returns: A table of port space coordinates,
1290 like this: ``{{x = 0, y = 2}, {x = 54, y = 23}}``.
1291 */
get_port_spaces(lua_State * L)1292 int LuaMap::get_port_spaces(lua_State* L) {
1293 lua_newtable(L);
1294 int counter = 0;
1295 for (const Coords& space : get_egbase(L).map().get_port_spaces()) {
1296 lua_pushinteger(L, ++counter);
1297 lua_newtable(L);
1298 lua_pushstring(L, "x");
1299 lua_pushint32(L, space.x);
1300 lua_settable(L, -3);
1301 lua_pushstring(L, "y");
1302 lua_pushint32(L, space.y);
1303 lua_settable(L, -3);
1304 lua_settable(L, -3);
1305 }
1306 return 1;
1307 }
1308
1309 /* RST
1310 .. attribute:: width
1311
1312 (RO) The width of the map in fields.
1313 */
get_width(lua_State * L)1314 int LuaMap::get_width(lua_State* L) {
1315 lua_pushuint32(L, get_egbase(L).map().get_width());
1316 return 1;
1317 }
1318 /* RST
1319 .. attribute:: height
1320
1321 (RO) The height of the map in fields.
1322 */
get_height(lua_State * L)1323 int LuaMap::get_height(lua_State* L) {
1324 lua_pushuint32(L, get_egbase(L).map().get_height());
1325 return 1;
1326 }
1327
1328 /* RST
1329 .. attribute:: player_slots
1330
1331 (RO) This is an :class:`array` that contains :class:`~wl.map.PlayerSlots`
1332 for each player defined in the map.
1333 */
get_player_slots(lua_State * L)1334 int LuaMap::get_player_slots(lua_State* L) {
1335 const Map& map = get_egbase(L).map();
1336
1337 lua_createtable(L, map.get_nrplayers(), 0);
1338 for (Widelands::PlayerNumber i = 0; i < map.get_nrplayers(); i++) {
1339 lua_pushuint32(L, i + 1);
1340 to_lua<LuaMaps::LuaPlayerSlot>(L, new LuaMaps::LuaPlayerSlot(i + 1));
1341 lua_settable(L, -3);
1342 }
1343
1344 return 1;
1345 }
1346
1347 /*
1348 ==========================================================
1349 LUA METHODS
1350 ==========================================================
1351 */
1352
1353 /* RST
1354 .. method:: count_conquerable_fields()
1355
1356 (RO) Counts all reachable fields that a player could build on.
1357
1358 **Note:** The fields are only calculated afresh when this is called for the first time.
1359
1360 :returns: An integer with the amount of fields.
1361 */
count_conquerable_fields(lua_State * L)1362 int LuaMap::count_conquerable_fields(lua_State* L) {
1363 lua_pushinteger(L, get_egbase(L).mutable_map()->count_all_conquerable_fields());
1364 return 1;
1365 }
1366
1367 /* RST
1368 .. method:: count_terrestrial_fields()
1369
1370 (RO) Counts all fields that are not swimmable.
1371
1372 **Note:** The fields are only calculated afresh when this is called for the first time.
1373
1374 :returns: An integer with the amount of fields.
1375 */
count_terrestrial_fields(lua_State * L)1376 int LuaMap::count_terrestrial_fields(lua_State* L) {
1377 lua_pushinteger(L, get_egbase(L).mutable_map()->count_all_fields_excluding_caps(MOVECAPS_SWIM));
1378 return 1;
1379 }
1380
1381 /* RST
1382 .. method:: count_owned_valuable_fields([immovable_attribute])
1383
1384 (RO) Counts the number of owned valuable fields for all players.
1385
1386 :arg name: *Optional*. If this is set, only count fields that have an
1387 immovable with the given atttribute.
1388 :type name: :class:`string`
1389
1390 :returns: A table mapping player numbers to their number of owned fields.
1391 */
count_owned_valuable_fields(lua_State * L)1392 int LuaMap::count_owned_valuable_fields(lua_State* L) {
1393 if (lua_gettop(L) > 2) {
1394 report_error(L, "Does not take more than one argument.");
1395 }
1396 const std::string attribute = lua_gettop(L) == 2 ? luaL_checkstring(L, -1) : "";
1397
1398 lua_newtable(L);
1399 for (const auto& fieldinfo : get_egbase(L).map().count_owned_valuable_fields(attribute)) {
1400 lua_pushinteger(L, fieldinfo.first);
1401 lua_pushinteger(L, fieldinfo.second);
1402 lua_settable(L, -3);
1403 }
1404 return 1;
1405 }
1406
1407 /* RST
1408 .. method:: find_ocean_fields(number)
1409
1410 Returns an array with the given number of Fields so that every field is swimmable,
1411 and from each field a sea route to any port space exists.
1412
1413 :arg number: The number of fields to find.
1414
1415 :returns: :class:`array` of :class:`wl.map.Field`
1416 */
find_ocean_fields(lua_State * L)1417 int LuaMap::find_ocean_fields(lua_State* L) {
1418 upcast(Game, game, &get_egbase(L));
1419 assert(game);
1420 const Map& map = game->map();
1421
1422 std::vector<LuaMaps::LuaField*> result;
1423 for (uint32_t i = luaL_checkuint32(L, 2); i;) {
1424 const uint32_t x = game->logic_rand() % map.get_width();
1425 const uint32_t y = game->logic_rand() % map.get_width();
1426 Widelands::Coords field(x, y);
1427 bool success = false;
1428 if (map[field].maxcaps() & Widelands::MOVECAPS_SWIM) {
1429 for (Widelands::Coords port : map.get_port_spaces()) {
1430 for (const Widelands::Coords& c : map.find_portdock(port)) {
1431 Widelands::Path p;
1432 if (map.findpath(field, c, 0, p, CheckStepDefault(MOVECAPS_SWIM)) >= 0) {
1433 success = true;
1434 break;
1435 }
1436 }
1437 if (success) {
1438 break;
1439 }
1440 }
1441 }
1442 if (success) {
1443 result.push_back(new LuaMaps::LuaField(x, y));
1444 --i;
1445 }
1446 }
1447
1448 lua_newtable(L);
1449 int counter = 0;
1450 for (auto& f : result) {
1451 lua_pushinteger(L, ++counter);
1452 to_lua<LuaMaps::LuaField>(L, f);
1453 lua_settable(L, -3);
1454 }
1455 return 1;
1456 }
1457
1458 /* RST
1459 .. method:: place_immovable(name, field, from_where)
1460
1461 Creates an immovable that is defined by the world (e.g. trees, rocks...)
1462 or a tribe (field) on a given field. If there is already an immovable on
1463 the field, an error is reported.
1464
1465 :arg name: The name of the immovable to create
1466 :type name: :class:`string`
1467 :arg field: The immovable is created on this field.
1468 :type field: :class:`wl.map.Field`
1469 :arg from_where: "world" if the immovable is defined in the world,
1470 "tribes" if it is defined in the tribes.
1471 :type from_where: :class:`string`
1472
1473 :returns: The created immovable.
1474 */
place_immovable(lua_State * const L)1475 int LuaMap::place_immovable(lua_State* const L) {
1476 std::string from_where;
1477
1478 const std::string objname = luaL_checkstring(L, 2);
1479 LuaMaps::LuaField* c = *get_user_class<LuaMaps::LuaField>(L, 3);
1480 if (lua_gettop(L) > 3 && !lua_isnil(L, 4)) {
1481 from_where = luaL_checkstring(L, 4);
1482 }
1483
1484 // Check if the map is still free here
1485 if (BaseImmovable const* const imm = c->fcoords(L).field->get_immovable()) {
1486 if (imm->get_size() >= BaseImmovable::SMALL) {
1487 report_error(L, "Node is no longer free!");
1488 }
1489 }
1490
1491 EditorGameBase& egbase = get_egbase(L);
1492
1493 BaseImmovable* m = nullptr;
1494 if (from_where == "world") {
1495 DescriptionIndex const imm_idx = egbase.world().get_immovable_index(objname);
1496 if (imm_idx == Widelands::INVALID_INDEX) {
1497 report_error(L, "Unknown world immovable <%s>", objname.c_str());
1498 }
1499
1500 m = &egbase.create_immovable(
1501 c->coords(), imm_idx, MapObjectDescr::OwnerType::kWorld, nullptr /* owner */);
1502 } else if (from_where == "tribes") {
1503 DescriptionIndex const imm_idx = egbase.tribes().immovable_index(objname);
1504 if (imm_idx == Widelands::INVALID_INDEX) {
1505 report_error(L, "Unknown tribes immovable <%s>", objname.c_str());
1506 }
1507
1508 m = &egbase.create_immovable(
1509 c->coords(), imm_idx, MapObjectDescr::OwnerType::kTribe, nullptr /* owner */);
1510 } else {
1511 report_error(
1512 L, "There are no immovables for <%s>. Use \"world\" or \"tribes\"", from_where.c_str());
1513 }
1514
1515 return LuaMaps::upcasted_map_object_to_lua(L, m);
1516 }
1517
1518 /* RST
1519 .. method:: get_field(x, y)
1520
1521 Returns a :class:`wl.map.Field` object of the given index.
1522 */
get_field(lua_State * L)1523 int LuaMap::get_field(lua_State* L) {
1524 uint32_t x = luaL_checkuint32(L, 2);
1525 uint32_t y = luaL_checkuint32(L, 3);
1526
1527 const Map& map = get_egbase(L).map();
1528
1529 if (x >= static_cast<uint32_t>(map.get_width())) {
1530 report_error(L, "x coordinate out of range!");
1531 }
1532 if (y >= static_cast<uint32_t>(map.get_height())) {
1533 report_error(L, "y coordinate out of range!");
1534 }
1535
1536 return to_lua<LuaMaps::LuaField>(L, new LuaMaps::LuaField(x, y));
1537 }
1538
1539 /* RST
1540 .. method:: recalculate()
1541
1542 This map recalculates the whole map state: height of fields, buildcaps,
1543 whether the map allows seafaring and so on. You only need to call this
1544 function if you changed :any:`raw_height` in any way.
1545 */
1546 // TODO(unknown): do we really want this function?
recalculate(lua_State * L)1547 int LuaMap::recalculate(lua_State* L) {
1548 EditorGameBase& egbase = get_egbase(L);
1549 egbase.mutable_map()->recalc_whole_map(egbase);
1550 return 0;
1551 }
1552
1553 /* RST
1554 .. method:: recalculate_seafaring()
1555
1556 This method recalculates whether the map allows seafaring.
1557 You only need to call this function if you have been changing terrains to/from
1558 water and wanted to defer recalculating whether the map allows seafaring.
1559 */
recalculate_seafaring(lua_State * L)1560 int LuaMap::recalculate_seafaring(lua_State* L) {
1561 get_egbase(L).mutable_map()->recalculate_allows_seafaring();
1562 return 0;
1563 }
1564
1565 /* RST
1566 .. method:: set_port_space(x, y, allowed)
1567
1568 Sets whether a port space is allowed at the coordinates (x, y).
1569 Returns false if the port space couldn't be set.
1570
1571 :arg x: The x coordinate of the port space to set/unset.
1572 :type x: :class:`int`
1573 :arg y: The y coordinate of the port space to set/unset.
1574 :type y: :class:`int`
1575 :arg allowed: Whether building a port will be allowed here.
1576 :type allowed: :class:`bool`
1577
1578 :returns: :const:`true` on success, or :const:`false` otherwise
1579 :rtype: :class:`bool`
1580 */
set_port_space(lua_State * L)1581 int LuaMap::set_port_space(lua_State* L) {
1582 const int x = luaL_checkint32(L, 2);
1583 const int y = luaL_checkint32(L, 3);
1584 const bool allowed = luaL_checkboolean(L, 4);
1585 const bool success = get_egbase(L).mutable_map()->set_port_space(
1586 get_egbase(L), Widelands::Coords(x, y), allowed, false, true);
1587 lua_pushboolean(L, success);
1588 return 1;
1589 }
1590
1591 /* RST
1592 .. method:: sea_route_exists(field, port)
1593
1594 Returns whether a sea route exists from the given field to the given port space.
1595
1596 :arg field: The field where to start
1597 :type field: :class:`wl.map.Field`
1598 :arg port: The port space to find
1599 :type port: :class:`wl.map.Field`
1600
1601 :rtype: :class:`bool`
1602 */
sea_route_exists(lua_State * L)1603 int LuaMap::sea_route_exists(lua_State* L) {
1604 const Widelands::Map& map = get_egbase(L).map();
1605 const Widelands::FCoords f_start = (*get_user_class<LuaMaps::LuaField>(L, 2))->fcoords(L);
1606 const Widelands::FCoords f_port = (*get_user_class<LuaMaps::LuaField>(L, 3))->fcoords(L);
1607 for (const Widelands::Coords& c : map.find_portdock(f_port)) {
1608 Widelands::Path p;
1609 if (map.findpath(f_start, c, 0, p, CheckStepDefault(MOVECAPS_SWIM)) >= 0) {
1610 lua_pushboolean(L, true);
1611 return 1;
1612 }
1613 }
1614 lua_pushboolean(L, false);
1615 return 1;
1616 }
1617
1618 /*
1619 ==========================================================
1620 C METHODS
1621 ==========================================================
1622 */
1623
1624 /* RST
1625 TribeDescription
1626 --------------------
1627 .. class:: TribeDescription
1628
1629 A static description of a tribe.
1630 This class contains information about which buildings, wares, workers etc. a tribe uses.
1631 */
1632 const char LuaTribeDescription::className[] = "TribeDescription";
1633 const MethodType<LuaTribeDescription> LuaTribeDescription::Methods[] = {
1634 METHOD(LuaTribeDescription, has_building),
1635 METHOD(LuaTribeDescription, has_ware),
1636 METHOD(LuaTribeDescription, has_worker),
1637 {nullptr, nullptr},
1638 };
1639 const PropertyType<LuaTribeDescription> LuaTribeDescription::Properties[] = {
1640 PROP_RO(LuaTribeDescription, buildings),
1641 PROP_RO(LuaTribeDescription, carrier),
1642 PROP_RO(LuaTribeDescription, carrier2),
1643 PROP_RO(LuaTribeDescription, descname),
1644 PROP_RO(LuaTribeDescription, geologist),
1645 PROP_RO(LuaTribeDescription, immovables),
1646 PROP_RO(LuaTribeDescription, resource_indicators),
1647 PROP_RO(LuaTribeDescription, name),
1648 PROP_RO(LuaTribeDescription, port),
1649 PROP_RO(LuaTribeDescription, ship),
1650 PROP_RO(LuaTribeDescription, soldier),
1651 PROP_RO(LuaTribeDescription, wares),
1652 PROP_RO(LuaTribeDescription, workers),
1653 {nullptr, nullptr, nullptr},
1654 };
1655
__persist(lua_State * L)1656 void LuaTribeDescription::__persist(lua_State* L) {
1657 const TribeDescr* descr = get();
1658 PERS_STRING("name", descr->name());
1659 }
1660
__unpersist(lua_State * L)1661 void LuaTribeDescription::__unpersist(lua_State* L) {
1662 std::string name;
1663 UNPERS_STRING("name", name)
1664 const Tribes& tribes = get_egbase(L).tribes();
1665 DescriptionIndex idx = tribes.safe_tribe_index(name);
1666 set_description_pointer(tribes.get_tribe_descr(idx));
1667 }
1668
1669 /*
1670 ==========================================================
1671 PROPERTIES
1672 ==========================================================
1673 */
1674
1675 /* RST
1676 .. attribute:: buildings
1677
1678 (RO) an array of :class:`LuaBuildingDescription` with all the buildings that the tribe can
1679 use, casted to their appropriate subclasses.
1680 */
get_buildings(lua_State * L)1681 int LuaTribeDescription::get_buildings(lua_State* L) {
1682 const TribeDescr& tribe = *get();
1683 lua_newtable(L);
1684 int counter = 0;
1685 for (DescriptionIndex building : tribe.buildings()) {
1686 lua_pushinteger(L, ++counter);
1687 upcasted_map_object_descr_to_lua(L, tribe.get_building_descr(building));
1688 lua_settable(L, -3);
1689 }
1690 return 1;
1691 }
1692
1693 /* RST
1694 .. attribute:: carrier
1695
1696 (RO) the :class:`string` internal name of the carrier type that this tribe uses
1697 */
1698
get_carrier(lua_State * L)1699 int LuaTribeDescription::get_carrier(lua_State* L) {
1700 lua_pushstring(L, get_egbase(L).tribes().get_worker_descr(get()->carrier())->name());
1701 return 1;
1702 }
1703
1704 /* RST
1705 .. attribute:: carrier2
1706
1707 (RO) the :class:`string` internal name of the carrier2 type that this tribe uses.
1708 e.g. 'atlanteans_horse'
1709 */
1710
get_carrier2(lua_State * L)1711 int LuaTribeDescription::get_carrier2(lua_State* L) {
1712 lua_pushstring(L, get_egbase(L).tribes().get_worker_descr(get()->carrier2())->name());
1713 return 1;
1714 }
1715
1716 /* RST
1717 .. attribute:: descname
1718
1719 (RO) a :class:`string` with the tribe's localized name
1720 */
1721
get_descname(lua_State * L)1722 int LuaTribeDescription::get_descname(lua_State* L) {
1723 lua_pushstring(L, get()->descname());
1724 return 1;
1725 }
1726
1727 /* RST
1728 .. attribute:: geologist
1729
1730 (RO) the :class:`string` internal name of the geologist type that this tribe uses
1731 */
1732
get_geologist(lua_State * L)1733 int LuaTribeDescription::get_geologist(lua_State* L) {
1734 lua_pushstring(L, get_egbase(L).tribes().get_worker_descr(get()->geologist())->name());
1735 return 1;
1736 }
1737
1738 /* RST
1739 .. attribute:: immovables
1740
1741 (RO) an array of :class:`LuaImmovableDescription` with all the immovables that the tribe can
1742 use.
1743 */
get_immovables(lua_State * L)1744 int LuaTribeDescription::get_immovables(lua_State* L) {
1745 const TribeDescr& tribe = *get();
1746 lua_newtable(L);
1747 int counter = 0;
1748 for (DescriptionIndex immovable : tribe.immovables()) {
1749 lua_pushinteger(L, ++counter);
1750 to_lua<LuaImmovableDescription>(
1751 L, new LuaImmovableDescription(tribe.get_immovable_descr(immovable)));
1752 lua_settable(L, -3);
1753 }
1754 return 1;
1755 }
1756
1757 /* RST
1758 .. attribute:: resource_indicators
1759
1760 (RO) the table `resource_indicators` as defined in the tribe's `tribename.lua`.
1761 See `data/tribes/atlanteans.lua` for more information on the table structure.
1762 */
get_resource_indicators(lua_State * L)1763 int LuaTribeDescription::get_resource_indicators(lua_State* L) {
1764 const TribeDescr& tribe = *get();
1765 lua_newtable(L);
1766 const ResourceIndicatorSet resis = tribe.resource_indicators();
1767 for (const auto& resilist : resis) {
1768 lua_pushstring(L, resilist.first);
1769 lua_newtable(L);
1770 for (const auto& resi : resilist.second) {
1771 lua_pushinteger(L, resi.first);
1772 lua_pushstring(L, tribe.get_immovable_descr(resi.second)->name());
1773 lua_settable(L, -3);
1774 }
1775 lua_settable(L, -3);
1776 }
1777 return 1;
1778 }
1779
1780 /* RST
1781 .. attribute:: name
1782
1783 (RO) a :class:`string` with the tribe's internal name
1784 */
1785
get_name(lua_State * L)1786 int LuaTribeDescription::get_name(lua_State* L) {
1787 lua_pushstring(L, get()->name());
1788 return 1;
1789 }
1790
1791 /* RST
1792 .. attribute:: port
1793
1794 (RO) the :class:`string` internal name of the port type that this tribe uses
1795 */
1796
get_port(lua_State * L)1797 int LuaTribeDescription::get_port(lua_State* L) {
1798 lua_pushstring(L, get_egbase(L).tribes().get_building_descr(get()->port())->name());
1799 return 1;
1800 }
1801
1802 /* RST
1803 .. attribute:: ship
1804
1805 (RO) the :class:`string` internal name of the ship type that this tribe uses
1806 */
1807
get_ship(lua_State * L)1808 int LuaTribeDescription::get_ship(lua_State* L) {
1809 lua_pushstring(L, get_egbase(L).tribes().get_ship_descr(get()->ship())->name());
1810 return 1;
1811 }
1812
1813 /* RST
1814 .. attribute:: soldier
1815
1816 (RO) the :class:`string` internal name of the soldier type that this tribe uses
1817 */
1818
get_soldier(lua_State * L)1819 int LuaTribeDescription::get_soldier(lua_State* L) {
1820 lua_pushstring(L, get_egbase(L).tribes().get_worker_descr(get()->soldier())->name());
1821 return 1;
1822 }
1823
1824 /* RST
1825 .. attribute:: wares
1826
1827 (RO) an array of :class:`LuaWareDescription` with all the wares that the tribe can use.
1828 */
get_wares(lua_State * L)1829 int LuaTribeDescription::get_wares(lua_State* L) {
1830 const TribeDescr& tribe = *get();
1831 lua_newtable(L);
1832 int counter = 0;
1833 for (DescriptionIndex ware : tribe.wares()) {
1834 lua_pushinteger(L, ++counter);
1835 to_lua<LuaWareDescription>(L, new LuaWareDescription(tribe.get_ware_descr(ware)));
1836 lua_settable(L, -3);
1837 }
1838 return 1;
1839 }
1840
1841 /* RST
1842 .. attribute:: workers
1843
1844 (RO) an array of :class:`LuaWorkerDescription` with all the workers that the tribe can use,
1845 casted to their appropriate subclasses.
1846 */
get_workers(lua_State * L)1847 int LuaTribeDescription::get_workers(lua_State* L) {
1848 const TribeDescr& tribe = *get();
1849 lua_newtable(L);
1850 int counter = 0;
1851 for (DescriptionIndex worker : tribe.workers()) {
1852 lua_pushinteger(L, ++counter);
1853 upcasted_map_object_descr_to_lua(L, tribe.get_worker_descr(worker));
1854 lua_settable(L, -3);
1855 }
1856 return 1;
1857 }
1858
1859 /* RST
1860 .. method:: has_building(buildingname)
1861
1862 Returns true if buildingname is a building and the tribe can use it.
1863
1864 :returns: :const:`true` or :const:`false`
1865 :rtype: :class:`bool`
1866 */
has_building(lua_State * L)1867 int LuaTribeDescription::has_building(lua_State* L) {
1868 const std::string buildingname = luaL_checkstring(L, 2);
1869 const DescriptionIndex index = get_egbase(L).tribes().building_index(buildingname);
1870 lua_pushboolean(L, get()->has_building(index));
1871 return 1;
1872 }
1873
1874 /* RST
1875 .. method:: has_ware(warename)
1876
1877 Returns true if warename is a ware and the tribe uses it.
1878
1879 :returns: :const:`true` or :const:`false`
1880 :rtype: :class:`bool`
1881 */
has_ware(lua_State * L)1882 int LuaTribeDescription::has_ware(lua_State* L) {
1883 const std::string warename = luaL_checkstring(L, 2);
1884 const DescriptionIndex index = get_egbase(L).tribes().ware_index(warename);
1885 lua_pushboolean(L, get()->has_ware(index));
1886 return 1;
1887 }
1888
1889 /* RST
1890 .. method:: has_worker(workername)
1891
1892 Returns true if workername is a worker and the tribe can use it.
1893
1894 :returns: :const:`true` or :const:`false`
1895 :rtype: :class:`bool`
1896 */
has_worker(lua_State * L)1897 int LuaTribeDescription::has_worker(lua_State* L) {
1898 const std::string workername = luaL_checkstring(L, 2);
1899 const DescriptionIndex index = get_egbase(L).tribes().worker_index(workername);
1900 lua_pushboolean(L, get()->has_worker(index));
1901 return 1;
1902 }
1903
1904 /* RST
1905 MapObjectDescription
1906 --------------------
1907
1908 .. class:: MapObjectDescription
1909
1910 A static description of a tribe's map object, so it can be used in help files
1911 without having to access an actual object on the map.
1912 This class contains the properties that are common to all map objects such as buildings or wares.
1913
1914 The dynamic MapObject class corresponding to this class is the base class for all Objects in
1915 widelands, including immovables and Bobs. This class can't be instantiated directly, but provides
1916 the base for all others.
1917 */
1918 const char LuaMapObjectDescription::className[] = "MapObjectDescription";
1919 const MethodType<LuaMapObjectDescription> LuaMapObjectDescription::Methods[] = {
1920 {nullptr, nullptr},
1921 };
1922 const PropertyType<LuaMapObjectDescription> LuaMapObjectDescription::Properties[] = {
1923 PROP_RO(LuaMapObjectDescription, descname), PROP_RO(LuaMapObjectDescription, helptext_script),
1924 PROP_RO(LuaMapObjectDescription, icon_name), PROP_RO(LuaMapObjectDescription, name),
1925 PROP_RO(LuaMapObjectDescription, type_name), {nullptr, nullptr, nullptr},
1926 };
1927
1928 // Only base classes can be persisted.
__persist(lua_State *)1929 void LuaMapObjectDescription::__persist(lua_State*) {
1930 NEVER_HERE();
1931 }
1932
__unpersist(lua_State *)1933 void LuaMapObjectDescription::__unpersist(lua_State*) {
1934 NEVER_HERE();
1935 }
1936
1937 /*
1938 ==========================================================
1939 PROPERTIES
1940 ==========================================================
1941 */
1942
1943 /* RST
1944 .. attribute:: descname
1945
1946 (RO) a :class:`string` with the map object's localized name
1947 */
1948
get_descname(lua_State * L)1949 int LuaMapObjectDescription::get_descname(lua_State* L) {
1950 lua_pushstring(L, get()->descname());
1951 return 1;
1952 }
1953
1954 /* RST
1955 .. attribute:: helptext_script
1956
1957 (RO) The path and filename to the helptext script. Can be empty.
1958 */
get_helptext_script(lua_State * L)1959 int LuaMapObjectDescription::get_helptext_script(lua_State* L) {
1960 lua_pushstring(L, get()->helptext_script());
1961 return 1;
1962 }
1963
1964 /* RST
1965 .. attribute:: icon_name
1966
1967 (RO) the filename for the menu icon.
1968 */
get_icon_name(lua_State * L)1969 int LuaMapObjectDescription::get_icon_name(lua_State* L) {
1970 lua_pushstring(L, get()->icon_filename());
1971 return 1;
1972 }
1973
1974 /* RST
1975 .. attribute:: name
1976
1977 (RO) a :class:`string` with the map object's internal name
1978 */
1979
get_name(lua_State * L)1980 int LuaMapObjectDescription::get_name(lua_State* L) {
1981 lua_pushstring(L, get()->name());
1982 return 1;
1983 }
1984
1985 /* RST
1986 .. attribute:: type_name
1987
1988 (RO) the map object's type as a string. Map object types are
1989 organized in a hierarchy, where an element that's lower in the
1990 hierarchy has all the properties of the higher-placed types,
1991 as well as its own additional properties. Any map object's
1992 description that isn't linked below can be accessed via its
1993 higher types, e.g. a ``bob`` is a
1994 :class:`general map object <MapObjectDescription>`, and a
1995 ``carrier`` is a :class:`worker <WorkerDescription>` as well as a
1996 general map object. Possible values are:
1997
1998 * **Bobs:** Bobs are map objects that can move around the map.
1999 Bob types are:
2000
2001 * :class:`bob <BobDescription>`, the abstract base type for
2002 all bobs,
2003 * :class:`critter <CritterDescription>`, animals that aren't
2004 controlled by any tribe,
2005 * :class:`ship <ShipDescription>`, a sea-going vessel
2006 belonging to a tribe that can ferry wares or an expedition,
2007 * :class:`worker <WorkerDescription>`, a worker belonging to
2008 a tribe,
2009 * :class:`carrier <CarrierDescription>`, a specialized
2010 worker for carrying items along a road,
2011 * :class:`soldier <SoldierDescription>`, a specialized worker
2012 that will fight for its tribe.
2013
2014 * **Wares:** :class:`ware <WareDescription>`, a ware used by
2015 buildings to produce other wares, workers or ships
2016 * **Immovables:** Immovables are map objects that have a fixed
2017 position on the map, like buildings or trees. Immovable types are:
2018
2019 * :class:`immovable <ImmovableDescription>` General immovables
2020 that can belong to a tribe (e.g. a wheat field) or to the
2021 world (e.g. trees or rocks).
2022
2023 * **Buildings:** Buildings always belong to a tribe. Building
2024 types are:
2025
2026 * :class:`building <BuildingDescription>`, the base class
2027 for all buildings
2028 * :class:`constructionsite <ConstructionSiteDescription>`,
2029 an actual building is being constructed here,
2030 * :class:`dismantlesite <DismantleSiteDescription>`, an
2031 actual building is being dismantled here,
2032 * :class:`warehouse <WarehouseDescription>`, a warehouse
2033 can store wares and workers. Headquarters and ports are
2034 special tapes of warehouses, but they belong to the same
2035 class,
2036 * :class:`militarysite <MilitarySiteDescription>`, a
2037 building manned by soldiers to expand a tribe's territory,
2038 * :class:`productionsite <ProductionSiteDescription>`, the
2039 most common type of building, which can produce wares,
2040 * :class:`trainingsite <TrainingSiteDescription>`, a
2041 specialized productionsite for improving soldiers.
2042
2043 * **Other Immovables:** Specialized immovables that aren't buildings:
2044
2045 * :class:`flag <FlagDescription>`, a flag that can hold
2046 wares for transport,
2047 * :class:`road <RoadDescription>`, a road or waterway
2048 connecting two flags,
2049 * :class:`portdock <PortdockDescription>`, a 'parking space'
2050 on water terrain where ships can load/unload wares and
2051 workers. A portdock is invisible to the player and one is
2052 automatically placed next to each port building.
2053
2054 * **Abstract:** These types are abstract map objects that are used by the engine and are
2055 not visible on the map.
2056
2057 * :class:`battle <BattleDescription>`, holds information
2058 about two soldiers in a fight,
2059 * :class:`fleet <FleetDescription>`, holds information for
2060 managing ships.
2061 */
get_type_name(lua_State * L)2062 int LuaMapObjectDescription::get_type_name(lua_State* L) {
2063 lua_pushstring(L, to_string(get()->type()));
2064 return 1;
2065 }
2066
2067 /* RST
2068 ImmovableDescription
2069 --------------------
2070
2071 .. class:: ImmovableDescription
2072
2073 Child of: :class:`MapObjectDescription`
2074
2075 A static description of a :class:`base immovable <BaseImmovable>`, so it can be used in help
2076 files without having to access an actual immovable on the map. See also
2077 :class:`MapObjectDescription` for more properties.
2078 */
2079 const char LuaImmovableDescription::className[] = "ImmovableDescription";
2080 const MethodType<LuaImmovableDescription> LuaImmovableDescription::Methods[] = {
2081 METHOD(LuaImmovableDescription, has_attribute),
2082 METHOD(LuaImmovableDescription, probability_to_grow),
2083 {nullptr, nullptr},
2084 };
2085 const PropertyType<LuaImmovableDescription> LuaImmovableDescription::Properties[] = {
2086 PROP_RO(LuaImmovableDescription, species),
2087 PROP_RO(LuaImmovableDescription, buildcost),
2088 PROP_RO(LuaImmovableDescription, editor_category),
2089 PROP_RO(LuaImmovableDescription, terrain_affinity),
2090 PROP_RO(LuaImmovableDescription, owner_type),
2091 PROP_RO(LuaImmovableDescription, size),
2092 {nullptr, nullptr, nullptr},
2093 };
2094
__persist(lua_State * L)2095 void LuaImmovableDescription::__persist(lua_State* L) {
2096 const ImmovableDescr* descr = get();
2097 PERS_STRING("name", descr->name());
2098 }
2099
__unpersist(lua_State * L)2100 void LuaImmovableDescription::__unpersist(lua_State* L) {
2101 std::string name;
2102 UNPERS_STRING("name", name)
2103 const World& world = get_egbase(L).world();
2104 DescriptionIndex idx = world.get_immovable_index(name);
2105 if (idx != INVALID_INDEX) {
2106 set_description_pointer(world.get_immovable_descr(idx));
2107 } else {
2108 const Tribes& tribes = get_egbase(L).tribes();
2109 idx = tribes.safe_immovable_index(name);
2110 set_description_pointer(tribes.get_immovable_descr(idx));
2111 }
2112 }
2113
2114 /* RST
2115 .. attribute:: species
2116
2117 the species name of a tree for editor lists
2118
2119 (RO) the localized species name of the immovable, or an empty string if it has none.
2120 */
get_species(lua_State * L)2121 int LuaImmovableDescription::get_species(lua_State* L) {
2122 lua_pushstring(L, get()->species());
2123 return 1;
2124 }
2125
2126 /* RST
2127 .. attribute:: buildcost
2128
2129 (RO) a table of ware-to-count pairs, describing the build cost for the
2130 immovable.
2131 */
get_buildcost(lua_State * L)2132 int LuaImmovableDescription::get_buildcost(lua_State* L) {
2133 return wares_or_workers_map_to_lua(L, get()->buildcost(), MapObjectType::WARE);
2134 }
2135
2136 /* RST
2137 .. attribute:: editor_category
2138
2139 the name and descname of the editor category of this immovable
2140
2141 (RO) a table with "name" and "descname" entries for the editor category, or nil if it has
2142 none.
2143 */
get_editor_category(lua_State * L)2144 int LuaImmovableDescription::get_editor_category(lua_State* L) {
2145 const EditorCategory* editor_category = get()->editor_category();
2146 if (editor_category != nullptr) {
2147 lua_newtable(L);
2148 lua_pushstring(L, "name");
2149 lua_pushstring(L, editor_category->name());
2150 lua_settable(L, -3);
2151 lua_pushstring(L, "descname");
2152 lua_pushstring(L, editor_category->descname());
2153 lua_settable(L, -3);
2154 } else {
2155 lua_pushnil(L);
2156 }
2157 return 1;
2158 }
2159
2160 /* RST
2161 .. attribute:: terrain_affinity
2162
2163 returns the terrain affinity values for this immovable
2164
2165 (RO) a table containing numbers labeled as pickiness (uint), preferred_fertility (uint),
2166 preferred_humidity (uint), and preferred_temperature (uint),
2167 or nil if the immovable has no terrain affinity.
2168 */
get_terrain_affinity(lua_State * L)2169 int LuaImmovableDescription::get_terrain_affinity(lua_State* L) {
2170 if (get()->has_terrain_affinity()) {
2171 const TerrainAffinity& affinity = get()->terrain_affinity();
2172 lua_newtable(L);
2173 lua_pushstring(L, "pickiness");
2174 lua_pushuint32(L, affinity.pickiness());
2175 lua_settable(L, -3);
2176 lua_pushstring(L, "preferred_fertility");
2177 lua_pushuint32(L, affinity.preferred_fertility());
2178 lua_settable(L, -3);
2179 lua_pushstring(L, "preferred_humidity");
2180 lua_pushuint32(L, affinity.preferred_humidity());
2181 lua_settable(L, -3);
2182 lua_pushstring(L, "preferred_temperature");
2183 lua_pushuint32(L, affinity.preferred_temperature());
2184 lua_settable(L, -3);
2185 } else {
2186 lua_pushnil(L);
2187 }
2188 return 1;
2189 }
2190
2191 /* RST
2192 .. attribute:: owner_type
2193
2194 the owner type of this immovable
2195
2196 (RO) "world" for world immovables and "tribe" for tribe immovables.
2197 */
get_owner_type(lua_State * L)2198 int LuaImmovableDescription::get_owner_type(lua_State* L) {
2199 switch (get()->owner_type()) {
2200 case MapObjectDescr::OwnerType::kWorld:
2201 lua_pushstring(L, "world");
2202 break;
2203 case MapObjectDescr::OwnerType::kTribe:
2204 lua_pushstring(L, "tribe");
2205 break;
2206 }
2207 return 1;
2208 }
2209
2210 /* RST
2211 .. attribute:: size
2212
2213 (RO) The size of this immovable. Can be either of
2214
2215 * :const:`none` -- Example: mushrooms. Immovables will be destroyed when
2216 something else is built on this field.
2217 * :const:`small` -- Example: trees or flags
2218 * :const:`medium` -- Example: Medium sized buildings
2219 * :const:`big` -- Example: Big sized buildings or rocks
2220 */
get_size(lua_State * L)2221 int LuaImmovableDescription::get_size(lua_State* L) {
2222 try {
2223 lua_pushstring(L, BaseImmovable::size_to_string(get()->get_size()));
2224 } catch (std::exception&) {
2225 report_error(L, "Unknown size %i in LuaImmovableDescription::get_size: %s", get()->get_size(),
2226 get()->name().c_str());
2227 }
2228 return 1;
2229 }
2230
2231 /*
2232 ==========================================================
2233 METHODS
2234 ==========================================================
2235 */
2236
2237 /* RST
2238 .. method:: has_attribute
2239
2240 whether the immovable has the given attribute
2241
2242 :arg attribute_name: The attribute that we are checking for.
2243 :type attribute_name: :class:`string`
2244
2245 (RO) true if the immovable has the attribute, false otherwise.
2246 */
has_attribute(lua_State * L)2247 int LuaImmovableDescription::has_attribute(lua_State* L) {
2248 if (lua_gettop(L) != 2) {
2249 report_error(L, "Takes only one argument.");
2250 }
2251 const uint32_t attribute_id = get()->get_attribute_id(luaL_checkstring(L, 2));
2252 lua_pushboolean(L, get()->has_attribute(attribute_id));
2253 return 1;
2254 }
2255
2256 /* RST
2257 .. method:: probability_to_grow
2258
2259 :arg terrain: The terrain that we are checking the probability for.
2260 :type terrain: :class:`wl.map.TerrainDescription`
2261
2262 (RO) A double describing the probability that this tree will grow on the given terrain.
2263 Returns nil if this immovable tree has no terrain affinity (all trees should have one).
2264 */
probability_to_grow(lua_State * L)2265 int LuaImmovableDescription::probability_to_grow(lua_State* L) {
2266 if (lua_gettop(L) != 2) {
2267 report_error(L, "Takes only one argument.");
2268 }
2269 if (get()->has_terrain_affinity()) {
2270 const TerrainDescription* terrain =
2271 (*get_user_class<LuaMaps::LuaTerrainDescription>(L, 2))->get();
2272 lua_pushdouble(L, Widelands::probability_to_grow(get()->terrain_affinity(), *terrain) /
2273 static_cast<double>(Widelands::TerrainAffinity::kPrecisionFactor));
2274 } else {
2275 lua_pushnil(L);
2276 }
2277 return 1;
2278 }
2279
2280 /* RST
2281 BuildingDescription
2282 -------------------
2283
2284 .. class:: BuildingDescription
2285
2286 Child of: :class:`MapObjectDescription`, :class:`ImmovableDescription`
2287
2288 A static description of a tribe's building, so it can be used in help files
2289 without having to access an actual building on the map.
2290 This class contains the properties that are common to all buildings.
2291 Further properties are implemented in the subclasses.
2292 See the parent classes for more properties.
2293 */
2294 const char LuaBuildingDescription::className[] = "BuildingDescription";
2295 const MethodType<LuaBuildingDescription> LuaBuildingDescription::Methods[] = {
2296 {nullptr, nullptr},
2297 };
2298 const PropertyType<LuaBuildingDescription> LuaBuildingDescription::Properties[] = {
2299 PROP_RO(LuaBuildingDescription, buildcost),
2300 PROP_RO(LuaBuildingDescription, buildable),
2301 PROP_RO(LuaBuildingDescription, conquers),
2302 PROP_RO(LuaBuildingDescription, destructible),
2303 PROP_RO(LuaBuildingDescription, enhanced),
2304 PROP_RO(LuaBuildingDescription, enhanced_from),
2305 PROP_RO(LuaBuildingDescription, enhancement_cost),
2306 PROP_RO(LuaBuildingDescription, enhancement),
2307 PROP_RO(LuaBuildingDescription, is_mine),
2308 PROP_RO(LuaBuildingDescription, is_port),
2309 PROP_RO(LuaBuildingDescription, size),
2310 PROP_RO(LuaBuildingDescription, returned_wares),
2311 PROP_RO(LuaBuildingDescription, returned_wares_enhanced),
2312 PROP_RO(LuaBuildingDescription, vision_range),
2313 PROP_RO(LuaBuildingDescription, workarea_radius),
2314 {nullptr, nullptr, nullptr},
2315 };
2316
__persist(lua_State * L)2317 void LuaBuildingDescription::__persist(lua_State* L) {
2318 const BuildingDescr* descr = get();
2319 PERS_STRING("name", descr->name());
2320 }
2321
__unpersist(lua_State * L)2322 void LuaBuildingDescription::__unpersist(lua_State* L) {
2323 std::string name;
2324 UNPERS_STRING("name", name)
2325 const Tribes& tribes = get_egbase(L).tribes();
2326 DescriptionIndex idx = tribes.safe_building_index(name.c_str());
2327 set_description_pointer(tribes.get_building_descr(idx));
2328 }
2329
2330 /*
2331 ==========================================================
2332 PROPERTIES
2333 ==========================================================
2334 */
2335
2336 /* RST
2337 .. attribute:: buildcost
2338
2339 (RO) a list of ware build cost for the building.
2340 */
get_buildcost(lua_State * L)2341 int LuaBuildingDescription::get_buildcost(lua_State* L) {
2342 return wares_or_workers_map_to_lua(L, get()->buildcost(), MapObjectType::WARE);
2343 }
2344
2345 /* RST
2346 .. attribute:: buildable
2347
2348 (RO) true if the building can be built.
2349 */
get_buildable(lua_State * L)2350 int LuaBuildingDescription::get_buildable(lua_State* L) {
2351 lua_pushboolean(L, get()->is_buildable());
2352 return 1;
2353 }
2354
2355 /* RST
2356 .. attribute:: conquers
2357
2358 (RO) the conquer range of the building as an int.
2359 */
get_conquers(lua_State * L)2360 int LuaBuildingDescription::get_conquers(lua_State* L) {
2361 lua_pushinteger(L, get()->get_conquers());
2362 return 1;
2363 }
2364
2365 /* RST
2366 .. attribute:: destructible
2367
2368 (RO) true if the building is destructible.
2369 */
get_destructible(lua_State * L)2370 int LuaBuildingDescription::get_destructible(lua_State* L) {
2371 lua_pushboolean(L, get()->is_destructible());
2372 return 1;
2373 }
2374
2375 /* RST
2376 .. attribute:: enhanced
2377
2378 (RO) true if the building is enhanced from another building.
2379 */
get_enhanced(lua_State * L)2380 int LuaBuildingDescription::get_enhanced(lua_State* L) {
2381 lua_pushboolean(L, get()->is_enhanced());
2382 return 1;
2383 }
2384
2385 /* RST
2386 .. attribute:: enhanced_from
2387
2388 (RO) returns the building that this was enhanced from, or nil if this isn't an enhanced
2389 building.
2390 */
get_enhanced_from(lua_State * L)2391 int LuaBuildingDescription::get_enhanced_from(lua_State* L) {
2392 if (get()->is_enhanced()) {
2393 const DescriptionIndex& enhanced_from = get()->enhanced_from();
2394 EditorGameBase& egbase = get_egbase(L);
2395 assert(egbase.tribes().building_exists(enhanced_from));
2396 return upcasted_map_object_descr_to_lua(L, egbase.tribes().get_building_descr(enhanced_from));
2397 }
2398 lua_pushnil(L);
2399 return 0;
2400 }
2401
2402 /* RST
2403 .. attribute:: enhancement_cost
2404
2405 (RO) a list of ware cost for enhancing to this building type.
2406 */
get_enhancement_cost(lua_State * L)2407 int LuaBuildingDescription::get_enhancement_cost(lua_State* L) {
2408 return wares_or_workers_map_to_lua(L, get()->enhancement_cost(), MapObjectType::WARE);
2409 }
2410
2411 /* RST
2412 .. attribute:: enhancement
2413
2414 (RO) a building description that this building can enhance to.
2415 */
get_enhancement(lua_State * L)2416 int LuaBuildingDescription::get_enhancement(lua_State* L) {
2417 const DescriptionIndex enhancement = get()->enhancement();
2418 if (enhancement == INVALID_INDEX) {
2419 return 0;
2420 }
2421 return upcasted_map_object_descr_to_lua(
2422 L, get_egbase(L).tribes().get_building_descr(enhancement));
2423 }
2424
2425 /* RST
2426 .. attribute:: is_mine
2427
2428 (RO) true if the building is a mine.
2429 */
get_is_mine(lua_State * L)2430 int LuaBuildingDescription::get_is_mine(lua_State* L) {
2431 lua_pushboolean(L, get()->get_ismine());
2432 return 1;
2433 }
2434
2435 /* RST
2436 .. attribute:: is_port
2437
2438 (RO) true if the building is a port.
2439 */
get_is_port(lua_State * L)2440 int LuaBuildingDescription::get_is_port(lua_State* L) {
2441 lua_pushboolean(L, get()->get_isport());
2442 return 1;
2443 }
2444
2445 /* RST
2446 .. attribute:: size
2447
2448 (RO) The size of this building. Can be either of
2449
2450 * :const:`small` -- Small sized buildings
2451 * :const:`medium` -- Medium sized buildings
2452 * :const:`big` -- Big sized buildings
2453 */
get_size(lua_State * L)2454 int LuaBuildingDescription::get_size(lua_State* L) {
2455 try {
2456 lua_pushstring(L, BaseImmovable::size_to_string(get()->get_size()));
2457 } catch (std::exception&) {
2458 report_error(L, "Unknown size %i in LuaBuildingDescription::get_size: %s", get()->get_size(),
2459 get()->name().c_str());
2460 }
2461 return 1;
2462 }
2463
2464 /* RST
2465 .. attribute:: returned_wares
2466
2467 (RO) a list of wares returned upon dismantling.
2468 */
get_returned_wares(lua_State * L)2469 int LuaBuildingDescription::get_returned_wares(lua_State* L) {
2470 return wares_or_workers_map_to_lua(L, get()->returned_wares(), MapObjectType::WARE);
2471 }
2472
2473 /* RST
2474 .. attribute:: returned_wares_enhanced
2475
2476 (RO) a list of wares returned upon dismantling an enhanced building.
2477 */
get_returned_wares_enhanced(lua_State * L)2478 int LuaBuildingDescription::get_returned_wares_enhanced(lua_State* L) {
2479 return wares_or_workers_map_to_lua(L, get()->returned_wares_enhanced(), MapObjectType::WARE);
2480 }
2481
2482 /* RST
2483 .. attribute:: vision range
2484
2485 (RO) the vision_range of the building as an int.
2486 */
get_vision_range(lua_State * L)2487 int LuaBuildingDescription::get_vision_range(lua_State* L) {
2488 lua_pushinteger(L, get()->vision_range());
2489 return 1;
2490 }
2491
2492 /* RST
2493 .. attribute:: workarea_radius
2494
2495 (RO) the first workarea_radius of the building as an int,
2496 nil in case bulding has no workareas
2497 */
get_workarea_radius(lua_State * L)2498 int LuaBuildingDescription::get_workarea_radius(lua_State* L) {
2499 const WorkareaInfo& workareaInfo = get()->workarea_info();
2500 if (!workareaInfo.empty()) {
2501 lua_pushinteger(L, workareaInfo.begin()->first);
2502 } else {
2503 lua_pushnil(L);
2504 }
2505 return 1;
2506 }
2507
2508 /* RST
2509 ConstructionSiteDescription
2510 ---------------------------
2511
2512 .. class:: ConstructionSiteDescription
2513
2514 Child of: :class:`MapObjectDescription`, :class:`ImmovableDescription`,
2515 :class:`BuildingDescription`
2516
2517 A static description of a tribe's constructionsite, so it can be used in help files
2518 without having to access an actual building on the map.
2519 See the parent classes for more properties.
2520 */
2521 const char LuaConstructionSiteDescription::className[] = "ConstructionSiteDescription";
2522 const MethodType<LuaConstructionSiteDescription> LuaConstructionSiteDescription::Methods[] = {
2523 {nullptr, nullptr},
2524 };
2525 const PropertyType<LuaConstructionSiteDescription> LuaConstructionSiteDescription::Properties[] = {
2526 {nullptr, nullptr, nullptr},
2527 };
2528
2529 /* RST
2530 DismantleSiteDescription
2531 ---------------------------
2532
2533 .. class:: DismantleSiteDescription
2534
2535 Child of: :class:`MapObjectDescription`, :class:`ImmovableDescription`,
2536 :class:`BuildingDescription`
2537
2538 A static description of a tribe's dismantlesite, so it can be used in help files
2539 without having to access an actual building on the map.
2540 See the parent classes for more properties.
2541 */
2542 const char LuaDismantleSiteDescription::className[] = "DismantleSiteDescription";
2543 const MethodType<LuaDismantleSiteDescription> LuaDismantleSiteDescription::Methods[] = {
2544 {nullptr, nullptr},
2545 };
2546 const PropertyType<LuaDismantleSiteDescription> LuaDismantleSiteDescription::Properties[] = {
2547 {nullptr, nullptr, nullptr},
2548 };
2549
2550 /* RST
2551 ProductionSiteDescription
2552 -------------------------
2553
2554 .. class:: ProductionSiteDescription
2555
2556 Child of: :class:`MapObjectDescription`, :class:`ImmovableDescription`,
2557 :class:`BuildingDescription`
2558
2559 A static description of a tribe's productionsite, so it can be used in help files
2560 without having to access an actual building on the map.
2561 This class contains the properties for productionsites that have workers.
2562 For militarysites and trainingsites, please use the subclasses.
2563 See the parent classes for more properties.
2564 */
2565 const char LuaProductionSiteDescription::className[] = "ProductionSiteDescription";
2566 const MethodType<LuaProductionSiteDescription> LuaProductionSiteDescription::Methods[] = {
2567 METHOD(LuaProductionSiteDescription, consumed_wares_workers),
2568 METHOD(LuaProductionSiteDescription, produced_wares),
2569 METHOD(LuaProductionSiteDescription, recruited_workers),
2570 {nullptr, nullptr},
2571 };
2572 const PropertyType<LuaProductionSiteDescription> LuaProductionSiteDescription::Properties[] = {
2573 PROP_RO(LuaProductionSiteDescription, inputs),
2574 PROP_RO(LuaProductionSiteDescription, output_ware_types),
2575 PROP_RO(LuaProductionSiteDescription, output_worker_types),
2576 PROP_RO(LuaProductionSiteDescription, production_programs),
2577 PROP_RO(LuaProductionSiteDescription, working_positions),
2578 {nullptr, nullptr, nullptr},
2579 };
2580
2581 /*
2582 ==========================================================
2583 PROPERTIES
2584 ==========================================================
2585 */
2586
2587 /* RST
2588 .. attribute:: inputs
2589
2590 (RO) An array with :class:`LuaWareDescription` containing the wares that
2591 the productionsite needs for its production.
2592 */
get_inputs(lua_State * L)2593 int LuaProductionSiteDescription::get_inputs(lua_State* L) {
2594 lua_newtable(L);
2595 int index = 1;
2596 for (const auto& input_ware : get()->input_wares()) {
2597 lua_pushint32(L, index++);
2598 const WareDescr* descr = get_egbase(L).tribes().get_ware_descr(input_ware.first);
2599 to_lua<LuaWareDescription>(L, new LuaWareDescription(descr));
2600 lua_settable(L, -3);
2601 }
2602 return 1;
2603 }
2604
2605 /* RST
2606 .. attribute:: output_ware_types
2607
2608 (RO) An array with :class:`LuaWareDescription` containing the wares that
2609 the productionsite can produce.
2610 */
get_output_ware_types(lua_State * L)2611 int LuaProductionSiteDescription::get_output_ware_types(lua_State* L) {
2612 lua_newtable(L);
2613 int index = 1;
2614 for (const auto& ware_index : get()->output_ware_types()) {
2615 lua_pushint32(L, index++);
2616 const WareDescr* descr = get_egbase(L).tribes().get_ware_descr(ware_index);
2617 to_lua<LuaWareDescription>(L, new LuaWareDescription(descr));
2618 lua_rawset(L, -3);
2619 }
2620
2621 return 1;
2622 }
2623
2624 /* RST
2625 .. attribute:: output_worker_types
2626
2627 (RO) An array with :class:`LuaWorkerDescription` containing the workers that
2628 the productionsite can produce.
2629 */
get_output_worker_types(lua_State * L)2630 int LuaProductionSiteDescription::get_output_worker_types(lua_State* L) {
2631 lua_newtable(L);
2632 int index = 1;
2633 for (const auto& worker_index : get()->output_worker_types()) {
2634 lua_pushint32(L, index++);
2635 const WorkerDescr* descr = get_egbase(L).tribes().get_worker_descr(worker_index);
2636 to_lua<LuaWorkerDescription>(L, new LuaWorkerDescription(descr));
2637 lua_rawset(L, -3);
2638 }
2639
2640 return 1;
2641 }
2642
2643 /* RST
2644 .. attribute:: production_programs
2645
2646 (RO) An array with the production program names as string.
2647 */
get_production_programs(lua_State * L)2648 int LuaProductionSiteDescription::get_production_programs(lua_State* L) {
2649 lua_newtable(L);
2650 int index = 1;
2651 for (const auto& program : get()->programs()) {
2652 lua_pushint32(L, index++);
2653 lua_pushstring(L, program.first);
2654 lua_settable(L, -3);
2655 }
2656 return 1;
2657 }
2658
2659 /* RST
2660 .. attribute:: working_positions
2661
2662 (RO) An array with :class:`WorkerDescription` containing the workers that
2663 can work here with their multiplicity, i.e. for a atlantean mine this
2664 would be { miner, miner, miner }.
2665 */
get_working_positions(lua_State * L)2666 int LuaProductionSiteDescription::get_working_positions(lua_State* L) {
2667 lua_newtable(L);
2668 int index = 1;
2669 for (const auto& positions_pair : get()->working_positions()) {
2670 int amount = positions_pair.second;
2671 while (amount > 0) {
2672 lua_pushint32(L, index++);
2673 const WorkerDescr* descr = get_egbase(L).tribes().get_worker_descr(positions_pair.first);
2674 to_lua<LuaWorkerDescription>(L, new LuaWorkerDescription(descr));
2675 lua_settable(L, -3);
2676 --amount;
2677 }
2678 }
2679 return 1;
2680 }
2681
2682 /* RST
2683 .. attribute:: consumed_wares_workers
2684
2685 :arg program_name: the name of the production program that we want to get the consumed wares
2686 for :type tribename: :class:`string`
2687
2688 (RO) Returns a table of {{ware name}, ware amount} for the wares consumed by this production
2689 program. Multiple entries in {ware name} are alternatives (OR logic)).
2690 */
consumed_wares_workers(lua_State * L)2691 int LuaProductionSiteDescription::consumed_wares_workers(lua_State* L) {
2692 std::string program_name = luaL_checkstring(L, -1);
2693 const Widelands::ProductionSiteDescr::Programs& programs = get()->programs();
2694 if (programs.count(program_name) == 1) {
2695 const ProductionProgram& program = *programs.at(program_name);
2696 lua_newtable(L);
2697 int counter = 0;
2698 for (const auto& group : program.consumed_wares_workers()) {
2699 lua_pushuint32(L, ++counter);
2700 lua_newtable(L);
2701 for (const auto& entry : group.first) {
2702 const DescriptionIndex& index = entry.first;
2703 if (entry.second == wwWARE) {
2704 lua_pushstring(L, get_egbase(L).tribes().get_ware_descr(index)->name());
2705 } else {
2706 lua_pushstring(L, get_egbase(L).tribes().get_worker_descr(index)->name());
2707 }
2708 lua_pushuint32(L, group.second);
2709 lua_settable(L, -3);
2710 }
2711 lua_settable(L, -3);
2712 }
2713 }
2714 return 1;
2715 }
2716
2717 /* RST
2718 .. attribute:: produced_wares
2719
2720 :arg program_name: the name of the production program that we want to get the produced wares
2721 for :type tribename: :class:`string`
2722
2723 (RO) Returns a table of {ware name, ware amount} for the wares produced by this production
2724 program
2725 */
produced_wares(lua_State * L)2726 int LuaProductionSiteDescription::produced_wares(lua_State* L) {
2727 std::string program_name = luaL_checkstring(L, -1);
2728 const Widelands::ProductionSiteDescr::Programs& programs = get()->programs();
2729 if (programs.count(program_name) == 1) {
2730 const ProductionProgram& program = *programs.at(program_name);
2731 return wares_or_workers_map_to_lua(L, program.produced_wares(), MapObjectType::WARE);
2732 }
2733 return 1;
2734 }
2735
2736 /* RST
2737 .. attribute:: recruited_workers
2738
2739 :arg program_name: the name of the production program that we want to get the recruited
2740 workers for :type tribename: :class:`string`
2741
2742 (RO) Returns a table of {worker name, worker amount} for the workers recruited
2743 by this production program
2744 */
recruited_workers(lua_State * L)2745 int LuaProductionSiteDescription::recruited_workers(lua_State* L) {
2746 std::string program_name = luaL_checkstring(L, -1);
2747 const Widelands::ProductionSiteDescr::Programs& programs = get()->programs();
2748 if (programs.count(program_name) == 1) {
2749 const ProductionProgram& program = *programs.at(program_name);
2750 return wares_or_workers_map_to_lua(L, program.recruited_workers(), MapObjectType::WORKER);
2751 }
2752 return 1;
2753 }
2754
2755 /* RST
2756 MilitarySiteDescription
2757 -----------------------
2758
2759 .. class:: MilitarySiteDescription
2760
2761 Child of: :class:`MapObjectDescription`, :class:`ImmovableDescription`,
2762 :class:`BuildingDescription`
2763
2764 A static description of a tribe's militarysite, so it can be used in help files
2765 without having to access an actual building on the map.
2766 A militarysite can garrison and heal soldiers, and it will expand your territory.
2767 See the parent classes for more properties.
2768 */
2769 const char LuaMilitarySiteDescription::className[] = "MilitarySiteDescription";
2770 const MethodType<LuaMilitarySiteDescription> LuaMilitarySiteDescription::Methods[] = {
2771 {nullptr, nullptr},
2772 };
2773 const PropertyType<LuaMilitarySiteDescription> LuaMilitarySiteDescription::Properties[] = {
2774 PROP_RO(LuaMilitarySiteDescription, heal_per_second),
2775 PROP_RO(LuaMilitarySiteDescription, max_number_of_soldiers),
2776 {nullptr, nullptr, nullptr},
2777 };
2778
2779 /*
2780 ==========================================================
2781 PROPERTIES
2782 ==========================================================
2783 */
2784
2785 /* RST
2786 .. attribute:: heal_per_second
2787
2788 (RO) The number of health healed per second by the militarysite
2789 */
get_heal_per_second(lua_State * L)2790 int LuaMilitarySiteDescription::get_heal_per_second(lua_State* L) {
2791 const MilitarySiteDescr* descr = get();
2792 lua_pushinteger(L, descr->get_heal_per_second());
2793 return 1;
2794 }
2795
2796 /* RST
2797 .. attribute:: max_number_of_soldiers
2798
2799 (RO) The number of soldiers that can be garrisoned at the militarysite
2800 */
get_max_number_of_soldiers(lua_State * L)2801 int LuaMilitarySiteDescription::get_max_number_of_soldiers(lua_State* L) {
2802 const MilitarySiteDescr* descr = get();
2803 lua_pushinteger(L, descr->get_max_number_of_soldiers());
2804 return 1;
2805 }
2806
2807 /* RST
2808 TrainingSiteDescription
2809 -----------------------
2810
2811 .. class:: TrainingSiteDescription
2812
2813 Child of: :class:`MapObjectDescription`, :class:`ImmovableDescription`,
2814 :class:`BuildingDescription`, :class:`ProductionSiteDescription`
2815
2816 A static description of a tribe's trainingsite, so it can be used in help files
2817 without having to access an actual building on the map.
2818 A training site can train some or all of a soldier's properties (Attack, Defense, Evade and
2819 Health). See the parent classes for more properties.
2820 */
2821 const char LuaTrainingSiteDescription::className[] = "TrainingSiteDescription";
2822 const MethodType<LuaTrainingSiteDescription> LuaTrainingSiteDescription::Methods[] = {
2823 {nullptr, nullptr},
2824 };
2825 const PropertyType<LuaTrainingSiteDescription> LuaTrainingSiteDescription::Properties[] = {
2826 PROP_RO(LuaTrainingSiteDescription, food_attack),
2827 PROP_RO(LuaTrainingSiteDescription, food_defense),
2828 PROP_RO(LuaTrainingSiteDescription, food_evade),
2829 PROP_RO(LuaTrainingSiteDescription, food_health),
2830 PROP_RO(LuaTrainingSiteDescription, max_attack),
2831 PROP_RO(LuaTrainingSiteDescription, max_defense),
2832 PROP_RO(LuaTrainingSiteDescription, max_evade),
2833 PROP_RO(LuaTrainingSiteDescription, max_health),
2834 PROP_RO(LuaTrainingSiteDescription, max_number_of_soldiers),
2835 PROP_RO(LuaTrainingSiteDescription, min_attack),
2836 PROP_RO(LuaTrainingSiteDescription, min_defense),
2837 PROP_RO(LuaTrainingSiteDescription, min_evade),
2838 PROP_RO(LuaTrainingSiteDescription, min_health),
2839 PROP_RO(LuaTrainingSiteDescription, weapons_attack),
2840 PROP_RO(LuaTrainingSiteDescription, weapons_defense),
2841 PROP_RO(LuaTrainingSiteDescription, weapons_evade),
2842 PROP_RO(LuaTrainingSiteDescription, weapons_health),
2843 {nullptr, nullptr, nullptr},
2844 };
2845
2846 /*
2847 ==========================================================
2848 PROPERTIES
2849 ==========================================================
2850 */
2851
2852 /* RST
2853 .. attribute:: food_attack
2854
2855 (RO) A table of tables with food ware names used for Attack training,
2856 e.g. {{"barbarians_bread"}, {"fish", "meat"}}
2857 */
get_food_attack(lua_State * L)2858 int LuaTrainingSiteDescription::get_food_attack(lua_State* L) {
2859 return food_list_to_lua(L, get()->get_food_attack());
2860 }
2861
2862 /* RST
2863 .. attribute:: food_defense
2864
2865 (RO) A table of tables with food ware names used for Defense training,
2866 e.g. {{"barbarians_bread"}, {"fish", "meat"}}
2867 */
get_food_defense(lua_State * L)2868 int LuaTrainingSiteDescription::get_food_defense(lua_State* L) {
2869 return food_list_to_lua(L, get()->get_food_defense());
2870 }
2871
2872 /* RST
2873 .. attribute:: food_evade
2874
2875 (RO) A table of tables with food ware names used for Evade training,
2876 e.g. {{"barbarians_bread"}, {"fish", "meat"}}
2877 */
get_food_evade(lua_State * L)2878 int LuaTrainingSiteDescription::get_food_evade(lua_State* L) {
2879 return food_list_to_lua(L, get()->get_food_evade());
2880 }
2881
2882 /* RST
2883 .. attribute:: food_health
2884
2885 (RO) A table of tables with food ware names used for Health training,
2886 e.g. {{"barbarians_bread"}, {"fish", "meat"}}
2887 */
get_food_health(lua_State * L)2888 int LuaTrainingSiteDescription::get_food_health(lua_State* L) {
2889 return food_list_to_lua(L, get()->get_food_health());
2890 }
2891
2892 /* RST
2893 .. attribute:: max_attack
2894
2895 (RO) The number of attack points that a soldier can train
2896 */
get_max_attack(lua_State * L)2897 int LuaTrainingSiteDescription::get_max_attack(lua_State* L) {
2898 const TrainingSiteDescr* descr = get();
2899 if (descr->get_train_attack()) {
2900 lua_pushinteger(L, descr->get_max_level(TrainingAttribute::kAttack));
2901 } else {
2902 lua_pushnil(L);
2903 }
2904 return 1;
2905 }
2906
2907 /* RST
2908 .. attribute:: max_defense
2909
2910 (RO) The number of defense points that a soldier can train
2911 */
get_max_defense(lua_State * L)2912 int LuaTrainingSiteDescription::get_max_defense(lua_State* L) {
2913 const TrainingSiteDescr* descr = get();
2914 if (descr->get_train_defense()) {
2915 lua_pushinteger(L, descr->get_max_level(TrainingAttribute::kDefense));
2916 } else {
2917 lua_pushnil(L);
2918 }
2919 return 1;
2920 }
2921
2922 /* RST
2923 .. attribute:: max_evade
2924
2925 (RO) The number of evade points that a soldier can train
2926 */
get_max_evade(lua_State * L)2927 int LuaTrainingSiteDescription::get_max_evade(lua_State* L) {
2928 const TrainingSiteDescr* descr = get();
2929 if (descr->get_train_evade()) {
2930 lua_pushinteger(L, descr->get_max_level(TrainingAttribute::kEvade));
2931 } else {
2932 lua_pushnil(L);
2933 }
2934 return 1;
2935 }
2936
2937 /* RST
2938 .. attribute:: max_health
2939
2940 (RO) The number of health points that a soldier can train
2941 */
get_max_health(lua_State * L)2942 int LuaTrainingSiteDescription::get_max_health(lua_State* L) {
2943 const TrainingSiteDescr* descr = get();
2944 if (descr->get_train_health()) {
2945 lua_pushinteger(L, descr->get_max_level(TrainingAttribute::kHealth));
2946 } else {
2947 lua_pushnil(L);
2948 }
2949 return 1;
2950 }
2951
2952 /* RST
2953 .. attribute:: max_number_of_soldiers
2954
2955 (RO) The number of soldiers that can be garrisoned at the trainingsite
2956 */
get_max_number_of_soldiers(lua_State * L)2957 int LuaTrainingSiteDescription::get_max_number_of_soldiers(lua_State* L) {
2958 const TrainingSiteDescr* descr = get();
2959 lua_pushinteger(L, descr->get_max_number_of_soldiers());
2960 return 1;
2961 }
2962
2963 /* RST
2964 .. attribute:: min_attack
2965
2966 (RO) The number of attack points that a soldier starts training with
2967 */
get_min_attack(lua_State * L)2968 int LuaTrainingSiteDescription::get_min_attack(lua_State* L) {
2969 const TrainingSiteDescr* descr = get();
2970 if (descr->get_train_attack()) {
2971 lua_pushinteger(L, descr->get_min_level(TrainingAttribute::kAttack));
2972 } else {
2973 lua_pushnil(L);
2974 }
2975 return 1;
2976 }
2977
2978 /* RST
2979 .. attribute:: min_defense
2980
2981 (RO) The number of defense points that a soldier starts training with
2982 */
get_min_defense(lua_State * L)2983 int LuaTrainingSiteDescription::get_min_defense(lua_State* L) {
2984 const TrainingSiteDescr* descr = get();
2985 if (descr->get_train_defense()) {
2986 lua_pushinteger(L, descr->get_min_level(TrainingAttribute::kDefense));
2987 } else {
2988 lua_pushnil(L);
2989 }
2990 return 1;
2991 }
2992
2993 /* RST
2994 .. attribute:: min_evade
2995
2996 (RO) The number of evade points that a soldier starts training with
2997 */
get_min_evade(lua_State * L)2998 int LuaTrainingSiteDescription::get_min_evade(lua_State* L) {
2999 const TrainingSiteDescr* descr = get();
3000 if (descr->get_train_evade()) {
3001 lua_pushinteger(L, descr->get_min_level(TrainingAttribute::kEvade));
3002 } else {
3003 lua_pushnil(L);
3004 }
3005 return 1;
3006 }
3007
3008 /* RST
3009 .. attribute:: min_health
3010
3011 (RO) The number of health points that a soldier starts training with
3012 */
get_min_health(lua_State * L)3013 int LuaTrainingSiteDescription::get_min_health(lua_State* L) {
3014 const TrainingSiteDescr* descr = get();
3015 if (descr->get_train_health()) {
3016 lua_pushinteger(L, descr->get_min_level(TrainingAttribute::kHealth));
3017 } else {
3018 lua_pushnil(L);
3019 }
3020 return 1;
3021 }
3022
3023 /* RST
3024 .. attribute:: weapons_attack
3025
3026 (RO) A table with weapon ware names used for Attack training
3027 */
get_weapons_attack(lua_State * L)3028 int LuaTrainingSiteDescription::get_weapons_attack(lua_State* L) {
3029 lua_newtable(L);
3030 int counter = 0;
3031 for (const std::string& weaponname : get()->get_weapons_attack()) {
3032 lua_pushuint32(L, ++counter);
3033 lua_pushstring(L, weaponname);
3034 lua_settable(L, -3);
3035 }
3036 return 1;
3037 }
3038
3039 /* RST
3040 .. attribute:: weapons_defense
3041
3042 (RO) A table with weapon ware names used for Defense training
3043 */
get_weapons_defense(lua_State * L)3044 int LuaTrainingSiteDescription::get_weapons_defense(lua_State* L) {
3045 lua_newtable(L);
3046 int counter = 0;
3047 for (const std::string& weaponname : get()->get_weapons_defense()) {
3048 lua_pushuint32(L, ++counter);
3049 lua_pushstring(L, weaponname);
3050 lua_settable(L, -3);
3051 }
3052 return 1;
3053 }
3054
3055 /* RST
3056 .. attribute:: weapons_evade
3057
3058 (RO) A table with weapon ware names used for Evade training
3059 */
get_weapons_evade(lua_State * L)3060 int LuaTrainingSiteDescription::get_weapons_evade(lua_State* L) {
3061 lua_newtable(L);
3062 int counter = 0;
3063 for (const std::string& weaponname : get()->get_weapons_evade()) {
3064 lua_pushuint32(L, ++counter);
3065 lua_pushstring(L, weaponname);
3066 lua_settable(L, -3);
3067 }
3068 return 1;
3069 }
3070
3071 /* RST
3072 .. attribute:: weapons_health
3073
3074 (RO) A table with weapon ware names used for Health training
3075 */
get_weapons_health(lua_State * L)3076 int LuaTrainingSiteDescription::get_weapons_health(lua_State* L) {
3077 lua_newtable(L);
3078 int counter = 0;
3079 for (const std::string& weaponname : get()->get_weapons_health()) {
3080 lua_pushuint32(L, ++counter);
3081 lua_pushstring(L, weaponname);
3082 lua_settable(L, -3);
3083 }
3084 return 1;
3085 }
3086
3087 /* RST
3088 WarehouseDescription
3089 --------------------
3090
3091 .. class:: WarehouseDescription
3092
3093 Child of: :class:`MapObjectDescription`, :class:`ImmovableDescription`,
3094 :class:`BuildingDescription`
3095
3096 A static description of a tribe's warehouse, so it can be used in help files
3097 without having to access an actual building on the map.
3098 Note that headquarters are also warehouses.
3099 A warehouse keeps people, animals and wares.
3100 See the parent classes for more properties.
3101 */
3102 const char LuaWarehouseDescription::className[] = "WarehouseDescription";
3103 const MethodType<LuaWarehouseDescription> LuaWarehouseDescription::Methods[] = {
3104 {nullptr, nullptr},
3105 };
3106 const PropertyType<LuaWarehouseDescription> LuaWarehouseDescription::Properties[] = {
3107 PROP_RO(LuaWarehouseDescription, heal_per_second), {nullptr, nullptr, nullptr},
3108 };
3109
3110 /*
3111 ==========================================================
3112 PROPERTIES
3113 ==========================================================
3114 */
3115
3116 /* RST
3117 .. attribute:: heal_per_second
3118
3119 (RO) The number of health healed per second by the warehouse
3120 */
get_heal_per_second(lua_State * L)3121 int LuaWarehouseDescription::get_heal_per_second(lua_State* L) {
3122 const WarehouseDescr* descr = get();
3123 lua_pushinteger(L, descr->get_heal_per_second());
3124 return 1;
3125 }
3126
3127 /* RST
3128 MarketDescription
3129 -----------------
3130
3131 .. class:: MarketDescription
3132
3133 Child of: :class:`MapObjectDescription`, :class:`ImmovableDescription`,
3134 :class:`BuildingDescription`
3135
3136 A static description of a tribe's market, so it can be used in help files
3137 without having to access an actual building on the map. A Market is used for
3138 trading over land with other players. See the parent classes for more
3139 properties.
3140 */
3141 // TODO(sirver,trading): Expose the properties of MarketDescription here once
3142 // the interface settles.
3143 const char LuaMarketDescription::className[] = "MarketDescription";
3144 const MethodType<LuaMarketDescription> LuaMarketDescription::Methods[] = {
3145 {nullptr, nullptr},
3146 };
3147 const PropertyType<LuaMarketDescription> LuaMarketDescription::Properties[] = {
3148 {nullptr, nullptr, nullptr},
3149 };
3150
3151 /*
3152 ==========================================================
3153 PROPERTIES
3154 ==========================================================
3155 */
3156
3157 /* RST
3158 WareDescription
3159 ---------------
3160
3161 .. class:: WareDescription
3162
3163 Child of: :class:`MapObjectDescription`
3164
3165 A static description of a tribe's ware, so it can be used in help files
3166 without having to access an actual instance of the ware on the map.
3167 See also :class:`MapObjectDescription` for more properties.
3168 */
3169 const char LuaWareDescription::className[] = "WareDescription";
3170 const MethodType<LuaWareDescription> LuaWareDescription::Methods[] = {
3171 METHOD(LuaWareDescription, consumers),
3172 METHOD(LuaWareDescription, is_construction_material),
3173 METHOD(LuaWareDescription, producers),
3174 {nullptr, nullptr},
3175 };
3176 const PropertyType<LuaWareDescription> LuaWareDescription::Properties[] = {
3177 {nullptr, nullptr, nullptr},
3178 };
3179
__persist(lua_State * L)3180 void LuaWareDescription::__persist(lua_State* L) {
3181 const WareDescr* descr = get();
3182 PERS_STRING("name", descr->name());
3183 }
3184
__unpersist(lua_State * L)3185 void LuaWareDescription::__unpersist(lua_State* L) {
3186 std::string name;
3187 UNPERS_STRING("name", name)
3188 const Tribes& tribes = get_egbase(L).tribes();
3189 DescriptionIndex idx = tribes.safe_ware_index(name.c_str());
3190 set_description_pointer(tribes.get_ware_descr(idx));
3191 }
3192
3193 /*
3194 ==========================================================
3195 PROPERTIES
3196 ==========================================================
3197 */
3198
3199 /* RST
3200 .. method:: consumers(tribename)
3201
3202 :arg tribename: the name of the tribe that this ware gets checked for
3203 :type tribename: :class:`string`
3204
3205 (RO) An array with :class:`LuaBuildingDescription` with buildings that
3206 need this ware for their production.
3207 */
consumers(lua_State * L)3208 int LuaWareDescription::consumers(lua_State* L) {
3209 if (lua_gettop(L) != 2) {
3210 report_error(L, "Takes only one argument.");
3211 }
3212 const Widelands::TribeDescr& tribe = get_tribe_descr(L, luaL_checkstring(L, 2));
3213
3214 lua_newtable(L);
3215 int index = 1;
3216 for (const DescriptionIndex& building_index : get()->consumers()) {
3217 if (tribe.has_building(building_index)) {
3218 lua_pushint32(L, index++);
3219 upcasted_map_object_descr_to_lua(
3220 L, get_egbase(L).tribes().get_building_descr(building_index));
3221 lua_rawset(L, -3);
3222 }
3223 }
3224 return 1;
3225 }
3226
3227 /* RST
3228 .. method:: is_construction_material(tribename)
3229
3230 :arg tribename: the name of the tribe that this ware gets checked for
3231 :type tribename: :class:`string`
3232
3233 (RO) A bool that is true if this ware is used by the tribe's construction sites.
3234 */
is_construction_material(lua_State * L)3235 int LuaWareDescription::is_construction_material(lua_State* L) {
3236 std::string tribename = luaL_checkstring(L, -1);
3237 const Tribes& tribes = get_egbase(L).tribes();
3238 if (Widelands::tribe_exists(tribename)) {
3239 const DescriptionIndex& ware_index = tribes.safe_ware_index(get()->name());
3240 int tribeindex = tribes.tribe_index(tribename);
3241 lua_pushboolean(L, tribes.get_tribe_descr(tribeindex)->is_construction_material(ware_index));
3242 } else {
3243 lua_pushboolean(L, false);
3244 }
3245 return 1;
3246 }
3247
3248 /* RST
3249 .. method:: producers(tribename)
3250
3251 :arg tribename: the name of the tribe that this ware gets checked for
3252 :type tribename: :class:`string`
3253
3254 (RO) An array with :class:`LuaBuildingDescription` with buildings that
3255 can procude this ware.
3256 */
producers(lua_State * L)3257 int LuaWareDescription::producers(lua_State* L) {
3258 if (lua_gettop(L) != 2) {
3259 report_error(L, "Takes only one argument.");
3260 }
3261 const Widelands::TribeDescr& tribe = get_tribe_descr(L, luaL_checkstring(L, 2));
3262
3263 lua_newtable(L);
3264 int index = 1;
3265 for (const DescriptionIndex& building_index : get()->producers()) {
3266 if (tribe.has_building(building_index)) {
3267 lua_pushint32(L, index++);
3268 upcasted_map_object_descr_to_lua(
3269 L, get_egbase(L).tribes().get_building_descr(building_index));
3270 lua_rawset(L, -3);
3271 }
3272 }
3273 return 1;
3274 }
3275
3276 /* RST
3277 WorkerDescription
3278 -----------------
3279
3280 .. class:: WorkerDescription
3281
3282 Child of: :class:`MapObjectDescription`
3283
3284 A static description of a tribe's worker, so it can be used in help files
3285 without having to access an actual instance of the worker on the map.
3286 See also :class:`MapObjectDescription` for more properties.
3287 */
3288 const char LuaWorkerDescription::className[] = "WorkerDescription";
3289 const MethodType<LuaWorkerDescription> LuaWorkerDescription::Methods[] = {
3290 {nullptr, nullptr},
3291 };
3292 const PropertyType<LuaWorkerDescription> LuaWorkerDescription::Properties[] = {
3293 PROP_RO(LuaWorkerDescription, becomes), PROP_RO(LuaWorkerDescription, buildcost),
3294 PROP_RO(LuaWorkerDescription, employers), PROP_RO(LuaWorkerDescription, buildable),
3295 PROP_RO(LuaWorkerDescription, needed_experience), {nullptr, nullptr, nullptr},
3296 };
3297
__persist(lua_State * L)3298 void LuaWorkerDescription::__persist(lua_State* L) {
3299 const WorkerDescr* descr = get();
3300 PERS_STRING("name", descr->name());
3301 }
3302
__unpersist(lua_State * L)3303 void LuaWorkerDescription::__unpersist(lua_State* L) {
3304 std::string name;
3305 UNPERS_STRING("name", name)
3306 const Tribes& tribes = get_egbase(L).tribes();
3307 DescriptionIndex idx = tribes.safe_worker_index(name.c_str());
3308 set_description_pointer(tribes.get_worker_descr(idx));
3309 }
3310
3311 /*
3312 ==========================================================
3313 PROPERTIES
3314 ==========================================================
3315 */
3316
3317 /* RST
3318 .. attribute:: becomes
3319
3320 (RO) The :class:`WorkerDescription` of the worker this one will level up
3321 to or :const:`nil` if it never levels up.
3322 */
get_becomes(lua_State * L)3323 int LuaWorkerDescription::get_becomes(lua_State* L) {
3324 const DescriptionIndex becomes_index = get()->becomes();
3325 if (becomes_index == INVALID_INDEX) {
3326 lua_pushnil(L);
3327 return 1;
3328 }
3329 return to_lua<LuaWorkerDescription>(
3330 L, new LuaWorkerDescription(get_egbase(L).tribes().get_worker_descr(becomes_index)));
3331 }
3332
3333 /* RST
3334 .. attribute:: buildcost
3335
3336 (RO) a list of building requirements, e.g. {"atlanteans_carrier", "ax"}
3337 */
get_buildcost(lua_State * L)3338 int LuaWorkerDescription::get_buildcost(lua_State* L) {
3339 lua_newtable(L);
3340 int index = 1;
3341 if (get()->is_buildable()) {
3342 for (const auto& buildcost_pair : get()->buildcost()) {
3343 lua_pushint32(L, index++);
3344 lua_pushstring(L, buildcost_pair.first);
3345 lua_settable(L, -3);
3346 }
3347 }
3348 return 1;
3349 }
3350
3351 /* RST
3352 .. attribute:: employers
3353
3354 (RO) An array with :class:`LuaBuildingDescription` with buildings where
3355 this worker can be employed.
3356 */
get_employers(lua_State * L)3357 int LuaWorkerDescription::get_employers(lua_State* L) {
3358 lua_newtable(L);
3359 int index = 1;
3360 for (const DescriptionIndex& building_index : get()->employers()) {
3361 lua_pushint32(L, index++);
3362 upcasted_map_object_descr_to_lua(
3363 L, get_egbase(L).tribes().get_building_descr(building_index));
3364 lua_rawset(L, -3);
3365 }
3366 return 1;
3367 }
3368
3369 /* RST
3370 .. attribute:: buildable
3371
3372 (RO) returns true if this worker is buildable
3373 */
get_buildable(lua_State * L)3374 int LuaWorkerDescription::get_buildable(lua_State* L) {
3375 lua_pushboolean(L, get()->is_buildable());
3376 return 1;
3377 }
3378
3379 /* RST
3380 .. attribute:: needed_experience
3381
3382 (RO) the experience the worker needs to reach this level.
3383 */
get_needed_experience(lua_State * L)3384 int LuaWorkerDescription::get_needed_experience(lua_State* L) {
3385 lua_pushinteger(L, get()->get_needed_experience());
3386 return 1;
3387 }
3388
3389 /* RST
3390 SoldierDescription
3391 --------------------
3392
3393 .. class:: SoldierDescription
3394
3395 Child of: :class:`MapObjectDescription`, :class:`WorkerDescription`
3396
3397 A static description of a tribe's soldier, so it can be used in help files
3398 without having to access an actual instance of the worker on the map.
3399 See the parent classes for more properties.
3400 */
3401 const char LuaSoldierDescription::className[] = "SoldierDescription";
3402 const MethodType<LuaSoldierDescription> LuaSoldierDescription::Methods[] = {
3403 {nullptr, nullptr},
3404 };
3405 const PropertyType<LuaSoldierDescription> LuaSoldierDescription::Properties[] = {
3406 PROP_RO(LuaSoldierDescription, max_health_level),
3407 PROP_RO(LuaSoldierDescription, max_attack_level),
3408 PROP_RO(LuaSoldierDescription, max_defense_level),
3409 PROP_RO(LuaSoldierDescription, max_evade_level),
3410 PROP_RO(LuaSoldierDescription, base_health),
3411 PROP_RO(LuaSoldierDescription, base_min_attack),
3412 PROP_RO(LuaSoldierDescription, base_max_attack),
3413 PROP_RO(LuaSoldierDescription, base_defense),
3414 PROP_RO(LuaSoldierDescription, base_evade),
3415 PROP_RO(LuaSoldierDescription, health_incr_per_level),
3416 PROP_RO(LuaSoldierDescription, attack_incr_per_level),
3417 PROP_RO(LuaSoldierDescription, defense_incr_per_level),
3418 PROP_RO(LuaSoldierDescription, evade_incr_per_level),
3419 {nullptr, nullptr, nullptr},
3420 };
3421
3422 /*
3423 ==========================================================
3424 PROPERTIES
3425 ==========================================================
3426 */
3427
3428 /* RST
3429 .. attribute:: get_max_health_level
3430
3431 (RO) The maximum health level that the soldier can have.
3432 */
get_max_health_level(lua_State * L)3433 int LuaSoldierDescription::get_max_health_level(lua_State* L) {
3434 lua_pushinteger(L, get()->get_max_health_level());
3435 return 1;
3436 }
3437
3438 /* RST
3439 .. attribute:: max_attack_level
3440
3441 (RO) The maximum attack level that the soldier can have.
3442 */
get_max_attack_level(lua_State * L)3443 int LuaSoldierDescription::get_max_attack_level(lua_State* L) {
3444 lua_pushinteger(L, get()->get_max_attack_level());
3445 return 1;
3446 }
3447
3448 /* RST
3449 .. attribute:: max_defense_level
3450
3451 (RO) The maximum defense level that the soldier can have.
3452 */
get_max_defense_level(lua_State * L)3453 int LuaSoldierDescription::get_max_defense_level(lua_State* L) {
3454 lua_pushinteger(L, get()->get_max_defense_level());
3455 return 1;
3456 }
3457
3458 /* RST
3459 .. attribute:: max_evade_level
3460
3461 (RO) The maximum evade level that the soldier can have.
3462 */
get_max_evade_level(lua_State * L)3463 int LuaSoldierDescription::get_max_evade_level(lua_State* L) {
3464 lua_pushinteger(L, get()->get_max_evade_level());
3465 return 1;
3466 }
3467
3468 /* RST
3469 .. attribute:: get_base_health
3470
3471 (RO) The health points that the soldier starts with
3472 */
get_base_health(lua_State * L)3473 int LuaSoldierDescription::get_base_health(lua_State* L) {
3474 lua_pushinteger(L, get()->get_base_health());
3475 return 1;
3476 }
3477
3478 /* RST
3479 .. attribute:: base_min_attack
3480
3481 (RO) The minimum random attack points that get added to a soldier's attack
3482 */
get_base_min_attack(lua_State * L)3483 int LuaSoldierDescription::get_base_min_attack(lua_State* L) {
3484 lua_pushinteger(L, get()->get_base_min_attack());
3485 return 1;
3486 }
3487
3488 /* RST
3489 .. attribute:: base_max_attack
3490
3491 (RO) The maximum random attack points that get added to a soldier's attack
3492 */
get_base_max_attack(lua_State * L)3493 int LuaSoldierDescription::get_base_max_attack(lua_State* L) {
3494 lua_pushinteger(L, get()->get_base_max_attack());
3495 return 1;
3496 }
3497
3498 /* RST
3499 .. attribute:: base_defense
3500
3501 (RO) The defense % that the soldier starts with
3502 */
get_base_defense(lua_State * L)3503 int LuaSoldierDescription::get_base_defense(lua_State* L) {
3504 lua_pushinteger(L, get()->get_base_defense());
3505 return 1;
3506 }
3507
3508 /* RST
3509 .. attribute:: base_evade
3510
3511 (RO) The evade % that the soldier starts with
3512 */
get_base_evade(lua_State * L)3513 int LuaSoldierDescription::get_base_evade(lua_State* L) {
3514 lua_pushinteger(L, get()->get_base_evade());
3515 return 1;
3516 }
3517
3518 /* RST
3519 .. attribute:: get_health_incr_per_level
3520
3521 (RO) The health points that the soldier will gain with each level.
3522 */
get_health_incr_per_level(lua_State * L)3523 int LuaSoldierDescription::get_health_incr_per_level(lua_State* L) {
3524 lua_pushinteger(L, get()->get_health_incr_per_level());
3525 return 1;
3526 }
3527
3528 /* RST
3529 .. attribute:: attack_incr_per_level
3530
3531 (RO) The attack points that the soldier will gain with each level.
3532 */
get_attack_incr_per_level(lua_State * L)3533 int LuaSoldierDescription::get_attack_incr_per_level(lua_State* L) {
3534 lua_pushinteger(L, get()->get_attack_incr_per_level());
3535 return 1;
3536 }
3537
3538 /* RST
3539 .. attribute:: defense_incr_per_level
3540
3541 (RO) The defense % that the soldier will gain with each level.
3542 */
get_defense_incr_per_level(lua_State * L)3543 int LuaSoldierDescription::get_defense_incr_per_level(lua_State* L) {
3544 lua_pushinteger(L, get()->get_defense_incr_per_level());
3545 return 1;
3546 }
3547
3548 /* RST
3549 .. attribute:: evade_incr_per_level
3550
3551 (RO) The evade % that the soldier will gain with each level.
3552 */
get_evade_incr_per_level(lua_State * L)3553 int LuaSoldierDescription::get_evade_incr_per_level(lua_State* L) {
3554 lua_pushinteger(L, get()->get_evade_incr_per_level());
3555 return 1;
3556 }
3557
3558 /* RST
3559 ResourceDescription
3560 --------------------
3561 .. class:: ResourceDescription
3562
3563 A static description of a resource.
3564 */
3565 const char LuaResourceDescription::className[] = "ResourceDescription";
3566 const MethodType<LuaResourceDescription> LuaResourceDescription::Methods[] = {
3567 METHOD(LuaResourceDescription, editor_image), {nullptr, nullptr},
3568 };
3569 const PropertyType<LuaResourceDescription> LuaResourceDescription::Properties[] = {
3570 PROP_RO(LuaResourceDescription, name),
3571 PROP_RO(LuaResourceDescription, descname),
3572 PROP_RO(LuaResourceDescription, is_detectable),
3573 PROP_RO(LuaResourceDescription, max_amount),
3574 PROP_RO(LuaResourceDescription, representative_image),
3575 {nullptr, nullptr, nullptr},
3576 };
3577
__persist(lua_State * L)3578 void LuaResourceDescription::__persist(lua_State* L) {
3579 const Widelands::ResourceDescription* descr = get();
3580 PERS_STRING("name", descr->name());
3581 }
3582
__unpersist(lua_State * L)3583 void LuaResourceDescription::__unpersist(lua_State* L) {
3584 std::string name;
3585 UNPERS_STRING("name", name)
3586 const World& world = get_egbase(L).world();
3587 const ResourceDescription* descr = world.get_resource(world.safe_resource_index(name.c_str()));
3588 set_description_pointer(descr);
3589 }
3590
3591 /*
3592 ==========================================================
3593 PROPERTIES
3594 ==========================================================
3595 */
3596
3597 /* RST
3598 .. attribute:: name
3599
3600 (RO) the :class:`string` internal name of this resource
3601 */
3602
get_name(lua_State * L)3603 int LuaResourceDescription::get_name(lua_State* L) {
3604 lua_pushstring(L, get()->name());
3605 return 1;
3606 }
3607
3608 /* RST
3609 .. attribute:: descname
3610
3611 (RO) the :class:`string` display name of this resource
3612 */
3613
get_descname(lua_State * L)3614 int LuaResourceDescription::get_descname(lua_State* L) {
3615 lua_pushstring(L, get()->descname());
3616 return 1;
3617 }
3618
3619 /* RST
3620 .. attribute:: is_detectable
3621
3622 (RO) true if geologists can find this resource
3623 */
3624
get_is_detectable(lua_State * L)3625 int LuaResourceDescription::get_is_detectable(lua_State* L) {
3626 lua_pushboolean(L, get()->detectable());
3627 return 1;
3628 }
3629
3630 /* RST
3631 .. attribute:: max_amount
3632
3633 (RO) the maximum amount of this resource that a terrain can have
3634 */
3635
get_max_amount(lua_State * L)3636 int LuaResourceDescription::get_max_amount(lua_State* L) {
3637 lua_pushinteger(L, get()->max_amount());
3638 return 1;
3639 }
3640
3641 /* RST
3642 .. attribute:: representative_image
3643
3644 (RO) the :class:`string` path to the image representing this resource in the GUI
3645 */
get_representative_image(lua_State * L)3646 int LuaResourceDescription::get_representative_image(lua_State* L) {
3647 lua_pushstring(L, get()->representative_image());
3648 return 1;
3649 }
3650
3651 /*
3652 ==========================================================
3653 METHODS
3654 ==========================================================
3655 */
3656
3657 /* RST
3658 .. method:: editor_image(amount)
3659
3660 :arg amount: The amount of the resource what we want an overlay image for
3661
3662 (RO) the :class:`string` path to the image representing the specified amount of this
3663 resource
3664 */
editor_image(lua_State * L)3665 int LuaResourceDescription::editor_image(lua_State* L) {
3666 if (lua_gettop(L) != 2) {
3667 report_error(L, "Takes only one argument.");
3668 }
3669 const uint32_t amount = luaL_checkuint32(L, 2);
3670 lua_pushstring(L, get()->editor_image(amount));
3671 return 1;
3672 }
3673
3674 /* RST
3675 TerrainDescription
3676 --------------------
3677 .. class:: TerrainDescription
3678
3679 A static description of a terrain.
3680 */
3681 const char LuaTerrainDescription::className[] = "TerrainDescription";
3682 const MethodType<LuaTerrainDescription> LuaTerrainDescription::Methods[] = {
3683 {nullptr, nullptr},
3684 };
3685 const PropertyType<LuaTerrainDescription> LuaTerrainDescription::Properties[] = {
3686 PROP_RO(LuaTerrainDescription, name),
3687 PROP_RO(LuaTerrainDescription, descname),
3688 PROP_RO(LuaTerrainDescription, default_resource),
3689 PROP_RO(LuaTerrainDescription, default_resource_amount),
3690 PROP_RO(LuaTerrainDescription, editor_category),
3691 PROP_RO(LuaTerrainDescription, fertility),
3692 PROP_RO(LuaTerrainDescription, humidity),
3693 PROP_RO(LuaTerrainDescription, representative_image),
3694 PROP_RO(LuaTerrainDescription, temperature),
3695 PROP_RO(LuaTerrainDescription, valid_resources),
3696 {nullptr, nullptr, nullptr},
3697 };
3698
__persist(lua_State * L)3699 void LuaTerrainDescription::__persist(lua_State* L) {
3700 const Widelands::TerrainDescription* descr = get();
3701 PERS_STRING("name", descr->name());
3702 }
3703
__unpersist(lua_State * L)3704 void LuaTerrainDescription::__unpersist(lua_State* L) {
3705 std::string name;
3706 UNPERS_STRING("name", name)
3707 set_description_pointer(get_egbase(L).world().terrain_descr(name));
3708 }
3709
3710 /*
3711 ==========================================================
3712 PROPERTIES
3713 ==========================================================
3714 */
3715
3716 /* RST
3717 .. attribute:: name
3718
3719 (RO) the :class:`string` internal name of this terrain
3720 */
3721
get_name(lua_State * L)3722 int LuaTerrainDescription::get_name(lua_State* L) {
3723 lua_pushstring(L, get()->name());
3724 return 1;
3725 }
3726
3727 /* RST
3728 .. attribute:: descname
3729
3730 (RO) the :class:`string` display name of this terrain
3731 */
3732
get_descname(lua_State * L)3733 int LuaTerrainDescription::get_descname(lua_State* L) {
3734 lua_pushstring(L, get()->descname());
3735 return 1;
3736 }
3737
3738 /* RST
3739 .. attribute:: get_default_resource
3740
3741 (RO) the :class:`wl.map.ResourceDescription` for the default resource provided by this
3742 terrain, or nil if the terrain has no default resource.
3743 */
3744
get_default_resource(lua_State * L)3745 int LuaTerrainDescription::get_default_resource(lua_State* L) {
3746 DescriptionIndex res_index = get()->get_default_resource();
3747 const World& world = get_egbase(L).world();
3748 if (res_index != Widelands::kNoResource && res_index < world.get_nr_resources()) {
3749 to_lua<LuaMaps::LuaResourceDescription>(
3750 L, new LuaMaps::LuaResourceDescription(world.get_resource(res_index)));
3751 } else {
3752 lua_pushnil(L);
3753 }
3754 return 1;
3755 }
3756
3757 /* RST
3758 .. attribute:: default_resource_amount
3759
3760 (RO) the int amount of the default resource provided by this terrain.
3761 */
3762
get_default_resource_amount(lua_State * L)3763 int LuaTerrainDescription::get_default_resource_amount(lua_State* L) {
3764 lua_pushinteger(L, get()->get_default_resource_amount());
3765 return 1;
3766 }
3767
3768 /* RST
3769 .. attribute:: the name and descname of the editor category of this terrain
3770
3771 (RO) a table with "name" and "descname" entries for the editor category, or nil if it has
3772 none.
3773 */
get_editor_category(lua_State * L)3774 int LuaTerrainDescription::get_editor_category(lua_State* L) {
3775 const EditorCategory* editor_category = get()->editor_category();
3776 if (editor_category != nullptr) {
3777 lua_newtable(L);
3778 lua_pushstring(L, "name");
3779 lua_pushstring(L, editor_category->name());
3780 lua_settable(L, -3);
3781 lua_pushstring(L, "descname");
3782 lua_pushstring(L, editor_category->descname());
3783 lua_settable(L, -3);
3784 } else {
3785 lua_pushnil(L);
3786 }
3787 return 1;
3788 }
3789
3790 /* RST
3791 .. attribute:: fertility
3792
3793 (RO) the :class:`uint` fertility value for this terrain
3794 */
3795
get_fertility(lua_State * L)3796 int LuaTerrainDescription::get_fertility(lua_State* L) {
3797 lua_pushuint32(L, get()->fertility());
3798 return 1;
3799 }
3800
3801 /* RST
3802 .. attribute:: humidity
3803
3804 (RO) the :class:`uint` humidity value for this terrain
3805 */
3806
get_humidity(lua_State * L)3807 int LuaTerrainDescription::get_humidity(lua_State* L) {
3808 lua_pushuint32(L, get()->humidity());
3809 return 1;
3810 }
3811
3812 /* RST
3813 .. attribute:: representative_image
3814
3815 (RO) the :class:`string` file path to a representative image
3816 */
get_representative_image(lua_State * L)3817 int LuaTerrainDescription::get_representative_image(lua_State* L) {
3818 lua_pushstring(L, get()->texture_paths().front());
3819 return 1;
3820 }
3821
3822 /* RST
3823 .. attribute:: temperature
3824
3825 (RO) the :class:`uint` temperature value for this terrain
3826 */
3827
get_temperature(lua_State * L)3828 int LuaTerrainDescription::get_temperature(lua_State* L) {
3829 lua_pushuint32(L, get()->temperature());
3830 return 1;
3831 }
3832
3833 /* RST
3834 .. attribute:: valid_resources
3835
3836 (RO) a list of :class:`wl.map.ResourceDescription` with all valid resources for this
3837 terrain.
3838 */
3839
get_valid_resources(lua_State * L)3840 int LuaTerrainDescription::get_valid_resources(lua_State* L) {
3841 const World& world = get_egbase(L).world();
3842 lua_newtable(L);
3843 int index = 1;
3844 for (DescriptionIndex res_index : get()->valid_resources()) {
3845 if (res_index != Widelands::kNoResource && res_index < world.get_nr_resources()) {
3846 lua_pushint32(L, index++);
3847 to_lua<LuaMaps::LuaResourceDescription>(
3848 L, new LuaMaps::LuaResourceDescription(world.get_resource(res_index)));
3849 lua_settable(L, -3);
3850 }
3851 }
3852 return 1;
3853 }
3854
3855 /*
3856 ==========================================================
3857 METHODS
3858 ==========================================================
3859 */
3860
3861 /* RST
3862 Economy
3863 -------
3864 .. class:: LuaEconomy
3865
3866 Provides access to an economy. A player can have multiple economies;
3867 you can get an economy from a :class:`Flag`.
3868 */
3869 const char LuaEconomy::className[] = "Economy";
3870 const MethodType<LuaEconomy> LuaEconomy::Methods[] = {
3871 METHOD(LuaEconomy, target_quantity), METHOD(LuaEconomy, set_target_quantity), {nullptr, nullptr},
3872 };
3873 const PropertyType<LuaEconomy> LuaEconomy::Properties[] = {
3874 {nullptr, nullptr, nullptr},
3875 };
3876
__persist(lua_State * L)3877 void LuaEconomy::__persist(lua_State* L) {
3878 const Widelands::Economy* economy = get();
3879 const Widelands::Player& player = economy->owner();
3880 PERS_UINT32("player", player.player_number());
3881 PERS_UINT32("economy", economy->serial());
3882 }
3883
__unpersist(lua_State * L)3884 void LuaEconomy::__unpersist(lua_State* L) {
3885 Widelands::PlayerNumber player_number;
3886 Widelands::Serial economy_serial;
3887 UNPERS_UINT32("player", player_number)
3888 UNPERS_UINT32("economy", economy_serial)
3889 const Widelands::Player& player = get_egbase(L).player(player_number);
3890 set_economy_pointer(player.get_economy(economy_serial));
3891 }
3892
3893 /* RST
3894 .. method:: target_quantity(name)
3895
3896 Returns the amount of the given ware or worker that should be kept in stock for this economy.
3897 Whether this works only for wares or only for workers is determined by the type of this
3898 economy.
3899
3900 **Warning**: Since economies can disappear when a player merges them
3901 through placing/deleting roads and flags, you must get a fresh economy
3902 object every time you use this function.
3903
3904 :arg name: the name of the ware or worker.
3905 :type name: :class:`string`
3906 */
target_quantity(lua_State * L)3907 int LuaEconomy::target_quantity(lua_State* L) {
3908 const std::string wname = luaL_checkstring(L, 2);
3909 switch (get()->type()) {
3910 case Widelands::wwWARE: {
3911 const Widelands::DescriptionIndex index = get_egbase(L).tribes().ware_index(wname);
3912 if (get_egbase(L).tribes().ware_exists(index)) {
3913 const Widelands::Economy::TargetQuantity& quantity = get()->target_quantity(index);
3914 lua_pushinteger(L, quantity.permanent);
3915 } else {
3916 report_error(L, "There is no ware '%s'.", wname.c_str());
3917 }
3918 break;
3919 }
3920 case Widelands::wwWORKER: {
3921 const Widelands::DescriptionIndex index = get_egbase(L).tribes().worker_index(wname);
3922 if (get_egbase(L).tribes().worker_exists(index)) {
3923 const Widelands::Economy::TargetQuantity& quantity = get()->target_quantity(index);
3924 lua_pushinteger(L, quantity.permanent);
3925 } else {
3926 report_error(L, "There is no worker '%s'.", wname.c_str());
3927 }
3928 break;
3929 }
3930 }
3931 return 1;
3932 }
3933
3934 /* RST
3935 .. method:: set_target_quantity(name)
3936
3937 Sets the amount of the given ware or worker type that should be kept in stock for this
3938 economy. Whether this works only for wares or only for workers is determined by the type of
3939 this economy.
3940
3941 **Warning**: Since economies can disappear when a player merges them
3942 through placing/deleting roads and flags, you must get a fresh economy
3943 object every time you use this function.
3944
3945 :arg workername: the name of the worker type.
3946 :type workername: :class:`string`
3947
3948 :arg amount: the new target amount for the worker. Needs to be >= 0.
3949 :type amount: :class:`integer`
3950 */
set_target_quantity(lua_State * L)3951 int LuaEconomy::set_target_quantity(lua_State* L) {
3952 const std::string wname = luaL_checkstring(L, 2);
3953 switch (get()->type()) {
3954 case Widelands::wwWARE: {
3955 const Widelands::DescriptionIndex index = get_egbase(L).tribes().ware_index(wname);
3956 if (get_egbase(L).tribes().ware_exists(index)) {
3957 const int quantity = luaL_checkinteger(L, 3);
3958 if (quantity < 0) {
3959 report_error(L, "Target ware quantity needs to be >= 0 but was '%d'.", quantity);
3960 }
3961 get()->set_target_quantity(index, quantity, get_egbase(L).get_gametime());
3962 } else {
3963 report_error(L, "There is no ware '%s'.", wname.c_str());
3964 }
3965 break;
3966 }
3967 case Widelands::wwWORKER: {
3968 const Widelands::DescriptionIndex index = get_egbase(L).tribes().worker_index(wname);
3969 if (get_egbase(L).tribes().worker_exists(index)) {
3970 const int quantity = luaL_checkinteger(L, 3);
3971 if (quantity < 0) {
3972 report_error(L, "Target worker quantity needs to be >= 0 but was '%d'.", quantity);
3973 }
3974 get()->set_target_quantity(index, quantity, get_egbase(L).get_gametime());
3975 } else {
3976 report_error(L, "There is no worker '%s'.", wname.c_str());
3977 }
3978 break;
3979 }
3980 }
3981 return 1;
3982 }
3983
3984 /* RST
3985 MapObject
3986 ---------
3987
3988 .. class:: MapObject
3989
3990 This is the base class for all objects in Widelands, including
3991 :class:`immovables <BaseImmovable>` and :class:`bobs <Bob>`. This
3992 class can't be instantiated directly, but provides the base for all
3993 others.
3994
3995 More properties are available through this object's
3996 :class:`MapObjectDescription`, which you can access via :any:`MapObject.descr`.
3997 */
3998 const char LuaMapObject::className[] = "MapObject";
3999 const MethodType<LuaMapObject> LuaMapObject::Methods[] = {
4000 METHOD(LuaMapObject, remove), METHOD(LuaMapObject, destroy),
4001 METHOD(LuaMapObject, __eq), METHOD(LuaMapObject, has_attribute),
4002 {nullptr, nullptr},
4003 };
4004 const PropertyType<LuaMapObject> LuaMapObject::Properties[] = {
4005 PROP_RO(LuaMapObject, __hash),
4006 PROP_RO(LuaMapObject, descr),
4007 PROP_RO(LuaMapObject, serial),
4008 {nullptr, nullptr, nullptr},
4009 };
4010
__persist(lua_State * L)4011 void LuaMapObject::__persist(lua_State* L) {
4012 MapObjectSaver& mos = *get_mos(L);
4013 Game& game = get_game(L);
4014
4015 uint32_t idx = 0;
4016 if (MapObject* obj = ptr_.get(game)) {
4017 idx = mos.get_object_file_index(*obj);
4018 }
4019
4020 PERS_UINT32("file_index", idx);
4021 }
__unpersist(lua_State * L)4022 void LuaMapObject::__unpersist(lua_State* L) {
4023 uint32_t idx;
4024 UNPERS_UINT32("file_index", idx)
4025
4026 if (!idx) {
4027 ptr_ = nullptr;
4028 } else {
4029 MapObjectLoader& mol = *get_mol(L);
4030 ptr_ = &mol.get<MapObject>(idx);
4031 }
4032 }
4033
4034 /*
4035 ==========================================================
4036 PROPERTIES
4037 ==========================================================
4038 */
4039 /* RST
4040 .. attribute:: __hash
4041
4042 (RO) The map object's serial. Used to identify a class in a Set.
4043 */
get___hash(lua_State * L)4044 int LuaMapObject::get___hash(lua_State* L) {
4045 lua_pushuint32(L, get(L, get_egbase(L))->serial());
4046 return 1;
4047 }
4048
4049 /* RST
4050 .. attribute:: serial
4051
4052 (RO) The serial number of this object. Note that this value does not stay
4053 constant after saving/loading.
4054 */
get_serial(lua_State * L)4055 int LuaMapObject::get_serial(lua_State* L) {
4056 lua_pushuint32(L, get(L, get_egbase(L))->serial());
4057 return 1;
4058 }
4059
4060 // use the dynamic type of BuildingDescription
4061 #define CAST_TO_LUA(klass, lua_klass) \
4062 to_lua<lua_klass>(L, new lua_klass(static_cast<const klass*>(desc)))
4063
4064 /* RST
4065 .. attribute:: descr
4066
4067 (RO) The description object for this immovable, e.g. BuildingDescription.
4068 */
get_descr(lua_State * L)4069 int LuaMapObject::get_descr(lua_State* L) {
4070 const MapObjectDescr* desc = &get(L, get_egbase(L))->descr();
4071 assert(desc != nullptr);
4072
4073 switch (desc->type()) {
4074 case MapObjectType::BUILDING:
4075 return CAST_TO_LUA(BuildingDescr, LuaBuildingDescription);
4076 case MapObjectType::CONSTRUCTIONSITE:
4077 return CAST_TO_LUA(ConstructionSiteDescr, LuaConstructionSiteDescription);
4078 case MapObjectType::DISMANTLESITE:
4079 return CAST_TO_LUA(DismantleSiteDescr, LuaDismantleSiteDescription);
4080 case MapObjectType::PRODUCTIONSITE:
4081 return CAST_TO_LUA(ProductionSiteDescr, LuaProductionSiteDescription);
4082 case MapObjectType::MILITARYSITE:
4083 return CAST_TO_LUA(MilitarySiteDescr, LuaMilitarySiteDescription);
4084 case MapObjectType::TRAININGSITE:
4085 return CAST_TO_LUA(TrainingSiteDescr, LuaTrainingSiteDescription);
4086 case MapObjectType::WAREHOUSE:
4087 return CAST_TO_LUA(WarehouseDescr, LuaWarehouseDescription);
4088 case MapObjectType::MARKET:
4089 return CAST_TO_LUA(MarketDescr, LuaMarketDescription);
4090 case MapObjectType::IMMOVABLE:
4091 return CAST_TO_LUA(ImmovableDescr, LuaImmovableDescription);
4092 case MapObjectType::WORKER:
4093 case MapObjectType::CARRIER:
4094 case MapObjectType::FERRY:
4095 case MapObjectType::SOLDIER:
4096 return CAST_TO_LUA(WorkerDescr, LuaWorkerDescription);
4097 case MapObjectType::MAPOBJECT:
4098 case MapObjectType::BATTLE:
4099 case MapObjectType::BOB:
4100 case MapObjectType::CRITTER:
4101 case MapObjectType::FERRY_FLEET:
4102 case MapObjectType::SHIP_FLEET:
4103 case MapObjectType::SHIP:
4104 case MapObjectType::FLAG:
4105 case MapObjectType::ROAD:
4106 case MapObjectType::WATERWAY:
4107 case MapObjectType::ROADBASE:
4108 case MapObjectType::PORTDOCK:
4109 case MapObjectType::WARE:
4110 return CAST_TO_LUA(MapObjectDescr, LuaMapObjectDescription);
4111 }
4112 NEVER_HERE();
4113 }
4114
4115 #undef CAST_TO_LUA
4116
4117 /*
4118 ==========================================================
4119 LUA METHODS
4120 ==========================================================
4121 */
__eq(lua_State * L)4122 int LuaMapObject::__eq(lua_State* L) {
4123 EditorGameBase& egbase = get_egbase(L);
4124 LuaMapObject* other = *get_base_user_class<LuaMapObject>(L, -1);
4125
4126 MapObject* me = get_or_zero(egbase);
4127 MapObject* you = other->get_or_zero(egbase);
4128
4129 // Both objects are destroyed (nullptr) or equal: they are equal
4130 if (me == you) {
4131 lua_pushboolean(L, true);
4132 } else if (me == nullptr ||
4133 you == nullptr) { // One of the objects is destroyed: they are distinct
4134 lua_pushboolean(L, false);
4135 } else { // Compare their serial number.
4136 lua_pushboolean(L, other->get(L, egbase)->serial() == get(L, egbase)->serial());
4137 }
4138
4139 return 1;
4140 }
4141
4142 /* RST
4143 .. method:: remove()
4144
4145 Removes this object immediately. If you want to destroy an
4146 object as if the player had see :func:`destroy`.
4147 */
remove(lua_State * L)4148 int LuaMapObject::remove(lua_State* L) {
4149 EditorGameBase& egbase = get_egbase(L);
4150 MapObject* o = get(L, egbase);
4151 if (!o) {
4152 return 0;
4153 }
4154
4155 o->remove(egbase);
4156 return 0;
4157 }
4158
4159 /* RST
4160 .. method:: destroy()
4161
4162 Removes this object immediately. Might do special actions (like leaving a
4163 burning fire). If you want to remove an object without side effects, see
4164 :func:`remove`.
4165 */
destroy(lua_State * L)4166 int LuaMapObject::destroy(lua_State* L) {
4167 EditorGameBase& egbase = get_egbase(L);
4168 MapObject* o = get(L, egbase);
4169 if (!o) {
4170 return 0;
4171 }
4172
4173 o->destroy(egbase);
4174 return 0;
4175 }
4176
4177 /* RST
4178 .. method:: has_attribute(string)
4179
4180 returns true, if the map object has this attribute, else false
4181 */
has_attribute(lua_State * L)4182 int LuaMapObject::has_attribute(lua_State* L) {
4183 EditorGameBase& egbase = get_egbase(L);
4184 MapObject* obj = get_or_zero(egbase);
4185 if (!obj) {
4186 lua_pushboolean(L, false);
4187 return 1;
4188 }
4189
4190 // Check if object has the attribute
4191 std::string attrib = luaL_checkstring(L, 2);
4192 if (obj->has_attribute(MapObjectDescr::get_attribute_id(attrib))) {
4193 lua_pushboolean(L, true);
4194 } else {
4195 lua_pushboolean(L, false);
4196 }
4197 return 1;
4198 }
4199
4200 /*
4201 ==========================================================
4202 C METHODS
4203 ==========================================================
4204 */
get(lua_State * L,EditorGameBase & egbase,std::string name)4205 MapObject* LuaMapObject::get(lua_State* L, EditorGameBase& egbase, std::string name) {
4206 MapObject* o = get_or_zero(egbase);
4207 if (!o) {
4208 report_error(L, "%s no longer exists!", name.c_str());
4209 }
4210 return o;
4211 }
get_or_zero(EditorGameBase & egbase)4212 MapObject* LuaMapObject::get_or_zero(EditorGameBase& egbase) {
4213 return ptr_.get(egbase);
4214 }
4215
4216 /* RST
4217 BaseImmovable
4218 -------------
4219
4220 .. class:: BaseImmovable
4221
4222 Child of: :class:`MapObject`
4223
4224 This is the base class for all immovables in Widelands.
4225
4226 More properties are available through this object's
4227 :class:`ImmovableDescription`, which you can access via :any:`MapObject.descr`.
4228 */
4229 const char LuaBaseImmovable::className[] = "BaseImmovable";
4230 const MethodType<LuaBaseImmovable> LuaBaseImmovable::Methods[] = {
4231 {nullptr, nullptr},
4232 };
4233 const PropertyType<LuaBaseImmovable> LuaBaseImmovable::Properties[] = {
4234 PROP_RO(LuaBaseImmovable, fields), {nullptr, nullptr, nullptr},
4235 };
4236
4237 /*
4238 ==========================================================
4239 PROPERTIES
4240 ==========================================================
4241 */
4242
4243 /* RST
4244 .. attribute:: fields
4245
4246 (RO) An :class:`array` of :class:`~wl.map.Field` that is occupied by this
4247 Immovable. If the immovable occupies more than one field (roads or big
4248 buildings for example) the first entry in this list will be the main field
4249 */
get_fields(lua_State * L)4250 int LuaBaseImmovable::get_fields(lua_State* L) {
4251 EditorGameBase& egbase = get_egbase(L);
4252
4253 BaseImmovable::PositionList pl = get(L, egbase)->get_positions(egbase);
4254
4255 lua_createtable(L, pl.size(), 0);
4256 uint32_t idx = 1;
4257 for (const Coords& coords : pl) {
4258 lua_pushuint32(L, idx++);
4259 to_lua<LuaField>(L, new LuaField(coords.x, coords.y));
4260 lua_rawset(L, -3);
4261 }
4262 return 1;
4263 }
4264
4265 /*
4266 ==========================================================
4267 LUA METHODS
4268 ==========================================================
4269 */
4270
4271 /*
4272 ==========================================================
4273 C METHODS
4274 ==========================================================
4275 */
4276
4277 /* RST
4278 PlayerImmovable
4279 ---------------
4280
4281 .. class:: PlayerImmovable
4282
4283 Child of: :class:`BaseImmovable`
4284
4285 All Immovables that belong to a Player (Buildings, Flags, ...) are based on
4286 this Class.
4287
4288 More properties are available through this object's
4289 :class:`ImmovableDescription`, which you can access via :any:`MapObject.descr`.
4290 */
4291 const char LuaPlayerImmovable::className[] = "PlayerImmovable";
4292 const MethodType<LuaPlayerImmovable> LuaPlayerImmovable::Methods[] = {
4293 {nullptr, nullptr},
4294 };
4295 const PropertyType<LuaPlayerImmovable> LuaPlayerImmovable::Properties[] = {
4296 PROP_RO(LuaPlayerImmovable, owner),
4297 PROP_RO(LuaPlayerImmovable, debug_ware_economy),
4298 PROP_RO(LuaPlayerImmovable, debug_worker_economy),
4299 {nullptr, nullptr, nullptr},
4300 };
4301
4302 /*
4303 ==========================================================
4304 PROPERTIES
4305 ==========================================================
4306 */
4307 /* RST
4308 .. attribute:: owner
4309
4310 (RO) The :class:`wl.game.Player` who owns this object.
4311 */
get_owner(lua_State * L)4312 int LuaPlayerImmovable::get_owner(lua_State* L) {
4313 get_factory(L).push_player(L, get(L, get_egbase(L))->get_owner()->player_number());
4314 return 1;
4315 }
4316
4317 // UNTESTED, for debug only
get_debug_ware_economy(lua_State * L)4318 int LuaPlayerImmovable::get_debug_ware_economy(lua_State* L) {
4319 lua_pushlightuserdata(L, get(L, get_egbase(L))->get_economy(wwWARE));
4320 return 1;
4321 }
get_debug_worker_economy(lua_State * L)4322 int LuaPlayerImmovable::get_debug_worker_economy(lua_State* L) {
4323 lua_pushlightuserdata(L, get(L, get_egbase(L))->get_economy(wwWORKER));
4324 return 1;
4325 }
4326
4327 /*
4328 ==========================================================
4329 LUA METHODS
4330 ==========================================================
4331 */
4332
4333 /*
4334 ==========================================================
4335 C METHODS
4336 ==========================================================
4337 */
4338
4339 /* RST
4340 Flag
4341 --------
4342
4343 .. class:: Flag
4344
4345 Child of: :class:`PlayerImmovable`, :class:`HasWares`
4346
4347 One flag in the economy of this Player.
4348
4349 More properties are available through this object's
4350 :class:`ImmovableDescription`, which you can access via :any:`MapObject.descr`.
4351 */
4352 const char LuaFlag::className[] = "Flag";
4353 const MethodType<LuaFlag> LuaFlag::Methods[] = {
4354 METHOD(LuaFlag, set_wares), METHOD(LuaFlag, get_wares), {nullptr, nullptr},
4355 };
4356 const PropertyType<LuaFlag> LuaFlag::Properties[] = {
4357 PROP_RO(LuaFlag, ware_economy), PROP_RO(LuaFlag, worker_economy), PROP_RO(LuaFlag, roads),
4358 PROP_RO(LuaFlag, building), {nullptr, nullptr, nullptr},
4359 };
4360
4361 /*
4362 ==========================================================
4363 PROPERTIES
4364 ==========================================================
4365 */
4366 /* RST
4367 .. attribute:: ware_economy
4368
4369 (RO) Returns the ware economy that this flag belongs to.
4370
4371 **Warning**: Since economies can disappear when a player merges them
4372 through placing/deleting roads and flags, you must get a fresh economy
4373 object every time you call another function on the resulting economy object.
4374
4375 :returns: The :class:`Economy` associated with the flag to handle wares.
4376 */
get_ware_economy(lua_State * L)4377 int LuaFlag::get_ware_economy(lua_State* L) {
4378 const Flag* f = get(L, get_egbase(L));
4379 return to_lua<LuaEconomy>(L, new LuaEconomy(f->get_economy(wwWARE)));
4380 }
4381
4382 /* RST
4383 .. attribute:: worker_economy
4384
4385 (RO) Returns the worker economy that this flag belongs to.
4386
4387 **Warning**: Since economies can disappear when a player merges them
4388 through placing/deleting roads and flags, you must get a fresh economy
4389 object every time you call another function on the resulting economy object.
4390
4391 :returns: The :class:`Economy` associated with the flag to handle workers.
4392 */
get_worker_economy(lua_State * L)4393 int LuaFlag::get_worker_economy(lua_State* L) {
4394 const Flag* f = get(L, get_egbase(L));
4395 return to_lua<LuaEconomy>(L, new LuaEconomy(f->get_economy(wwWORKER)));
4396 }
4397
4398 /* RST
4399 .. attribute:: roads
4400
4401 (RO) Array of roads leading to the flag. Directions
4402 can be tr,r,br,bl,l and tl
4403 Note that waterways are currently treated like roads.
4404
4405 :returns: The array of 'direction:road', if any
4406 */
get_roads(lua_State * L)4407 int LuaFlag::get_roads(lua_State* L) {
4408
4409 const std::vector<std::string> directions = {"tr", "r", "br", "bl", "l", "tl"};
4410
4411 lua_newtable(L);
4412
4413 EditorGameBase& egbase = get_egbase(L);
4414 Flag* f = get(L, egbase);
4415
4416 for (uint32_t i = 1; i <= 6; i++) {
4417 if (f->get_roadbase(i) != nullptr) {
4418 lua_pushstring(L, directions.at(i - 1));
4419 upcasted_map_object_to_lua(L, f->get_roadbase(i));
4420 lua_rawset(L, -3);
4421 }
4422 }
4423 return 1;
4424 }
4425
4426 /* RST
4427 .. attribute:: building
4428
4429 (RO) building belonging to the flag
4430 */
get_building(lua_State * L)4431 int LuaFlag::get_building(lua_State* L) {
4432
4433 EditorGameBase& egbase = get_egbase(L);
4434 Flag* f = get(L, egbase);
4435
4436 PlayerImmovable* building = f->get_building();
4437 if (!building) {
4438 return 0;
4439 } else {
4440 upcasted_map_object_to_lua(L, building);
4441 }
4442 return 1;
4443 }
4444 /*
4445 ==========================================================
4446 LUA METHODS
4447 ==========================================================
4448 */
4449 // Documented in ParentClass
set_wares(lua_State * L)4450 int LuaFlag::set_wares(lua_State* L) {
4451 EditorGameBase& egbase = get_egbase(L);
4452 Flag* f = get(L, egbase);
4453 const Tribes& tribes = egbase.tribes();
4454
4455 InputMap setpoints;
4456 parse_wares_workers_counted(L, f->owner().tribe(), &setpoints, true);
4457 WaresWorkersMap c_wares = count_wares_on_flag_(*f, tribes);
4458
4459 Widelands::Quantity nwares = 0;
4460
4461 for (const auto& ware : c_wares) {
4462 // all wares currently on the flag without a setpoint should be removed
4463 if (!setpoints.count(std::make_pair(ware.first, Widelands::WareWorker::wwWARE))) {
4464 setpoints.insert(
4465 std::make_pair(std::make_pair(ware.first, Widelands::WareWorker::wwWARE), 0));
4466 }
4467 nwares += ware.second;
4468 }
4469
4470 // The idea is to change as little as possible on this flag
4471 for (const auto& sp : setpoints) {
4472 uint32_t cur = 0;
4473 const Widelands::DescriptionIndex& index = sp.first.first;
4474 WaresWorkersMap::iterator i = c_wares.find(index);
4475 if (i != c_wares.end()) {
4476 cur = i->second;
4477 }
4478
4479 int d = sp.second - cur;
4480 nwares += d;
4481
4482 if (f->total_capacity() < nwares) {
4483 report_error(L, "Flag has no capacity left!");
4484 }
4485
4486 if (d < 0) {
4487 while (d) {
4488 for (const WareInstance* ware : f->get_wares()) {
4489 if (tribes.ware_index(ware->descr().name()) == index) {
4490 const_cast<WareInstance*>(ware)->remove(egbase);
4491 ++d;
4492 break;
4493 }
4494 }
4495 }
4496 } else if (d > 0) {
4497 // add wares
4498 const WareDescr& wd = *tribes.get_ware_descr(index);
4499 for (int32_t j = 0; j < d; j++) {
4500 WareInstance& ware = *new WareInstance(index, &wd);
4501 ware.init(egbase);
4502 f->add_ware(egbase, ware);
4503 }
4504 }
4505 #ifndef NDEBUG
4506 if (sp.second > 0) {
4507 c_wares = count_wares_on_flag_(*f, tribes);
4508 assert(c_wares.count(index) == 1);
4509 assert(c_wares.at(index) == sp.second);
4510 }
4511 #endif
4512 }
4513 return 0;
4514 }
4515
4516 // Documented in parent Class
get_wares(lua_State * L)4517 int LuaFlag::get_wares(lua_State* L) {
4518 EditorGameBase& egbase = get_egbase(L);
4519 const Tribes& tribes = egbase.tribes();
4520 Flag* flag = get(L, egbase);
4521 const TribeDescr& tribe = flag->owner().tribe();
4522
4523 DescriptionIndex ware_index = INVALID_INDEX;
4524 std::vector<DescriptionIndex> ware_list;
4525 RequestedWareWorker parse_output =
4526 parse_wares_workers_list(L, tribe, &ware_index, &ware_list, true);
4527
4528 WaresWorkersMap wares = count_wares_on_flag_(*flag, tribes);
4529
4530 // Here we create the output - either a single integer of table of pairs
4531 if (ware_index != INVALID_INDEX) {
4532 uint32_t wares_here = 0;
4533 if (wares.count(ware_index)) {
4534 wares_here = wares[ware_index];
4535 }
4536 lua_pushuint32(L, wares_here);
4537 } else {
4538 // or it is a list of wares
4539 assert(!ware_list.empty());
4540 lua_newtable(L);
4541 // iterating over list of queryied wares
4542 for (auto idx : ware_list) {
4543
4544 uint32_t cnt = 0;
4545 if (wares.count(idx)) {
4546 cnt = wares[idx];
4547 }
4548 // the information is pushed if count > 0, or the ware was explicitely asked for
4549 if (parse_output != RequestedWareWorker::kAll || cnt > 0) {
4550 lua_pushstring(L, tribe.get_ware_descr(idx)->name());
4551 lua_pushuint32(L, cnt);
4552 lua_settable(L, -3);
4553 }
4554 }
4555 }
4556
4557 return 1;
4558 }
4559
4560 /*
4561 ==========================================================
4562 C METHODS
4563 ==========================================================
4564 */
4565
4566 /* RST
4567 Road
4568 ----
4569
4570 .. class:: Road
4571
4572 Child of: :class:`PlayerImmovable`, :class:`HasWorkers`
4573
4574 A road connecting two flags in the economy of this Player.
4575 Waterways are currently treated like roads in scripts; however,
4576 there are significant differences. You can check whether an
4577 instance of Road is a road or waterway using `get_road_type()`.
4578
4579 More properties are available through this object's
4580 :class:`ImmovableDescription`, which you can access via :any:`MapObject.descr`.
4581 */
4582 const char LuaRoad::className[] = "Road";
4583 const MethodType<LuaRoad> LuaRoad::Methods[] = {
4584 METHOD(LuaRoad, get_workers), METHOD(LuaRoad, set_workers), {nullptr, nullptr},
4585 };
4586 const PropertyType<LuaRoad> LuaRoad::Properties[] = {
4587 PROP_RO(LuaRoad, length), PROP_RO(LuaRoad, start_flag), PROP_RO(LuaRoad, end_flag),
4588 PROP_RO(LuaRoad, valid_workers), PROP_RO(LuaRoad, road_type), {nullptr, nullptr, nullptr},
4589 };
4590
4591 /*
4592 ==========================================================
4593 PROPERTIES
4594 ==========================================================
4595 */
4596 /* RST
4597 .. attribute:: length
4598
4599 (RO) The length of the roads in number of edges.
4600 */
get_length(lua_State * L)4601 int LuaRoad::get_length(lua_State* L) {
4602 lua_pushuint32(L, get(L, get_egbase(L))->get_path().get_nsteps());
4603 return 1;
4604 }
4605
4606 /* RST
4607 .. attribute:: start_flag
4608
4609 (RO) The flag were this road starts
4610 */
get_start_flag(lua_State * L)4611 int LuaRoad::get_start_flag(lua_State* L) {
4612 return to_lua<LuaFlag>(L, new LuaFlag(get(L, get_egbase(L))->get_flag(RoadBase::FlagStart)));
4613 }
4614
4615 /* RST
4616 .. attribute:: end_flag
4617
4618 (RO) The flag were this road ends
4619 */
get_end_flag(lua_State * L)4620 int LuaRoad::get_end_flag(lua_State* L) {
4621 return to_lua<LuaFlag>(L, new LuaFlag(get(L, get_egbase(L))->get_flag(RoadBase::FlagEnd)));
4622 }
4623
4624 /* RST
4625 .. attribute:: road_type
4626
4627 (RO) Type of road. Can be any either of:
4628
4629 * normal
4630 * busy
4631 * waterway
4632 */
get_road_type(lua_State * L)4633 int LuaRoad::get_road_type(lua_State* L) {
4634 RoadBase* r = get(L, get_egbase(L));
4635 if (r->descr().type() == MapObjectType::WATERWAY) {
4636 lua_pushstring(L, "waterway");
4637 } else if (upcast(Road, road, r)) {
4638 lua_pushstring(L, road->is_busy() ? "busy" : "normal");
4639 } else {
4640 report_error(L, "Unknown road type! Please report as a bug!");
4641 }
4642 return 1;
4643 }
4644
4645 // documented in parent class
get_valid_workers(lua_State * L)4646 int LuaRoad::get_valid_workers(lua_State* L) {
4647 RoadBase* road = get(L, get_egbase(L));
4648 return workers_map_to_lua(L, get_valid_workers_for(*road));
4649 }
4650
4651 /*
4652 ==========================================================
4653 LUA METHODS
4654 ==========================================================
4655 */
4656
4657 // documented in parent class
get_workers(lua_State * L)4658 int LuaRoad::get_workers(lua_State* L) {
4659 RoadBase* road = get(L, get_egbase(L));
4660 return do_get_workers(L, *road, get_valid_workers_for(*road));
4661 }
4662
set_workers(lua_State * L)4663 int LuaRoad::set_workers(lua_State* L) {
4664 RoadBase* road = get(L, get_egbase(L));
4665 return do_set_workers<LuaRoad>(L, road, get_valid_workers_for(*road));
4666 }
4667
4668 /*
4669 ==========================================================
4670 C METHODS
4671 ==========================================================
4672 */
4673
create_new_worker(PlayerImmovable & pi,EditorGameBase & egbase,const WorkerDescr * wdes)4674 int LuaRoad::create_new_worker(PlayerImmovable& pi,
4675 EditorGameBase& egbase,
4676 const WorkerDescr* wdes) {
4677 RoadBase& r = static_cast<RoadBase&>(pi);
4678
4679 if (r.get_workers().size()) {
4680 return -1; // No space
4681 }
4682
4683 // Determine Idle position.
4684 Flag& start = r.get_flag(RoadBase::FlagStart);
4685 Coords idle_position = start.get_position();
4686 const Path& path = r.get_path();
4687 Path::StepVector::size_type idle_index = r.get_idle_index();
4688 for (Path::StepVector::size_type i = 0; i < idle_index; ++i) {
4689 egbase.map().get_neighbour(idle_position, path[i], &idle_position);
4690 }
4691
4692 Carrier& carrier =
4693 dynamic_cast<Carrier&>(wdes->create(egbase, r.get_owner(), &r, idle_position));
4694
4695 if (upcast(Game, game, &egbase)) {
4696 carrier.start_task_road(*game);
4697 }
4698
4699 r.assign_carrier(carrier, 0);
4700 return 0;
4701 }
4702
4703 /* RST
4704 PortDock
4705 --------
4706
4707 .. class:: PortDock
4708
4709 Child of: :class:`PlayerImmovable`
4710
4711 Each :class:`Warehouse` that is a port has a dock attached to
4712 it. The PortDock is an immovable that also occupies a field on
4713 the water near the port.
4714
4715 More properties are available through this object's
4716 :class:`ImmovableDescription`, which you can access via :any:`MapObject.descr`.
4717 */
4718
4719 const char LuaPortDock::className[] = "PortDock";
4720 const MethodType<LuaPortDock> LuaPortDock::Methods[] = {
4721 {nullptr, nullptr},
4722 };
4723 const PropertyType<LuaPortDock> LuaPortDock::Properties[] = {
4724 {nullptr, nullptr, nullptr},
4725 };
4726
4727 /*
4728 ==========================================================
4729 PROPERTIES
4730 ==========================================================
4731 */
4732
4733 /*
4734 ==========================================================
4735 LUA METHODS
4736 ==========================================================
4737 */
4738
4739 /*
4740 ==========================================================
4741 C METHODS
4742 ==========================================================
4743 */
4744
4745 /* RST
4746 Building
4747 --------
4748
4749 .. class:: Building
4750
4751 Child of: :class:`PlayerImmovable`
4752
4753 This represents a building owned by a player.
4754
4755 More properties are available through this object's
4756 :class:`BuildingDescription`, which you can access via :any:`MapObject.descr`.
4757 */
4758 const char LuaBuilding::className[] = "Building";
4759 const MethodType<LuaBuilding> LuaBuilding::Methods[] = {
4760 {nullptr, nullptr},
4761 };
4762 const PropertyType<LuaBuilding> LuaBuilding::Properties[] = {
4763 PROP_RO(LuaBuilding, flag), {nullptr, nullptr, nullptr},
4764 };
4765
4766 /*
4767 ==========================================================
4768 PROPERTIES
4769 ==========================================================
4770 */
4771
4772 /* RST
4773 .. attribute:: flag
4774
4775 (RO) The flag that belongs to this building (that is to the bottom right
4776 of it's main location).
4777 */
4778 // UNTESTED
get_flag(lua_State * L)4779 int LuaBuilding::get_flag(lua_State* L) {
4780 return upcasted_map_object_to_lua(L, &get(L, get_egbase(L))->base_flag());
4781 }
4782
4783 /*
4784 ==========================================================
4785 LUA METHODS
4786 ==========================================================
4787 */
4788
4789 /*
4790 ==========================================================
4791 C METHODS
4792 ==========================================================
4793 */
4794
4795 /* RST
4796 ConstructionSite
4797 -----------------
4798
4799 .. class:: ConstructionSite
4800
4801 Child of: :class:`Building`
4802
4803 A ConstructionSite as it appears in Game. This is only a minimal wrapping at
4804 the moment.
4805
4806 More properties are available through this object's
4807 :class:`ConstructionSiteDescription`, which you can access via :any:`MapObject.descr`.
4808 */
4809 const char LuaConstructionSite::className[] = "ConstructionSite";
4810 const MethodType<LuaConstructionSite> LuaConstructionSite::Methods[] = {
4811 {nullptr, nullptr},
4812 };
4813 const PropertyType<LuaConstructionSite> LuaConstructionSite::Properties[] = {
4814 PROP_RO(LuaConstructionSite, building), {nullptr, nullptr, nullptr},
4815 };
4816
4817 /*
4818 ==========================================================
4819 PROPERTIES
4820 ==========================================================
4821 */
4822 /* RST
4823 .. attribute:: building
4824
4825 (RO) The name of the building that is constructed here
4826 */
get_building(lua_State * L)4827 int LuaConstructionSite::get_building(lua_State* L) {
4828 lua_pushstring(L, get(L, get_egbase(L))->building().name());
4829 return 1;
4830 }
4831
4832 /*
4833 ==========================================================
4834 LUA METHODS
4835 ==========================================================
4836 */
4837
4838 /*
4839 ==========================================================
4840 C METHODS
4841 ==========================================================
4842 */
4843
4844 /* RST
4845 Warehouse
4846 ---------
4847
4848 .. class:: Warehouse
4849
4850 Child of: :class:`Building`, :class:`HasWares`, :class:`HasWorkers`,
4851 :class:`HasSoldiers`
4852
4853 Every Headquarter, Port or Warehouse on the Map is of this type.
4854
4855 More properties are available through this object's
4856 :class:`WarehouseDescription`, which you can access via :any:`MapObject.descr`.
4857 */
4858 const char LuaWarehouse::className[] = "Warehouse";
4859 const MethodType<LuaWarehouse> LuaWarehouse::Methods[] = {
4860 METHOD(LuaWarehouse, set_wares),
4861 METHOD(LuaWarehouse, get_wares),
4862 METHOD(LuaWarehouse, set_workers),
4863 METHOD(LuaWarehouse, get_workers),
4864 METHOD(LuaWarehouse, set_soldiers),
4865 METHOD(LuaWarehouse, get_soldiers),
4866 METHOD(LuaWarehouse, set_warehouse_policies),
4867 METHOD(LuaWarehouse, get_warehouse_policies),
4868 METHOD(LuaWarehouse, start_expedition),
4869 METHOD(LuaWarehouse, cancel_expedition),
4870 {nullptr, nullptr},
4871 };
4872 const PropertyType<LuaWarehouse> LuaWarehouse::Properties[] = {
4873 PROP_RO(LuaWarehouse, portdock),
4874 PROP_RO(LuaWarehouse, expedition_in_progress),
4875 {nullptr, nullptr, nullptr},
4876 };
4877
4878 /*
4879 ==========================================================
4880 PROPERTIES
4881 ==========================================================
4882 */
4883 // UNTESTED
4884 /* RST
4885 .. attribute:: portdock
4886
4887 (RO) If this Warehouse is a port, returns the
4888 :class:`PortDock` attached to it, otherwise nil.
4889 */
get_portdock(lua_State * L)4890 int LuaWarehouse::get_portdock(lua_State* L) {
4891 return upcasted_map_object_to_lua(L, get(L, get_egbase(L))->get_portdock());
4892 }
4893
4894 /* RST
4895 .. attribute:: expedition_in_progress
4896
4897 (RO) If this Warehouse is a port, and an expedition is in
4898 progress, returns true, otherwise nil
4899 */
get_expedition_in_progress(lua_State * L)4900 int LuaWarehouse::get_expedition_in_progress(lua_State* L) {
4901
4902 EditorGameBase& egbase = get_egbase(L);
4903
4904 if (is_a(Game, &egbase)) {
4905 const PortDock* pd = get(L, egbase)->get_portdock();
4906 if (pd) {
4907 if (pd->expedition_started()) {
4908 return 1;
4909 }
4910 }
4911 }
4912 return 0;
4913 }
4914
4915 /*
4916 ==========================================================
4917 LUA METHODS
4918 ==========================================================
4919 */
4920
get_workers(lua_State * L)4921 int LuaWarehouse::get_workers(lua_State* L) {
4922 Warehouse* wh = get(L, get_egbase(L));
4923 const TribeDescr& tribe = wh->owner().tribe();
4924
4925 // Parsing the argument(s), result will be either single index
4926 // or list of indexes
4927 DescriptionIndex worker_index = INVALID_INDEX;
4928 std::vector<DescriptionIndex> workers_list;
4929 parse_wares_workers_list(L, tribe, &worker_index, &workers_list, false);
4930
4931 // Here we create the output - either a single integer of table of pairs
4932 if (worker_index != INVALID_INDEX) {
4933 lua_pushuint32(L, wh->get_workers().stock(worker_index));
4934 } else if (!workers_list.empty()) {
4935 lua_newtable(L);
4936 for (auto idx : workers_list) {
4937 lua_pushstring(L, tribe.get_worker_descr(idx)->name());
4938 lua_pushuint32(L, wh->get_workers().stock(idx));
4939 lua_settable(L, -3);
4940 }
4941 } else {
4942 NEVER_HERE();
4943 }
4944 return 1;
4945 }
4946
get_wares(lua_State * L)4947 int LuaWarehouse::get_wares(lua_State* L) {
4948 Warehouse* wh = get(L, get_egbase(L));
4949 const TribeDescr& tribe = wh->owner().tribe();
4950
4951 // Parsing the argument(s), result will be either single index
4952 // or list of indexes
4953 DescriptionIndex ware_index = INVALID_INDEX;
4954 std::vector<DescriptionIndex> ware_list;
4955 parse_wares_workers_list(L, tribe, &ware_index, &ware_list, true);
4956
4957 // Here we create the output - either a single integer of table of pairs
4958 if (ware_index != INVALID_INDEX) {
4959 lua_pushuint32(L, wh->get_wares().stock(ware_index));
4960 } else if (!ware_list.empty()) {
4961 lua_newtable(L);
4962 for (auto idx : ware_list) {
4963 lua_pushstring(L, tribe.get_ware_descr(idx)->name());
4964 lua_pushuint32(L, wh->get_wares().stock(idx));
4965 lua_settable(L, -3);
4966 }
4967 } else {
4968 NEVER_HERE();
4969 }
4970 return 1;
4971 }
4972
set_wares(lua_State * L)4973 int LuaWarehouse::set_wares(lua_State* L) {
4974 Warehouse* wh = get(L, get_egbase(L));
4975 const TribeDescr& tribe = wh->owner().tribe();
4976 InputMap setpoints;
4977 parse_wares_workers_counted(L, tribe, &setpoints, true);
4978
4979 for (const auto& ware : setpoints) {
4980 const Widelands::DescriptionIndex& index = ware.first.first;
4981 int32_t d = ware.second - wh->get_wares().stock(index);
4982 if (d < 0) {
4983 wh->remove_wares(index, -d);
4984 } else if (d > 0) {
4985 wh->insert_wares(index, d);
4986 }
4987 }
4988 return 0;
4989 }
4990
set_workers(lua_State * L)4991 int LuaWarehouse::set_workers(lua_State* L) {
4992 Warehouse* wh = get(L, get_egbase(L));
4993 const TribeDescr& tribe = wh->owner().tribe();
4994 InputMap setpoints;
4995 parse_wares_workers_counted(L, tribe, &setpoints, false);
4996
4997 for (const auto& worker : setpoints) {
4998 const Widelands::DescriptionIndex& index = worker.first.first;
4999 int32_t d = worker.second - wh->get_workers().stock(index);
5000 if (d < 0) {
5001 wh->remove_workers(index, -d);
5002 } else if (d > 0) {
5003 wh->insert_workers(index, d);
5004 }
5005 }
5006 return 0;
5007 }
5008
5009 // Transforms the given warehouse policy to a string which is used by the lua code
wh_policy_to_string(lua_State * L,StockPolicy p)5010 inline void wh_policy_to_string(lua_State* L, StockPolicy p) {
5011 switch (p) {
5012 case StockPolicy::kNormal:
5013 lua_pushstring(L, "normal");
5014 break;
5015 case StockPolicy::kPrefer:
5016 lua_pushstring(L, "prefer");
5017 break;
5018 case StockPolicy::kDontStock:
5019 lua_pushstring(L, "dontstock");
5020 break;
5021 case StockPolicy::kRemove:
5022 lua_pushstring(L, "remove");
5023 break;
5024 }
5025 }
5026 // Transforms the given string from the lua code to a warehouse policy
string_to_wh_policy(lua_State * L,uint32_t index)5027 inline StockPolicy string_to_wh_policy(lua_State* L, uint32_t index) {
5028 std::string str = luaL_checkstring(L, index);
5029 if (str == "normal") {
5030 return StockPolicy::kNormal;
5031 } else if (str == "prefer") {
5032 return StockPolicy::kPrefer;
5033 } else if (str == "dontstock") {
5034 return StockPolicy::kDontStock;
5035 } else if (str == "remove") {
5036 return StockPolicy::kRemove;
5037 } else {
5038 report_error(L, "<%s> is no valid warehouse policy!", str.c_str());
5039 }
5040 }
5041
do_set_ware_policy(Warehouse * wh,const DescriptionIndex idx,const StockPolicy p)5042 inline bool do_set_ware_policy(Warehouse* wh, const DescriptionIndex idx, const StockPolicy p) {
5043 wh->set_ware_policy(idx, p);
5044 return true;
5045 }
5046
5047 /**
5048 * Sets the given policy for the given ware in the given warehouse and return true.
5049 * If the no ware with the given name exists for the tribe of the warehouse, return false.
5050 */
do_set_ware_policy(Warehouse * wh,const std::string & name,const StockPolicy p)5051 inline bool do_set_ware_policy(Warehouse* wh, const std::string& name, const StockPolicy p) {
5052 const TribeDescr& tribe = wh->owner().tribe();
5053 DescriptionIndex idx = tribe.ware_index(name);
5054 if (!tribe.has_ware(idx)) {
5055 return false;
5056 }
5057 return do_set_ware_policy(wh, idx, p);
5058 }
5059
do_set_worker_policy(Warehouse * wh,const DescriptionIndex idx,const StockPolicy p)5060 inline bool do_set_worker_policy(Warehouse* wh, const DescriptionIndex idx, const StockPolicy p) {
5061 const TribeDescr& tribe = wh->owner().tribe();
5062 // If the worker does not cost anything, ignore it
5063 // Otherwise, an unlimited stream of carriers might leave the warehouse
5064 if (tribe.get_worker_descr(idx)->is_buildable() &&
5065 tribe.get_worker_descr(idx)->buildcost().empty()) {
5066 return true;
5067 }
5068 wh->set_worker_policy(idx, p);
5069 return true;
5070 }
5071
5072 /**
5073 * Sets the given policy for the given worker in the given warehouse and returns true.
5074 * Also returns true if the given worker does not cost anything but in this case does not set its
5075 * policy.
5076 * If no worker with the given name exists for the tribe of the warehouse, return false.
5077 */
do_set_worker_policy(Warehouse * wh,const std::string & name,const StockPolicy p)5078 inline bool do_set_worker_policy(Warehouse* wh, const std::string& name, const StockPolicy p) {
5079 const TribeDescr& tribe = wh->owner().tribe();
5080 DescriptionIndex idx = tribe.worker_index(name);
5081 if (!tribe.has_worker(idx)) {
5082 return false;
5083 }
5084 return do_set_worker_policy(wh, idx, p);
5085 }
5086 /* RST
5087 .. method:: set_warehouse_policies(which, policy)
5088
5089 Sets the policies how the warehouse should handle the given wares and workers.
5090
5091 Usage example:
5092
5093 .. code-block:: lua
5094
5095 wh:set_warehouse_policies("coal", "prefer")
5096
5097 :arg which: behaves like for :meth:`HasWares.get_wares`.
5098
5099 :arg policy: the policy to apply for all the wares and workers given in `which`.
5100 :type policy: a string out of "normal", "prefer", "dontstock", "remove".
5101 */
set_warehouse_policies(lua_State * L)5102 int LuaWarehouse::set_warehouse_policies(lua_State* L) {
5103 int32_t nargs = lua_gettop(L);
5104 if (nargs != 3) {
5105 report_error(L, "Wrong number of arguments to set_warehouse_policies!");
5106 }
5107
5108 Warehouse* wh = get(L, get_egbase(L));
5109 StockPolicy p = string_to_wh_policy(L, -1);
5110 lua_pop(L, 1);
5111 const TribeDescr& tribe = wh->owner().tribe();
5112
5113 // takes either "all", a name or an array of names
5114 if (lua_isstring(L, 2)) {
5115 const std::string& what = luaL_checkstring(L, -1);
5116 if (what == "all") {
5117 for (const DescriptionIndex& i : tribe.wares()) {
5118 do_set_ware_policy(wh, i, p);
5119 }
5120 for (const DescriptionIndex& i : tribe.workers()) {
5121 do_set_worker_policy(wh, i, p);
5122 }
5123 } else {
5124 // Only one item requested
5125 if (!do_set_ware_policy(wh, what, p) && !do_set_worker_policy(wh, what, p)) {
5126 // Unknown whatever, abort
5127 report_error(L, "Unknown name: <%s>", what.c_str());
5128 }
5129 }
5130 } else {
5131 // array of names
5132 luaL_checktype(L, 2, LUA_TTABLE);
5133 lua_pushnil(L);
5134 while (lua_next(L, 2) != 0) {
5135 const std::string& what = luaL_checkstring(L, -1);
5136 if (!do_set_ware_policy(wh, what, p) && !do_set_worker_policy(wh, what, p)) {
5137 // Note that this will change the policy for entries earlier in the list
5138 // but when the user provides broken data its his own fault
5139 report_error(L, "Unknown name: <%s>", what.c_str());
5140 }
5141 lua_pop(L, 1);
5142 }
5143 }
5144
5145 return 0;
5146 }
5147
5148 // Gets the warehouse policy by ware/worker-name or id
5149 #define WH_GET_POLICY(type) \
5150 inline void do_get_##type##_policy(lua_State* L, Warehouse* wh, const DescriptionIndex idx) { \
5151 wh_policy_to_string(L, wh->get_##type##_policy(idx)); \
5152 } \
5153 \
5154 inline bool do_get_##type##_policy(lua_State* L, Warehouse* wh, const std::string& name) { \
5155 const TribeDescr& tribe = wh->owner().tribe(); \
5156 DescriptionIndex idx = tribe.type##_index(name); \
5157 if (!tribe.has_##type(idx)) { \
5158 return false; \
5159 } \
5160 do_get_##type##_policy(L, wh, idx); \
5161 return true; \
5162 }
5163
5164 WH_GET_POLICY(ware)
WH_GET_POLICY(worker)5165 WH_GET_POLICY(worker)
5166 #undef WH_GET_POLICY
5167
5168 /* RST
5169 .. method:: get_warehouse_policies(which)
5170
5171 Gets the policies how the warehouse should handle the given wares and workers.
5172 The method to handle is one of the strings "normal", "prefer", "dontstock", "remove".
5173
5174 Usage example:
5175
5176 .. code-block:: lua
5177
5178 wh:get_warehouse_policies({"ax", "coal"})
5179 -- Returns a table like {ax="normal", coal="prefer"}
5180
5181 :arg which: behaves like for :meth:`HasWares.get_wares`.
5182
5183 :returns: :class:`string` or :class:`table`
5184 */
5185 int LuaWarehouse::get_warehouse_policies(lua_State* L) {
5186 int32_t nargs = lua_gettop(L);
5187 if (nargs != 2) {
5188 report_error(L, "Wrong number of arguments to get_warehouse_policies!");
5189 }
5190 Warehouse* wh = get(L, get_egbase(L));
5191 const TribeDescr& tribe = wh->owner().tribe();
5192 // takes either "all", a single name or an array of names
5193 if (lua_isstring(L, 2)) {
5194 std::string what = luaL_checkstring(L, -1);
5195 if (what == "all") {
5196 lua_newtable(L);
5197 for (const DescriptionIndex& i : tribe.wares()) {
5198 std::string name = tribe.get_ware_descr(i)->name();
5199 lua_pushstring(L, name.c_str());
5200 do_get_ware_policy(L, wh, i);
5201 lua_rawset(L, -3);
5202 }
5203 for (const DescriptionIndex& i : tribe.workers()) {
5204 std::string name = tribe.get_worker_descr(i)->name();
5205 lua_pushstring(L, name.c_str());
5206 do_get_worker_policy(L, wh, i);
5207 lua_rawset(L, -3);
5208 }
5209 } else {
5210 // Only one item requested
5211 if (!do_get_ware_policy(L, wh, what) && !do_get_worker_policy(L, wh, what)) {
5212 // Unknown whatever, abort
5213 report_error(L, "Unknown name: <%s>", what.c_str());
5214 }
5215 }
5216 } else {
5217 // array of names
5218 luaL_checktype(L, 2, LUA_TTABLE);
5219 lua_newtable(L);
5220 lua_pushnil(L);
5221 while (lua_next(L, 2) != 0) {
5222 // Stack is: ... input_table new_table nil input_key input_value
5223 // input_value is the name of the ware or worker and will be added into the new table
5224 // input_key is an index and is dropped by the next call of lua_next()
5225 const std::string& what = luaL_checkstring(L, -1);
5226 if (!do_get_ware_policy(L, wh, what) && !do_get_worker_policy(L, wh, what)) {
5227 // Note that this will change the policy for entries earlier in the list
5228 // but when the user provides broken data its his own fault
5229 report_error(L, "Unknown name: <%s>", what.c_str());
5230 }
5231 lua_rawset(L, -4);
5232 }
5233 }
5234 return 1;
5235 }
5236
5237 // documented in parent class
get_soldiers(lua_State * L)5238 int LuaWarehouse::get_soldiers(lua_State* L) {
5239 Warehouse* wh = get(L, get_egbase(L));
5240 return do_get_soldiers(L, *wh->soldier_control(), wh->owner().tribe());
5241 }
5242
5243 // documented in parent class
set_soldiers(lua_State * L)5244 int LuaWarehouse::set_soldiers(lua_State* L) {
5245 Warehouse* wh = get(L, get_egbase(L));
5246 return do_set_soldiers(L, wh->get_position(), wh->mutable_soldier_control(), wh->get_owner());
5247 }
5248
5249 /* RST
5250 .. method:: start_expedition()
5251
5252 Starts preparation for expedition
5253
5254 */
start_expedition(lua_State * L)5255 int LuaWarehouse::start_expedition(lua_State* L) {
5256
5257 EditorGameBase& egbase = get_egbase(L);
5258 Warehouse* wh = get(L, egbase);
5259
5260 if (!wh) {
5261 return 0;
5262 }
5263
5264 if (upcast(Game, game, &egbase)) {
5265 const PortDock* pd = wh->get_portdock();
5266 if (!pd) {
5267 return 0;
5268 }
5269 if (!pd->expedition_started()) {
5270 game->send_player_start_or_cancel_expedition(*wh);
5271 return 1;
5272 }
5273 }
5274
5275 return 0;
5276 }
5277
5278 /* RST
5279 .. method:: cancel_expedition()
5280
5281 Cancels an expedition if in progress
5282
5283 */
cancel_expedition(lua_State * L)5284 int LuaWarehouse::cancel_expedition(lua_State* L) {
5285
5286 EditorGameBase& egbase = get_egbase(L);
5287 Warehouse* wh = get(L, egbase);
5288
5289 if (!wh) {
5290 return 0;
5291 }
5292
5293 if (upcast(Game, game, &egbase)) {
5294 const PortDock* pd = wh->get_portdock();
5295 if (!pd) {
5296 return 0;
5297 }
5298 if (pd->expedition_started()) {
5299 game->send_player_start_or_cancel_expedition(*wh);
5300 return 1;
5301 }
5302 }
5303
5304 return 0;
5305 }
5306
5307 /*
5308 ==========================================================
5309 C METHODS
5310 ==========================================================
5311 */
5312
5313 /* RST
5314 ProductionSite
5315 --------------
5316
5317 .. class:: ProductionSite
5318
5319 Child of: :class:`Building`, :class:`HasInputs`, :class:`HasWorkers`
5320
5321 Every building that produces anything.
5322
5323 More properties are available through this object's
5324 :class:`ProductionSiteDescription`, which you can access via :any:`MapObject.descr`.
5325 */
5326 const char LuaProductionSite::className[] = "ProductionSite";
5327 const MethodType<LuaProductionSite> LuaProductionSite::Methods[] = {
5328 METHOD(LuaProductionSite, set_inputs),
5329 METHOD(LuaProductionSite, get_inputs),
5330 METHOD(LuaProductionSite, get_workers),
5331 METHOD(LuaProductionSite, set_workers),
5332 METHOD(LuaProductionSite, toggle_start_stop),
5333
5334 {nullptr, nullptr},
5335 };
5336 const PropertyType<LuaProductionSite> LuaProductionSite::Properties[] = {
5337 PROP_RO(LuaProductionSite, valid_workers),
5338 PROP_RO(LuaProductionSite, valid_inputs),
5339 PROP_RO(LuaProductionSite, is_stopped),
5340 {nullptr, nullptr, nullptr},
5341 };
5342
5343 /*
5344 ==========================================================
5345 PROPERTIES
5346 ==========================================================
5347 */
5348 // documented in parent class
get_valid_inputs(lua_State * L)5349 int LuaProductionSite::get_valid_inputs(lua_State* L) {
5350 EditorGameBase& egbase = get_egbase(L);
5351 ProductionSite* ps = get(L, egbase);
5352
5353 lua_newtable(L);
5354 for (const auto& input_ware : ps->descr().input_wares()) {
5355 const WareDescr* descr = egbase.tribes().get_ware_descr(input_ware.first);
5356 lua_pushstring(L, descr->name());
5357 lua_pushuint32(L, input_ware.second);
5358 lua_rawset(L, -3);
5359 }
5360 for (const auto& input_worker : ps->descr().input_workers()) {
5361 const WorkerDescr* descr = egbase.tribes().get_worker_descr(input_worker.first);
5362 lua_pushstring(L, descr->name());
5363 lua_pushuint32(L, input_worker.second);
5364 lua_rawset(L, -3);
5365 }
5366 return 1;
5367 }
5368
5369 // documented in parent class
get_valid_workers(lua_State * L)5370 int LuaProductionSite::get_valid_workers(lua_State* L) {
5371 ProductionSite* ps = get(L, get_egbase(L));
5372 return workers_map_to_lua(L, get_valid_workers_for(*ps));
5373 }
5374
5375 /* RST
5376 .. attribute:: is_stopped
5377
5378 (RO) Returns whether this productionsite is currently active or stopped
5379
5380 :returns: true if the productionsite has been started,
5381 false if it has been stopped.
5382 */
get_is_stopped(lua_State * L)5383 int LuaProductionSite::get_is_stopped(lua_State* L) {
5384 ProductionSite* ps = get(L, get_egbase(L));
5385 lua_pushboolean(L, ps->is_stopped());
5386 return 1;
5387 }
5388
5389 /*
5390 ==========================================================
5391 LUA METHODS
5392 ==========================================================
5393 */
5394 // documented in parent class
set_inputs(lua_State * L)5395 int LuaProductionSite::set_inputs(lua_State* L) {
5396 ProductionSite* ps = get(L, get_egbase(L));
5397 const TribeDescr& tribe = ps->owner().tribe();
5398 InputMap setpoints = parse_set_input_arguments(L, tribe);
5399
5400 InputSet valid_inputs;
5401 for (const auto& input_ware : ps->descr().input_wares()) {
5402 valid_inputs.insert(std::make_pair(input_ware.first, wwWARE));
5403 }
5404 for (const auto& input_worker : ps->descr().input_workers()) {
5405 valid_inputs.insert(std::make_pair(input_worker.first, wwWORKER));
5406 }
5407 for (const auto& sp : setpoints) {
5408 if (!valid_inputs.count(sp.first)) {
5409 report_error(L, "<%s> can't be stored in this building: %s!",
5410 sp.first.second == wwWARE ?
5411 tribe.get_ware_descr(sp.first.first)->name().c_str() :
5412 tribe.get_worker_descr(sp.first.first)->name().c_str(),
5413 ps->descr().name().c_str());
5414 }
5415 InputQueue& iq = ps->inputqueue(sp.first.first, sp.first.second);
5416 if (sp.second > iq.get_max_size()) {
5417 report_error(
5418 L, "Not enough space for %u inputs, only for %i", sp.second, iq.get_max_size());
5419 }
5420 iq.set_filled(sp.second);
5421 }
5422
5423 return 0;
5424 }
5425
5426 // documented in parent class
get_inputs(lua_State * L)5427 int LuaProductionSite::get_inputs(lua_State* L) {
5428 ProductionSite* ps = get(L, get_egbase(L));
5429 const TribeDescr& tribe = ps->owner().tribe();
5430
5431 bool return_number = false;
5432 InputSet input_set = parse_get_input_arguments(L, tribe, &return_number);
5433
5434 InputSet valid_inputs;
5435 for (const auto& input_ware : ps->descr().input_wares()) {
5436 valid_inputs.insert(std::make_pair(input_ware.first, wwWARE));
5437 }
5438 for (const auto& input_worker : ps->descr().input_workers()) {
5439 valid_inputs.insert(std::make_pair(input_worker.first, wwWORKER));
5440 }
5441
5442 if (input_set.size() == tribe.get_nrwares() + tribe.get_nrworkers()) { // Want all returned
5443 input_set = valid_inputs;
5444 }
5445
5446 if (!return_number) {
5447 lua_newtable(L);
5448 }
5449
5450 for (const auto& input : input_set) {
5451 uint32_t cnt = 0;
5452 if (valid_inputs.count(input)) {
5453 cnt = ps->inputqueue(input.first, input.second).get_filled();
5454 }
5455
5456 if (return_number) { // this is the only thing the customer wants to know
5457 lua_pushuint32(L, cnt);
5458 break;
5459 } else {
5460 lua_pushstring(L, input.second == wwWARE ? tribe.get_ware_descr(input.first)->name() :
5461 tribe.get_worker_descr(input.first)->name());
5462 lua_pushuint32(L, cnt);
5463 lua_settable(L, -3);
5464 }
5465 }
5466 return 1;
5467 }
5468
5469 // documented in parent class
get_workers(lua_State * L)5470 int LuaProductionSite::get_workers(lua_State* L) {
5471 ProductionSite* ps = get(L, get_egbase(L));
5472 return do_get_workers(L, *ps, get_valid_workers_for(*ps));
5473 }
5474
5475 // documented in parent class
set_workers(lua_State * L)5476 int LuaProductionSite::set_workers(lua_State* L) {
5477 ProductionSite* ps = get(L, get_egbase(L));
5478 return do_set_workers<LuaProductionSite>(L, ps, get_valid_workers_for(*ps));
5479 }
5480
5481 /* RST
5482 .. method:: toggle_start_stop()
5483
5484 If :any:`ProductionSite.is_stopped`, sends a command to start this productionsite.
5485 Otherwise, sends a command to stop this productionsite.
5486 */
toggle_start_stop(lua_State * L)5487 int LuaProductionSite::toggle_start_stop(lua_State* L) {
5488 Game& game = get_game(L);
5489 ProductionSite* ps = get(L, game);
5490 game.send_player_start_stop_building(*ps);
5491 return 1;
5492 }
5493
5494 /*
5495 ==========================================================
5496 C METHODS
5497 ==========================================================
5498 */
5499
create_new_worker(PlayerImmovable & pi,EditorGameBase & egbase,const WorkerDescr * wdes)5500 int LuaProductionSite::create_new_worker(PlayerImmovable& pi,
5501 EditorGameBase& egbase,
5502 const WorkerDescr* wdes) {
5503 ProductionSite& ps = static_cast<ProductionSite&>(pi);
5504 return ps.warp_worker(egbase, *wdes);
5505 }
5506
5507 /* RST
5508 Market
5509 ---------
5510
5511 .. class:: Market
5512
5513 Child of: :class:`Building`, :class:`HasWares`, :class:`HasWorkers`
5514
5515 A Market used for trading with other players.
5516
5517 More properties are available through this object's
5518 :class:`MarketDescription`, which you can access via :any:`MapObject.descr`.
5519 */
5520 const char LuaMarket::className[] = "Market";
5521 const MethodType<LuaMarket> LuaMarket::Methods[] = {
5522 METHOD(LuaMarket, propose_trade),
5523 // TODO(sirver,trading): Implement and fix documentation.
5524 // METHOD(LuaMarket, set_wares),
5525 // METHOD(LuaMarket, get_wares),
5526 // METHOD(LuaMarket, set_workers),
5527 // METHOD(LuaMarket, get_workers),
5528 {nullptr, nullptr},
5529 };
5530 const PropertyType<LuaMarket> LuaMarket::Properties[] = {
5531 {nullptr, nullptr, nullptr},
5532 };
5533
5534 /*
5535 ==========================================================
5536 PROPERTIES
5537 ==========================================================
5538 */
5539
5540 /*
5541 ==========================================================
5542 LUA METHODS
5543 ==========================================================
5544 */
5545
5546 /* RST
5547 .. method:: propose_trade(other_market, num_batches, items_to_send, items_to_receive)
5548
5549 TODO(sirver,trading): document
5550
5551 :returns: :const:`nil`
5552 */
propose_trade(lua_State * L)5553 int LuaMarket::propose_trade(lua_State* L) {
5554 if (lua_gettop(L) != 5) {
5555 report_error(L, "Takes 4 arguments.");
5556 }
5557 Game& game = get_game(L);
5558 Market* self = get(L, game);
5559 Market* other_market = (*get_user_class<LuaMarket>(L, 2))->get(L, game);
5560 const int num_batches = luaL_checkinteger(L, 3);
5561
5562 const BillOfMaterials items_to_send =
5563 parse_wares_as_bill_of_material(L, 4, self->owner().tribe());
5564 // TODO(sirver,trading): unsure if correct. Test inter-tribe trading, i.e.
5565 // barbarians trading with empire, but shipping atlantean only wares.
5566 const BillOfMaterials items_to_receive =
5567 parse_wares_as_bill_of_material(L, 5, self->owner().tribe());
5568 const int trade_id = game.propose_trade(
5569 Trade{items_to_send, items_to_receive, num_batches, self->serial(), other_market->serial()});
5570
5571 // TODO(sirver,trading): Wrap 'Trade' into its own Lua class?
5572 lua_pushint32(L, trade_id);
5573 return 1;
5574 }
5575
5576 /*
5577 ==========================================================
5578 C METHODS
5579 ==========================================================
5580 */
5581
5582 /* RST
5583 MilitarySite
5584 --------------
5585
5586 .. class:: MilitarySite
5587
5588 Child of: :class:`Building`, :class:`HasSoldiers`
5589
5590 Miltary Buildings
5591
5592 More properties are available through this object's
5593 :class:`MilitarySiteDescription`, which you can access via :any:`MapObject.descr`.
5594 */
5595 const char LuaMilitarySite::className[] = "MilitarySite";
5596 const MethodType<LuaMilitarySite> LuaMilitarySite::Methods[] = {
5597 METHOD(LuaMilitarySite, get_soldiers), METHOD(LuaMilitarySite, set_soldiers), {nullptr, nullptr},
5598 };
5599 const PropertyType<LuaMilitarySite> LuaMilitarySite::Properties[] = {
5600 PROP_RO(LuaMilitarySite, max_soldiers), {nullptr, nullptr, nullptr},
5601 };
5602
5603 /*
5604 ==========================================================
5605 PROPERTIES
5606 ==========================================================
5607 */
5608
5609 // documented in parent class
get_max_soldiers(lua_State * L)5610 int LuaMilitarySite::get_max_soldiers(lua_State* L) {
5611 lua_pushuint32(L, get(L, get_egbase(L))->soldier_control()->soldier_capacity());
5612 return 1;
5613 }
5614
5615 /*
5616 ==========================================================
5617 LUA METHODS
5618 ==========================================================
5619 */
5620
5621 // documented in parent class
get_soldiers(lua_State * L)5622 int LuaMilitarySite::get_soldiers(lua_State* L) {
5623 MilitarySite* ms = get(L, get_egbase(L));
5624 return do_get_soldiers(L, *ms->soldier_control(), ms->owner().tribe());
5625 }
5626
5627 // documented in parent class
set_soldiers(lua_State * L)5628 int LuaMilitarySite::set_soldiers(lua_State* L) {
5629 MilitarySite* ms = get(L, get_egbase(L));
5630 return do_set_soldiers(L, ms->get_position(), ms->mutable_soldier_control(), ms->get_owner());
5631 }
5632
5633 /*
5634 ==========================================================
5635 C METHODS
5636 ==========================================================
5637 */
5638
5639 /* RST
5640 TrainingSite
5641 --------------
5642
5643 .. class:: TrainingSite
5644
5645 Child of: :class:`ProductionSite`, :class:`HasSoldiers`
5646
5647 A specialized production site for training soldiers.
5648
5649 More properties are available through this object's
5650 :class:`TrainingSiteDescription`, which you can access via :any:`MapObject.descr`.
5651 */
5652 const char LuaTrainingSite::className[] = "TrainingSite";
5653 const MethodType<LuaTrainingSite> LuaTrainingSite::Methods[] = {
5654 METHOD(LuaTrainingSite, get_soldiers), METHOD(LuaTrainingSite, set_soldiers), {nullptr, nullptr},
5655 };
5656 const PropertyType<LuaTrainingSite> LuaTrainingSite::Properties[] = {
5657 PROP_RO(LuaTrainingSite, max_soldiers), {nullptr, nullptr, nullptr},
5658 };
5659
5660 /*
5661 ==========================================================
5662 PROPERTIES
5663 ==========================================================
5664 */
5665
5666 // documented in parent class
get_max_soldiers(lua_State * L)5667 int LuaTrainingSite::get_max_soldiers(lua_State* L) {
5668 lua_pushuint32(L, get(L, get_egbase(L))->soldier_control()->soldier_capacity());
5669 return 1;
5670 }
5671
5672 /*
5673 ==========================================================
5674 LUA METHODS
5675 ==========================================================
5676 */
5677
5678 // documented in parent class
get_soldiers(lua_State * L)5679 int LuaTrainingSite::get_soldiers(lua_State* L) {
5680 TrainingSite* ts = get(L, get_egbase(L));
5681 return do_get_soldiers(L, *ts->soldier_control(), ts->owner().tribe());
5682 }
5683
5684 // documented in parent class
set_soldiers(lua_State * L)5685 int LuaTrainingSite::set_soldiers(lua_State* L) {
5686 TrainingSite* ts = get(L, get_egbase(L));
5687 return do_set_soldiers(L, ts->get_position(), ts->mutable_soldier_control(), ts->get_owner());
5688 }
5689
5690 /*
5691 ==========================================================
5692 C METHODS
5693 ==========================================================
5694 */
5695
5696 /* RST
5697 Bob
5698 ---
5699
5700 .. class:: Bob
5701
5702 Child of: :class:`MapObject`
5703
5704 This is the base class for all Bobs in widelands.
5705
5706 More properties are available through this object's
5707 :class:`MapObjectDescription`, which you can access via :any:`MapObject.descr`.
5708 */
5709 const char LuaBob::className[] = "Bob";
5710 const MethodType<LuaBob> LuaBob::Methods[] = {
5711 METHOD(LuaBob, has_caps), {nullptr, nullptr},
5712 };
5713 const PropertyType<LuaBob> LuaBob::Properties[] = {
5714 PROP_RO(LuaBob, field), {nullptr, nullptr, nullptr},
5715 };
5716
5717 /*
5718 ==========================================================
5719 PROPERTIES
5720 ==========================================================
5721 */
5722
5723 /* RST
5724 .. attribute:: field
5725
5726 (RO) The field the bob is located on
5727 */
5728 // UNTESTED
get_field(lua_State * L)5729 int LuaBob::get_field(lua_State* L) {
5730
5731 EditorGameBase& egbase = get_egbase(L);
5732
5733 Coords coords = get(L, egbase)->get_position();
5734
5735 return to_lua<LuaMaps::LuaField>(L, new LuaMaps::LuaField(coords.x, coords.y));
5736 }
5737
5738 /*
5739 ==========================================================
5740 LUA METHODS
5741 ==========================================================
5742 */
5743 /* RST
5744 .. method:: has_caps(capname)
5745
5746 Similar to :meth:`Field::has_caps`.
5747
5748 :arg capname: can be either of
5749
5750 * :const:`swims`: This bob can swim.
5751 * :const:`walks`: This bob can walk.
5752 */
5753 // UNTESTED
has_caps(lua_State * L)5754 int LuaBob::has_caps(lua_State* L) {
5755 std::string query = luaL_checkstring(L, 2);
5756
5757 uint32_t movecaps = get(L, get_egbase(L))->descr().movecaps();
5758
5759 if (query == "swims") {
5760 lua_pushboolean(L, movecaps & MOVECAPS_SWIM);
5761 } else if (query == "walks") {
5762 lua_pushboolean(L, movecaps & MOVECAPS_WALK);
5763 } else {
5764 report_error(L, "Unknown caps queried: %s!", query.c_str());
5765 }
5766
5767 return 1;
5768 }
5769
5770 /*
5771 ==========================================================
5772 C METHODS
5773 ==========================================================
5774 */
5775
5776 /* RST
5777 Ship
5778 ----
5779
5780 .. class:: Ship
5781
5782 This represents a ship in game.
5783
5784 More properties are available through this object's
5785 :class:`MapObjectDescription`, which you can access via :any:`MapObject.descr`.
5786 */
5787
5788 const char LuaShip::className[] = "Ship";
5789 const MethodType<LuaShip> LuaShip::Methods[] = {
5790 METHOD(LuaShip, get_wares),
5791 METHOD(LuaShip, get_workers),
5792 METHOD(LuaShip, build_colonization_port),
5793 METHOD(LuaShip, make_expedition),
5794 {nullptr, nullptr},
5795 };
5796 const PropertyType<LuaShip> LuaShip::Properties[] = {
5797 PROP_RO(LuaShip, debug_ware_economy),
5798 PROP_RO(LuaShip, debug_worker_economy),
5799 PROP_RO(LuaShip, last_portdock),
5800 PROP_RO(LuaShip, destination),
5801 PROP_RO(LuaShip, state),
5802 PROP_RW(LuaShip, scouting_direction),
5803 PROP_RW(LuaShip, island_explore_direction),
5804 PROP_RO(LuaShip, shipname),
5805 PROP_RW(LuaShip, capacity),
5806 {nullptr, nullptr, nullptr},
5807 };
5808
5809 /*
5810 ==========================================================
5811 PROPERTIES
5812 ==========================================================
5813 */
5814 // UNTESTED, for debug only
get_debug_ware_economy(lua_State * L)5815 int LuaShip::get_debug_ware_economy(lua_State* L) {
5816 lua_pushlightuserdata(L, get(L, get_egbase(L))->get_economy(wwWARE));
5817 return 1;
5818 }
get_debug_worker_economy(lua_State * L)5819 int LuaShip::get_debug_worker_economy(lua_State* L) {
5820 lua_pushlightuserdata(L, get(L, get_egbase(L))->get_economy(wwWORKER));
5821 return 1;
5822 }
5823
5824 /* RST
5825 .. attribute:: destination
5826
5827 (RO) Either :const:`nil` if there is no current destination, otherwise
5828 the :class:`PortDock`.
5829 */
5830 // UNTESTED
get_destination(lua_State * L)5831 int LuaShip::get_destination(lua_State* L) {
5832 return upcasted_map_object_to_lua(L, get(L, get_egbase(L))->get_destination());
5833 }
5834
5835 /* RST
5836 .. attribute:: last_portdock
5837
5838 (RO) Either :const:`nil` if no port was ever visited or the last portdock
5839 was destroyed, otherwise the :class:`PortDock` of the last visited port.
5840 */
5841 // UNTESTED
get_last_portdock(lua_State * L)5842 int LuaShip::get_last_portdock(lua_State* L) {
5843 EditorGameBase& egbase = get_egbase(L);
5844 return upcasted_map_object_to_lua(L, get(L, egbase)->get_lastdock(egbase));
5845 }
5846
5847 /* RST
5848 .. attribute:: state
5849
5850 Query which state the ship is in:
5851
5852 - transport,
5853 - exp_waiting, exp_scouting, exp_found_port_space, exp_colonizing,
5854 - sink_request, sink_animation
5855
5856 (RW) returns the :class:`string` ship's state, or :const:`nil` if there is no valid state.
5857
5858
5859 */
5860 // UNTESTED sink states
get_state(lua_State * L)5861 int LuaShip::get_state(lua_State* L) {
5862 EditorGameBase& egbase = get_egbase(L);
5863 if (is_a(Game, &egbase)) {
5864 switch (get(L, egbase)->get_ship_state()) {
5865 case Ship::ShipStates::kTransport:
5866 lua_pushstring(L, "transport");
5867 break;
5868 case Ship::ShipStates::kExpeditionWaiting:
5869 lua_pushstring(L, "exp_waiting");
5870 break;
5871 case Ship::ShipStates::kExpeditionScouting:
5872 lua_pushstring(L, "exp_scouting");
5873 break;
5874 case Ship::ShipStates::kExpeditionPortspaceFound:
5875 lua_pushstring(L, "exp_found_port_space");
5876 break;
5877 case Ship::ShipStates::kExpeditionColonizing:
5878 lua_pushstring(L, "exp_colonizing");
5879 break;
5880 case Ship::ShipStates::kSinkRequest:
5881 lua_pushstring(L, "sink_request");
5882 break;
5883 case Ship::ShipStates::kSinkAnimation:
5884 lua_pushstring(L, "sink_animation");
5885 }
5886 return 1;
5887 }
5888 return 0;
5889 }
5890
get_scouting_direction(lua_State * L)5891 int LuaShip::get_scouting_direction(lua_State* L) {
5892 EditorGameBase& egbase = get_egbase(L);
5893 if (is_a(Game, &egbase)) {
5894 switch (get(L, egbase)->get_scouting_direction()) {
5895 case WalkingDir::WALK_NE:
5896 lua_pushstring(L, "ne");
5897 break;
5898 case WalkingDir::WALK_E:
5899 lua_pushstring(L, "e");
5900 break;
5901 case WalkingDir::WALK_SE:
5902 lua_pushstring(L, "se");
5903 break;
5904 case WalkingDir::WALK_SW:
5905 lua_pushstring(L, "sw");
5906 break;
5907 case WalkingDir::WALK_W:
5908 lua_pushstring(L, "w");
5909 break;
5910 case WalkingDir::WALK_NW:
5911 lua_pushstring(L, "nw");
5912 break;
5913 case WalkingDir::IDLE:
5914 return 0;
5915 }
5916 return 1;
5917 }
5918 return 0;
5919 }
5920
set_scouting_direction(lua_State * L)5921 int LuaShip::set_scouting_direction(lua_State* L) {
5922 EditorGameBase& egbase = get_egbase(L);
5923 if (upcast(Game, game, &egbase)) {
5924 std::string dirname = luaL_checkstring(L, 3);
5925 WalkingDir dir = WalkingDir::IDLE;
5926
5927 if (dirname == "ne") {
5928 dir = WalkingDir::WALK_NE;
5929 } else if (dirname == "e") {
5930 dir = WalkingDir::WALK_E;
5931 } else if (dirname == "se") {
5932 dir = WalkingDir::WALK_SE;
5933 } else if (dirname == "sw") {
5934 dir = WalkingDir::WALK_SW;
5935 } else if (dirname == "w") {
5936 dir = WalkingDir::WALK_W;
5937 } else if (dirname == "nw") {
5938 dir = WalkingDir::WALK_NW;
5939 } else {
5940 return 0;
5941 }
5942 game->send_player_ship_scouting_direction(*get(L, egbase), dir);
5943 return 1;
5944 }
5945 return 0;
5946 }
5947
5948 /* RST
5949 .. attribute:: island_explore_direction
5950
5951 (RW) actual direction if the ship sails around an island.
5952 Sets/returns cw, ccw or nil
5953
5954 */
get_island_explore_direction(lua_State * L)5955 int LuaShip::get_island_explore_direction(lua_State* L) {
5956 EditorGameBase& egbase = get_egbase(L);
5957 if (is_a(Game, &egbase)) {
5958 switch (get(L, egbase)->get_island_explore_direction()) {
5959 case IslandExploreDirection::kCounterClockwise:
5960 lua_pushstring(L, "ccw");
5961 break;
5962 case IslandExploreDirection::kClockwise:
5963 lua_pushstring(L, "cw");
5964 break;
5965 case IslandExploreDirection::kNotSet:
5966 return 0;
5967 }
5968 return 1;
5969 }
5970 return 0;
5971 }
5972
set_island_explore_direction(lua_State * L)5973 int LuaShip::set_island_explore_direction(lua_State* L) {
5974 EditorGameBase& egbase = get_egbase(L);
5975 if (upcast(Game, game, &egbase)) {
5976 Ship* ship = get(L, egbase);
5977 std::string dir = luaL_checkstring(L, 3);
5978 if (dir == "ccw") {
5979 game->send_player_ship_explore_island(*ship, IslandExploreDirection::kCounterClockwise);
5980 } else if (dir == "cw") {
5981 game->send_player_ship_explore_island(*ship, IslandExploreDirection::kClockwise);
5982 } else {
5983 return 0;
5984 }
5985 return 1;
5986 }
5987 return 0;
5988 }
5989
5990 /* RST
5991 .. attribute:: shipname
5992
5993 Get name of ship:
5994
5995 (RO) returns the :class:`string` ship's name.
5996
5997
5998 */
get_shipname(lua_State * L)5999 int LuaShip::get_shipname(lua_State* L) {
6000 EditorGameBase& egbase = get_egbase(L);
6001 Ship* ship = get(L, egbase);
6002 lua_pushstring(L, ship->get_shipname().c_str());
6003 return 1;
6004 }
6005
6006 /* RST
6007 .. attribute:: capacity
6008
6009 The ship's current capacity. Defaults to the capacity defined in the tribe's singleton ship description.
6010
6011 Do not change this value if the ship is currently shipping more items than the new capacity allows.
6012
6013 (RW) returns the current capacity of this ship
6014
6015 */
get_capacity(lua_State * L)6016 int LuaShip::get_capacity(lua_State* L) {
6017 lua_pushuint32(L, get(L, get_egbase(L))->get_capacity());
6018 return 1;
6019 }
set_capacity(lua_State * L)6020 int LuaShip::set_capacity(lua_State* L) {
6021 Widelands::Ship& s = *get(L, get_egbase(L));
6022 const uint32_t c = luaL_checkuint32(L, -1);
6023 if (s.get_nritems() > c) {
6024 report_error(L, "Ship is currently transporting %u items – cannot set capacity to %u",
6025 s.get_nritems(), c);
6026 }
6027 s.set_capacity(c);
6028 return 0;
6029 }
6030
6031 /*
6032 ==========================================================
6033 LUA METHODS
6034 ==========================================================
6035 */
6036
6037 /* RST
6038 .. method:: get_wares()
6039
6040 Returns the number of wares on this ship. This does not implement
6041 everything that :class:`HasWares` offers.
6042
6043 :returns: the number of wares
6044 */
6045 // UNTESTED
get_wares(lua_State * L)6046 int LuaShip::get_wares(lua_State* L) {
6047 EditorGameBase& egbase = get_egbase(L);
6048 int nwares = 0;
6049 WareInstance* ware;
6050 Ship* ship = get(L, egbase);
6051 for (uint32_t i = 0; i < ship->get_nritems(); ++i) {
6052 const ShippingItem& item = ship->get_item(i);
6053 item.get(egbase, &ware, nullptr);
6054 if (ware != nullptr) {
6055 ++nwares;
6056 }
6057 }
6058 lua_pushint32(L, nwares);
6059 return 1;
6060 }
6061
6062 /* RST
6063 .. method:: get_workers()
6064
6065 Returns the number of workers on this ship. This does not implement
6066 everything that :class:`HasWorkers` offers.
6067
6068 :returns: the number of workers
6069 */
6070 // UNTESTED
get_workers(lua_State * L)6071 int LuaShip::get_workers(lua_State* L) {
6072 EditorGameBase& egbase = get_egbase(L);
6073 int nworkers = 0;
6074 Worker* worker;
6075 Ship* ship = get(L, egbase);
6076 for (uint32_t i = 0; i < ship->get_nritems(); ++i) {
6077 const ShippingItem& item = ship->get_item(i);
6078 item.get(egbase, nullptr, &worker);
6079 if (worker != nullptr) {
6080 ++nworkers;
6081 }
6082 }
6083 lua_pushint32(L, nworkers);
6084 return 1;
6085 }
6086
6087 /* RST
6088 .. method:: build_colonization_port()
6089
6090 Returns true if port space construction was started (ship was in adequate
6091 status and a found portspace was nearby)
6092
6093 :returns: true/false
6094 */
build_colonization_port(lua_State * L)6095 int LuaShip::build_colonization_port(lua_State* L) {
6096 EditorGameBase& egbase = get_egbase(L);
6097 Ship* ship = get(L, egbase);
6098 if (ship->get_ship_state() == Widelands::Ship::ShipStates::kExpeditionPortspaceFound) {
6099 if (upcast(Game, game, &egbase)) {
6100 game->send_player_ship_construct_port(*ship, ship->exp_port_spaces().front());
6101 return 1;
6102 }
6103 }
6104 return 0;
6105 }
6106
6107 /* RST
6108 .. method:: make_expedition([items])
6109
6110 Turns this ship into an expedition ship without a base port. Creates all necessary
6111 wares and a builder plus, if desired, the specified additional items.
6112 Any items previously present in the ship will be deleted.
6113
6114 The ship must be empty and not an expedition ship when this method is called.
6115
6116 :returns: nil
6117 */
make_expedition(lua_State * L)6118 int LuaShip::make_expedition(lua_State* L) {
6119 upcast(Game, game, &get_egbase(L));
6120 assert(game);
6121 Ship* ship = get(L, *game);
6122 assert(ship);
6123 if (ship->get_ship_state() != Widelands::Ship::ShipStates::kTransport ||
6124 ship->get_nritems() > 0) {
6125 report_error(L, "Ship.make_expedition can be used only on empty transport ships!");
6126 }
6127
6128 const Widelands::TribeDescr& tribe = ship->owner().tribe();
6129 for (const auto& pair : tribe.get_building_descr(tribe.port())->buildcost()) {
6130 for (size_t i = pair.second; i > 0; --i) {
6131 Widelands::WareInstance& w =
6132 *new Widelands::WareInstance(pair.first, tribe.get_ware_descr(pair.first));
6133 w.init(*game);
6134 ship->add_item(*game, Widelands::ShippingItem(w));
6135 }
6136 }
6137 ship->add_item(*game, Widelands::ShippingItem(
6138 tribe.get_worker_descr(tribe.builder())
6139 ->create(*game, ship->get_owner(), nullptr, ship->get_position())));
6140 std::map<Widelands::DescriptionIndex, uint32_t>
6141 workers_to_create; // Lua table sorting order is not deterministic and may cause desyncs
6142 if (lua_gettop(L) > 1) {
6143 luaL_checktype(L, 2, LUA_TTABLE);
6144 lua_pushnil(L);
6145 while (lua_next(L, 2) != 0) {
6146 uint32_t amount = luaL_checkuint32(L, -1);
6147 lua_pop(L, 1);
6148 std::string what = luaL_checkstring(L, -1);
6149 Widelands::DescriptionIndex index = game->tribes().ware_index(what);
6150 if (tribe.has_ware(index)) {
6151 while (amount > 0) {
6152 Widelands::WareInstance& w =
6153 *new Widelands::WareInstance(index, tribe.get_ware_descr(index));
6154 w.init(*game);
6155 ship->add_item(*game, Widelands::ShippingItem(w));
6156 --amount;
6157 }
6158 } else {
6159 index = tribe.worker_index(what);
6160 if (tribe.has_worker(index)) {
6161 workers_to_create[index] = amount;
6162 } else {
6163 report_error(L, "Invalid ware or worker: %s", what.c_str());
6164 }
6165 }
6166 }
6167 }
6168
6169 for (auto& pair : workers_to_create) {
6170 for (; pair.second; --pair.second) {
6171 ship->add_item(*game, Widelands::ShippingItem(tribe.get_worker_descr(pair.first)
6172 ->create(*game, ship->get_owner(),
6173 nullptr, ship->get_position())));
6174 }
6175 }
6176
6177 ship->set_destination(*game, nullptr);
6178 ship->start_task_expedition(*game);
6179
6180 return 0;
6181 }
6182
6183 /*
6184 ==========================================================
6185 C METHODS
6186 ==========================================================
6187 */
6188
6189 /* RST
6190 Worker
6191 ------
6192
6193 .. class:: Worker
6194
6195 Child of: :class:`Bob`
6196
6197 All workers that are visible on the map are of this kind.
6198
6199 More properties are available through this object's
6200 :class:`WorkerDescription`, which you can access via :any:`MapObject.descr`.
6201 */
6202
6203 const char LuaWorker::className[] = "Worker";
6204 const MethodType<LuaWorker> LuaWorker::Methods[] = {
6205 {nullptr, nullptr},
6206 };
6207 const PropertyType<LuaWorker> LuaWorker::Properties[] = {
6208 PROP_RO(LuaWorker, owner), PROP_RO(LuaWorker, location), {nullptr, nullptr, nullptr},
6209 };
6210
6211 /*
6212 ==========================================================
6213 PROPERTIES
6214 ==========================================================
6215 */
6216 /* RST
6217 .. attribute:: owner
6218
6219 (RO) The :class:`wl.game.Player` who owns this worker.
6220 */
6221 // UNTESTED
get_owner(lua_State * L)6222 int LuaWorker::get_owner(lua_State* L) {
6223 get_factory(L).push_player(L, get(L, get_egbase(L))->get_owner()->player_number());
6224 return 1;
6225 }
6226
6227 /* RST
6228 .. attribute:: location
6229
6230 (RO) The location where this worker is situated. This will be either a
6231 :class:`Building`, :class:`Road`, :class:`Flag` or :const:`nil`. Note
6232 that a worker that is stored in a warehouse has a location :const:`nil`.
6233 A worker that is out working (e.g. hunter) has as a location his
6234 building. A stationed soldier has his military building as location.
6235 Workers on transit usually have the Road they are currently on as
6236 location.
6237 */
6238 // UNTESTED
get_location(lua_State * L)6239 int LuaWorker::get_location(lua_State* L) {
6240 EditorGameBase& egbase = get_egbase(L);
6241 return upcasted_map_object_to_lua(
6242 L, static_cast<BaseImmovable*>(get(L, egbase)->get_location(egbase)));
6243 }
6244
6245 /*
6246 ==========================================================
6247 LUA METHODS
6248 ==========================================================
6249 */
6250
6251 /*
6252 ==========================================================
6253 C METHODS
6254 ==========================================================
6255 */
6256
6257 /* RST
6258 Soldier
6259 -------
6260
6261 .. class:: Soldier
6262
6263 Child of: :class:`Worker`
6264
6265 All soldiers that are on the map are represented by this class.
6266
6267 More properties are available through this object's
6268 :class:`SoldierDescription`, which you can access via :any:`MapObject.descr`.
6269 */
6270
6271 const char LuaSoldier::className[] = "Soldier";
6272 const MethodType<LuaSoldier> LuaSoldier::Methods[] = {
6273 {nullptr, nullptr},
6274 };
6275 const PropertyType<LuaSoldier> LuaSoldier::Properties[] = {
6276 PROP_RO(LuaSoldier, attack_level), PROP_RO(LuaSoldier, defense_level),
6277 PROP_RO(LuaSoldier, health_level), PROP_RO(LuaSoldier, evade_level),
6278 {nullptr, nullptr, nullptr},
6279 };
6280
6281 /*
6282 ==========================================================
6283 PROPERTIES
6284 ==========================================================
6285 */
6286 /* RST
6287 .. attribute:: attack_level
6288
6289 (RO) The current attack level of this soldier
6290 */
6291 // UNTESTED
get_attack_level(lua_State * L)6292 int LuaSoldier::get_attack_level(lua_State* L) {
6293 lua_pushuint32(L, get(L, get_egbase(L))->get_attack_level());
6294 return 1;
6295 }
6296
6297 /* RST
6298 .. attribute:: defense_level
6299
6300 (RO) The current defense level of this soldier
6301 */
6302 // UNTESTED
get_defense_level(lua_State * L)6303 int LuaSoldier::get_defense_level(lua_State* L) {
6304 lua_pushuint32(L, get(L, get_egbase(L))->get_defense_level());
6305 return 1;
6306 }
6307
6308 /* RST
6309 .. attribute:: health_level
6310
6311 (RO) The current health level of this soldier
6312 */
6313 // UNTESTED
get_health_level(lua_State * L)6314 int LuaSoldier::get_health_level(lua_State* L) {
6315 lua_pushuint32(L, get(L, get_egbase(L))->get_health_level());
6316 return 1;
6317 }
6318
6319 /* RST
6320 .. attribute:: evade_level
6321
6322 (RO) The current evade level of this soldier
6323 */
6324 // UNTESTED
get_evade_level(lua_State * L)6325 int LuaSoldier::get_evade_level(lua_State* L) {
6326 lua_pushuint32(L, get(L, get_egbase(L))->get_evade_level());
6327 return 1;
6328 }
6329
6330 /*
6331 ==========================================================
6332 LUA METHODS
6333 ==========================================================
6334 */
6335
6336 /*
6337 ==========================================================
6338 C METHODS
6339 ==========================================================
6340 */
6341
6342 /* RST
6343 Field
6344 -----
6345
6346 .. class:: Field
6347
6348 This class represents one Field in Widelands. The field may contain
6349 immovables like Flags or Buildings and can be connected via Roads. Every
6350 Field has two Triangles associated with itself: the right and the down one.
6351
6352 You cannot instantiate this directly, access it via
6353 wl.Game().map.get_field() instead.
6354 */
6355
6356 const char LuaField::className[] = "Field";
6357 const MethodType<LuaField> LuaField::Methods[] = {
6358 METHOD(LuaField, __eq), METHOD(LuaField, __tostring), METHOD(LuaField, region),
6359 METHOD(LuaField, has_caps), METHOD(LuaField, has_max_caps), {nullptr, nullptr},
6360 };
6361 const PropertyType<LuaField> LuaField::Properties[] = {
6362 PROP_RO(LuaField, __hash),
6363 PROP_RO(LuaField, x),
6364 PROP_RO(LuaField, y),
6365 PROP_RO(LuaField, rn),
6366 PROP_RO(LuaField, ln),
6367 PROP_RO(LuaField, trn),
6368 PROP_RO(LuaField, tln),
6369 PROP_RO(LuaField, bln),
6370 PROP_RO(LuaField, brn),
6371 PROP_RO(LuaField, immovable),
6372 PROP_RO(LuaField, bobs),
6373 PROP_RW(LuaField, terr),
6374 PROP_RW(LuaField, terd),
6375 PROP_RW(LuaField, height),
6376 PROP_RW(LuaField, raw_height),
6377 PROP_RO(LuaField, viewpoint_x),
6378 PROP_RO(LuaField, viewpoint_y),
6379 PROP_RW(LuaField, resource),
6380 PROP_RW(LuaField, resource_amount),
6381 PROP_RO(LuaField, initial_resource_amount),
6382 PROP_RO(LuaField, claimers),
6383 PROP_RO(LuaField, owner),
6384 PROP_RO(LuaField, buildable),
6385 {nullptr, nullptr, nullptr},
6386 };
6387
__persist(lua_State * L)6388 void LuaField::__persist(lua_State* L) {
6389 PERS_INT32("x", coords_.x);
6390 PERS_INT32("y", coords_.y);
6391 }
6392
__unpersist(lua_State * L)6393 void LuaField::__unpersist(lua_State* L) {
6394 UNPERS_INT32("x", coords_.x)
6395 UNPERS_INT32("y", coords_.y)
6396 }
6397
6398 /*
6399 ==========================================================
6400 PROPERTIES
6401 ==========================================================
6402 */
6403 /* RST
6404 .. attribute:: __hash
6405
6406 (RO) The hashed coordinates of the field's position. Used to identify a class in a Set.
6407 */
get___hash(lua_State * L)6408 int LuaField::get___hash(lua_State* L) {
6409 lua_pushuint32(L, coords_.hash());
6410 return 1;
6411 }
6412
6413 /* RST
6414 .. attribute:: x, y
6415
6416 (RO) The x/y coordinate of this field
6417 */
get_x(lua_State * L)6418 int LuaField::get_x(lua_State* L) {
6419 lua_pushuint32(L, coords_.x);
6420 return 1;
6421 }
get_y(lua_State * L)6422 int LuaField::get_y(lua_State* L) {
6423 lua_pushuint32(L, coords_.y);
6424 return 1;
6425 }
6426
6427 /* RST
6428 .. attribute:: height
6429
6430 (RW) The height of this field. The default height is 10, you can increase
6431 or decrease this value to build mountains. Note though that if you change
6432 this value too much, all surrounding fields will also change their
6433 heights because the slope is constrained. If you are changing the height
6434 of many terrains at once, use :attr:`raw_height` instead and then call
6435 :any:`recalculate` afterwards.
6436 */
get_height(lua_State * L)6437 int LuaField::get_height(lua_State* L) {
6438 lua_pushuint32(L, fcoords(L).field->get_height());
6439 return 1;
6440 }
set_height(lua_State * L)6441 int LuaField::set_height(lua_State* L) {
6442 uint32_t height = luaL_checkuint32(L, -1);
6443 FCoords f = fcoords(L);
6444
6445 if (f.field->get_height() == height) {
6446 return 0;
6447 }
6448
6449 if (height > MAX_FIELD_HEIGHT) {
6450 report_error(L, "height must be <= %i", MAX_FIELD_HEIGHT);
6451 }
6452
6453 EditorGameBase& egbase = get_egbase(L);
6454 egbase.mutable_map()->set_height(egbase, f, height);
6455
6456 return 0;
6457 }
6458
6459 /* RST
6460 .. attribute:: raw_height
6461
6462 (RW) The same as :attr:`height`, but setting this will not trigger a
6463 recalculation of the surrounding fields. You can use this field to
6464 change the height of many fields on a map quickly, then use
6465 :any:`recalculate` to make sure that everything is in order.
6466 */
6467 // UNTESTED
get_raw_height(lua_State * L)6468 int LuaField::get_raw_height(lua_State* L) {
6469 lua_pushuint32(L, fcoords(L).field->get_height());
6470 return 1;
6471 }
set_raw_height(lua_State * L)6472 int LuaField::set_raw_height(lua_State* L) {
6473 uint32_t height = luaL_checkuint32(L, -1);
6474 FCoords f = fcoords(L);
6475
6476 if (f.field->get_height() == height) {
6477 return 0;
6478 }
6479
6480 if (height > MAX_FIELD_HEIGHT) {
6481 report_error(L, "height must be <= %i", MAX_FIELD_HEIGHT);
6482 }
6483
6484 f.field->set_height(height);
6485
6486 return 0;
6487 }
6488
6489 /* RST
6490 .. attribute:: viewpoint_x, viewpoint_y
6491
6492 (RO) Returns the position in pixels to move the view to to center
6493 this field for the current interactive player
6494 */
get_viewpoint_x(lua_State * L)6495 int LuaField::get_viewpoint_x(lua_State* L) {
6496 Vector2f point =
6497 MapviewPixelFunctions::to_map_pixel_with_normalization(get_egbase(L).map(), coords_);
6498 lua_pushdouble(L, point.x);
6499 return 1;
6500 }
get_viewpoint_y(lua_State * L)6501 int LuaField::get_viewpoint_y(lua_State* L) {
6502 Vector2f point =
6503 MapviewPixelFunctions::to_map_pixel_with_normalization(get_egbase(L).map(), coords_);
6504 lua_pushdouble(L, point.y);
6505 return 1;
6506 }
6507
6508 /* RST
6509 .. attribute:: resource
6510
6511 (RW) The name of the resource that is available in this field or
6512 :const:`nil`
6513
6514 :see also: :attr:`resource_amount`
6515 */
get_resource(lua_State * L)6516 int LuaField::get_resource(lua_State* L) {
6517
6518 const ResourceDescription* rDesc =
6519 get_egbase(L).world().get_resource(fcoords(L).field->get_resources());
6520
6521 lua_pushstring(L, rDesc ? rDesc->name().c_str() : "none");
6522
6523 return 1;
6524 }
set_resource(lua_State * L)6525 int LuaField::set_resource(lua_State* L) {
6526 auto& egbase = get_egbase(L);
6527 DescriptionIndex res = egbase.world().resource_index(luaL_checkstring(L, -1));
6528
6529 if (res == Widelands::INVALID_INDEX) {
6530 report_error(L, "Illegal resource: '%s'", luaL_checkstring(L, -1));
6531 }
6532
6533 auto c = fcoords(L);
6534 const auto current_amount = c.field->get_resources_amount();
6535 auto* map = egbase.mutable_map();
6536 map->initialize_resources(c, res, c.field->get_initial_res_amount());
6537 map->set_resources(c, current_amount);
6538 return 0;
6539 }
6540
6541 /* RST
6542 .. attribute:: resource_amount
6543
6544 (RW) How many items of the resource is available in this field.
6545
6546 :see also: :attr:`resource`
6547 */
get_resource_amount(lua_State * L)6548 int LuaField::get_resource_amount(lua_State* L) {
6549 lua_pushuint32(L, fcoords(L).field->get_resources_amount());
6550 return 1;
6551 }
set_resource_amount(lua_State * L)6552 int LuaField::set_resource_amount(lua_State* L) {
6553 EditorGameBase& egbase = get_egbase(L);
6554 auto c = fcoords(L);
6555 DescriptionIndex res = c.field->get_resources();
6556 auto amount = luaL_checkint32(L, -1);
6557 const ResourceDescription* resDesc = egbase.world().get_resource(res);
6558 ResourceAmount max_amount = resDesc ? resDesc->max_amount() : 0;
6559
6560 if (amount < 0 || amount > max_amount) {
6561 report_error(L, "Illegal amount: %i, must be >= 0 and <= %i", amount,
6562 static_cast<unsigned int>(max_amount));
6563 }
6564
6565 auto* map = egbase.mutable_map();
6566 if (is_a(Game, &egbase)) {
6567 map->set_resources(c, amount);
6568 } else {
6569 // in editor, reset also initial amount
6570 map->initialize_resources(c, res, amount);
6571 }
6572 return 0;
6573 }
6574 /* RST
6575 .. attribute:: initial_resource_amount
6576
6577 (RO) Starting value of resource. It is set be resource_amount
6578
6579 :see also: :attr:`resource`
6580 */
get_initial_resource_amount(lua_State * L)6581 int LuaField::get_initial_resource_amount(lua_State* L) {
6582 lua_pushuint32(L, fcoords(L).field->get_initial_res_amount());
6583 return 1;
6584 }
6585 /* RST
6586 .. attribute:: immovable
6587
6588 (RO) The immovable that stands on this field or :const:`nil`. If you want
6589 to remove an immovable, you can use :func:`wl.map.MapObject.remove`.
6590 */
get_immovable(lua_State * L)6591 int LuaField::get_immovable(lua_State* L) {
6592 BaseImmovable* bi = get_egbase(L).map().get_immovable(coords_);
6593
6594 if (!bi) {
6595 return 0;
6596 } else {
6597 upcasted_map_object_to_lua(L, bi);
6598 }
6599 return 1;
6600 }
6601
6602 /* RST
6603 .. attribute:: bobs
6604
6605 (RO) An :class:`array` of :class:`~wl.map.Bob` that are associated
6606 with this field
6607 */
6608 // UNTESTED
get_bobs(lua_State * L)6609 int LuaField::get_bobs(lua_State* L) {
6610 Bob* b = fcoords(L).field->get_first_bob();
6611
6612 lua_newtable(L);
6613 uint32_t cidx = 1;
6614 while (b) {
6615 lua_pushuint32(L, cidx++);
6616 upcasted_map_object_to_lua(L, b);
6617 lua_rawset(L, -3);
6618 b = b->get_next_bob();
6619 }
6620 return 1;
6621 }
6622
6623 /* RST
6624 .. attribute:: terr, terd
6625
6626 (RW) The terrain of the right/down triangle. This is a string value
6627 containing the name of the terrain as it is defined in the world
6628 configuration. You can change the terrain by simply assigning another
6629 valid name to these variables. If you are changing the terrain from or to
6630 water, the map will not recalculate whether it allows seafaring, because
6631 this recalculation can take up a lot of performance. If you need this
6632 recalculated, you can do so by calling :any:`recalculate_seafaring` after
6633 you're done changing terrains.
6634 */
get_terr(lua_State * L)6635 int LuaField::get_terr(lua_State* L) {
6636 TerrainDescription& td = get_egbase(L).world().terrain_descr(fcoords(L).field->terrain_r());
6637 lua_pushstring(L, td.name().c_str());
6638 return 1;
6639 }
set_terr(lua_State * L)6640 int LuaField::set_terr(lua_State* L) {
6641 const char* name = luaL_checkstring(L, -1);
6642 EditorGameBase& egbase = get_egbase(L);
6643 const DescriptionIndex td = egbase.world().terrains().get_index(name);
6644 if (td == static_cast<DescriptionIndex>(Widelands::INVALID_INDEX)) {
6645 report_error(L, "Unknown terrain '%s'", name);
6646 }
6647
6648 egbase.mutable_map()->change_terrain(egbase, TCoords<FCoords>(fcoords(L), TriangleIndex::R), td);
6649
6650 lua_pushstring(L, name);
6651 return 1;
6652 }
6653
get_terd(lua_State * L)6654 int LuaField::get_terd(lua_State* L) {
6655 TerrainDescription& td = get_egbase(L).world().terrain_descr(fcoords(L).field->terrain_d());
6656 lua_pushstring(L, td.name().c_str());
6657 return 1;
6658 }
set_terd(lua_State * L)6659 int LuaField::set_terd(lua_State* L) {
6660 const char* name = luaL_checkstring(L, -1);
6661 EditorGameBase& egbase = get_egbase(L);
6662 const DescriptionIndex td = egbase.world().terrains().get_index(name);
6663 if (td == static_cast<DescriptionIndex>(INVALID_INDEX)) {
6664 report_error(L, "Unknown terrain '%s'", name);
6665 }
6666
6667 egbase.mutable_map()->change_terrain(egbase, TCoords<FCoords>(fcoords(L), TriangleIndex::D), td);
6668
6669 lua_pushstring(L, name);
6670 return 1;
6671 }
6672
6673 /* RST
6674 .. attribute:: rn, ln, brn, bln, trn, tln
6675
6676 (RO) The neighbour fields of this field. The abbreviations stand for:
6677
6678 * rn -- Right neighbour
6679 * ln -- Left neighbour
6680 * brn -- Bottom right neighbour
6681 * bln -- Bottom left neighbour
6682 * trn -- Top right neighbour
6683 * tln -- Top left neighbour
6684
6685 Note that the widelands map wraps at its borders, that is the following
6686 holds:
6687
6688 .. code-block:: lua
6689
6690 wl.map.Field(wl.map.get_width()-1, 10).rn == wl.map.Field(0, 10)
6691 */
6692 #define GET_X_NEIGHBOUR(X) \
6693 int LuaField::get_##X(lua_State* L) { \
6694 Coords n; \
6695 get_egbase(L).map().get_##X(coords_, &n); \
6696 to_lua<LuaField>(L, new LuaField(n.x, n.y)); \
6697 return 1; \
6698 }
6699 GET_X_NEIGHBOUR(rn)
GET_X_NEIGHBOUR(ln)6700 GET_X_NEIGHBOUR(ln)
6701 GET_X_NEIGHBOUR(trn)
6702 GET_X_NEIGHBOUR(tln)
6703 GET_X_NEIGHBOUR(bln)
6704 GET_X_NEIGHBOUR(brn)
6705
6706 /* RST
6707 .. attribute:: owner
6708
6709 (RO) The current owner of the field or :const:`nil` if noone owns it. See
6710 also :attr:`claimers`.
6711 */
6712 int LuaField::get_owner(lua_State* L) {
6713 PlayerNumber current_owner = fcoords(L).field->get_owned_by();
6714 if (current_owner) {
6715 get_factory(L).push_player(L, current_owner);
6716 return 1;
6717 }
6718 return 0;
6719 }
6720
6721 /* RST
6722 .. attribute:: buildable
6723
6724 (RO) Returns :const:`true` if a flag or building could be built on this field,
6725 independently of whether anybody currently owns this field.
6726 */
get_buildable(lua_State * L)6727 int LuaField::get_buildable(lua_State* L) {
6728 const NodeCaps caps = fcoords(L).field->nodecaps();
6729 const bool is_buildable = (caps & BUILDCAPS_FLAG) || (caps & BUILDCAPS_SMALL) ||
6730 (caps & BUILDCAPS_MEDIUM) || (caps & BUILDCAPS_BIG) ||
6731 (caps & BUILDCAPS_MINE);
6732 lua_pushboolean(L, is_buildable);
6733 return 1;
6734 }
6735
6736 /* RST
6737 .. attribute:: claimers
6738
6739 (RO) An :class:`array` of players that have military influence over this
6740 field sorted by the amount of influence they have. Note that this does
6741 not necessarily mean that claimers[1] is also the owner of the field, as
6742 a field that houses a surrounded military building is owned by the
6743 surrounded player, but others have more military influence over it.
6744
6745 Note: The one currently owning the field is in :attr:`owner`.
6746 */
get_claimers(lua_State * L)6747 int LuaField::get_claimers(lua_State* L) {
6748 EditorGameBase& egbase = get_egbase(L);
6749 const Map& map = egbase.map();
6750
6751 std::vector<PlrInfluence> claimers;
6752
6753 iterate_players_existing(other_p, map.get_nrplayers(), egbase, plr)
6754 claimers.push_back(PlrInfluence(
6755 plr->player_number(), plr->military_influence(map.get_index(coords_, map.get_width()))));
6756
6757 std::stable_sort(claimers.begin(), claimers.end(), sort_claimers);
6758
6759 lua_createtable(L, 1, 0); // We mostly expect one claimer per field.
6760
6761 // Push the players with military influence
6762 uint32_t cidx = 1;
6763 for (const PlrInfluence& claimer : claimers) {
6764 if (claimer.second <= 0) {
6765 continue;
6766 }
6767 lua_pushuint32(L, cidx++);
6768 get_factory(L).push_player(L, claimer.first);
6769 lua_rawset(L, -3);
6770 }
6771
6772 return 1;
6773 }
6774
6775 /*
6776 ==========================================================
6777 LUA METHODS
6778 ==========================================================
6779 */
__eq(lua_State * L)6780 int LuaField::__eq(lua_State* L) {
6781 lua_pushboolean(L, (*get_user_class<LuaField>(L, -1))->coords_ == coords_);
6782 return 1;
6783 }
6784
__tostring(lua_State * L)6785 int LuaField::__tostring(lua_State* L) {
6786 const std::string pushme = (boost::format("Field(%i,%i)") % coords_.x % coords_.y).str();
6787 lua_pushstring(L, pushme);
6788 return 1;
6789 }
6790
6791 /* RST
6792 .. function:: region(r1[, r2])
6793
6794 Returns an array of all Fields inside the given region. If one argument
6795 is given it defines the radius of the region. If both arguments are
6796 specified, the first one defines the outer radius and the second one the
6797 inner radius and a hollow region is returned, that is all fields in the
6798 outer radius region minus all fields in the inner radius region.
6799
6800 A small example:
6801
6802 .. code-block:: lua
6803
6804 f:region(1)
6805
6806 will return an array with the following entries (Note: Ordering of the
6807 fields inside the array is not guaranteed):
6808
6809 .. code-block:: lua
6810
6811 {f, f.rn, f.ln, f.brn, f.bln, f.tln, f.trn}
6812
6813 :returns: The array of the given fields.
6814 :rtype: :class:`array`
6815 */
region(lua_State * L)6816 int LuaField::region(lua_State* L) {
6817 uint32_t n = lua_gettop(L);
6818
6819 if (n == 3) {
6820 uint32_t radius = luaL_checkuint32(L, -2);
6821 uint32_t inner_radius = luaL_checkuint32(L, -1);
6822 return hollow_region(L, radius, inner_radius);
6823 }
6824
6825 uint32_t radius = luaL_checkuint32(L, -1);
6826 return region(L, radius);
6827 }
6828
6829 /* RST
6830 .. method:: has_caps(capname)
6831
6832 Returns :const:`true` if the field has this caps associated
6833 with it, otherwise returns false.
6834 Note: Immovables will hide the caps. If you want to have the caps
6835 without immovables use has_max_caps instead
6836
6837 :arg capname: can be either of
6838
6839 * :const:`small`: Can a small building be built here?
6840 * :const:`medium`: Can a medium building be built here?
6841 * :const:`big`: Can a big building be built here?
6842 * :const:`mine`: Can a mine be built here?
6843 * :const:`port`: Can a port be built here?
6844 * :const:`flag`: Can a flag be built here?
6845 * :const:`walkable`: Is this field passable for walking bobs?
6846 * :const:`swimmable`: Is this field passable for swimming bobs?
6847 */
has_caps(lua_State * L)6848 int LuaField::has_caps(lua_State* L) {
6849 const FCoords& f = fcoords(L);
6850 std::string query = luaL_checkstring(L, 2);
6851 lua_pushboolean(L, check_has_caps(L, query, f, f.field->nodecaps(), get_egbase(L).map()));
6852 return 1;
6853 }
6854
6855 /* RST
6856 .. method:: has_max_caps(capname)
6857
6858 Returns :const:`true` if the field has this maximum caps (not taking immovables into account)
6859 associated with it, otherwise returns false.
6860
6861 :arg capname: can be either of
6862
6863 * :const:`small`: Can a small building be built here?
6864 * :const:`medium`: Can a medium building be built here?
6865 * :const:`big`: Can a big building be built here?
6866 * :const:`mine`: Can a mine be built here?
6867 * :const:`port`: Can a port be built here?
6868 * :const:`flag`: Can a flag be built here?
6869 * :const:`walkable`: Is this field passable for walking bobs?
6870 * :const:`swimmable`: Is this field passable for swimming bobs?
6871 */
has_max_caps(lua_State * L)6872 int LuaField::has_max_caps(lua_State* L) {
6873 const FCoords& f = fcoords(L);
6874 std::string query = luaL_checkstring(L, 2);
6875 lua_pushboolean(
6876 L, check_has_caps(L, luaL_checkstring(L, 2), f, f.field->maxcaps(), get_egbase(L).map()));
6877 return 1;
6878 }
6879
6880 /*
6881 ==========================================================
6882 C METHODS
6883 ==========================================================
6884 */
region(lua_State * L,uint32_t radius)6885 int LuaField::region(lua_State* L, uint32_t radius) {
6886 const Map& map = get_egbase(L).map();
6887 MapRegion<Area<FCoords>> mr(map, Area<FCoords>(fcoords(L), radius));
6888
6889 lua_newtable(L);
6890 uint32_t idx = 1;
6891 do {
6892 lua_pushuint32(L, idx++);
6893 const FCoords& loc = mr.location();
6894 to_lua<LuaField>(L, new LuaField(loc.x, loc.y));
6895 lua_settable(L, -3);
6896 } while (mr.advance(map));
6897
6898 return 1;
6899 }
6900
hollow_region(lua_State * L,uint32_t radius,uint32_t inner_radius)6901 int LuaField::hollow_region(lua_State* L, uint32_t radius, uint32_t inner_radius) {
6902 const Map& map = get_egbase(L).map();
6903 HollowArea<Area<>> har(Area<>(coords_, radius), inner_radius);
6904
6905 MapHollowRegion<Area<>> mr(map, har);
6906
6907 lua_newtable(L);
6908 uint32_t idx = 1;
6909 do {
6910 lua_pushuint32(L, idx++);
6911 to_lua<LuaField>(L, new LuaField(mr.location()));
6912 lua_settable(L, -3);
6913 } while (mr.advance(map));
6914
6915 return 1;
6916 }
6917
fcoords(lua_State * L)6918 const Widelands::FCoords LuaField::fcoords(lua_State* L) {
6919 return get_egbase(L).map().get_fcoords(coords_);
6920 }
6921
6922 /* RST
6923 PlayerSlot
6924 ----------
6925
6926 .. class:: PlayerSlot
6927
6928 A player description as it is in the map. This contains information
6929 about the start position, the name of the player if this map is played
6930 as scenario and it's tribe. Note that these information can be different
6931 than the players actually valid in the game as in single player games,
6932 the player can choose most parameters freely.
6933 */
6934 const char LuaPlayerSlot::className[] = "PlayerSlot";
6935 const MethodType<LuaPlayerSlot> LuaPlayerSlot::Methods[] = {
6936 {nullptr, nullptr},
6937 };
6938 const PropertyType<LuaPlayerSlot> LuaPlayerSlot::Properties[] = {
6939 PROP_RO(LuaPlayerSlot, tribe_name),
6940 PROP_RO(LuaPlayerSlot, name),
6941 PROP_RO(LuaPlayerSlot, starting_field),
6942 {nullptr, nullptr, nullptr},
6943 };
6944
__persist(lua_State * L)6945 void LuaPlayerSlot::__persist(lua_State* L) {
6946 PERS_UINT32("player", player_number_);
6947 }
6948
__unpersist(lua_State * L)6949 void LuaPlayerSlot::__unpersist(lua_State* L) {
6950 UNPERS_UINT32("player", player_number_)
6951 }
6952
6953 /*
6954 ==========================================================
6955 PROPERTIES
6956 ==========================================================
6957 */
6958 /* RST
6959 .. attribute:: tribe_name
6960
6961 (RO) The name of the tribe suggested for this player in this map
6962 */
get_tribe_name(lua_State * L)6963 int LuaPlayerSlot::get_tribe_name(lua_State* L) {
6964 lua_pushstring(L, get_egbase(L).map().get_scenario_player_tribe(player_number_));
6965 return 1;
6966 }
6967
6968 /* RST
6969 .. attribute:: name
6970
6971 (RO) The name for this player as suggested in this map
6972 */
get_name(lua_State * L)6973 int LuaPlayerSlot::get_name(lua_State* L) {
6974 lua_pushstring(L, get_egbase(L).map().get_scenario_player_name(player_number_));
6975 return 1;
6976 }
6977
6978 /* RST
6979 .. attribute:: starting_field
6980
6981 (RO) The starting_field for this player as set in the map.
6982 Note that it is not guaranteed that the HQ of the player is on this
6983 field as scenarios and starting conditions are free to place the HQ
6984 wherever it want. This field is only centered when the game starts.
6985 */
get_starting_field(lua_State * L)6986 int LuaPlayerSlot::get_starting_field(lua_State* L) {
6987 to_lua<LuaField>(L, new LuaField(get_egbase(L).map().get_starting_pos(player_number_)));
6988 return 1;
6989 }
6990
6991 /*
6992 ==========================================================
6993 LUA METHODS
6994 ==========================================================
6995 */
6996
6997 /*
6998 ==========================================================
6999 C METHODS
7000 ==========================================================
7001 */
7002
7003 /*
7004 * ========================================================================
7005 * MODULE FUNCTIONS
7006 * ========================================================================
7007 */
7008
7009 const static struct luaL_Reg wlmap[] = {{nullptr, nullptr}};
7010
luaopen_wlmap(lua_State * L)7011 void luaopen_wlmap(lua_State* L) {
7012 lua_getglobal(L, "wl"); // S: wl_table
7013 lua_pushstring(L, "map"); // S: wl_table "map"
7014 luaL_newlib(L, wlmap); // S: wl_table "map" wl.map_table
7015 lua_settable(L, -3); // S: wl_table
7016 lua_pop(L, 1); // S:
7017
7018 register_class<LuaMap>(L, "map");
7019 register_class<LuaTribeDescription>(L, "map");
7020 register_class<LuaMapObjectDescription>(L, "map");
7021
7022 register_class<LuaImmovableDescription>(L, "map", true);
7023 add_parent<LuaImmovableDescription, LuaMapObjectDescription>(L);
7024 lua_pop(L, 1); // Pop the meta table
7025
7026 register_class<LuaBuildingDescription>(L, "map", true);
7027 add_parent<LuaBuildingDescription, LuaMapObjectDescription>(L);
7028 lua_pop(L, 1); // Pop the meta table
7029
7030 register_class<LuaConstructionSiteDescription>(L, "map", true);
7031 add_parent<LuaConstructionSiteDescription, LuaBuildingDescription>(L);
7032 add_parent<LuaConstructionSiteDescription, LuaMapObjectDescription>(L);
7033 lua_pop(L, 1); // Pop the meta table
7034
7035 register_class<LuaDismantleSiteDescription>(L, "map", true);
7036 add_parent<LuaDismantleSiteDescription, LuaBuildingDescription>(L);
7037 add_parent<LuaDismantleSiteDescription, LuaMapObjectDescription>(L);
7038 lua_pop(L, 1); // Pop the meta table
7039
7040 register_class<LuaProductionSiteDescription>(L, "map", true);
7041 add_parent<LuaProductionSiteDescription, LuaBuildingDescription>(L);
7042 add_parent<LuaProductionSiteDescription, LuaMapObjectDescription>(L);
7043 lua_pop(L, 1); // Pop the meta table
7044
7045 register_class<LuaMilitarySiteDescription>(L, "map", true);
7046 add_parent<LuaMilitarySiteDescription, LuaBuildingDescription>(L);
7047 add_parent<LuaMilitarySiteDescription, LuaMapObjectDescription>(L);
7048 lua_pop(L, 1); // Pop the meta table
7049
7050 register_class<LuaTrainingSiteDescription>(L, "map", true);
7051 add_parent<LuaTrainingSiteDescription, LuaProductionSiteDescription>(L);
7052 add_parent<LuaTrainingSiteDescription, LuaBuildingDescription>(L);
7053 add_parent<LuaTrainingSiteDescription, LuaMapObjectDescription>(L);
7054 lua_pop(L, 1); // Pop the meta table
7055
7056 register_class<LuaWarehouseDescription>(L, "map", true);
7057 add_parent<LuaWarehouseDescription, LuaBuildingDescription>(L);
7058 add_parent<LuaWarehouseDescription, LuaMapObjectDescription>(L);
7059 lua_pop(L, 1); // Pop the meta table
7060
7061 register_class<LuaMarketDescription>(L, "map", true);
7062 add_parent<LuaMarketDescription, LuaBuildingDescription>(L);
7063 add_parent<LuaMarketDescription, LuaMapObjectDescription>(L);
7064 lua_pop(L, 1); // Pop the meta table
7065
7066 register_class<LuaWareDescription>(L, "map", true);
7067 add_parent<LuaWareDescription, LuaMapObjectDescription>(L);
7068 lua_pop(L, 1); // Pop the meta table
7069
7070 register_class<LuaWorkerDescription>(L, "map", true);
7071 add_parent<LuaWorkerDescription, LuaMapObjectDescription>(L);
7072 lua_pop(L, 1); // Pop the meta table
7073
7074 register_class<LuaSoldierDescription>(L, "map", true);
7075 add_parent<LuaSoldierDescription, LuaWorkerDescription>(L);
7076 add_parent<LuaSoldierDescription, LuaMapObjectDescription>(L);
7077 lua_pop(L, 1); // Pop the meta table
7078
7079 register_class<LuaResourceDescription>(L, "map");
7080 register_class<LuaTerrainDescription>(L, "map");
7081
7082 register_class<LuaField>(L, "map");
7083 register_class<LuaPlayerSlot>(L, "map");
7084 register_class<LuaEconomy>(L, "map");
7085 register_class<LuaMapObject>(L, "map");
7086
7087 register_class<LuaBob>(L, "map", true);
7088 add_parent<LuaBob, LuaMapObject>(L);
7089 lua_pop(L, 1); // Pop the meta table
7090
7091 register_class<LuaWorker>(L, "map", true);
7092 add_parent<LuaWorker, LuaBob>(L);
7093 add_parent<LuaWorker, LuaMapObject>(L);
7094 lua_pop(L, 1); // Pop the meta table
7095
7096 register_class<LuaSoldier>(L, "map", true);
7097 add_parent<LuaSoldier, LuaWorker>(L);
7098 add_parent<LuaSoldier, LuaBob>(L);
7099 add_parent<LuaSoldier, LuaMapObject>(L);
7100 lua_pop(L, 1); // Pop the meta table
7101
7102 register_class<LuaShip>(L, "map", true);
7103 add_parent<LuaShip, LuaBob>(L);
7104 add_parent<LuaShip, LuaMapObject>(L);
7105 lua_pop(L, 1); // Pop the meta table
7106
7107 register_class<LuaBaseImmovable>(L, "map", true);
7108 add_parent<LuaBaseImmovable, LuaMapObject>(L);
7109 lua_pop(L, 1); // Pop the meta table
7110
7111 register_class<LuaPlayerImmovable>(L, "map", true);
7112 add_parent<LuaPlayerImmovable, LuaBaseImmovable>(L);
7113 add_parent<LuaPlayerImmovable, LuaMapObject>(L);
7114 lua_pop(L, 1); // Pop the meta table
7115
7116 register_class<LuaBuilding>(L, "map", true);
7117 add_parent<LuaBuilding, LuaPlayerImmovable>(L);
7118 add_parent<LuaBuilding, LuaBaseImmovable>(L);
7119 add_parent<LuaBuilding, LuaMapObject>(L);
7120 lua_pop(L, 1); // Pop the meta table
7121
7122 register_class<LuaPortDock>(L, "map", true);
7123 add_parent<LuaPortDock, LuaPlayerImmovable>(L);
7124 add_parent<LuaPortDock, LuaBaseImmovable>(L);
7125 add_parent<LuaPortDock, LuaMapObject>(L);
7126 lua_pop(L, 1); // Pop the meta table
7127
7128 register_class<LuaFlag>(L, "map", true);
7129 add_parent<LuaFlag, LuaPlayerImmovable>(L);
7130 add_parent<LuaFlag, LuaBaseImmovable>(L);
7131 add_parent<LuaFlag, LuaMapObject>(L);
7132 lua_pop(L, 1); // Pop the meta table
7133
7134 register_class<LuaRoad>(L, "map", true);
7135 add_parent<LuaRoad, LuaPlayerImmovable>(L);
7136 add_parent<LuaRoad, LuaBaseImmovable>(L);
7137 add_parent<LuaRoad, LuaMapObject>(L);
7138 lua_pop(L, 1); // Pop the meta table
7139
7140 register_class<LuaConstructionSite>(L, "map", true);
7141 add_parent<LuaConstructionSite, LuaBuilding>(L);
7142 add_parent<LuaConstructionSite, LuaPlayerImmovable>(L);
7143 add_parent<LuaConstructionSite, LuaBaseImmovable>(L);
7144 add_parent<LuaConstructionSite, LuaMapObject>(L);
7145 lua_pop(L, 1); // Pop the meta table
7146
7147 register_class<LuaWarehouse>(L, "map", true);
7148 add_parent<LuaWarehouse, LuaBuilding>(L);
7149 add_parent<LuaWarehouse, LuaPlayerImmovable>(L);
7150 add_parent<LuaWarehouse, LuaBaseImmovable>(L);
7151 add_parent<LuaWarehouse, LuaMapObject>(L);
7152 lua_pop(L, 1); // Pop the meta table
7153
7154 register_class<LuaMarket>(L, "map", true);
7155 add_parent<LuaMarket, LuaBuilding>(L);
7156 add_parent<LuaMarket, LuaPlayerImmovable>(L);
7157 add_parent<LuaMarket, LuaBaseImmovable>(L);
7158 add_parent<LuaMarket, LuaMapObject>(L);
7159 lua_pop(L, 1); // Pop the meta table
7160
7161 register_class<LuaProductionSite>(L, "map", true);
7162 add_parent<LuaProductionSite, LuaBuilding>(L);
7163 add_parent<LuaProductionSite, LuaPlayerImmovable>(L);
7164 add_parent<LuaProductionSite, LuaBaseImmovable>(L);
7165 add_parent<LuaProductionSite, LuaMapObject>(L);
7166 lua_pop(L, 1); // Pop the meta table
7167
7168 register_class<LuaMilitarySite>(L, "map", true);
7169 add_parent<LuaMilitarySite, LuaBuilding>(L);
7170 add_parent<LuaMilitarySite, LuaPlayerImmovable>(L);
7171 add_parent<LuaMilitarySite, LuaBaseImmovable>(L);
7172 add_parent<LuaMilitarySite, LuaMapObject>(L);
7173 lua_pop(L, 1); // Pop the meta table
7174
7175 register_class<LuaTrainingSite>(L, "map", true);
7176 add_parent<LuaTrainingSite, LuaProductionSite>(L);
7177 add_parent<LuaTrainingSite, LuaBuilding>(L);
7178 add_parent<LuaTrainingSite, LuaPlayerImmovable>(L);
7179 add_parent<LuaTrainingSite, LuaBaseImmovable>(L);
7180 add_parent<LuaTrainingSite, LuaMapObject>(L);
7181 lua_pop(L, 1); // Pop the meta table
7182 }
7183 } // namespace LuaMaps
7184