The Battle for Wesnoth  1.17.8+dev
lua_unit.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2022
3  by Guillaume Melquiond <guillaume.melquiond@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #include "scripting/lua_unit.hpp"
17 
18 #include "formatter.hpp"
19 #include "game_board.hpp"
20 #include "log.hpp"
21 #include "map/location.hpp" // for map_location
22 #include "map/map.hpp"
23 #include "resources.hpp"
24 #include "scripting/lua_common.hpp"
26 #include "scripting/push_check.hpp"
28 #include "units/unit.hpp"
29 #include "units/map.hpp"
31 #include "game_version.hpp"
32 #include "deprecation.hpp"
33 
34 #include "lua/lauxlib.h"
35 
36 static lg::log_domain log_scripting_lua("scripting/lua");
37 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
38 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
39 
40 static const char getunitKey[] = "unit";
41 static const char ustatusKey[] = "unit status";
42 static const char unitvarKey[] = "unit variables";
43 
45 {
46 }
47 
49 {
50  if (ptr) return ptr.get();
51  if (c_ptr) return c_ptr;
52  if (side) {
54  }
56  if (!ui.valid()) return nullptr;
57  return ui.get_shared_ptr().get(); //&*ui would not be legal, must get new shared_ptr by copy ctor because the unit_map itself is holding a boost shared pointer.
58 }
60 {
61  if (ptr) return ptr;
62  if (side) {
64  }
66  if (!ui.valid()) return unit_ptr();
67  return ui.get_shared_ptr(); //&*ui would not be legal, must get new shared_ptr by copy ctor because the unit_map itself is holding a boost shared pointer.
68 }
69 
70 // Having this function here not only simplifies other code, it allows us to move
71 // pointers around from one structure to another.
72 // This makes bare pointer->map in particular about 2 orders of magnitude faster,
73 // as benchmarked from Lua code.
75 {
76  if (ptr) {
77  auto [unit_it, success] = resources::gameboard->units().replace(loc, ptr);
78 
79  if(success) {
80  ptr.reset();
81  uid = unit_it->underlying_id();
82  } else {
83  ERR_LUA << "Could not move unit " << ptr->underlying_id() << " onto map location " << loc;
84  return false;
85  }
86  } else if (side) { // recall list
88  if (it) {
89  side = 0;
90  // uid may be changed by unit_map on insertion
91  uid = resources::gameboard->units().replace(loc, it).first->underlying_id();
92  } else {
93  ERR_LUA << "Could not find unit " << uid << " on recall list of side " << side;
94  return false;
95  }
96  } else { // on map
98  if (ui != resources::gameboard->units().end()) {
99  map_location from = ui->get_location();
100  if (from != loc) { // This check is redundant in current usage
102  resources::gameboard->units().move(from, loc);
103  }
104  // No need to change our contents
105  } else {
106  ERR_LUA << "Could not find unit " << uid << " on the map";
107  return false;
108  }
109  }
110  return true;
111 }
112 
113 bool luaW_isunit(lua_State* L, int index)
114 {
115  return luaL_testudata(L, index,getunitKey) != nullptr;
116 }
117 
118 enum {
123 };
124 
125 static lua_unit* internal_get_unit(lua_State *L, int index, bool only_on_map, int& error)
126 {
127  error = LU_OK;
128  if(!luaW_isunit(L, index)) {
129  error = LU_NOT_UNIT;
130  return nullptr;
131  }
132  lua_unit* lu = static_cast<lua_unit*>(lua_touserdata(L, index));
133  if(only_on_map && !lu->on_map()) {
134  error = LU_NOT_ON_MAP;
135  }
136  if(!lu->get()) {
137  error = LU_NOT_VALID;
138  }
139  return lu;
140 }
141 
142 unit* luaW_tounit(lua_State *L, int index, bool only_on_map)
143 {
144  int error;
145  lua_unit* lu = internal_get_unit(L, index, only_on_map, error);
146  if(error != LU_OK) {
147  return nullptr;
148  }
149  return lu->get();
150 }
151 
152 unit_ptr luaW_tounit_ptr(lua_State *L, int index, bool only_on_map)
153 {
154  int error;
155  lua_unit* lu = internal_get_unit(L, index, only_on_map, error);
156  if(error != LU_OK) {
157  return nullptr;
158  }
159  return lu->get_shared();
160 }
161 
162 lua_unit* luaW_tounit_ref(lua_State *L, int index)
163 {
164  int error;
165  return internal_get_unit(L, index, false, error);
166 }
167 
168 static void unit_show_error(lua_State *L, int index, int error)
169 {
170  switch(error) {
171  case LU_NOT_UNIT:
172  luaW_type_error(L, index, "unit");
173  break;
174  case LU_NOT_VALID:
175  luaL_argerror(L, index, "unit not found");
176  break;
177  case LU_NOT_ON_MAP:
178  luaL_argerror(L, index, "unit not found on map");
179  break;
180  }
181 }
182 
183 unit_ptr luaW_checkunit_ptr(lua_State *L, int index, bool only_on_map)
184 {
185  int error;
186  lua_unit* lu = internal_get_unit(L, index, only_on_map, error);
187  unit_show_error(L, index, error);
188  return lu->get_shared();
189 }
190 
191 unit& luaW_checkunit(lua_State *L, int index, bool only_on_map)
192 {
193  int error;
194  lua_unit* lu = internal_get_unit(L, index, only_on_map, error);
195  unit_show_error(L, index, error);
196  return *lu->get();
197 }
198 
199 lua_unit* luaW_checkunit_ref(lua_State *L, int index)
200 {
201  int error;
202  lua_unit* lu = internal_get_unit(L, index, false, error);
203  unit_show_error(L, index, error);
204  return lu;
205 }
206 
207 void lua_unit::setmetatable(lua_State *L)
208 {
209  luaL_setmetatable(L, getunitKey);
210 }
211 
212 lua_unit* luaW_pushlocalunit(lua_State *L, unit& u)
213 {
214  lua_unit* res = new(L) lua_unit(u);
216  return res;
217 }
218 
219 /**
220  * Destroys a unit object before it is collected (__gc metamethod).
221  */
222 static int impl_unit_collect(lua_State *L)
223 {
224  lua_unit *u = static_cast<lua_unit *>(lua_touserdata(L, 1));
225  u->lua_unit::~lua_unit();
226  return 0;
227 }
228 
229 /**
230  * Checks two lua proxy units for equality. (__eq metamethod)
231  */
232 static int impl_unit_equality(lua_State* L)
233 {
234  unit& left = luaW_checkunit(L, 1);
235  unit& right = luaW_checkunit(L, 2);
236  const bool equal = left.underlying_id() == right.underlying_id();
237  lua_pushboolean(L, equal);
238  return 1;
239 }
240 
241 /**
242  * Turns a lua proxy unit to string. (__tostring metamethod)
243  */
244 static int impl_unit_tostring(lua_State* L)
245 {
246  const lua_unit* lu = luaW_tounit_ref(L, 1);
247  unit &u = *lu->get();
248  std::ostringstream str;
249 
250  str << "unit: <";
251  if(!u.id().empty()) {
252  str << u.id() << " ";
253  } else {
254  str << u.type_id() << " ";
255  }
256  if(int side = lu->on_recall_list()) {
257  str << "at (side " << side << " recall list)";
258  } else {
259  str << "at (" << u.get_location() << ")";
260  }
261  str << '>';
262 
263  lua_push(L, str.str());
264  return 1;
265 }
266 
267 /**
268  * Gets some data on a unit (__index metamethod).
269  * - Arg 1: full userdata containing the unit id.
270  * - Arg 2: string containing the name of the property.
271  * - Ret 1: something containing the attribute.
272  */
273 static int impl_unit_get(lua_State *L)
274 {
275  lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
276  char const *m = luaL_checkstring(L, 2);
277  const unit* pu = lu->get();
278 
279  if(strcmp(m, "valid") == 0) {
280  if(!pu) {
281  return 0;
282  }
283  if(lu->on_map()) {
284  lua_pushstring(L, "map");
285  } else if(lu->on_recall_list()) {
286  lua_pushstring(L, "recall");
287  } else {
288  lua_pushstring(L, "private");
289  }
290  return 1;
291  }
292 
293  if(!pu) {
294  return luaL_argerror(L, 1, "unknown unit");
295  }
296 
297  const unit& u = *pu;
298 
299  // Find the corresponding attribute.
300  return_int_attrib("x", u.get_location().wml_x());
301  return_int_attrib("y", u.get_location().wml_y());
302  if(strcmp(m, "loc") == 0) {
303  luaW_pushlocation(L, u.get_location());
304  return 1;
305  }
306  if(strcmp(m, "goto") == 0) {
307  luaW_pushlocation(L, u.get_goto());
308  return 1;
309  }
310  return_int_attrib("side", u.side());
311  return_string_attrib("id", u.id());
312  return_string_attrib("type", u.type_id());
313  return_string_attrib("image_mods", u.effect_image_mods());
314  return_string_attrib("usage", u.usage());
315  return_string_attrib("ellipse", u.image_ellipse());
316  return_string_attrib("halo", u.image_halo());
317  return_int_attrib("hitpoints", u.hitpoints());
318  return_int_attrib("max_hitpoints", u.max_hitpoints());
319  return_int_attrib("experience", u.experience());
320  return_int_attrib("max_experience", u.max_experience());
321  return_int_attrib("recall_cost", u.recall_cost());
322  return_int_attrib("moves", u.movement_left());
323  return_int_attrib("max_moves", u.total_movement());
324  return_int_attrib("max_attacks", u.max_attacks());
325  return_int_attrib("attacks_left", u.attacks_left());
326  return_int_attrib("vision", u.vision());
327  return_int_attrib("jamming", u.jamming());
328  return_tstring_attrib("name", u.name());
329  return_tstring_attrib("description", u.unit_description());
330  return_bool_attrib("canrecruit", u.can_recruit());
331  return_bool_attrib("renamable", !u.unrenamable());
332  return_int_attrib("level", u.level());
333  return_int_attrib("cost", u.cost());
334 
335  return_vector_string_attrib("extra_recruit", u.recruits());
336  return_vector_string_attrib("advances_to", u.advances_to());
337 
338  if(strcmp(m, "alignment") == 0) {
339  lua_push(L, unit_alignments::get_string(u.alignment()));
340  return 1;
341  }
342 
343  if(strcmp(m, "upkeep") == 0) {
344  unit::upkeep_t upkeep = u.upkeep_raw();
345 
346  // Need to keep these separate in order to ensure an int value is always used if applicable.
347  if(int* v = utils::get_if<int>(&upkeep)) {
348  lua_push(L, *v);
349  } else {
350  const std::string type = utils::visit(unit::upkeep_type_visitor{}, upkeep);
351  lua_push(L, type);
352  }
353 
354  return 1;
355  }
356  if(strcmp(m, "advancements") == 0) {
357  lua_push(L, u.modification_advancements());
358  return 1;
359  }
360  if(strcmp(m, "overlays") == 0) {
361  lua_push(L, u.overlays());
362  return 1;
363  }
364  if(strcmp(m, "traits") == 0) {
365  lua_push(L, u.get_traits_list());
366  return 1;
367  }
368  if(strcmp(m, "abilities") == 0) {
369  lua_push(L, u.get_ability_list());
370  return 1;
371  }
372  if(strcmp(m, "status") == 0) {
373  lua_createtable(L, 1, 0);
374  lua_pushvalue(L, 1);
375  lua_rawseti(L, -2, 1);
376  luaL_setmetatable(L, ustatusKey);
377  return 1;
378  }
379  if(strcmp(m, "variables") == 0) {
380  lua_createtable(L, 1, 0);
381  lua_pushvalue(L, 1);
382  lua_rawseti(L, -2, 1);
383  luaL_setmetatable(L, unitvarKey);
384  return 1;
385  }
386  if(strcmp(m, "attacks") == 0) {
387  push_unit_attacks_table(L, 1);
388  return 1;
389  }
390  if(strcmp(m, "petrified") == 0) {
391  deprecated_message("(unit).petrified", DEP_LEVEL::INDEFINITE, {1,17,0}, "use (unit).status.petrified instead");
392  lua_pushboolean(L, u.incapacitated());
393  return 1;
394  }
395  return_vector_string_attrib("animations", u.anim_comp().get_flags());
396  return_cfg_attrib("recall_filter", cfg = u.recall_filter());
397  return_bool_attrib("hidden", u.get_hidden());
398  return_bool_attrib("resting", u.resting());
399  return_string_attrib("role", u.get_role());
400  return_string_attrib("race", u.race()->id());
401  return_string_attrib("gender", gender_string(u.gender()));
402  return_string_attrib("variation", u.variation());
403  return_string_attrib("undead_variation", u.undead_variation());
404  return_bool_attrib("zoc", u.get_emit_zoc());
405  return_string_attrib("facing", map_location::write_direction(u.facing()));
406  return_string_attrib("portrait", u.big_profile() == u.absolute_image()
407  ? u.absolute_image() + u.image_mods() + "~XBRZ(2)"
408  : u.big_profile());
409  return_cfg_attrib("__cfg", u.write(cfg); u.get_location().write(cfg));
410 
411  if(luaW_getglobal(L, "wesnoth", "units", m)) {
412  return 1;
413  }
414  return 0;
415 }
416 
417 /**
418  * Sets some data on a unit (__newindex metamethod).
419  * - Arg 1: full userdata containing the unit id.
420  * - Arg 2: string containing the name of the property.
421  * - Arg 3: something containing the attribute.
422  */
423 static int impl_unit_set(lua_State *L)
424 {
425  lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
426  char const *m = luaL_checkstring(L, 2);
427  unit* pu = lu->get();
428  if (!pu) return luaL_argerror(L, 1, "unknown unit");
429  unit &u = *pu;
430 
431  // Find the corresponding attribute.
432  //modify_int_attrib_check_range("side", u.set_side(value), 1, static_cast<int>(teams().size())); TODO: Figure out if this is a good idea, to refer to teams() and make this depend on having a gamestate
433  modify_int_attrib("side", u.set_side(value));
434  modify_int_attrib("moves", u.set_movement(value));
435  modify_int_attrib("max_moves", u.set_total_movement(value));
436  modify_int_attrib("max_attacks", u.set_max_attacks(value));
437  modify_int_attrib("hitpoints", u.set_hitpoints(value));
438  modify_int_attrib("max_hitpoints", u.set_max_hitpoints(value));
439  modify_int_attrib("experience", u.set_experience(value));
440  modify_int_attrib("max_experience", u.set_max_experience(value));
441  modify_int_attrib("recall_cost", u.set_recall_cost(value));
442  modify_int_attrib("attacks_left", u.set_attacks(value));
443  modify_int_attrib("level", u.set_level(value));
444  modify_bool_attrib("resting", u.set_resting(value));
445  modify_tstring_attrib("name", u.set_name(value));
446  modify_tstring_attrib("description", u.set_unit_description(value));
447  modify_string_attrib("portrait", u.set_big_profile(value));
448  modify_string_attrib("role", u.set_role(value));
449  modify_string_attrib("facing", u.set_facing(map_location::parse_direction(value)));
450  modify_string_attrib("usage", u.set_usage(value));
451  modify_string_attrib("undead_variation", u.set_undead_variation(value));
452  modify_string_attrib("ellipse", u.set_image_ellipse(value));
453  modify_string_attrib("halo", u.set_image_halo(value));
454  modify_bool_attrib("hidden", u.set_hidden(value));
455  modify_bool_attrib("zoc", u.set_emit_zoc(value));
456  modify_bool_attrib("canrecruit", u.set_can_recruit(value));
457  modify_bool_attrib("renamable", u.set_unrenamable(!value));
458  modify_cfg_attrib("recall_filter", u.set_recall_filter(cfg));
459 
460  modify_vector_string_attrib("extra_recruit", u.set_recruits(value));
461  modify_vector_string_attrib("advances_to", u.set_advances_to(value));
462  if(strcmp(m, "alignment") == 0) {
463  u.set_alignment(lua_enum_check<unit_alignments>(L, 3));
464  return 0;
465  }
466 
467  if(strcmp(m, "advancements") == 0) {
468  u.set_advancements(lua_check<std::vector<config>>(L, 3));
469  return 0;
470  }
471 
472  if(strcmp(m, "upkeep") == 0) {
473  if(lua_isnumber(L, 3)) {
474  u.set_upkeep(static_cast<int>(luaL_checkinteger(L, 3)));
475  return 0;
476  }
477  const char* v = luaL_checkstring(L, 3);
478  if((strcmp(v, "loyal") == 0) || (strcmp(v, "free") == 0)) {
479  u.set_upkeep(unit::upkeep_loyal());
480  } else if(strcmp(v, "full") == 0) {
481  u.set_upkeep(unit::upkeep_full());
482  } else {
483  std::string err_msg = "unknown upkeep value of unit: ";
484  err_msg += v;
485  return luaL_argerror(L, 2, err_msg.c_str());
486  }
487  return 0;
488  }
489 
490  if(!lu->on_map()) {
491  map_location loc = u.get_location();
492  modify_int_attrib("x", loc.set_wml_x(value); u.set_location(loc));
493  modify_int_attrib("y", loc.set_wml_y(value); u.set_location(loc));
494  modify_string_attrib("id", u.set_id(value));
495  if(strcmp(m, "loc") == 0) {
496  luaW_tolocation(L, 3, loc);
497  u.set_location(loc);
498  return 0;
499  }
500  } else {
501  const bool is_key_x = strcmp(m, "x") == 0;
502  const bool is_key_y = strcmp(m, "y") == 0;
503  const bool is_loc_key = strcmp(m, "loc") == 0;
504 
505  // Handle moving an on-map unit
506  if(is_key_x || is_key_y || is_loc_key) {
507  game_board* gb = resources::gameboard;
508 
509  if(!gb) {
510  return 0;
511  }
512 
513  map_location src = u.get_location();
514  map_location dst = src;
515 
516  if(is_key_x) {
517  dst.set_wml_x(luaL_checkinteger(L, 3));
518  } else if(is_key_y) {
519  dst.set_wml_y(luaL_checkinteger(L, 3));
520  } else {
521  dst = luaW_checklocation(L, 3);
522  }
523 
524  // TODO: could probably be relegated to a helper function.
525  if(src != dst) {
526  // If the dst isn't on the map, the unit will be clobbered. Guard against that.
527  if(!gb->map().on_board(dst)) {
528  std::string err_msg = formatter() << "destination hex not on map (excluding border): " << dst;
529  return luaL_argerror(L, 2, err_msg.c_str());
530  }
531 
532  auto [unit_iterator, success] = gb->units().move(src, dst);
533 
534  if(success) {
535  unit_iterator->anim_comp().set_standing();
536  }
537  }
538 
539  return 0;
540  }
541  }
542 
543  if(strcmp(m, "goto") == 0) {
544  u.set_goto(luaW_checklocation(L, 3));
545  return 0;
546  }
547 
548  std::string err_msg = "unknown modifiable property of unit: ";
549  err_msg += m;
550  return luaL_argerror(L, 2, err_msg.c_str());
551 }
552 
553 /**
554  * Gets the status of a unit (__index metamethod).
555  * - Arg 1: table containing the userdata containing the unit id.
556  * - Arg 2: string containing the name of the status.
557  * - Ret 1: boolean.
558  */
559 static int impl_unit_status_get(lua_State *L)
560 {
561  if(!lua_istable(L, 1)) {
562  return luaW_type_error(L, 1, "unit status");
563  }
564  lua_rawgeti(L, 1, 1);
565  const unit* u = luaW_tounit(L, -1);
566  if(!u) {
567  return luaL_argerror(L, 1, "unknown unit");
568  }
569  char const *m = luaL_checkstring(L, 2);
570  lua_pushboolean(L, u->get_state(m));
571  return 1;
572 }
573 
574 /**
575  * Sets the status of a unit (__newindex metamethod).
576  * - Arg 1: table containing the userdata containing the unit id.
577  * - Arg 2: string containing the name of the status.
578  * - Arg 3: boolean.
579  */
580 static int impl_unit_status_set(lua_State *L)
581 {
582  if(!lua_istable(L, 1)) {
583  return luaW_type_error(L, 1, "unit status");
584  }
585  lua_rawgeti(L, 1, 1);
586  unit* u = luaW_tounit(L, -1);
587  if(!u) {
588  return luaL_argerror(L, 1, "unknown unit");
589  }
590  char const *m = luaL_checkstring(L, 2);
591  u->set_state(m, luaW_toboolean(L, 3));
592  return 0;
593 }
594 
595 /**
596  * Gets the variable of a unit (__index metamethod).
597  * - Arg 1: table containing the userdata containing the unit id.
598  * - Arg 2: string containing the name of the status.
599  * - Ret 1: boolean.
600  */
601 static int impl_unit_variables_get(lua_State *L)
602 {
603  if(!lua_istable(L, 1)) {
604  return luaW_type_error(L, 1, "unit variables");
605  }
606  lua_rawgeti(L, 1, 1);
607  const unit* u = luaW_tounit(L, -1);
608  if(!u) {
609  return luaL_argerror(L, 2, "unknown unit");
610  }
611  char const *m = luaL_checkstring(L, 2);
612  return_cfgref_attrib("__cfg", u->variables());
613 
614  variable_access_const v(m, u->variables());
615  return luaW_pushvariable(L, v) ? 1 : 0;
616 }
617 
618 /**
619  * Sets the variable of a unit (__newindex metamethod).
620  * - Arg 1: table containing the userdata containing the unit id.
621  * - Arg 2: string containing the name of the status.
622  * - Arg 3: scalar.
623  */
624 static int impl_unit_variables_set(lua_State *L)
625 {
626  if(!lua_istable(L, 1)) {
627  return luaW_type_error(L, 1, "unit variables");
628  }
629  lua_rawgeti(L, 1, 1);
630  unit* u = luaW_tounit(L, -1);
631  if(!u) {
632  return luaL_argerror(L, 2, "unknown unit");
633  }
634  char const *m = luaL_checkstring(L, 2);
635  modify_cfg_attrib("__cfg", u->variables() = cfg);
636  config& vars = u->variables();
637  if(lua_isnoneornil(L, 3)) {
638  try {
639  variable_access_throw(m, vars).clear(false);
640  } catch(const invalid_variablename_exception&) {
641  }
642  return 0;
643  }
644  variable_access_create v(m, vars);
645  luaW_checkvariable(L, v, 3);
646  return 0;
647 }
648 
649 namespace lua_units {
650  std::string register_metatables(lua_State* L)
651  {
652  std::ostringstream cmd_out;
653 
654  // Create the getunit metatable.
655  cmd_out << "Adding getunit metatable...\n";
656 
657  luaL_newmetatable(L, getunitKey);
658  lua_pushcfunction(L, impl_unit_collect);
659  lua_setfield(L, -2, "__gc");
660  lua_pushcfunction(L, impl_unit_equality);
661  lua_setfield(L, -2, "__eq");
662  lua_pushcfunction(L, impl_unit_tostring);
663  lua_setfield(L, -2, "__tostring");
664  lua_pushcfunction(L, impl_unit_get);
665  lua_setfield(L, -2, "__index");
666  lua_pushcfunction(L, impl_unit_set);
667  lua_setfield(L, -2, "__newindex");
668  lua_pushstring(L, "unit");
669  lua_setfield(L, -2, "__metatable");
670 
671  // Create the unit status metatable.
672  cmd_out << "Adding unit status metatable...\n";
673 
674  luaL_newmetatable(L, ustatusKey);
675  lua_pushcfunction(L, impl_unit_status_get);
676  lua_setfield(L, -2, "__index");
677  lua_pushcfunction(L, impl_unit_status_set);
678  lua_setfield(L, -2, "__newindex");
679  lua_pushstring(L, "unit status");
680  lua_setfield(L, -2, "__metatable");
681 
682  // Create the unit variables metatable.
683  cmd_out << "Adding unit variables metatable...\n";
684 
685  luaL_newmetatable(L, unitvarKey);
686  lua_pushcfunction(L, impl_unit_variables_get);
687  lua_setfield(L, -2, "__index");
688  lua_pushcfunction(L, impl_unit_variables_set);
689  lua_setfield(L, -2, "__newindex");
690  lua_pushstring(L, "unit variables");
691  lua_setfield(L, -2, "__metatable");
692 
693  return cmd_out.str();
694  }
695 }
static lg::log_domain log_scripting_lua("scripting/lua")
bool luaW_checkvariable(lua_State *L, variable_access_create &v, int n)
variable_info_mutable< variable_info_implementation::vi_policy_throw > variable_access_throw
&#39;Throw if nonexistent&#39; access.
static void setmetatable(lua_State *L)
Definition: lua_unit.cpp:207
std::string register_metatables(lua_State *L)
Definition: lua_unit.cpp:650
virtual const unit_map & units() const override
Definition: game_board.hpp:113
This class represents a single unit of a specific type.
Definition: unit.hpp:120
const std::string & type_id() const
The id of this unit&#39;s type.
Definition: unit.cpp:1806
Interfaces for manipulating version numbers of engine, add-ons, etc.
int luaW_type_error(lua_State *L, int narg, const char *tname)
unit & luaW_checkunit(lua_State *L, int index, bool only_on_map)
Converts a Lua value to a unit pointer.
Definition: lua_unit.cpp:191
~lua_unit()
Definition: lua_unit.cpp:44
bool get_state(const std::string &state) const
Check if the unit is affected by a status effect.
Definition: unit.cpp:1316
bool luaW_isunit(lua_State *L, int index)
Test if a Lua value is a unit.
Definition: lua_unit.cpp:113
friend lua_unit * luaW_pushlocalunit(lua_State *L, unit &u)
Pushes a private unit on the stack.
Definition: lua_unit.cpp:212
lua_unit * luaW_tounit_ref(lua_State *L, int index)
Similar to luaW_tounit but returns a lua_unit; use this if you need to handle map and recall units di...
Definition: lua_unit.cpp:162
config & variables()
Gets any user-defined variables this unit &#39;owns&#39;.
Definition: unit.hpp:693
bool luaW_pushvariable(lua_State *L, variable_access_const &v)
Definition: lua_common.cpp:996
#define ERR_LUA
Definition: lua_unit.cpp:38
static int impl_unit_variables_get(lua_State *L)
Gets the variable of a unit (__index metamethod).
Definition: lua_unit.cpp:601
static int impl_unit_tostring(lua_State *L)
Turns a lua proxy unit to string.
Definition: lua_unit.cpp:244
static int impl_unit_variables_set(lua_State *L)
Sets the variable of a unit (__newindex metamethod).
Definition: lua_unit.cpp:624
std::size_t erase(const map_location &l)
Erases the unit at location l, if any.
Definition: map.cpp:288
Additional functionality for a non-const variable_info.
static const char getunitKey[]
Definition: lua_unit.cpp:40
static int impl_unit_get(lua_State *L)
Gets some data on a unit (__index metamethod).
Definition: lua_unit.cpp:273
static int impl_unit_status_set(lua_State *L)
Sets the status of a unit (__newindex metamethod).
Definition: lua_unit.cpp:580
map_location luaW_checklocation(lua_State *L, int index)
Converts an optional table or pair of integers to a map location object.
Definition: lua_common.cpp:793
std::shared_ptr< unit > unit_ptr
Definition: ptr.hpp:26
static const char unitvarKey[]
Definition: lua_unit.cpp:42
#define return_cfgref_attrib(name, accessor)
Definition: lua_common.hpp:309
unit_ptr extract_if_matches_underlying_id(std::size_t uid)
Find a unit by underlying id, and extract if found.
umap_retval_pair_t replace(const map_location &l, unit_ptr p)
Works like unit_map::add; but l is emptied first, if needed.
Definition: map.cpp:215
static int impl_unit_equality(lua_State *L)
Checks two lua proxy units for equality.
Definition: lua_unit.cpp:232
team & get_team(int i)
Definition: game_board.hpp:98
const std::string & id() const
Gets this unit&#39;s id.
Definition: unit.hpp:370
void set_state(const std::string &state, bool value)
Set whether the unit is affected by a status effect.
Definition: unit.cpp:1364
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:991
unit_ptr luaW_checkunit_ptr(lua_State *L, int index, bool only_on_map)
Similar to luaW_checkunit but returns a unit_ptr; use this instead of luaW_checkunit when using an ap...
Definition: lua_unit.cpp:183
std::ostringstream wrapper.
Definition: formatter.hpp:39
unit * luaW_tounit(lua_State *L, int index, bool only_on_map)
Converts a Lua value to a unit pointer.
Definition: lua_unit.cpp:142
unit * c_ptr
Definition: lua_unit.hpp:85
game_board * gameboard
Definition: resources.cpp:21
umap_retval_pair_t move(const map_location &src, const map_location &dst)
Moves a unit from location src to location dst.
Definition: map.cpp:93
unit_ptr find_if_matches_underlying_id(std::size_t uid)
Find a unit by underlying id.
Encapsulates the map of the game.
Definition: location.hpp:38
std::size_t uid
Definition: lua_unit.hpp:82
Storage for a unit, either owned by the Lua code (ptr != 0), a local variable unit (c_ptr != 0)...
Definition: lua_unit.hpp:80
unit_iterator find(std::size_t id)
Definition: map.cpp:301
pointer get_shared_ptr() const
This is exactly the same as operator-> but it&#39;s slightly more readable, and can replace &*iter syntax...
Definition: map.hpp:218
static void unit_show_error(lua_State *L, int index, int error)
Definition: lua_unit.cpp:168
int side
Definition: lua_unit.hpp:84
static int impl_unit_collect(lua_State *L)
Destroys a unit object before it is collected (__gc metamethod).
Definition: lua_unit.cpp:222
static lua_unit * internal_get_unit(lua_State *L, int index, bool only_on_map, int &error)
Definition: lua_unit.cpp:125
lua_unit * luaW_checkunit_ref(lua_State *L, int index)
Similar to luaW_checkunit but returns a lua_unit; use this if you need to handle map and recall units...
Definition: lua_unit.cpp:199
unit_ptr get_shared() const
Definition: lua_unit.cpp:59
unit * get() const
Definition: lua_unit.cpp:48
lua_unit(const lua_unit &)=delete
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:72
Information on a WML variable.
bool put_map(const map_location &loc)
Definition: lua_unit.cpp:74
double t
Definition: astarsearch.cpp:65
#define modify_cfg_attrib(name, accessor)
Definition: lua_common.hpp:415
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1345
unit_ptr luaW_tounit_ptr(lua_State *L, int index, bool only_on_map)
Similar to luaW_tounit but returns a unit_ptr; use this instead of luaW_tounit when using an api that...
Definition: lua_unit.cpp:152
Standard logging facilities (interface).
recall_list_manager & recall_list()
Definition: team.hpp:203
unit_ptr ptr
Definition: lua_unit.hpp:83
static int impl_unit_status_get(lua_State *L)
Gets the status of a unit (__index metamethod).
Definition: lua_unit.cpp:559
static const char ustatusKey[]
Definition: lua_unit.cpp:41
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:60
bool valid() const
Definition: map.hpp:274
static int impl_unit_set(lua_State *L)
Sets some data on a unit (__newindex metamethod).
Definition: lua_unit.cpp:423
std::size_t underlying_id() const
This unit&#39;s unique internal ID.
Definition: unit.hpp:382