SimpleAI
 All Classes Namespaces Files Functions Variables Typedefs Macros Groups Pages
LUAFunctions.h
1 /***
2  * @file LUAFunctions.h
3  * @ingroup LUA
4  */
5 #pragma once
6 
7 #include "common/LUA.h"
8 
9 namespace ai {
10 
11 struct luaAI_AI {
12  AIPtr ai;
13 };
14 
16  ICharacterPtr character;
17 };
18 
19 static inline const char *luaAI_metaai() {
20  return "__meta_ai";
21 }
22 
23 static inline const char *luaAI_metazone() {
24  return "__meta_zone";
25 }
26 
27 static inline const char* luaAI_metaaggromgr() {
28  return "__meta_aggromgr";
29 }
30 
31 static inline const char* luaAI_metaregistry() {
32  return "__meta_registry";
33 }
34 
35 static inline const char* luaAI_metagroupmgr() {
36  return "__meta_groupmgr";
37 }
38 
39 static inline const char* luaAI_metacharacter() {
40  return "__meta_character";
41 }
42 
43 static inline const char* luaAI_metavec() {
44  return "__meta_vec";
45 }
46 
47 static void luaAI_registerfuncs(lua_State* s, const luaL_Reg* funcs, const char *name) {
48  luaL_newmetatable(s, name);
49  // assign the metatable to __index
50  lua_pushvalue(s, -1);
51  lua_setfield(s, -2, "__index");
52  luaL_setfuncs(s, funcs, 0);
53 }
54 
55 static void luaAI_setupmetatable(lua_State* s, const std::string& type, const luaL_Reg *funcs, const std::string& name) {
56  const std::string& metaFull = "__meta_" + name + "_" + type;
57  // make global
58  lua_setfield(s, LUA_REGISTRYINDEX, metaFull.c_str());
59  // put back onto stack
60  lua_getfield(s, LUA_REGISTRYINDEX, metaFull.c_str());
61 
62  // setup meta table - create a new one manually, otherwise we aren't
63  // able to override the particular function on a per instance base. Also
64  // this 'metatable' must not be in the global registry.
65  lua_createtable(s, 0, 2);
66  lua_pushvalue(s, -1);
67  lua_setfield(s, -2, "__index");
68  lua_pushstring(s, name.c_str());
69  lua_setfield(s, -2, "__name");
70  lua_pushstring(s, type.c_str());
71  lua_setfield(s, -2, "type");
72  luaL_setfuncs(s, funcs, 0);
73  lua_setmetatable(s, -2);
74 }
75 
76 static int luaAI_newindex(lua_State* s) {
77  // -3 is userdata
78  lua_getmetatable(s, -3);
79  // -3 is now the field string
80  const char *field = luaL_checkstring(s, -3);
81  // push -2 to -1 (the value)
82  lua_pushvalue(s, -2);
83  // set the value into the field
84  lua_setfield(s, -2, field);
85  lua_pop(s, 1);
86  return 0;
87 }
88 
89 template<class T>
90 static inline T luaAI_getudata(lua_State* s, int n, const char *name) {
91  void* dataVoid = luaL_checkudata(s, n, name);
92  if (dataVoid == nullptr) {
93  std::string error(name);
94  error.append(" userdata must not be null");
95  luaL_argcheck(s, dataVoid != nullptr, n, error.c_str());
96  }
97  return (T) dataVoid;
98 }
99 
100 template<class T>
101 static inline T* luaAI_newuserdata(lua_State* s, const T& data) {
102  T* udata = (T*) lua_newuserdata(s, sizeof(T));
103  *udata = data;
104  return udata;
105 }
106 
107 static void luaAI_globalpointer(lua_State* s, void* pointer, const char *name) {
108  lua_pushlightuserdata(s, pointer);
109  lua_setglobal(s, name);
110 }
111 
112 static int luaAI_assignmetatable(lua_State* s, const char *name) {
113  luaL_getmetatable(s, name);
114 #if AI_LUA_SANTITY
115  if (!lua_istable(s, -1)) {
116  ai_log_error("LUA: metatable for %s doesn't exist", name);
117  return 0;
118  }
119 #endif
120  lua_setmetatable(s, -2);
121  return 1;
122 }
123 
124 template<class T>
125 static inline int luaAI_pushudata(lua_State* s, const T& data, const char *name) {
126  luaAI_newuserdata<T>(s, data);
127  return luaAI_assignmetatable(s, name);
128 }
129 
130 template<class T>
131 static T* luaAI_getlightuserdata(lua_State *s, const char *name) {
132  lua_getglobal(s, name);
133  if (lua_isnil(s, -1)) {
134  return nullptr;
135  }
136  T* data = (T*) lua_touserdata(s, -1);
137  lua_pop(s, 1);
138  return data;
139 }
140 
141 static luaAI_AI* luaAI_toai(lua_State *s, int n) {
142  luaAI_AI* ai = luaAI_getudata<luaAI_AI*>(s, n, luaAI_metaai());
143  if (!ai->ai) {
144  luaL_error(s, "AI is already destroyed");
145  }
146  return ai;
147 }
148 
149 static luaAI_ICharacter* luaAI_tocharacter(lua_State *s, int n) {
150  luaAI_ICharacter* chr = luaAI_getudata<luaAI_ICharacter*>(s, n, luaAI_metacharacter());
151  if (!chr->character) {
152  luaL_error(s, "ICharacter is already destroyed");
153  }
154  return chr;
155 }
156 
157 static Zone* luaAI_tozone(lua_State *s, int n) {
158  return *(Zone**)luaAI_getudata<Zone*>(s, n, luaAI_metazone());
159 }
160 
161 static AggroMgr* luaAI_toaggromgr(lua_State *s, int n) {
162  return *(AggroMgr**)luaAI_getudata<AggroMgr*>(s, n, luaAI_metaaggromgr());
163 }
164 
165 static GroupMgr* luaAI_togroupmgr(lua_State *s, int n) {
166  return *(GroupMgr**)luaAI_getudata<GroupMgr*>(s, n, luaAI_metagroupmgr());
167 }
168 
169 static glm::vec3* luaAI_tovec(lua_State *s, int n) {
170  return luaAI_getudata<glm::vec3*>(s, n, luaAI_metavec());
171 }
172 
173 static int luaAI_pushzone(lua_State* s, Zone* zone) {
174  if (zone == nullptr) {
175  lua_pushnil(s);
176  return 1;
177  }
178  return luaAI_pushudata<Zone*>(s, zone, luaAI_metazone());
179 }
180 
181 static int luaAI_pushaggromgr(lua_State* s, AggroMgr* aggroMgr) {
182  return luaAI_pushudata<AggroMgr*>(s, aggroMgr, luaAI_metaaggromgr());
183 }
184 
185 static int luaAI_pushgroupmgr(lua_State* s, GroupMgr* groupMgr) {
186  return luaAI_pushudata<GroupMgr*>(s, groupMgr, luaAI_metagroupmgr());
187 }
188 
189 static int luaAI_pushcharacter(lua_State* s, const ICharacterPtr& character) {
190  luaAI_ICharacter* raw = (luaAI_ICharacter*) lua_newuserdata(s, sizeof(luaAI_ICharacter));
191  luaAI_ICharacter* udata = new (raw)luaAI_ICharacter();
192  udata->character = character;
193  return luaAI_assignmetatable(s, luaAI_metacharacter());
194 }
195 
196 static int luaAI_pushai(lua_State* s, const AIPtr& ai) {
197  luaAI_AI* raw = (luaAI_AI*) lua_newuserdata(s, sizeof(luaAI_AI));
198  luaAI_AI* udata = new (raw)luaAI_AI();
199  udata->ai = ai;
200  return luaAI_assignmetatable(s, luaAI_metaai());
201 }
202 
203 static int luaAI_pushvec(lua_State* s, const glm::vec3& v) {
204  return luaAI_pushudata<glm::vec3>(s, v, luaAI_metavec());
205 }
206 
207 /***
208  * Get the position of the group (average)
209  * @tparam integer groupId
210  * @treturn vec The average position of the group
211  * @function groupMgr:position
212  */
213 static int luaAI_groupmgrposition(lua_State* s) {
214  const GroupMgr* groupMgr = luaAI_togroupmgr(s, 1);
215  const GroupId groupId = (GroupId)luaL_checkinteger(s, 2);
216  return luaAI_pushvec(s, groupMgr->getPosition(groupId));
217 }
218 
219 /***
220  * Add an entity from the group
221  * @tparam integer groupId
222  * @tparam ai ai
223  * @treturn boolean Boolean to indicate whether the add was successful
224  * @function groupMgr:add
225  */
226 static int luaAI_groupmgradd(lua_State* s) {
227  GroupMgr* groupMgr = luaAI_togroupmgr(s, 1);
228  const GroupId groupId = (GroupId)luaL_checkinteger(s, 2);
229  luaAI_AI* ai = luaAI_toai(s, 3);
230  const bool state = groupMgr->add(groupId, ai->ai);
231  lua_pushboolean(s, state);
232  return 1;
233 }
234 
235 /***
236  * Remove an entity from the group
237  * @tparam integer groupId
238  * @tparam ai ai
239  * @treturn boolean Boolean to indicate whether the removal was successful
240  * @function groupMgr:remove
241  */
242 static int luaAI_groupmgrremove(lua_State* s) {
243  GroupMgr* groupMgr = luaAI_togroupmgr(s, 1);
244  const GroupId groupId = (GroupId)luaL_checkinteger(s, 2);
245  luaAI_AI* ai = luaAI_toai(s, 3);
246  const bool state = groupMgr->remove(groupId, ai->ai);
247  lua_pushboolean(s, state);
248  return 1;
249 }
250 
251 /***
252  * Checks whether a give ai is the group leader of a particular group
253  * @tparam integer groupId
254  * @tparam ai ai
255  * @treturn boolean Boolean to indicate whether the given AI is the group leader of the given group
256  * @function groupMgr:isLeader
257  */
258 static int luaAI_groupmgrisleader(lua_State* s) {
259  const GroupMgr* groupMgr = luaAI_togroupmgr(s, 1);
260  const GroupId groupId = (GroupId)luaL_checkinteger(s, 2);
261  luaAI_AI* ai = luaAI_toai(s, 3);
262  const bool state = groupMgr->isGroupLeader(groupId, ai->ai);
263  lua_pushboolean(s, state);
264  return 1;
265 }
266 
267 /***
268  * Checks whether a give ai is part of the given group
269  * @tparam integer groupId
270  * @tparam ai ai
271  * @treturn boolean Boolean to indicate whether the given AI is part of the given group
272  * @function groupMgr:isInGroup
273  */
274 static int luaAI_groupmgrisingroup(lua_State* s) {
275  const GroupMgr* groupMgr = luaAI_togroupmgr(s, 1);
276  const GroupId groupId = (GroupId)luaL_checkinteger(s, 2);
277  luaAI_AI* ai = luaAI_toai(s, 3);
278  const bool state = groupMgr->isInGroup(groupId, ai->ai);
279  lua_pushboolean(s, state);
280  return 1;
281 }
282 
283 /***
284  * Checks whether a give ai is part of any group
285  * @tparam ai ai
286  * @treturn boolean Boolean to indicate whether the given AI is part of any group
287  * @function groupMgr:isInAnyGroup
288  */
289 static int luaAI_groupmgrisinanygroup(lua_State* s) {
290  const GroupMgr* groupMgr = luaAI_togroupmgr(s, 1);
291  luaAI_AI* ai = luaAI_toai(s, 2);
292  const bool state = groupMgr->isInAnyGroup(ai->ai);
293  lua_pushboolean(s, state);
294  return 1;
295 }
296 
297 /***
298  * Get the group size
299  * @tparam integer groupId
300  * @treturn integer Size of the group (members)
301  * @function groupMgr:size
302  */
303 static int luaAI_groupmgrsize(lua_State* s) {
304  const GroupMgr* groupMgr = luaAI_togroupmgr(s, 1);
305  const GroupId groupId = (GroupId)luaL_checkinteger(s, 2);
306  lua_pushinteger(s, groupMgr->getGroupSize(groupId));
307  return 1;
308 }
309 
310 /***
311  * Get the group leader ai of a given group
312  * @tparam integer groupId
313  * @treturn ai AI of the group leader, or nil, if there is no such group
314  * @function groupMgr:leader
315  */
316 static int luaAI_groupmgrleader(lua_State* s) {
317  const GroupMgr* groupMgr = luaAI_togroupmgr(s, 1);
318  const GroupId groupId = (GroupId)luaL_checkinteger(s, 2);
319  const AIPtr& ai = groupMgr->getLeader(groupId);
320  if (!ai) {
321  lua_pushnil(s);
322  } else {
323  luaAI_pushai(s, ai);
324  }
325  return 1;
326 }
327 
328 static int luaAI_groupmgrtostring(lua_State* s) {
329  const GroupMgr* groupMgr = luaAI_togroupmgr(s, 1);
330  lua_pushfstring(s, "groupmgr: %p", groupMgr);
331  return 1;
332 }
333 
334 /***
335  * Execute a function for all entities of the zone
336  * @tparam function The function to execute
337  * @function zone:execute
338  */
339 static int luaAI_zoneexecute(lua_State* s) {
340  Zone* zone = luaAI_tozone(s, 1);
341  luaL_checktype(s, 2, LUA_TFUNCTION);
342  const int topIndex = lua_gettop(s);
343  zone->execute([=] (const AIPtr& ai) {
344  if (luaAI_pushai(s, ai) <= 0) {
345  return;
346  }
347  lua_pcall(s, 1, 0, 0);
348  const int stackDelta = lua_gettop(s) - topIndex;
349  if (stackDelta > 0) {
350  lua_pop(s, stackDelta);
351  }
352  });
353  return 0;
354 }
355 
356 /***
357  * Get the group manager of the zone
358  * @treturn groupMgr The groupMgr of the zone
359  * @function zone:groupMgr
360  */
361 static int luaAI_zonegroupmgr(lua_State* s) {
362  Zone* zone = luaAI_tozone(s, 1);
363  return luaAI_pushgroupmgr(s, &zone->getGroupMgr());
364 }
365 
366 static int luaAI_zonetostring(lua_State* s) {
367  const Zone* zone = luaAI_tozone(s, 1);
368  lua_pushfstring(s, "zone: %s", zone->getName().c_str());
369  return 1;
370 }
371 
372 /***
373  * Get the name of the zone
374  * @treturn string The name of the zone
375  * @function zone:name
376  */
377 static int luaAI_zonename(lua_State* s) {
378  const Zone* zone = luaAI_tozone(s, 1);
379  lua_pushstring(s, zone->getName().c_str());
380  return 1;
381 }
382 
383 /***
384  * Get the ai instance for some character id in the zone
385  * @tparam integer id The character id to get the AI for
386  * @treturn ai AI instance for some character id in the zone, or nil if no such character
387  * was found in the zone
388  * @function zone:ai
389  */
390 static int luaAI_zoneai(lua_State* s) {
391  Zone* zone = luaAI_tozone(s, 1);
392  const CharacterId id = (CharacterId)luaL_checkinteger(s, 2);
393  const AIPtr& ai = zone->getAI(id);
394  if (!ai) {
395  lua_pushnil(s);
396  } else {
397  luaAI_pushai(s, ai);
398  }
399  return 1;
400 }
401 
402 /***
403  * Get the size of the zone - as in: How many entities are in that particular zone
404  * @treturn integer The amount of entities in the zone
405  * @function zone:size
406  */
407 static int luaAI_zonesize(lua_State* s) {
408  const Zone* zone = luaAI_tozone(s, 1);
409  lua_pushinteger(s, zone->size());
410  return 1;
411 }
412 
413 /***
414  * Get the highest aggro entry
415  * @treturn integer The current highest aggro entry character id or nil
416  * @treturn number The current highest aggro entry value or nil.
417  * @function aggroMgr:highestEntry
418  */
419 static int luaAI_aggromgrhighestentry(lua_State* s) {
420  AggroMgr* aggroMgr = luaAI_toaggromgr(s, 1);
421  EntryPtr entry = aggroMgr->getHighestEntry();
422  if (entry == nullptr) {
423  lua_pushnil(s);
424  lua_pushnil(s);
425  } else {
426  lua_pushinteger(s, entry->getCharacterId());
427  lua_pushnumber(s, entry->getAggro());
428  }
429  return 2;
430 }
431 
432 /***
433  * Return the current aggro manager entries
434  * @treturn {integer, number, ...} Table with character id and aggro value
435  * @function aggroMgr:entries
436  */
437 static int luaAI_aggromgrentries(lua_State* s) {
438  AggroMgr* aggroMgr = luaAI_toaggromgr(s, 1);
439  const AggroMgr::Entries& entries = aggroMgr->getEntries();
440  lua_newtable(s);
441  const int top = lua_gettop(s);
442  for (auto it = entries.begin(); it != entries.end(); ++it) {
443  lua_pushinteger(s, it->getCharacterId());
444  lua_pushnumber(s, it->getAggro());
445  lua_settable(s, top);
446  }
447  return 1;
448 }
449 
450 /***
451  * Set the reduction type to a ratio-per-second style
452  * @tparam number reduceRatioSecond
453  * @tparam number minAggro
454  * @function aggroMgr:reduceByRatio
455  */
456 static int luaAI_aggromgrsetreducebyratio(lua_State* s) {
457  AggroMgr* aggroMgr = luaAI_toaggromgr(s, 1);
458  const lua_Number reduceRatioSecond = luaL_checknumber(s, 2);
459  const lua_Number minAggro = luaL_checknumber(s, 3);
460  aggroMgr->setReduceByRatio((float)reduceRatioSecond, (float)minAggro);
461  return 0;
462 }
463 
464 /***
465  * Set the reduction type to a value-by-second style
466  * @tparam number reduceValueSecond
467  * @function aggroMgr:reduceByValue
468  */
469 static int luaAI_aggromgrsetreducebyvalue(lua_State* s) {
470  AggroMgr* aggroMgr = luaAI_toaggromgr(s, 1);
471  const lua_Number reduceValueSecond = luaL_checknumber(s, 2);
472  aggroMgr->setReduceByValue((float)reduceValueSecond);
473  return 0;
474 }
475 
476 /***
477  * Reset the reduction values of the aggro manager
478  * @function aggroMgr:resetReduceValue
479  */
480 static int luaAI_aggromgrresetreducevalue(lua_State* s) {
481  AggroMgr* aggroMgr = luaAI_toaggromgr(s, 1);
482  aggroMgr->resetReduceValue();
483  return 0;
484 }
485 
486 /***
487  * Apply aggro on some other character
488  * @tparam integer id The character id to get aggro on
489  * @tparam number amount The amount of aggro to apply
490  * @treturn number The amount of aggro you have on the given entity
491  * @function aggroMgr:addAggro
492  */
493 static int luaAI_aggromgraddaggro(lua_State* s) {
494  AggroMgr* aggroMgr = luaAI_toaggromgr(s, 1);
495  const CharacterId chrId = (CharacterId)luaL_checkinteger(s, 2);
496  const lua_Number amount = luaL_checknumber(s, 3);
497  const EntryPtr& entry = aggroMgr->addAggro(chrId, (float)amount);
498  lua_pushnumber(s, entry->getAggro());
499  return 1;
500 }
501 
502 static int luaAI_aggromgrtostring(lua_State* s) {
503  lua_pushliteral(s, "aggroMgr");
504  return 1;
505 }
506 
507 /***
508  * The character id
509  * @treturn integer The id of a character
510  * @function character:id
511  */
512 static int luaAI_characterid(lua_State* s) {
513  const luaAI_ICharacter* chr = luaAI_tocharacter(s, 1);
514  lua_pushinteger(s, chr->character->getId());
515  return 1;
516 }
517 
518 /***
519  * Get the position of the character
520  * @treturn vec position of the character
521  * @function character:position
522  */
523 static int luaAI_characterposition(lua_State* s) {
524  const luaAI_ICharacter* chr = luaAI_tocharacter(s, 1);
525  return luaAI_pushvec(s, chr->character->getPosition());
526 }
527 
528 /***
529  * Set the position of the character
530  * @tparam vec position
531  * @function character:setPosition
532  */
533 static int luaAI_charactersetposition(lua_State* s) {
534  luaAI_ICharacter* chr = luaAI_tocharacter(s, 1);
535  const glm::vec3* v = luaAI_tovec(s, 2);
536  chr->character->setPosition(*v);
537  return 0;
538 }
539 
540 /***
541  * Get the speed of the character
542  * @treturn number Speed value of the character
543  * @function character:speed
544  */
545 static int luaAI_characterspeed(lua_State* s) {
546  const luaAI_ICharacter* chr = luaAI_tocharacter(s, 1);
547  lua_pushnumber(s, chr->character->getSpeed());
548  return 1;
549 }
550 
551 /***
552  * Get the orientation of the character
553  * @treturn number orientation value of the character
554  * @function character:orientation
555  */
556 static int luaAI_characterorientation(lua_State* s) {
557  const luaAI_ICharacter* chr = luaAI_tocharacter(s, 1);
558  lua_pushnumber(s, chr->character->getOrientation());
559  return 1;
560 }
561 
562 /***
563  * Set the speed for a character
564  * @tparam number speed
565  * @function character:setSpeed
566  */
567 static int luaAI_charactersetspeed(lua_State* s) {
568  luaAI_ICharacter* chr = luaAI_tocharacter(s, 1);
569  const lua_Number value = luaL_checknumber(s, 2);
570  chr->character->setSpeed((float)value);
571  return 0;
572 }
573 
574 /***
575  * Set the orientation for a character
576  * @tparam number orientation
577  * @function character:setOrientation
578  */
579 static int luaAI_charactersetorientation(lua_State* s) {
580  luaAI_ICharacter* chr = luaAI_tocharacter(s, 1);
581  const lua_Number value = luaL_checknumber(s, 2);
582  chr->character->setOrientation((float)value);
583  return 0;
584 }
585 
586 /***
587  * Equal check for a character
588  * @treturn boolean
589  * @function character:__eq
590  */
591 static int luaAI_charactereq(lua_State* s) {
592  const luaAI_ICharacter* a = luaAI_tocharacter(s, 1);
593  const luaAI_ICharacter* b = luaAI_tocharacter(s, 2);
594  const bool e = *a->character == *b->character;
595  lua_pushboolean(s, e);
596  return 1;
597 }
598 
599 /***
600  * Garbage collector callback for a character
601  * @function character:__gc
602  */
603 static int luaAI_charactergc(lua_State* s) {
604  luaAI_ICharacter* chr = luaAI_tocharacter(s, -1);
605  chr->character = ICharacterPtr();
606  return 0;
607 }
608 
609 /***
610  * Pushes the table of character (debugger) attributes onto the stack
611  * @treturn {string, string, ....} Table with the key/value pair of the character attributes
612  * @function character:attributes
613  */
614 static int luaAI_characterattributes(lua_State* s) {
615  const luaAI_ICharacter* chr = luaAI_tocharacter(s, 1);
616  const CharacterAttributes& attributes = chr->character->getAttributes();
617  lua_newtable(s);
618  const int top = lua_gettop(s);
619  for (auto it = attributes.begin(); it != attributes.end(); ++it) {
620  const std::string& key = it->first;
621  const std::string& value = it->second;
622  lua_pushlstring(s, key.c_str(), key.size());
623  lua_pushlstring(s, value.c_str(), value.size());
624  lua_settable(s, top);
625  }
626  return 1;
627 }
628 
629 /***
630  * Set a debugger attribute to the character
631  * @tparam string key The key of the attribute
632  * @tparam string value The value of the attribute
633  * @function character:setAttribute
634  */
635 static int luaAI_charactersetattribute(lua_State* s) {
636  luaAI_ICharacter* chr = luaAI_tocharacter(s, 1);
637  const char* key = luaL_checkstring(s, 2);
638  const char* value = luaL_checkstring(s, 3);
639  chr->character->setAttribute(key, value);
640  return 0;
641 }
642 
643 static int luaAI_charactertostring(lua_State* s) {
644  luaAI_ICharacter* character = luaAI_tocharacter(s, 1);
645  lua_pushfstring(s, "Character: %d", (lua_Integer)character->character->getId());
646  return 1;
647 }
648 
649 /***
650  * Get the character id
651  * @treturn integer Integer with the character id
652  * @function ai:id
653  */
654 static int luaAI_aiid(lua_State* s) {
655  const luaAI_AI* ai = luaAI_toai(s, 1);
656  lua_pushinteger(s, ai->ai->getId());
657  return 1;
658 }
659 
660 /***
661  * Get the active lifetime of the ai
662  * @treturn integer Integer with the active lifetime of the ai
663  * @function ai:time
664  */
665 static int luaAI_aitime(lua_State* s) {
666  const luaAI_AI* ai = luaAI_toai(s, 1);
667  lua_pushinteger(s, ai->ai->getTime());
668  return 1;
669 }
670 
671 /***
672  * Get the filtered entities of the ai
673  * @treturn {integer, integer, ...} A table with key/value (index, characterid) pairs of the filtered entities
674  * @function ai:filteredEntities
675  */
676 static int luaAI_aifilteredentities(lua_State* s) {
677  const luaAI_AI* ai = luaAI_toai(s, 1);
678  const FilteredEntities& filteredEntities = ai->ai->getFilteredEntities();
679  lua_newtable(s);
680  const int top = lua_gettop(s);
681  int i = 0;
682  for (auto it = filteredEntities.begin(); it != filteredEntities.end(); ++it) {
683  lua_pushinteger(s, ++i);
684  lua_pushinteger(s, *it);
685  lua_settable(s, top);
686  }
687  return 1;
688 }
689 
690 /***
691  * Get the zone of the ai
692  * @treturn zone The zone where the ai is active in or nil
693  * @function ai:zone
694  */
695 static int luaAI_aigetzone(lua_State* s) {
696  const luaAI_AI* ai = luaAI_toai(s, 1);
697  return luaAI_pushzone(s, ai->ai->getZone());
698 }
699 
700 /***
701  * Get the aggro mgr of the ai
702  * @treturn aggroMgr the aggro manager of the ai
703  * @function ai:aggroMgr
704  */
705 static int luaAI_aigetaggromgr(lua_State* s) {
706  luaAI_AI* ai = luaAI_toai(s, 1);
707  return luaAI_pushaggromgr(s, &ai->ai->getAggroMgr());
708 }
709 
710 /***
711  * Get the character of the ai
712  * @treturn character the character of the ai
713  * @function ai:character
714  */
715 static int luaAI_aigetcharacter(lua_State* s) {
716  const luaAI_AI* ai = luaAI_toai(s, 1);
717  return luaAI_pushcharacter(s, ai->ai->getCharacter());
718 }
719 
720 /***
721  * Check whether the ai has a zone
722  * @treturn boolean true if the ai has a zone, false otherwise
723  * @function ai:hasZone
724  */
725 static int luaAI_aihaszone(lua_State* s) {
726  const luaAI_AI* ai = luaAI_toai(s, 1);
727  lua_pushboolean(s, ai->ai->hasZone() ? 1 : 0);
728  return 1;
729 }
730 
731 /***
732  * Equality for two ai instances
733  * @treturn boolean true if the two given ai's are equal
734  * @function ai:__eq
735  */
736 static int luaAI_aieq(lua_State* s) {
737  const luaAI_AI* a = luaAI_toai(s, 1);
738  const luaAI_AI* b = luaAI_toai(s, 2);
739  const bool e = a->ai->getId() == b->ai->getId();
740  lua_pushboolean(s, e);
741  return 1;
742 }
743 
744 /***
745  * Garbage collector callback for ai instances
746  * @function ai:__gc
747  */
748 static int luaAI_aigc(lua_State* s) {
749  luaAI_AI* ai = luaAI_toai(s, -1);
750  ai->ai = AIPtr();
751  return 0;
752 }
753 
754 static int luaAI_aitostring(lua_State* s) {
755  const luaAI_AI* ai = luaAI_toai(s, 1);
756  TreeNodePtr treeNode = ai->ai->getBehaviour();
757  if (treeNode) {
758  lua_pushfstring(s, "ai: %s", treeNode->getName().c_str());
759  } else {
760  lua_pushstring(s, "ai: no behaviour tree set");
761  }
762  return 1;
763 }
764 
765 /***
766  * Vector addition
767  * @tparam vec a
768  * @tparam vec b
769  * @treturn vec the sum of a + b
770  * @function vec:__add
771  */
772 static int luaAI_vecadd(lua_State* s) {
773  const glm::vec3* a = luaAI_tovec(s, 1);
774  const glm::vec3* b = luaAI_tovec(s, 2);
775  const glm::vec3& c = *a + *b;
776  return luaAI_pushvec(s, c);
777 }
778 
779 /***
780  * Vector dot product also as vec:__mul
781  * @tparam vec a
782  * @tparam vec b
783  * @treturn number The dot product of a and b
784  * @function vec:dot
785  */
786 static int luaAI_vecdot(lua_State* s) {
787  const glm::vec3* a = luaAI_tovec(s, 1);
788  const glm::vec3* b = luaAI_tovec(s, 2);
789  const float c = glm::dot(*a, *b);
790  lua_pushnumber(s, c);
791  return 1;
792 }
793 
794 /***
795  * Vector div function
796  * @tparam vec a
797  * @tparam vec b
798  * @treturn vec a / b
799  * @function vec:__div
800  */
801 static int luaAI_vecdiv(lua_State* s) {
802  const glm::vec3* a = luaAI_tovec(s, 1);
803  const glm::vec3* b = luaAI_tovec(s, 2);
804  const glm::vec3& c = *a / *b;
805  luaAI_pushvec(s, c);
806  return 1;
807 }
808 
809 static int luaAI_veclen(lua_State* s) {
810  const glm::vec3* a = luaAI_tovec(s, 1);
811  const float c = glm::length(*a);
812  lua_pushnumber(s, c);
813  return 1;
814 }
815 
816 static int luaAI_veceq(lua_State* s) {
817  const glm::vec3* a = luaAI_tovec(s, 1);
818  const glm::vec3* b = luaAI_tovec(s, 2);
819  const bool e = glm::all(glm::epsilonEqual(*a, *b, 0.0001f));
820  lua_pushboolean(s, e);
821  return 1;
822 }
823 
824 /***
825  * Vector subtraction
826  * @tparam vec a
827  * @tparam vec b
828  * @treturn vec the result of a - b
829  * @function vec:__sub
830  */
831 static int luaAI_vecsub(lua_State* s) {
832  const glm::vec3* a = luaAI_tovec(s, 1);
833  const glm::vec3* b = luaAI_tovec(s, 2);
834  const glm::vec3& c = *a - *b;
835  luaAI_pushvec(s, c);
836  return 1;
837 }
838 
839 /***
840  * Negates a given vector
841  * @tparam vec a
842  * @treturn vec The result of -a
843  * @function vec:__unm
844  */
845 static int luaAI_vecnegate(lua_State* s) {
846  const glm::vec3* a = luaAI_tovec(s, 1);
847  luaAI_pushvec(s, -(*a));
848  return 1;
849 }
850 
851 static int luaAI_vectostring(lua_State* s) {
852  const glm::vec3* a = luaAI_tovec(s, 1);
853  lua_pushfstring(s, "vec: %f:%f:%f", a->x, a->y, a->z);
854  return 1;
855 }
856 
857 static int luaAI_vecindex(lua_State *s) {
858  const glm::vec3* v = luaAI_tovec(s, 1);
859  const char* i = luaL_checkstring(s, 2);
860 
861  switch (*i) {
862  case '0':
863  case 'x':
864  case 'r':
865  lua_pushnumber(s, v->x);
866  break;
867  case '1':
868  case 'y':
869  case 'g':
870  lua_pushnumber(s, v->y);
871  break;
872  case '2':
873  case 'z':
874  case 'b':
875  lua_pushnumber(s, v->z);
876  break;
877  default:
878  lua_pushnil(s);
879  break;
880  }
881 
882  return 1;
883 }
884 
885 static int luaAI_vecnewindex(lua_State *s) {
886  glm::vec3* v = luaAI_tovec(s, 1);
887  const char *i = luaL_checkstring(s, 2);
888  const lua_Number t = luaL_checknumber(s, 3);
889 
890  switch (*i) {
891  case '0':
892  case 'x':
893  case 'r':
894  v->x = (float)t;
895  break;
896  case '1':
897  case 'y':
898  case 'g':
899  v->y = (float)t;
900  break;
901  case '2':
902  case 'z':
903  case 'b':
904  v->z = (float)t;
905  break;
906  default:
907  break;
908  }
909 
910  return 1;
911 }
912 
913 }
Definition: LUAFunctions.h:11
#define ai_log_error(...)
Logging macro to provide your own loggers.
Definition: Types.h:23
Definition: LUAFunctions.h:15