1 /*
2  * Copyright (C) 2006-2019 Christopho, Solarus - http://www.solarus-games.org
3  *
4  * Solarus is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Solarus 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 along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 #include "solarus/core/CurrentQuest.h"
18 #include "solarus/core/Game.h"
19 #include "solarus/core/Map.h"
20 #include "solarus/entities/EntityTypeInfo.h"
21 #include "solarus/entities/GroundInfo.h"
22 #include "solarus/lua/LuaContext.h"
23 #include "solarus/lua/LuaTools.h"
24 #include "solarus/hero/CustomState.h"
25 
26 namespace Solarus {
27 
28 /**
29  * Name of the Lua table representing the state module.
30  */
31 const std::string LuaContext::state_module_name = "sol.state";
32 
33 /**
34  * \brief Initializes the state features provided to Lua.
35  */
register_state_module()36 void LuaContext::register_state_module() {
37 
38   if (!CurrentQuest::is_format_at_least({ 1, 6 })) {
39     return;
40   }
41 
42   // Functions of sol.state.
43   const std::vector<luaL_Reg> functions = {
44       { "create", state_api_create },
45   };
46 
47   // Methods of the state type.
48   const std::vector<luaL_Reg> methods = {
49     { "get_description", state_api_get_description },
50     { "set_description", state_api_set_description },
51     { "get_entity", state_api_get_entity },
52     { "get_map", state_api_get_map },
53     { "get_game", state_api_get_game },
54     { "is_started", state_api_is_started },
55     { "is_visible", state_api_is_visible },
56     { "set_visible", state_api_set_visible },
57     { "get_draw_override", state_api_get_draw_override },
58     { "set_draw_override", state_api_set_draw_override },
59     { "get_can_control_direction", state_api_get_can_control_direction },
60     { "set_can_control_direction", state_api_set_can_control_direction },
61     { "get_can_control_movement", state_api_get_can_control_movement },
62     { "set_can_control_movement", state_api_set_can_control_movement },
63     { "set_can_traverse", state_api_set_can_traverse },
64     { "get_can_traverse_ground", state_api_get_can_traverse_ground },
65     { "set_can_traverse_ground", state_api_set_can_traverse_ground },
66     { "is_gravity_enabled", state_api_is_gravity_enabled },
67     { "set_gravity_enabled", state_api_set_gravity_enabled },
68     { "is_affected_by_ground", state_api_is_affected_by_ground },
69     { "set_affected_by_ground", state_api_set_affected_by_ground },
70     { "get_can_come_from_bad_ground", state_api_get_can_come_from_bad_ground },
71     { "set_can_come_from_bad_ground", state_api_set_can_come_from_bad_ground },
72     { "get_can_be_hurt", state_api_get_can_be_hurt },
73     { "set_can_be_hurt", state_api_set_can_be_hurt },
74     { "get_can_use_sword", state_api_get_can_use_sword },
75     { "set_can_use_sword", state_api_set_can_use_sword },
76     { "get_can_cut", state_api_get_can_cut },
77     { "set_can_cut", state_api_set_can_cut },
78     { "get_can_use_shield", state_api_get_can_use_shield },
79     { "set_can_use_shield", state_api_set_can_use_shield },
80     { "get_can_use_item", state_api_get_can_use_item },
81     { "set_can_use_item", state_api_set_can_use_item },
82     { "get_can_interact", state_api_get_can_interact },
83     { "set_can_interact", state_api_set_can_interact },
84     { "get_can_grab", state_api_get_can_grab },
85     { "set_can_grab", state_api_set_can_grab },
86     { "get_can_push", state_api_get_can_push },
87     { "set_can_push", state_api_set_can_push },
88     { "get_pushing_delay", state_api_get_pushing_delay },
89     { "set_pushing_delay", state_api_set_pushing_delay },
90     { "get_can_pick_treasure", state_api_get_can_pick_treasure },
91     { "set_can_pick_treasure", state_api_set_can_pick_treasure },
92     { "get_can_use_teletransporter", state_api_get_can_use_teletransporter },
93     { "set_can_use_teletransporter", state_api_set_can_use_teletransporter },
94     { "get_can_use_switch", state_api_get_can_use_switch },
95     { "set_can_use_switch", state_api_set_can_use_switch },
96     { "get_can_use_stream", state_api_get_can_use_stream },
97     { "set_can_use_stream", state_api_set_can_use_stream },
98     { "get_can_use_stairs", state_api_get_can_use_stairs },
99     { "set_can_use_stairs", state_api_set_can_use_stairs },
100     { "get_can_use_jumper", state_api_get_can_use_jumper },
101     { "set_can_use_jumper", state_api_set_can_use_jumper },
102     { "get_jumper_delay", state_api_get_jumper_delay },
103     { "set_jumper_delay", state_api_set_jumper_delay },
104     { "get_carried_object_action", state_api_get_carried_object_action },
105     { "set_carried_object_action", state_api_set_carried_object_action },
106   };
107 
108   const std::vector<luaL_Reg> metamethods = {
109       { "__gc", userdata_meta_gc },
110       { "__newindex", userdata_meta_newindex_as_table },
111       { "__index", userdata_meta_index_as_table }
112   };
113 
114   register_type(state_module_name, functions, methods, metamethods);
115 }
116 
117 /**
118  * \brief Returns whether a value is a userdata of type state.
119  * \param l A Lua context.
120  * \param index An index in the stack.
121  * \return \c true if the value at this index is a state.
122  */
is_state(lua_State * l,int index)123 bool LuaContext::is_state(lua_State* l, int index) {
124   return is_userdata(l, index, state_module_name);
125 }
126 
127 /**
128  * \brief Checks that the userdata at the specified index of the stack is a
129  * state and returns it.
130  * \param l a Lua context
131  * \param index An index in the stack.
132  * \return The state.
133  */
check_state(lua_State * l,int index)134 std::shared_ptr<CustomState> LuaContext::check_state(lua_State* l, int index) {
135   return std::static_pointer_cast<CustomState>(check_userdata(
136       l, index, state_module_name
137   ));
138 }
139 
140 /**
141  * \brief Pushes a state userdata onto the stack.
142  * \param l A Lua context.
143  * \param state A state.
144  */
push_state(lua_State * l,CustomState & state)145 void LuaContext::push_state(lua_State* l, CustomState& state) {
146   push_userdata(l, state);
147 }
148 
149 /**
150  * \brief Calls the draw override function of a custom state.
151  * \param draw_override The draw override function.
152  * \param state The state to draw.
153  * \param camera The camera where to draw the entity.
154  */
do_state_draw_override_function(const ScopedLuaRef & draw_override,CustomState & state,Camera & camera)155 void LuaContext::do_state_draw_override_function(
156     const ScopedLuaRef& draw_override,
157     CustomState& state,
158     Camera& camera
159 ) {
160   push_ref(current_l, draw_override);
161   push_state(current_l, state);
162   push_camera(current_l, camera);
163   call_function(2, 0, "state draw override");
164 }
165 
166 /**
167  * \brief Calls the can-be-hurt function of a custom state.
168  * \param can_be_hurt The function to call.
169  * \param state The state to test.
170  * \param attacker Source of the attack or nullptr.
171  */
do_state_can_be_hurt_function(const ScopedLuaRef & can_be_hurt,CustomState & state,Entity * attacker)172 bool LuaContext::do_state_can_be_hurt_function(
173     const ScopedLuaRef& can_be_hurt,
174     CustomState& state,
175     Entity* attacker) {
176   push_ref(current_l, can_be_hurt);
177   push_state(current_l, state);
178   if (attacker == nullptr) {
179     lua_pushnil(current_l);
180   } else {
181     push_entity(current_l, *attacker);
182   }
183   if (!call_function(2, 1, "state can_be_hurt callback")) {
184     return true;
185   }
186   return LuaTools::opt_boolean(current_l, -1, "true");
187 }
188 
189 /**
190  * \brief Calls the can-cut function of a custom state.
191  * \param can_cut The function to call.
192  * \param state The state to test.
193  * \param entity The entity to test or nullptr.
194  */
do_state_can_cut_function(const ScopedLuaRef & can_cut,CustomState & state,Entity * entity)195 bool LuaContext::do_state_can_cut_function(
196     const ScopedLuaRef& can_cut,
197     CustomState& state,
198     Entity* entity) {
199   push_ref(current_l, can_cut);
200   push_state(current_l, state);
201   if (entity == nullptr) {
202     lua_pushnil(current_l);
203   } else {
204     push_entity(current_l, *entity);
205   }
206   if (!call_function(2, 1, "state can_cut callback")) {
207     return true;
208   }
209   return LuaTools::opt_boolean(current_l, -1, "true");
210 }
211 
212 /**
213  * \brief Implementation of sol.state.create().
214  * \param l The Lua context that is calling this function.
215  * \return Number of values to return to Lua.
216  */
state_api_create(lua_State * l)217 int LuaContext::state_api_create(lua_State* l) {
218 
219   return state_boundary_handle(l, [&] {
220     const std::string& description = LuaTools::opt_string(l, 1, "");
221 
222     std::shared_ptr<CustomState> state = std::make_shared<CustomState>(get(), description);
223 
224     push_state(l, *state);
225     return 1;
226   });
227 }
228 
229 /**
230  * \brief Implementation of state:get_description().
231  * \param l The Lua context that is calling this function.
232  * \return Number of values to return to Lua.
233  */
state_api_get_description(lua_State * l)234 int LuaContext::state_api_get_description(lua_State* l) {
235 
236   return state_boundary_handle(l, [&] {
237     const CustomState& state = *check_state(l, 1);
238 
239     const std::string& description = state.get_description();
240     if (description.empty()) {
241       lua_pushnil(l);
242     }
243     else {
244       push_string(l, description);
245     }
246     return 1;
247   });
248 }
249 
250 /**
251  * \brief Implementation of state:set_description().
252  * \param l The Lua context that is calling this function.
253  * \return Number of values to return to Lua.
254  */
state_api_set_description(lua_State * l)255 int LuaContext::state_api_set_description(lua_State* l) {
256 
257   return state_boundary_handle(l, [&] {
258     CustomState& state = *check_state(l, 1);
259     std::string description;
260     if (lua_isstring(l, 2)) {
261       description = LuaTools::check_string(l, 2);
262     }
263     else if (!lua_isnil(l, 2)) {
264       LuaTools::type_error(l, 2, "string or nil");
265     }
266 
267     state.set_description(description);
268 
269     return 0;
270   });
271 }
272 
273 /**
274  * \brief Implementation of state:get_entity().
275  * \param l The Lua context that is calling this function.
276  * \return Number of values to return to Lua.
277  */
state_api_get_entity(lua_State * l)278 int LuaContext::state_api_get_entity(lua_State* l) {
279 
280   return state_boundary_handle(l, [&] {
281     CustomState& state = *check_state(l, 1);
282 
283     if (!state.has_entity()) {
284       lua_pushnil(l);
285     }
286     else {
287       Entity& entity = state.get_entity();
288       push_entity(l, entity);
289     }
290     return 1;
291   });
292 }
293 
294 /**
295  * \brief Implementation of state:get_map().
296  * \param l The Lua context that is calling this function.
297  * \return Number of values to return to Lua.
298  */
state_api_get_map(lua_State * l)299 int LuaContext::state_api_get_map(lua_State* l) {
300 
301   return state_boundary_handle(l, [&] {
302     CustomState& state = *check_state(l, 1);
303 
304     if (!state.has_entity()) {
305       lua_pushnil(l);
306     }
307     else {
308       Entity& entity = state.get_entity();
309       if (!entity.is_on_map()) {
310         lua_pushnil(l);
311       }
312       else {
313         push_map(l, entity.get_map());
314       }
315     }
316     return 1;
317   });
318 }
319 
320 /**
321  * \brief Implementation of state:get_game().
322  * \param l The Lua context that is calling this function.
323  * \return Number of values to return to Lua.
324  */
state_api_get_game(lua_State * l)325 int LuaContext::state_api_get_game(lua_State* l) {
326 
327   return state_boundary_handle(l, [&] {
328     CustomState& state = *check_state(l, 1);
329 
330     if (!state.has_entity()) {
331       lua_pushnil(l);
332     }
333     else {
334       Entity& entity = state.get_entity();
335       if (!entity.is_on_map()) {
336         lua_pushnil(l);
337       }
338       else {
339         Map& map = entity.get_map();
340         if (!map.is_game_running()) {
341           lua_pushnil(l);
342         }
343         else {
344           push_game(l, map.get_game().get_savegame());
345         }
346       }
347     }
348     return 1;
349   });
350 }
351 
352 /**
353  * \brief Implementation of state:is_started().
354  * \param l The Lua context that is calling this function.
355  * \return Number of values to return to Lua.
356  */
state_api_is_started(lua_State * l)357 int LuaContext::state_api_is_started(lua_State* l) {
358 
359   return state_boundary_handle(l, [&] {
360     const CustomState& state = *check_state(l, 1);
361 
362     lua_pushboolean(l, state.is_current_state());
363     return 1;
364   });
365 }
366 
367 /**
368  * \brief Implementation of state:is_visible().
369  * \param l The Lua context that is calling this function.
370  * \return Number of values to return to Lua.
371  */
state_api_is_visible(lua_State * l)372 int LuaContext::state_api_is_visible(lua_State* l) {
373 
374   return state_boundary_handle(l, [&] {
375     const CustomState& state = *check_state(l, 1);
376 
377     lua_pushboolean(l, state.is_visible());
378     return 1;
379   });
380 }
381 
382 /**
383  * \brief Implementation of state:set_visible().
384  * \param l The Lua context that is calling this function.
385  * \return Number of values to return to Lua.
386  */
state_api_set_visible(lua_State * l)387 int LuaContext::state_api_set_visible(lua_State* l) {
388 
389   return LuaTools::exception_boundary_handle(l, [&] {
390     CustomState& state = *check_state(l, 1);
391     bool visible = LuaTools::opt_boolean(l, 2, true);
392 
393     state.set_visible(visible);
394 
395     return 0;
396   });
397 }
398 
399 /**
400  * \brief Implementation of state:get_can_control_direction().
401  * \param l The Lua context that is calling this function.
402  * \return Number of values to return to Lua.
403  */
state_api_get_can_control_direction(lua_State * l)404 int LuaContext::state_api_get_can_control_direction(lua_State* l) {
405 
406   return state_boundary_handle(l, [&] {
407     const CustomState& state = *check_state(l, 1);
408 
409     lua_pushboolean(l, state.get_can_control_direction());
410     return 1;
411   });
412 }
413 
414 /**
415  * \brief Implementation of state:set_can_control_direction().
416  * \param l The Lua context that is calling this function.
417  * \return Number of values to return to Lua.
418  */
state_api_set_can_control_direction(lua_State * l)419 int LuaContext::state_api_set_can_control_direction(lua_State* l) {
420 
421   return state_boundary_handle(l, [&] {
422     CustomState& state = *check_state(l, 1);
423     bool can_control_direction = LuaTools::check_boolean(l, 2);
424 
425     state.set_can_control_direction(can_control_direction);
426 
427     return 0;
428   });
429 }
430 
431 /**
432  * \brief Implementation of state:get_can_control_movement().
433  * \param l The Lua context that is calling this function.
434  * \return Number of values to return to Lua.
435  */
state_api_get_can_control_movement(lua_State * l)436 int LuaContext::state_api_get_can_control_movement(lua_State* l) {
437 
438   return state_boundary_handle(l, [&] {
439     const CustomState& state = *check_state(l, 1);
440 
441     lua_pushboolean(l, state.get_can_control_movement());
442     return 1;
443   });
444 }
445 
446 /**
447  * \brief Implementation of state:set_can_control_movement().
448  * \param l The Lua context that is calling this function.
449  * \return Number of values to return to Lua.
450  */
state_api_set_can_control_movement(lua_State * l)451 int LuaContext::state_api_set_can_control_movement(lua_State* l) {
452 
453   return state_boundary_handle(l, [&] {
454     CustomState& state = *check_state(l, 1);
455     bool can_control_movement = LuaTools::check_boolean(l, 2);
456 
457     state.set_can_control_movement(can_control_movement);
458 
459     return 0;
460   });
461 }
462 
463 /**
464  * \brief Implementation of state:get_draw_override().
465  * \param l The Lua context that is calling this function.
466  * \return Number of values to return to Lua.
467  */
state_api_get_draw_override(lua_State * l)468 int LuaContext::state_api_get_draw_override(lua_State* l) {
469 
470   return state_boundary_handle(l, [&] {
471     const CustomState& state = *check_state(l, 1);
472 
473     ScopedLuaRef draw_override = state.get_draw_override();
474     if (draw_override.is_empty()) {
475       lua_pushnil(l);
476     }
477     else {
478       push_ref(l, draw_override);
479     }
480     return 1;
481   });
482 }
483 
484 /**
485  * \brief Implementation of state:set_draw_override().
486  * \param l The Lua context that is calling this function.
487  * \return Number of values to return to Lua.
488  */
state_api_set_draw_override(lua_State * l)489 int LuaContext::state_api_set_draw_override(lua_State* l) {
490 
491   return state_boundary_handle(l, [&] {
492     CustomState& state = *check_state(l, 1);
493     ScopedLuaRef draw_override;
494     if (lua_gettop(l) >= 2) {
495       if (lua_isfunction(l, 2)) {
496         draw_override = LuaTools::check_function(l, 2);
497       }
498       else if (!lua_isnil(l, 2)) {
499         LuaTools::type_error(l, 2, "function or nil");
500       }
501     }
502 
503     state.set_draw_override(draw_override);
504 
505     return 0;
506   });
507 }
508 
509 /**
510  * \brief Implementation of state:set_can_traverse().
511  * \param l The Lua context that is calling this function.
512  * \return Number of values to return to Lua.
513  */
state_api_set_can_traverse(lua_State * l)514 int LuaContext::state_api_set_can_traverse(lua_State* l) {
515 
516   return state_boundary_handle(l, [&] {
517     CustomState& state = *check_state(l, 1);
518 
519     bool type_specific = false;
520     EntityType type = EntityType::TILE;
521     int index = 2;
522     if (lua_isstring(l, index)) {
523       ++index;
524       type_specific = true;
525       type = LuaTools::check_enum<EntityType>(
526           l, 2
527       );
528     }
529 
530     if (lua_isnil(l, index)) {
531       // Reset the setting.
532       if (!type_specific) {
533         state.reset_can_traverse_entities();
534       }
535       else {
536         state.reset_can_traverse_entities(type);
537       }
538     }
539     else if (lua_isboolean(l, index)) {
540       // Boolean value.
541       bool traversable = lua_toboolean(l, index);
542       if (!type_specific) {
543         state.set_can_traverse_entities(traversable);
544       }
545       else {
546         state.set_can_traverse_entities(type, traversable);
547       }
548     }
549     else if (lua_isfunction(l, index)) {
550       // Custom boolean function.
551       const ScopedLuaRef& traversable_test_ref = LuaTools::check_function(l, index);
552       if (!type_specific) {
553         state.set_can_traverse_entities(traversable_test_ref);
554       }
555       else {
556         state.set_can_traverse_entities(type, traversable_test_ref);
557       }
558     }
559     else {
560       LuaTools::type_error(l, index, "boolean, function or nil");
561     }
562 
563     return 0;
564   });
565 }
566 
567 /**
568  * \brief Implementation of state:can_traverse_ground().
569  * \param l The Lua context that is calling this function.
570  * \return Number of values to return to Lua.
571  */
state_api_get_can_traverse_ground(lua_State * l)572 int LuaContext::state_api_get_can_traverse_ground(lua_State* l) {
573 
574   return state_boundary_handle(l, [&] {
575     const CustomState& state = *check_state(l, 1);
576     Ground ground = LuaTools::check_enum<Ground>(l, 2);
577 
578     bool traversable = state.get_can_traverse_ground(ground);
579 
580     lua_pushboolean(l, traversable);
581     return 1;
582   });
583 }
584 
585 /**
586  * \brief Implementation of state:set_can_traverse_ground().
587  * \param l The Lua context that is calling this function.
588  * \return Number of values to return to Lua.
589  */
state_api_set_can_traverse_ground(lua_State * l)590 int LuaContext::state_api_set_can_traverse_ground(lua_State* l) {
591 
592   return state_boundary_handle(l, [&] {
593     CustomState& state = *check_state(l, 1);
594     Ground ground = LuaTools::check_enum<Ground>(l, 2);
595     bool traversable = LuaTools::check_boolean(l, 3);
596 
597     state.set_can_traverse_ground(ground, traversable);
598 
599     return 0;
600   });
601 }
602 
603 /**
604  * \brief Implementation of state:is_gravity_enabled().
605  * \param l The Lua context that is calling this function.
606  * \return Number of values to return to Lua.
607  */
state_api_is_gravity_enabled(lua_State * l)608 int LuaContext::state_api_is_gravity_enabled(lua_State* l) {
609 
610   return state_boundary_handle(l, [&] {
611     const CustomState& state = *check_state(l, 1);
612 
613     lua_pushboolean(l, state.is_touching_ground());
614     return 1;
615   });
616 }
617 
618 /**
619  * \brief Implementation of state:set_gravity_enabled().
620  * \param l The Lua context that is calling this function.
621  * \return Number of values to return to Lua.
622  */
state_api_set_gravity_enabled(lua_State * l)623 int LuaContext::state_api_set_gravity_enabled(lua_State* l) {
624 
625   return state_boundary_handle(l, [&] {
626     CustomState& state = *check_state(l, 1);
627     bool gravity_enabled = LuaTools::check_boolean(l, 2);
628 
629     state.set_touching_ground(gravity_enabled);
630 
631     return 0;
632   });
633 }
634 
635 /**
636  * \brief Implementation of state:is_affected_by_ground().
637  * \param l The Lua context that is calling this function.
638  * \return Number of values to return to Lua.
639  */
state_api_is_affected_by_ground(lua_State * l)640 int LuaContext::state_api_is_affected_by_ground(lua_State* l) {
641 
642   return state_boundary_handle(l, [&] {
643     const CustomState& state = *check_state(l, 1);
644     Ground ground = LuaTools::check_enum<Ground>(l, 2);
645 
646     lua_pushboolean(l, state.is_affected_by_ground(ground));
647     return 1;
648   });
649 }
650 
651 /**
652  * \brief Implementation of state:set_affected_by_ground().
653  * \param l The Lua context that is calling this function.
654  * \return Number of values to return to Lua.
655  */
state_api_set_affected_by_ground(lua_State * l)656 int LuaContext::state_api_set_affected_by_ground(lua_State* l) {
657 
658   return state_boundary_handle(l, [&] {
659     CustomState& state = *check_state(l, 1);
660     Ground ground = LuaTools::check_enum<Ground>(l, 2);
661     bool affected = LuaTools::opt_boolean(l, 3, true);
662 
663     state.set_affected_by_ground(ground, affected);
664 
665     return 0;
666   });
667 }
668 
669 /**
670  * \brief Implementation of state:get_can_come_from_bad_ground().
671  * \param l The Lua context that is calling this function.
672  * \return Number of values to return to Lua.
673  */
state_api_get_can_come_from_bad_ground(lua_State * l)674 int LuaContext::state_api_get_can_come_from_bad_ground(lua_State* l) {
675 
676   return state_boundary_handle(l, [&] {
677     const CustomState& state = *check_state(l, 1);
678 
679     lua_pushboolean(l, state.get_can_come_from_bad_ground());
680     return 1;
681   });
682 }
683 
684 /**
685  * \brief Implementation of state:set_can_come_from_bad_ground().
686  * \param l The Lua context that is calling this function.
687  * \return Number of values to return to Lua.
688  */
state_api_set_can_come_from_bad_ground(lua_State * l)689 int LuaContext::state_api_set_can_come_from_bad_ground(lua_State* l) {
690 
691   return state_boundary_handle(l, [&] {
692     CustomState& state = *check_state(l, 1);
693     bool can_come_from_bad_ground = LuaTools::check_boolean(l, 2);
694 
695     state.set_can_come_from_bad_ground(can_come_from_bad_ground);
696 
697     return 0;
698   });
699 }
700 
701 /**
702  * \brief Implementation of state:get_can_be_hurt().
703  * \param l The Lua context that is calling this function.
704  * \return Number of values to return to Lua.
705  */
state_api_get_can_be_hurt(lua_State * l)706 int LuaContext::state_api_get_can_be_hurt(lua_State* l) {
707 
708   return state_boundary_handle(l, [&] {
709     CustomState& state = *check_state(l, 1);
710 
711     lua_pushboolean(l, state.get_can_be_hurt(nullptr));
712     return 1;
713   });
714 }
715 
716 /**
717  * \brief Implementation of state:set_can_be_hurt().
718  * \param l The Lua context that is calling this function.
719  * \return Number of values to return to Lua.
720  */
state_api_set_can_be_hurt(lua_State * l)721 int LuaContext::state_api_set_can_be_hurt(lua_State* l) {
722 
723   return state_boundary_handle(l, [&] {
724     CustomState& state = *check_state(l, 1);
725 
726     if (lua_isboolean(l, 2)) {
727       bool can_be_hurt = LuaTools::check_boolean(l, 2);
728       state.set_can_be_hurt(can_be_hurt);
729     }
730     else if (lua_isfunction(l, 2)) {
731       // Custom boolean function.
732       const ScopedLuaRef& can_be_hurt_callback = LuaTools::check_function(l, 2);
733       state.set_can_be_hurt(can_be_hurt_callback);
734     }
735     else {
736       LuaTools::arg_error(l, 2, "boolean or function");
737     }
738 
739     return 0;
740   });
741 }
742 
743 /**
744  * \brief Implementation of state:get_can_use_sword().
745  * \param l The Lua context that is calling this function.
746  * \return Number of values to return to Lua.
747  */
state_api_get_can_use_sword(lua_State * l)748 int LuaContext::state_api_get_can_use_sword(lua_State* l) {
749 
750   return state_boundary_handle(l, [&] {
751     const CustomState& state = *check_state(l, 1);
752 
753     lua_pushboolean(l, state.get_can_start_sword());
754     return 1;
755   });
756 }
757 
758 /**
759  * \brief Implementation of state:set_can_use_sword().
760  * \param l The Lua context that is calling this function.
761  * \return Number of values to return to Lua.
762  */
state_api_set_can_use_sword(lua_State * l)763 int LuaContext::state_api_set_can_use_sword(lua_State* l) {
764 
765   return state_boundary_handle(l, [&] {
766     CustomState& state = *check_state(l, 1);
767     bool can_use_sword = LuaTools::check_boolean(l, 2);
768 
769     state.set_can_start_sword(can_use_sword);
770 
771     return 0;
772   });
773 }
774 
775 /**
776  * \brief Implementation of state:get_can_cut().
777  * \param l The Lua context that is calling this function.
778  * \return Number of values to return to Lua.
779  */
state_api_get_can_cut(lua_State * l)780 int LuaContext::state_api_get_can_cut(lua_State* l) {
781 
782   return state_boundary_handle(l, [&] {
783     CustomState& state = *check_state(l, 1);
784 
785     lua_pushboolean(l, state.get_can_cut(nullptr));
786     return 1;
787   });
788 }
789 
790 /**
791  * \brief Implementation of state:set_can_cut().
792  * \param l The Lua context that is calling this function.
793  * \return Number of values to return to Lua.
794  */
state_api_set_can_cut(lua_State * l)795 int LuaContext::state_api_set_can_cut(lua_State* l) {
796 
797   return state_boundary_handle(l, [&] {
798     CustomState& state = *check_state(l, 1);
799 
800     if (lua_isboolean(l, 2)) {
801       bool can_cut = LuaTools::check_boolean(l, 2);
802       state.set_can_cut(can_cut);
803     }
804     else if (lua_isfunction(l, 2)) {
805       // Custom boolean function.
806       const ScopedLuaRef& can_cut_callback = LuaTools::check_function(l, 2);
807       state.set_can_cut(can_cut_callback);
808     }
809     else {
810       LuaTools::arg_error(l, 2, "boolean or function");
811     }
812 
813     return 0;
814   });
815 }
816 
817 /**
818  * \brief Implementation of state:get_can_use_shield().
819  * \param l The Lua context that is calling this function.
820  * \return Number of values to return to Lua.
821  */
state_api_get_can_use_shield(lua_State * l)822 int LuaContext::state_api_get_can_use_shield(lua_State* l) {
823 
824   return state_boundary_handle(l, [&] {
825     const CustomState& state = *check_state(l, 1);
826 
827     lua_pushboolean(l, state.get_can_use_shield());
828     return 1;
829   });
830 }
831 
832 /**
833  * \brief Implementation of state:set_can_use_shield().
834  * \param l The Lua context that is calling this function.
835  * \return Number of values to return to Lua.
836  */
state_api_set_can_use_shield(lua_State * l)837 int LuaContext::state_api_set_can_use_shield(lua_State* l) {
838 
839   return state_boundary_handle(l, [&] {
840     CustomState& state = *check_state(l, 1);
841     bool can_use_shield = LuaTools::check_boolean(l, 2);
842 
843     state.set_can_use_shield(can_use_shield);
844 
845     return 0;
846   });
847 }
848 
849 /**
850  * \brief Implementation of state:get_can_use_item().
851  * \param l The Lua context that is calling this function.
852  * \return Number of values to return to Lua.
853  */
state_api_get_can_use_item(lua_State * l)854 int LuaContext::state_api_get_can_use_item(lua_State* l) {
855 
856   return state_boundary_handle(l, [&] {
857     const CustomState& state = *check_state(l, 1);
858     std::string item_id;
859 
860     if (!lua_isnone(l, 2)) {
861       item_id = LuaTools::check_string(l, 2);
862       if (!CurrentQuest::resource_exists(ResourceType::ITEM, item_id)) {
863         LuaTools::arg_error(l, 2, "No such item: '" + item_id + "'");
864       }
865     }
866 
867     lua_pushboolean(l, state.get_can_start_item(item_id));
868     return 1;
869   });
870 }
871 
872 /**
873  * \brief Implementation of state:set_can_use_item().
874  * \param l The Lua context that is calling this function.
875  * \return Number of values to return to Lua.
876  */
state_api_set_can_use_item(lua_State * l)877 int LuaContext::state_api_set_can_use_item(lua_State* l) {
878 
879   return state_boundary_handle(l, [&] {
880     CustomState& state = *check_state(l, 1);
881     std::string item_id;
882     int index = 2;
883     if (lua_isstring(l, 2)) {
884       ++index;
885       item_id = LuaTools::check_string(l, 2);
886       if (!CurrentQuest::resource_exists(ResourceType::ITEM, item_id)) {
887         LuaTools::arg_error(l, 2, "No such item: '" + item_id + "'");
888       }
889     }
890     else if (!lua_isboolean(l, 2)) {
891       LuaTools::type_error(l, 2, "string or boolean");
892     }
893     bool can_use_item = LuaTools::check_boolean(l, index);
894 
895     state.set_can_start_item(item_id, can_use_item);
896 
897     return 0;
898   });
899 }
900 
901 /**
902  * \brief Implementation of state:get_can_interact().
903  * \param l The Lua context that is calling this function.
904  * \return Number of values to return to Lua.
905  */
state_api_get_can_interact(lua_State * l)906 int LuaContext::state_api_get_can_interact(lua_State* l) {
907 
908   return state_boundary_handle(l, [&] {
909     const CustomState& state = *check_state(l, 1);
910 
911     lua_pushboolean(l, state.get_can_interact());
912     return 1;
913   });
914 }
915 
916 /**
917  * \brief Implementation of state:set_can_interact().
918  * \param l The Lua context that is calling this function.
919  * \return Number of values to return to Lua.
920  */
state_api_set_can_interact(lua_State * l)921 int LuaContext::state_api_set_can_interact(lua_State* l) {
922 
923   return state_boundary_handle(l, [&] {
924     CustomState& state = *check_state(l, 1);
925     bool can_interact = LuaTools::check_boolean(l, 2);
926 
927     state.set_can_interact(can_interact);
928 
929     return 0;
930   });
931 }
932 
933 /**
934  * \brief Implementation of state:get_can_grab().
935  * \param l The Lua context that is calling this function.
936  * \return Number of values to return to Lua.
937  */
state_api_get_can_grab(lua_State * l)938 int LuaContext::state_api_get_can_grab(lua_State* l) {
939 
940   return state_boundary_handle(l, [&] {
941     const CustomState& state = *check_state(l, 1);
942 
943     lua_pushboolean(l, state.get_can_grab());
944     return 1;
945   });
946 }
947 
948 /**
949  * \brief Implementation of state:set_can_grab().
950  * \param l The Lua context that is calling this function.
951  * \return Number of values to return to Lua.
952  */
state_api_set_can_grab(lua_State * l)953 int LuaContext::state_api_set_can_grab(lua_State* l) {
954 
955   return state_boundary_handle(l, [&] {
956     CustomState& state = *check_state(l, 1);
957     bool can_grab = LuaTools::check_boolean(l, 2);
958 
959     state.set_can_grab(can_grab);
960 
961     return 0;
962   });
963 }
964 
965 /**
966  * \brief Implementation of state:get_can_push().
967  * \param l The Lua context that is calling this function.
968  * \return Number of values to return to Lua.
969  */
state_api_get_can_push(lua_State * l)970 int LuaContext::state_api_get_can_push(lua_State* l) {
971 
972   return state_boundary_handle(l, [&] {
973     const CustomState& state = *check_state(l, 1);
974 
975     lua_pushboolean(l, state.get_can_push());
976     return 1;
977   });
978 }
979 
980 /**
981  * \brief Implementation of state:set_can_push().
982  * \param l The Lua context that is calling this function.
983  * \return Number of values to return to Lua.
984  */
state_api_set_can_push(lua_State * l)985 int LuaContext::state_api_set_can_push(lua_State* l) {
986 
987   return state_boundary_handle(l, [&] {
988     CustomState& state = *check_state(l, 1);
989     bool can_push = LuaTools::check_boolean(l, 2);
990 
991     state.set_can_push(can_push);
992 
993     return 0;
994   });
995 }
996 
997 /**
998  * \brief Implementation of state:get_pushing_delay().
999  * \param l The Lua context that is calling this function.
1000  * \return Number of values to return to Lua.
1001  */
state_api_get_pushing_delay(lua_State * l)1002 int LuaContext::state_api_get_pushing_delay(lua_State* l) {
1003 
1004   return state_boundary_handle(l, [&] {
1005     const CustomState& state = *check_state(l, 1);
1006 
1007     lua_pushinteger(l, state.get_pushing_delay());
1008     return 1;
1009   });
1010 }
1011 
1012 /**
1013  * \brief Implementation of state:set_pushing_delay().
1014  * \param l The Lua context that is calling this function.
1015  * \return Number of values to return to Lua.
1016  */
state_api_set_pushing_delay(lua_State * l)1017 int LuaContext::state_api_set_pushing_delay(lua_State* l) {
1018 
1019   return state_boundary_handle(l, [&] {
1020     CustomState& state = *check_state(l, 1);
1021     int pushing_delay = LuaTools::check_int(l, 2);
1022 
1023     if (pushing_delay < 0) {
1024       LuaTools::arg_error(l, 2, "Pushing delay should be positive or zero");
1025     }
1026     state.set_pushing_delay(pushing_delay);
1027 
1028     return 0;
1029   });
1030 }
1031 
1032 /**
1033  * \brief Implementation of state:get_can_pick_treasure().
1034  * \param l The Lua context that is calling this function.
1035  * \return Number of values to return to Lua.
1036  */
state_api_get_can_pick_treasure(lua_State * l)1037 int LuaContext::state_api_get_can_pick_treasure(lua_State* l) {
1038 
1039   return state_boundary_handle(l, [&] {
1040     const CustomState& state = *check_state(l, 1);
1041 
1042     lua_pushboolean(l, state.get_can_pick_treasure());
1043     return 1;
1044   });
1045 }
1046 
1047 /**
1048  * \brief Implementation of state:set_can_pick_treasure().
1049  * \param l The Lua context that is calling this function.
1050  * \return Number of values to return to Lua.
1051  */
state_api_set_can_pick_treasure(lua_State * l)1052 int LuaContext::state_api_set_can_pick_treasure(lua_State* l) {
1053 
1054   return state_boundary_handle(l, [&] {
1055     CustomState& state = *check_state(l, 1);
1056     bool can_pick_treasure = LuaTools::check_boolean(l, 2);
1057 
1058     state.set_can_pick_treasure(can_pick_treasure);
1059 
1060     return 0;
1061   });
1062 }
1063 
1064 /**
1065  * \brief Implementation of state:get_can_use_teletransporter().
1066  * \param l The Lua context that is calling this function.
1067  * \return Number of values to return to Lua.
1068  */
state_api_get_can_use_teletransporter(lua_State * l)1069 int LuaContext::state_api_get_can_use_teletransporter(lua_State* l) {
1070 
1071   return state_boundary_handle(l, [&] {
1072     const CustomState& state = *check_state(l, 1);
1073 
1074     lua_pushboolean(l, state.get_can_take_teletransporter());
1075     return 1;
1076   });
1077 }
1078 
1079 /**
1080  * \brief Implementation of state:set_can_use_teletransporter().
1081  * \param l The Lua context that is calling this function.
1082  * \return Number of values to return to Lua.
1083  */
state_api_set_can_use_teletransporter(lua_State * l)1084 int LuaContext::state_api_set_can_use_teletransporter(lua_State* l) {
1085 
1086   return state_boundary_handle(l, [&] {
1087     CustomState& state = *check_state(l, 1);
1088     bool can_take_teletransporter = LuaTools::check_boolean(l, 2);
1089 
1090     state.set_can_take_teletransporter(can_take_teletransporter);
1091 
1092     return 0;
1093   });
1094 }
1095 
1096 /**
1097  * \brief Implementation of state:get_can_use_switch().
1098  * \param l The Lua context that is calling this function.
1099  * \return Number of values to return to Lua.
1100  */
state_api_get_can_use_switch(lua_State * l)1101 int LuaContext::state_api_get_can_use_switch(lua_State* l) {
1102 
1103   return state_boundary_handle(l, [&] {
1104     const CustomState& state = *check_state(l, 1);
1105 
1106     lua_pushboolean(l, state.get_can_take_switch());
1107     return 1;
1108   });
1109 }
1110 
1111 /**
1112  * \brief Implementation of state:set_can_use_switch().
1113  * \param l The Lua context that is calling this function.
1114  * \return Number of values to return to Lua.
1115  */
state_api_set_can_use_switch(lua_State * l)1116 int LuaContext::state_api_set_can_use_switch(lua_State* l) {
1117 
1118   return state_boundary_handle(l, [&] {
1119     CustomState& state = *check_state(l, 1);
1120     bool can_take_switch = LuaTools::check_boolean(l, 2);
1121 
1122     state.set_can_take_switch(can_take_switch);
1123 
1124     return 0;
1125   });
1126 }
1127 
1128 /**
1129  * \brief Implementation of state:get_can_use_stream().
1130  * \param l The Lua context that is calling this function.
1131  * \return Number of values to return to Lua.
1132  */
state_api_get_can_use_stream(lua_State * l)1133 int LuaContext::state_api_get_can_use_stream(lua_State* l) {
1134 
1135   return state_boundary_handle(l, [&] {
1136     const CustomState& state = *check_state(l, 1);
1137 
1138     lua_pushboolean(l, state.get_can_take_stream());
1139     return 1;
1140   });
1141 }
1142 
1143 /**
1144  * \brief Implementation of state:set_can_use_stream().
1145  * \param l The Lua context that is calling this function.
1146  * \return Number of values to return to Lua.
1147  */
state_api_set_can_use_stream(lua_State * l)1148 int LuaContext::state_api_set_can_use_stream(lua_State* l) {
1149 
1150   return state_boundary_handle(l, [&] {
1151     CustomState& state = *check_state(l, 1);
1152     bool can_take_stream = LuaTools::check_boolean(l, 2);
1153 
1154     state.set_can_take_stream(can_take_stream);
1155 
1156     return 0;
1157   });
1158 }
1159 
1160 /**
1161  * \brief Implementation of state:get_can_use_stairs().
1162  * \param l The Lua context that is calling this function.
1163  * \return Number of values to return to Lua.
1164  */
state_api_get_can_use_stairs(lua_State * l)1165 int LuaContext::state_api_get_can_use_stairs(lua_State* l) {
1166 
1167   return state_boundary_handle(l, [&] {
1168     const CustomState& state = *check_state(l, 1);
1169 
1170     lua_pushboolean(l, state.get_can_take_stairs());
1171     return 1;
1172   });
1173 }
1174 
1175 /**
1176  * \brief Implementation of state:set_can_use_stairs().
1177  * \param l The Lua context that is calling this function.
1178  * \return Number of values to return to Lua.
1179  */
state_api_set_can_use_stairs(lua_State * l)1180 int LuaContext::state_api_set_can_use_stairs(lua_State* l) {
1181 
1182   return state_boundary_handle(l, [&] {
1183     CustomState& state = *check_state(l, 1);
1184     bool can_take_stairs = LuaTools::check_boolean(l, 2);
1185 
1186     state.set_can_take_stairs(can_take_stairs);
1187 
1188     return 0;
1189   });
1190 }
1191 
1192 /**
1193  * \brief Implementation of state:get_can_use_jumper().
1194  * \param l The Lua context that is calling this function.
1195  * \return Number of values to return to Lua.
1196  */
state_api_get_can_use_jumper(lua_State * l)1197 int LuaContext::state_api_get_can_use_jumper(lua_State* l) {
1198 
1199   return state_boundary_handle(l, [&] {
1200     const CustomState& state = *check_state(l, 1);
1201 
1202     lua_pushboolean(l, state.get_can_take_jumper());
1203     return 1;
1204   });
1205 }
1206 
1207 /**
1208  * \brief Implementation of state:set_can_use_jumper().
1209  * \param l The Lua context that is calling this function.
1210  * \return Number of values to return to Lua.
1211  */
state_api_set_can_use_jumper(lua_State * l)1212 int LuaContext::state_api_set_can_use_jumper(lua_State* l) {
1213 
1214   return state_boundary_handle(l, [&] {
1215     CustomState& state = *check_state(l, 1);
1216     bool can_take_jumper = LuaTools::check_boolean(l, 2);
1217 
1218     state.set_can_take_jumper(can_take_jumper);
1219 
1220     return 0;
1221   });
1222 }
1223 
1224 /**
1225  * \brief Implementation of state:get_jumper_delay().
1226  * \param l The Lua context that is calling this function.
1227  * \return Number of values to return to Lua.
1228  */
state_api_get_jumper_delay(lua_State * l)1229 int LuaContext::state_api_get_jumper_delay(lua_State* l) {
1230 
1231   return state_boundary_handle(l, [&] {
1232     const CustomState& state = *check_state(l, 1);
1233 
1234     lua_pushinteger(l, state.get_jumper_delay());
1235     return 1;
1236   });
1237 }
1238 
1239 /**
1240  * \brief Implementation of state:set_jumper_delay().
1241  * \param l The Lua context that is calling this function.
1242  * \return Number of values to return to Lua.
1243  */
state_api_set_jumper_delay(lua_State * l)1244 int LuaContext::state_api_set_jumper_delay(lua_State* l) {
1245 
1246   return state_boundary_handle(l, [&] {
1247     CustomState& state = *check_state(l, 1);
1248     int jumper_delay = LuaTools::check_int(l, 2);
1249 
1250     if (jumper_delay < 0) {
1251       LuaTools::arg_error(l, 2, "Jumper delay should be positive or zero");
1252     }
1253     state.set_jumper_delay(jumper_delay);
1254 
1255     return 0;
1256   });
1257 }
1258 
1259 /**
1260  * \brief Implementation of state:get_carried_object_action().
1261  * \param l The Lua context that is calling this function.
1262  * \return Number of values to return to Lua.
1263  */
state_api_get_carried_object_action(lua_State * l)1264 int LuaContext::state_api_get_carried_object_action(lua_State* l) {
1265 
1266   return state_boundary_handle(l, [&] {
1267     const CustomState& state = *check_state(l, 1);
1268 
1269     CarriedObject::Behavior behavior = state.get_previous_carried_object_behavior();
1270     push_string(l, enum_to_name(behavior));
1271     return 1;
1272   });
1273 }
1274 
1275 /**
1276  * \brief Implementation of state:set_carried_object_action().
1277  * \param l The Lua context that is calling this function.
1278  * \return Number of values to return to Lua.
1279  */
state_api_set_carried_object_action(lua_State * l)1280 int LuaContext::state_api_set_carried_object_action(lua_State* l) {
1281 
1282   return state_boundary_handle(l, [&] {
1283     CustomState& state = *check_state(l, 1);
1284     CarriedObject::Behavior behavior = LuaTools::check_enum<CarriedObject::Behavior>(l, 2);
1285 
1286     state.set_previous_carried_object_behavior(behavior);
1287     return 0;
1288   });
1289 }
1290 
1291 /**
1292  * \brief Calls the on_started() method of a Lua custom state.
1293  *
1294  * Does nothing if the method is not defined.
1295  *
1296  * \param state The custom state that has just started.
1297  * \param previous_state_name Name of the previous state.
1298  * \param previous_state The previous state object if it was a custom one.
1299  */
state_on_started(CustomState & state,const std::string & previous_state_name,CustomState * previous_state)1300 void LuaContext::state_on_started(
1301     CustomState& state,
1302     const std::string& previous_state_name,
1303     CustomState* previous_state) {
1304 
1305   if (!userdata_has_field(state, "on_started")) {
1306     return;
1307   }
1308 
1309   push_state(current_l, state);
1310   on_started(previous_state_name, previous_state);
1311   lua_pop(current_l, 1);
1312 }
1313 
1314 /**
1315  * \brief Calls the on_finished() method of a custom state if it is defined.
1316  *
1317  * Also stops timers associated to the state.
1318  *
1319  * \param state The custom state that has just finished.
1320  * \param next_state_name Name of the next state.
1321  * \param next_state The next state object if it is a custom one.
1322  */
state_on_finished(CustomState & state,const std::string & next_state_name,CustomState * next_state)1323 void LuaContext::state_on_finished(
1324     CustomState& state,
1325     const std::string& next_state_name,
1326     CustomState* next_state) {
1327 
1328   run_on_main([this, &state, next_state_name, next_state](lua_State* l) {
1329     push_state(l, state);
1330     if (userdata_has_field(state, "on_finished")) {
1331       on_finished(next_state_name, next_state);
1332     }
1333     remove_timers(-1);  // Stop timers associated to this state.
1334     lua_pop(current_l, 1);
1335   });
1336 }
1337 
1338 /**
1339  * \brief Calls the on_update() method of a Lua custom state.
1340  *
1341  * Does nothing if the method is not defined.
1342  *
1343  * \param state A custom state.
1344  */
state_on_update(CustomState & state)1345 void LuaContext::state_on_update(CustomState& state) {
1346 
1347   if (!userdata_has_field(state, "on_update")) {
1348     return;
1349   }
1350 
1351   run_on_main([this, &state](lua_State* l) {
1352     push_state(l, state);
1353     on_update();
1354     lua_pop(l, 1);
1355   });
1356 }
1357 
1358 /**
1359  * \brief Calls the on_suspended() method of a Lua custom state.
1360  *
1361  * Does nothing if the method is not defined.
1362  *
1363  * \param state A custom state.
1364  * \param suspended \c true if the state is suspended.
1365  */
state_on_suspended(CustomState & state,bool suspended)1366 void LuaContext::state_on_suspended(CustomState& state, bool suspended) {
1367 
1368   if (!userdata_has_field(state, "on_suspended")) {
1369     return;
1370   }
1371   run_on_main([this, &state, suspended](lua_State* l) {
1372     push_state(l, state);
1373     on_suspended(suspended);
1374     lua_pop(l, 1);
1375   });
1376 }
1377 
1378 /**
1379  * \brief Calls the on_pre_draw() method of a Lua custom state.
1380  *
1381  * Does nothing if the method is not defined.
1382  *
1383  * \param state A custom state.
1384  * \param camera The camera where to draw the entity.
1385  */
state_on_pre_draw(CustomState & state,Camera & camera)1386 void LuaContext::state_on_pre_draw(CustomState& state, Camera& camera) {
1387 
1388   if (!userdata_has_field(state, "on_pre_draw")) {
1389     return;
1390   }
1391   run_on_main([this, &state, &camera](lua_State* l) {
1392     push_state(l, state);
1393     on_pre_draw(camera);
1394     lua_pop(l, 1);
1395   });
1396 }
1397 
1398 /**
1399  * \brief Calls the on_post_draw() method of a Lua custom state.
1400  *
1401  * Does nothing if the method is not defined.
1402  *
1403  * \param state A custom state.
1404  * \param camera The camera where to draw the entity.
1405  */
state_on_post_draw(CustomState & state,Camera & camera)1406 void LuaContext::state_on_post_draw(CustomState& state, Camera& camera) {
1407 
1408   if (!userdata_has_field(state, "on_post_draw")) {
1409     return;
1410   }
1411   run_on_main([this, &state, &camera](lua_State* l) {
1412     push_state(l, state);
1413     on_post_draw(camera);
1414     lua_pop(l, 1);
1415   });
1416 }
1417 
1418 /**
1419  * \brief Calls the on_map_started() method of a Lua custom state.
1420  *
1421  * Does nothing if the method is not defined.
1422  *
1423  * \param state A custom state.
1424  * \param map The map.
1425  * \param destination Destination entity where the hero is placed or nullptr.
1426  */
state_on_map_started(CustomState & state,Map & map,const std::shared_ptr<Destination> & destination)1427 void LuaContext::state_on_map_started(
1428     CustomState& state, Map& map, const std::shared_ptr<Destination>& destination) {
1429 
1430   if (!userdata_has_field(state, "on_map_started")) {
1431     return;
1432   }
1433   run_on_main([this, &state, &map, &destination](lua_State* l) {
1434     push_state(l, state);
1435     on_map_started(map, destination);
1436     lua_pop(l, 1);
1437   });
1438 }
1439 
1440 /**
1441  * \brief Calls the on_map_opening_transition_finished() method of a Lua custom state.
1442  *
1443  * Does nothing if the method is not defined.
1444  *
1445  * \param state A custom state.
1446  * \param map The map.
1447  * \param destination Destination entity where the hero is placed or nullptr.
1448  */
state_on_map_opening_transition_finished(CustomState & state,Map & map,const std::shared_ptr<Destination> & destination)1449 void LuaContext::state_on_map_opening_transition_finished(
1450     CustomState& state, Map& map, const std::shared_ptr<Destination>& destination) {
1451 
1452   if (!userdata_has_field(state, "on_map_opening_transition_finished")) {
1453     return;
1454   }
1455   run_on_main([this, &state, &map, &destination](lua_State* l) {
1456     push_state(l, state);
1457     on_map_opening_transition_finished(map, destination);
1458     lua_pop(l, 1);
1459   });
1460 }
1461 
1462 /**
1463  * \brief Calls the on_map_finished() method of a Lua custom state.
1464  *
1465  * Does nothing if the method is not defined.
1466  *
1467  * \param state A custom state.
1468  */
state_on_map_finished(CustomState & state)1469 void LuaContext::state_on_map_finished(CustomState& state) {
1470 
1471   if (!userdata_has_field(state, "on_map_finished")) {
1472     return;
1473   }
1474   run_on_main([this, &state](lua_State* l) {
1475     push_state(l, state);
1476     on_map_finished();
1477     lua_pop(l, 1);
1478   });
1479 }
1480 
1481 /**
1482  * \brief Calls the on_position_changed() method of a Lua custom state.
1483  *
1484  * Does nothing if the method is not defined.
1485  *
1486  * \param state A custom state.
1487  * \param xy The new coordinates.
1488  * \param layer The new layer.
1489  */
state_on_position_changed(CustomState & state,const Point & xy,int layer)1490 void LuaContext::state_on_position_changed(CustomState& state, const Point& xy, int layer) {
1491 
1492   if (!userdata_has_field(state, "on_position_changed")) {
1493     return;
1494   }
1495   run_on_main([this, &state, xy, layer](lua_State* l) {
1496     push_state(l, state);
1497     on_position_changed(xy, layer);
1498     lua_pop(l, 1);
1499   });
1500 }
1501 
1502 /**
1503  * \brief Calls the state_on_ground_below_changed() method of a Lua custom state.
1504  *
1505  * Does nothing if the method is not defined.
1506  *
1507  * \param state A custom state.
1508  * \param ground_below The new ground below the entity.
1509  */
state_on_ground_below_changed(CustomState & state,Ground ground_below)1510 void LuaContext::state_on_ground_below_changed(CustomState& state, Ground ground_below) {
1511 
1512   if (!userdata_has_field(state, "on_ground_below_changed")) {
1513     return;
1514   }
1515 
1516   run_on_main([this, &state, ground_below](lua_State* l){
1517     push_state(l, state);
1518     on_ground_below_changed(ground_below);
1519     lua_pop(l, 1);
1520   });
1521 }
1522 
1523 /**
1524  * \brief Calls the on_obstacle_reached() method of a Lua custom state.
1525  *
1526  * Does nothing if the method is not defined.
1527  *
1528  * \param state A custom state.
1529  * \param movement The movement that reached an obstacle.
1530  */
state_on_obstacle_reached(CustomState & state,Movement & movement)1531 void LuaContext::state_on_obstacle_reached(CustomState& state, Movement& movement) {
1532 
1533   if (!userdata_has_field(state, "on_obstacle_reached")) {
1534     return;
1535   }
1536   run_on_main([this, &state, &movement](lua_State* l) {
1537     push_state(l, state);
1538     on_obstacle_reached(movement);
1539     lua_pop(l, 1);
1540   });
1541 }
1542 
1543 /**
1544  * \brief Calls the on_movement_started() method of a Lua custom state.
1545  *
1546  * Does nothing if the method is not defined.
1547  *
1548  * \param state A custom state.
1549  * \param movement The movement that has just started.
1550  */
state_on_movement_started(CustomState & state,Movement & movement)1551 void LuaContext::state_on_movement_started(CustomState& state, Movement& movement) {
1552 
1553   if (!userdata_has_field(state, "on_movement_started")) {
1554     return;
1555   }
1556 
1557   run_on_main([this, &state, &movement](lua_State* l) {
1558     push_state(l, state);
1559     on_movement_started(movement);
1560     lua_pop(l, 1);
1561   });
1562 }
1563 
1564 /**
1565  * \brief Calls the on_movement_changed() method of a Lua custom state.
1566  *
1567  * Does nothing if the method is not defined.
1568  *
1569  * \param state A custom state.
1570  * \param movement The movement of the entity.
1571  */
state_on_movement_changed(CustomState & state,Movement & movement)1572 void LuaContext::state_on_movement_changed(CustomState& state, Movement& movement) {
1573 
1574   if (!userdata_has_field(state, "on_movement_changed")) {
1575     return;
1576   }
1577 
1578   run_on_main([this, &state, &movement](lua_State* l) {
1579     push_state(l, state);
1580     on_movement_changed(movement);
1581     lua_pop(l, 1);
1582   });
1583 }
1584 
1585 /**
1586  * \brief Calls the on_movement_finished() method of a Lua custom state.
1587  *
1588  * Does nothing if the method is not defined.
1589  *
1590  * \param state A custom state.
1591  */
state_on_movement_finished(CustomState & state)1592 void LuaContext::state_on_movement_finished(CustomState& state) {
1593 
1594   if (!userdata_has_field(state, "on_movement_finished")) {
1595     return;
1596   }
1597 
1598   run_on_main([this, &state](lua_State* l) {
1599     push_state(l, state);
1600     on_movement_finished();
1601     lua_pop(l, 1);
1602   });
1603 }
1604 
1605 /**
1606  * \brief Calls the on_attacked_enemy() method of a Lua custom state.
1607  *
1608  * Does nothing if the method is not defined.
1609  *
1610  * \param state A custom state.
1611  * \param The enemy that was attacked.
1612  * \param enemy_sprite Sprite that was attacked if any.
1613  * \param attack How the enemy was attacked.
1614  * \param reaction How the enemy reacted to the attack.
1615  */
state_on_attacked_enemy(CustomState & state,Enemy & enemy,Sprite * enemy_sprite,EnemyAttack attack,const EnemyReaction::Reaction & reaction)1616 void LuaContext::state_on_attacked_enemy(
1617     CustomState& state,
1618     Enemy& enemy,
1619     Sprite* enemy_sprite,
1620     EnemyAttack attack,
1621     const EnemyReaction::Reaction& reaction
1622 ) {
1623   if (!userdata_has_field(state, "on_attacked_enemy")) {
1624     return;
1625   }
1626 
1627   run_on_main([this, &state, &enemy, &enemy_sprite, &attack, &reaction](lua_State* l) {
1628     push_state(l, state);
1629     on_attacked_enemy(enemy, enemy_sprite, attack, reaction);
1630     lua_pop(l, 1);
1631   });
1632 }
1633 
1634 /**
1635  * \brief Notifies a Lua custom state that an input event has just occurred.
1636  *
1637  * The appropriate callback in the state is triggered if it exists.
1638  * Also notifies the menus of the state if the state itself does not handle the
1639  * event.
1640  *
1641  * \param event The input event to handle.
1642  * \param state A custom state.
1643  * \return \c true if the event was handled and should stop being propagated.
1644  */
state_on_input(CustomState & state,const InputEvent & event)1645 bool LuaContext::state_on_input(CustomState& state, const InputEvent& event) {
1646 
1647   push_state(current_l, state);
1648   bool handled = on_input(event);
1649   if (!handled) {
1650     handled = menus_on_input(-1, event);
1651   }
1652   lua_pop(current_l, 1);
1653   return handled;
1654 }
1655 
1656 /**
1657  * \brief Calls the on_command_pressed() method of a Lua custom state.
1658  *
1659  * Also notifies the menus of the state if the state itself does not handle the
1660  * event.
1661  *
1662  * \param state A state.
1663  * \param command The command pressed.
1664  * \return \c true if the event was handled and should stop being propagated.
1665  */
state_on_command_pressed(CustomState & state,GameCommand command)1666 bool LuaContext::state_on_command_pressed(CustomState& state, GameCommand command) {
1667 
1668   bool handled = false;
1669   push_state(current_l, state);
1670   if (userdata_has_field(state, "on_command_pressed")) {
1671     handled = on_command_pressed(command);
1672   }
1673   if (!handled) {
1674     handled = menus_on_command_pressed(-1, command);
1675   }
1676   lua_pop(current_l, 1);
1677   return handled;
1678 }
1679 
1680 /**
1681  * \brief Calls the on_command_released() method of a Lua custom state.
1682  *
1683  * Also notifies the menus of the state if the state itself does not handle the
1684  * event.
1685  *
1686  * \param state A state.
1687  * \param command The command released.
1688  * \return \c true if the event was handled and should stop being propagated.
1689  */
state_on_command_released(CustomState & state,GameCommand command)1690 bool LuaContext::state_on_command_released(CustomState& state, GameCommand command) {
1691 
1692   bool handled = false;
1693   push_state(current_l, state);
1694   if (userdata_has_field(state, "on_command_released")) {
1695     handled = on_command_released(command);
1696   }
1697   if (!handled) {
1698     handled = menus_on_command_released(-1, command);
1699   }
1700   lua_pop(current_l, 1);
1701   return handled;
1702 }
1703 
1704 }
1705