luascript.cpp

main 16069 lines · 648.1 KB Raw
Alex Alex Commit Server upload 18/10/2026 23:38
1/**
2 * The Forgotten Server - a free and open-source MMORPG server emulator
3 * Copyright (C) 2019 Mark Samman <mark.samman@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#include "enums.h"
21#include "otpch.h"
22
23#include <boost/range/adaptor/reversed.hpp>
24
25#include "bed.h"
26#include "chat.h"
27#include "configmanager.h"
28#include "databasemanager.h"
29#include "databasetasks.h"
30#include "events.h"
31#include "game.h"
32#include "globalevent.h"
33#include "iologindata.h"
34#include "luascript.h"
35#include "monster.h"
36#include "movement.h"
37#include "player.h"
38#include "protocolstatus.h"
39#include "scheduler.h"
40#include "script.h"
41#include "spells.h"
42#include "teleport.h"
43#include "weapons.h"
44
45extern Chat *g_chat;
46extern Game g_game;
47extern Monsters g_monsters;
48extern ConfigManager g_config;
49extern Vocations g_vocations;
50extern Spells *g_spells;
51extern Events *g_events;
52extern Actions *g_actions;
53extern TalkActions *g_talkActions;
54extern CreatureEvents *g_creatureEvents;
55extern MoveEvents *g_moveEvents;
56extern GlobalEvents *g_globalEvents;
57extern Scripts *g_scripts;
58extern Weapons *g_weapons;
59
60ScriptEnvironment::DBResultMap ScriptEnvironment::tempResults;
61uint32_t ScriptEnvironment::lastResultId = 0;
62
63std::multimap<ScriptEnvironment *, Item *> ScriptEnvironment::tempItems;
64
65LuaEnvironment g_luaEnvironment;
66
67ScriptEnvironment::ScriptEnvironment() { resetEnv(); }
68
69ScriptEnvironment::~ScriptEnvironment() { resetEnv(); }
70
71void ScriptEnvironment::resetEnv() {
72 scriptId = 0;
73 callbackId = 0;
74 timerEvent = false;
75 interface = nullptr;
76 localMap.clear();
77 tempResults.clear();
78
79 auto pair = tempItems.equal_range(this);
80 auto it = pair.first;
81 while (it != pair.second) {
82 Item *item = it->second;
83 if (item->getParent() == VirtualCylinder::virtualCylinder) {
84 g_game.ReleaseItem(item);
85 }
86 it = tempItems.erase(it);
87 }
88}
89
90bool ScriptEnvironment::setCallbackId(int32_t callbackId,
91 LuaScriptInterface *scriptInterface) {
92 if (this->callbackId != 0) {
93 // nested callbacks are not allowed
94 if (interface) {
95 interface->reportErrorFunc("Nested callbacks!");
96 }
97 return false;
98 }
99
100 this->callbackId = callbackId;
101 interface = scriptInterface;
102 return true;
103}
104
105void ScriptEnvironment::getEventInfo(int32_t &scriptId,
106 LuaScriptInterface *&scriptInterface,
107 int32_t &callbackId,
108 bool &timerEvent) const {
109 scriptId = this->scriptId;
110 scriptInterface = interface;
111 callbackId = this->callbackId;
112 timerEvent = this->timerEvent;
113}
114
115uint32_t ScriptEnvironment::addThing(Thing *thing) {
116 if (!thing || thing->isRemoved()) {
117 return 0;
118 }
119
120 Creature *creature = thing->getCreature();
121 if (creature) {
122 return creature->getID();
123 }
124
125 Item *item = thing->getItem();
126 if (item && item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) {
127 return item->getUniqueId();
128 }
129
130 for (const auto &it : localMap) {
131 if (it.second == item) {
132 return it.first;
133 }
134 }
135
136 localMap[++lastUID] = item;
137 return lastUID;
138}
139
140void ScriptEnvironment::insertItem(uint32_t uid, Item *item) {
141 auto result = localMap.emplace(uid, item);
142 if (!result.second) {
143 std::cout << std::endl << "Lua Script Error: Thing uid already taken.";
144 }
145}
146
147Thing *ScriptEnvironment::getThingByUID(uint32_t uid) {
148 if (uid >= 0x10000000) {
149 return g_game.getCreatureByID(uid);
150 }
151
152 if (uid <= std::numeric_limits<uint16_t>::max()) {
153 Item *item = g_game.getUniqueItem(uid);
154 if (item && !item->isRemoved()) {
155 return item;
156 }
157 return nullptr;
158 }
159
160 auto it = localMap.find(uid);
161 if (it != localMap.end()) {
162 Item *item = it->second;
163 if (!item->isRemoved()) {
164 return item;
165 }
166 }
167 return nullptr;
168}
169
170Item *ScriptEnvironment::getItemByUID(uint32_t uid) {
171 Thing *thing = getThingByUID(uid);
172 if (!thing) {
173 return nullptr;
174 }
175 return thing->getItem();
176}
177
178Container *ScriptEnvironment::getContainerByUID(uint32_t uid) {
179 Item *item = getItemByUID(uid);
180 if (!item) {
181 return nullptr;
182 }
183 return item->getContainer();
184}
185
186void ScriptEnvironment::removeItemByUID(uint32_t uid) {
187 if (uid <= std::numeric_limits<uint16_t>::max()) {
188 g_game.removeUniqueItem(uid);
189 return;
190 }
191
192 auto it = localMap.find(uid);
193 if (it != localMap.end()) {
194 localMap.erase(it);
195 }
196}
197
198void ScriptEnvironment::addTempItem(Item *item) {
199 tempItems.emplace(this, item);
200}
201
202void ScriptEnvironment::removeTempItem(Item *item) {
203 for (auto it = tempItems.begin(), end = tempItems.end(); it != end; ++it) {
204 if (it->second == item) {
205 tempItems.erase(it);
206 break;
207 }
208 }
209}
210
211uint32_t ScriptEnvironment::addResult(DBResult_ptr res) {
212 tempResults[++lastResultId] = res;
213 return lastResultId;
214}
215
216bool ScriptEnvironment::removeResult(uint32_t id) {
217 auto it = tempResults.find(id);
218 if (it == tempResults.end()) {
219 return false;
220 }
221
222 tempResults.erase(it);
223 return true;
224}
225
226DBResult_ptr ScriptEnvironment::getResultByID(uint32_t id) {
227 auto it = tempResults.find(id);
228 if (it == tempResults.end()) {
229 return nullptr;
230 }
231 return it->second;
232}
233
234std::string LuaScriptInterface::getErrorDesc(ErrorCode_t code) {
235 switch (code) {
236 case LUA_ERROR_PLAYER_NOT_FOUND:
237 return "Player not found";
238 case LUA_ERROR_CREATURE_NOT_FOUND:
239 return "Creature not found";
240 case LUA_ERROR_ITEM_NOT_FOUND:
241 return "Item not found";
242 case LUA_ERROR_THING_NOT_FOUND:
243 return "Thing not found";
244 case LUA_ERROR_TILE_NOT_FOUND:
245 return "Tile not found";
246 case LUA_ERROR_HOUSE_NOT_FOUND:
247 return "House not found";
248 case LUA_ERROR_COMBAT_NOT_FOUND:
249 return "Combat not found";
250 case LUA_ERROR_CONDITION_NOT_FOUND:
251 return "Condition not found";
252 case LUA_ERROR_AREA_NOT_FOUND:
253 return "Area not found";
254 case LUA_ERROR_CONTAINER_NOT_FOUND:
255 return "Container not found";
256 case LUA_ERROR_VARIANT_NOT_FOUND:
257 return "Variant not found";
258 case LUA_ERROR_VARIANT_UNKNOWN:
259 return "Unknown variant type";
260 case LUA_ERROR_SPELL_NOT_FOUND:
261 return "Spell not found";
262 default:
263 return "Bad error code";
264 }
265}
266
267ScriptEnvironment LuaScriptInterface::scriptEnv[16];
268int32_t LuaScriptInterface::scriptEnvIndex = -1;
269
270LuaScriptInterface::LuaScriptInterface(std::string interfaceName)
271 : interfaceName(std::move(interfaceName)) {
272 if (!g_luaEnvironment.getLuaState()) {
273 g_luaEnvironment.initState();
274 }
275}
276
277LuaScriptInterface::~LuaScriptInterface() { closeState(); }
278
279bool LuaScriptInterface::reInitState() {
280 g_luaEnvironment.clearCombatObjects(this);
281 g_luaEnvironment.clearAreaObjects(this);
282
283 closeState();
284 return initState();
285}
286
287/// Same as lua_pcall, but adds stack trace to error strings in called function.
288int LuaScriptInterface::protectedCall(lua_State *L, int nargs, int nresults) {
289 int error_index = lua_gettop(L) - nargs;
290 lua_pushcfunction(L, luaErrorHandler);
291 lua_insert(L, error_index);
292
293 int ret = lua_pcall(L, nargs, nresults, error_index);
294 lua_remove(L, error_index);
295 return ret;
296}
297
298int32_t LuaScriptInterface::loadFile(const std::string &file,
299 Npc *npc /* = nullptr*/) {
300 // loads file as a chunk at stack top
301 int ret = luaL_loadfile(luaState, file.c_str());
302 if (ret != 0) {
303 lastLuaError = popString(luaState);
304 return -1;
305 }
306
307 // check that it is loaded as a function
308 if (!isFunction(luaState, -1)) {
309 return -1;
310 }
311
312 loadingFile = file;
313
314 if (!reserveScriptEnv()) {
315 return -1;
316 }
317
318 ScriptEnvironment *env = getScriptEnv();
319 env->setScriptId(EVENT_ID_LOADING, this);
320 env->setNpc(npc);
321
322 // execute it
323 ret = protectedCall(luaState, 0, 0);
324 if (ret != 0) {
325 reportError(nullptr, popString(luaState));
326 resetScriptEnv();
327 return -1;
328 }
329
330 resetScriptEnv();
331 return 0;
332}
333
334int32_t LuaScriptInterface::getEvent(const std::string &eventName) {
335 // get our events table
336 lua_rawgeti(luaState, LUA_REGISTRYINDEX, eventTableRef);
337 if (!isTable(luaState, -1)) {
338 lua_pop(luaState, 1);
339 return -1;
340 }
341
342 // get current event function pointer
343 lua_getglobal(luaState, eventName.c_str());
344 if (!isFunction(luaState, -1)) {
345 lua_pop(luaState, 2);
346 return -1;
347 }
348
349 // save in our events table
350 lua_pushvalue(luaState, -1);
351 lua_rawseti(luaState, -3, runningEventId);
352 lua_pop(luaState, 2);
353
354 // reset global value of this event
355 lua_pushnil(luaState);
356 lua_setglobal(luaState, eventName.c_str());
357
358 cacheFiles[runningEventId] = loadingFile + ":" + eventName;
359 return runningEventId++;
360}
361
362int32_t LuaScriptInterface::getEvent() {
363 // check if function is on the stack
364 if (!isFunction(luaState, -1)) {
365 return -1;
366 }
367
368 // get our events table
369 lua_rawgeti(luaState, LUA_REGISTRYINDEX, eventTableRef);
370 if (!isTable(luaState, -1)) {
371 lua_pop(luaState, 1);
372 return -1;
373 }
374
375 // save in our events table
376 lua_pushvalue(luaState, -2);
377 lua_rawseti(luaState, -2, runningEventId);
378 lua_pop(luaState, 2);
379
380 cacheFiles[runningEventId] = loadingFile + ":callback";
381 return runningEventId++;
382}
383
384int32_t LuaScriptInterface::getMetaEvent(const std::string &globalName,
385 const std::string &eventName) {
386 // get our events table
387 lua_rawgeti(luaState, LUA_REGISTRYINDEX, eventTableRef);
388 if (!isTable(luaState, -1)) {
389 lua_pop(luaState, 1);
390 return -1;
391 }
392
393 // get current event function pointer
394 lua_getglobal(luaState, globalName.c_str());
395 lua_getfield(luaState, -1, eventName.c_str());
396 if (!isFunction(luaState, -1)) {
397 lua_pop(luaState, 3);
398 return -1;
399 }
400
401 // save in our events table
402 lua_pushvalue(luaState, -1);
403 lua_rawseti(luaState, -4, runningEventId);
404 lua_pop(luaState, 1);
405
406 // reset global value of this event
407 lua_pushnil(luaState);
408 lua_setfield(luaState, -2, eventName.c_str());
409 lua_pop(luaState, 2);
410
411 cacheFiles[runningEventId] = loadingFile + ":" + globalName + "@" + eventName;
412 return runningEventId++;
413}
414
415const std::string &LuaScriptInterface::getFileById(int32_t scriptId) {
416 if (scriptId == EVENT_ID_LOADING) {
417 return loadingFile;
418 }
419
420 auto it = cacheFiles.find(scriptId);
421 if (it == cacheFiles.end()) {
422 static const std::string &unk = "(Unknown scriptfile)";
423 return unk;
424 }
425 return it->second;
426}
427
428std::string LuaScriptInterface::getStackTrace(const std::string &error_desc) {
429 lua_getglobal(luaState, "debug");
430 if (!isTable(luaState, -1)) {
431 lua_pop(luaState, 1);
432 return error_desc;
433 }
434
435 lua_getfield(luaState, -1, "traceback");
436 if (!isFunction(luaState, -1)) {
437 lua_pop(luaState, 2);
438 return error_desc;
439 }
440
441 lua_replace(luaState, -2);
442 pushString(luaState, error_desc);
443 lua_call(luaState, 1, 1);
444 return popString(luaState);
445}
446
447void LuaScriptInterface::reportError(const char *function,
448 const std::string &error_desc,
449 bool stack_trace /* = false*/) {
450 int32_t scriptId;
451 int32_t callbackId;
452 bool timerEvent;
453 LuaScriptInterface *scriptInterface;
454 getScriptEnv()->getEventInfo(scriptId, scriptInterface, callbackId,
455 timerEvent);
456
457 std::cout << std::endl << "Lua Script Error: ";
458
459 if (scriptInterface) {
460 std::cout << '[' << scriptInterface->getInterfaceName() << "] "
461 << std::endl;
462
463 if (timerEvent) {
464 std::cout << "in a timer event called from: " << std::endl;
465 }
466
467 if (callbackId) {
468 std::cout << "in callback: " << scriptInterface->getFileById(callbackId)
469 << std::endl;
470 }
471
472 std::cout << scriptInterface->getFileById(scriptId) << std::endl;
473 }
474
475 if (function) {
476 std::cout << function << "(). ";
477 }
478
479 if (stack_trace && scriptInterface) {
480 std::cout << scriptInterface->getStackTrace(error_desc) << std::endl;
481 } else {
482 std::cout << error_desc << std::endl;
483 }
484}
485
486bool LuaScriptInterface::pushFunction(int32_t functionId) {
487 lua_rawgeti(luaState, LUA_REGISTRYINDEX, eventTableRef);
488 if (!isTable(luaState, -1)) {
489 return false;
490 }
491
492 lua_rawgeti(luaState, -1, functionId);
493 lua_replace(luaState, -2);
494 return isFunction(luaState, -1);
495}
496
497bool LuaScriptInterface::initState() {
498 luaState = g_luaEnvironment.getLuaState();
499 if (!luaState) {
500 return false;
501 }
502
503 lua_newtable(luaState);
504 eventTableRef = luaL_ref(luaState, LUA_REGISTRYINDEX);
505 runningEventId = EVENT_ID_USER;
506 return true;
507}
508
509bool LuaScriptInterface::closeState() {
510 if (!g_luaEnvironment.getLuaState() || !luaState) {
511 return false;
512 }
513
514 cacheFiles.clear();
515 if (eventTableRef != -1) {
516 luaL_unref(luaState, LUA_REGISTRYINDEX, eventTableRef);
517 eventTableRef = -1;
518 }
519
520 luaState = nullptr;
521 return true;
522}
523
524int LuaScriptInterface::luaErrorHandler(lua_State *L) {
525 const std::string &errorMessage = popString(L);
526 auto interface = getScriptEnv()->getScriptInterface();
527 assert(interface); // This fires if the ScriptEnvironment hasn't been setup
528 pushString(L, interface->getStackTrace(errorMessage));
529 return 1;
530}
531
532bool LuaScriptInterface::callFunction(int params) {
533 bool result = false;
534 int size = lua_gettop(luaState);
535 if (protectedCall(luaState, params, 1) != 0) {
536 LuaScriptInterface::reportError(
537 nullptr, LuaScriptInterface::getString(luaState, -1));
538 } else {
539 result = LuaScriptInterface::getBoolean(luaState, -1);
540 }
541
542 lua_pop(luaState, 1);
543 if ((lua_gettop(luaState) + params + 1) != size) {
544 LuaScriptInterface::reportError(nullptr, "Stack size changed!");
545 }
546
547 resetScriptEnv();
548 return result;
549}
550
551void LuaScriptInterface::callVoidFunction(int params) {
552 int size = lua_gettop(luaState);
553 if (protectedCall(luaState, params, 0) != 0) {
554 LuaScriptInterface::reportError(nullptr,
555 LuaScriptInterface::popString(luaState));
556 }
557
558 if ((lua_gettop(luaState) + params + 1) != size) {
559 LuaScriptInterface::reportError(nullptr, "Stack size changed!");
560 }
561
562 resetScriptEnv();
563}
564
565void LuaScriptInterface::pushVariant(lua_State *L, const LuaVariant &var) {
566 lua_createtable(L, 0, 2);
567 setField(L, "type", var.type);
568 switch (var.type) {
569 case VARIANT_NUMBER:
570 setField(L, "number", var.number);
571 break;
572 case VARIANT_STRING:
573 setField(L, "string", var.text);
574 break;
575 case VARIANT_TARGETPOSITION:
576 case VARIANT_POSITION: {
577 pushPosition(L, var.pos);
578 lua_setfield(L, -2, "pos");
579 break;
580 }
581 default:
582 break;
583 }
584 setMetatable(L, -1, "Variant");
585}
586
587void LuaScriptInterface::pushThing(lua_State *L, Thing *thing) {
588 if (!thing) {
589 lua_createtable(L, 0, 4);
590 setField(L, "uid", 0);
591 setField(L, "itemid", 0);
592 setField(L, "actionid", 0);
593 setField(L, "type", 0);
594 return;
595 }
596
597 if (Item *item = thing->getItem()) {
598 pushUserdata<Item>(L, item);
599 setItemMetatable(L, -1, item);
600 } else if (Creature *creature = thing->getCreature()) {
601 pushUserdata<Creature>(L, creature);
602 setCreatureMetatable(L, -1, creature);
603 } else {
604 lua_pushnil(L);
605 }
606}
607
608void LuaScriptInterface::pushCylinder(lua_State *L, Cylinder *cylinder) {
609 if (Creature *creature = cylinder->getCreature()) {
610 pushUserdata<Creature>(L, creature);
611 setCreatureMetatable(L, -1, creature);
612 } else if (Item *parentItem = cylinder->getItem()) {
613 pushUserdata<Item>(L, parentItem);
614 setItemMetatable(L, -1, parentItem);
615 } else if (Tile *tile = cylinder->getTile()) {
616 pushUserdata<Tile>(L, tile);
617 setMetatable(L, -1, "Tile");
618 } else if (cylinder == VirtualCylinder::virtualCylinder) {
619 pushBoolean(L, true);
620 } else {
621 lua_pushnil(L);
622 }
623}
624
625void LuaScriptInterface::pushString(lua_State *L, const std::string &value) {
626 lua_pushlstring(L, value.c_str(), value.length());
627}
628
629void LuaScriptInterface::pushCallback(lua_State *L, int32_t callback) {
630 lua_rawgeti(L, LUA_REGISTRYINDEX, callback);
631}
632
633std::string LuaScriptInterface::popString(lua_State *L) {
634 if (lua_gettop(L) == 0) {
635 return std::string();
636 }
637
638 std::string str(getString(L, -1));
639 lua_pop(L, 1);
640 return str;
641}
642
643int32_t LuaScriptInterface::popCallback(lua_State *L) {
644 return luaL_ref(L, LUA_REGISTRYINDEX);
645}
646
647// Metatables
648void LuaScriptInterface::setMetatable(lua_State *L, int32_t index,
649 const std::string &name) {
650 luaL_getmetatable(L, name.c_str());
651 lua_setmetatable(L, index - 1);
652}
653
654void LuaScriptInterface::setWeakMetatable(lua_State *L, int32_t index,
655 const std::string &name) {
656 static std::set<std::string> weakObjectTypes;
657 const std::string &weakName = name + "_weak";
658
659 auto result = weakObjectTypes.emplace(name);
660 if (result.second) {
661 luaL_getmetatable(L, name.c_str());
662 int childMetatable = lua_gettop(L);
663
664 luaL_newmetatable(L, weakName.c_str());
665 int metatable = lua_gettop(L);
666
667 static const std::vector<std::string> methodKeys = {"__index",
668 "__metatable", "__eq"};
669 for (const std::string &metaKey : methodKeys) {
670 lua_getfield(L, childMetatable, metaKey.c_str());
671 lua_setfield(L, metatable, metaKey.c_str());
672 }
673
674 static const std::vector<int> methodIndexes = {'h', 'p', 't'};
675 for (int metaIndex : methodIndexes) {
676 lua_rawgeti(L, childMetatable, metaIndex);
677 lua_rawseti(L, metatable, metaIndex);
678 }
679
680 lua_pushnil(L);
681 lua_setfield(L, metatable, "__gc");
682
683 lua_remove(L, childMetatable);
684 } else {
685 luaL_getmetatable(L, weakName.c_str());
686 }
687 lua_setmetatable(L, index - 1);
688}
689
690void LuaScriptInterface::setItemMetatable(lua_State *L, int32_t index,
691 const Item *item) {
692 if (item->getContainer()) {
693 luaL_getmetatable(L, "Container");
694 } else if (item->getTeleport()) {
695 luaL_getmetatable(L, "Teleport");
696 } else {
697 luaL_getmetatable(L, "Item");
698 }
699 lua_setmetatable(L, index - 1);
700}
701
702void LuaScriptInterface::setCreatureMetatable(lua_State *L, int32_t index,
703 const Creature *creature) {
704 if (creature->getPlayer()) {
705 luaL_getmetatable(L, "Player");
706 } else if (creature->getMonster()) {
707 luaL_getmetatable(L, "Monster");
708 } else {
709 luaL_getmetatable(L, "Npc");
710 }
711 lua_setmetatable(L, index - 1);
712}
713
714// Get
715std::string LuaScriptInterface::getString(lua_State *L, int32_t arg) {
716 size_t len;
717 const char *c_str = lua_tolstring(L, arg, &len);
718 if (!c_str || len == 0) {
719 return std::string();
720 }
721 return std::string(c_str, len);
722}
723
724Position LuaScriptInterface::getPosition(lua_State *L, int32_t arg,
725 int32_t &stackpos) {
726 Position position;
727 position.x = getField<uint16_t>(L, arg, "x");
728 position.y = getField<uint16_t>(L, arg, "y");
729 position.z = getField<uint8_t>(L, arg, "z");
730
731 lua_getfield(L, arg, "stackpos");
732 if (lua_isnil(L, -1) == 1) {
733 stackpos = 0;
734 } else {
735 stackpos = getNumber<int32_t>(L, -1);
736 }
737
738 lua_pop(L, 4);
739 return position;
740}
741
742Position LuaScriptInterface::getPosition(lua_State *L, int32_t arg) {
743 Position position;
744 position.x = getField<uint16_t>(L, arg, "x");
745 position.y = getField<uint16_t>(L, arg, "y");
746 position.z = getField<uint8_t>(L, arg, "z");
747
748 lua_pop(L, 3);
749 return position;
750}
751
752Outfit_t LuaScriptInterface::getOutfit(lua_State *L, int32_t arg) {
753 Outfit_t outfit;
754 outfit.lookMount = getField<uint16_t>(L, arg, "lookMount");
755 outfit.lookWings = getField<uint16_t>(L, arg, "lookWings");
756 outfit.lookAura = getField<uint16_t>(L, arg, "lookAura");
757 outfit.lookAddons = getField<uint8_t>(L, arg, "lookAddons");
758
759 outfit.lookFeet = getField<uint8_t>(L, arg, "lookFeet");
760 outfit.lookLegs = getField<uint8_t>(L, arg, "lookLegs");
761 outfit.lookBody = getField<uint8_t>(L, arg, "lookBody");
762 outfit.lookHead = getField<uint8_t>(L, arg, "lookHead");
763
764 outfit.lookTypeEx = getField<uint16_t>(L, arg, "lookTypeEx");
765 outfit.lookType = getField<uint16_t>(L, arg, "lookType");
766
767 outfit.lookShader = getField<uint16_t>(L, arg, "lookShader");
768 outfit.lookWings = getField<uint16_t>(L, arg, "lookWings");
769 outfit.lookAura = getField<uint16_t>(L, arg, "lookAura");
770
771 lua_pop(L, 8);
772 return outfit;
773}
774
775LuaVariant LuaScriptInterface::getVariant(lua_State *L, int32_t arg) {
776 LuaVariant var;
777 switch (var.type = getField<LuaVariantType_t>(L, arg, "type")) {
778 case VARIANT_NUMBER: {
779 var.number = getField<uint32_t>(L, arg, "number");
780 lua_pop(L, 2);
781 break;
782 }
783
784 case VARIANT_STRING: {
785 var.text = getFieldString(L, arg, "string");
786 lua_pop(L, 2);
787 break;
788 }
789
790 case VARIANT_POSITION:
791 case VARIANT_TARGETPOSITION: {
792 lua_getfield(L, arg, "pos");
793 var.pos = getPosition(L, lua_gettop(L));
794 lua_pop(L, 2);
795 break;
796 }
797
798 default: {
799 var.type = VARIANT_NONE;
800 lua_pop(L, 1);
801 break;
802 }
803 }
804 return var;
805}
806
807InstantSpell *LuaScriptInterface::getInstantSpell(lua_State *L, int32_t arg) {
808 InstantSpell *spell =
809 g_spells->getInstantSpellByName(getFieldString(L, arg, "name"));
810 lua_pop(L, 1);
811 return spell;
812}
813
814Thing *LuaScriptInterface::getThing(lua_State *L, int32_t arg) {
815 Thing *thing;
816 if (lua_getmetatable(L, arg) != 0) {
817 lua_rawgeti(L, -1, 't');
818 switch (getNumber<uint32_t>(L, -1)) {
819 case LuaData_Item:
820 thing = getUserdata<Item>(L, arg);
821 break;
822 case LuaData_Container:
823 thing = getUserdata<Container>(L, arg);
824 break;
825 case LuaData_Teleport:
826 thing = getUserdata<Teleport>(L, arg);
827 break;
828 case LuaData_Player:
829 thing = getUserdata<Player>(L, arg);
830 break;
831 case LuaData_Monster:
832 thing = getUserdata<Monster>(L, arg);
833 break;
834 case LuaData_Npc:
835 thing = getUserdata<Npc>(L, arg);
836 break;
837 default:
838 thing = nullptr;
839 break;
840 }
841 lua_pop(L, 2);
842 } else {
843 thing = getScriptEnv()->getThingByUID(getNumber<uint32_t>(L, arg));
844 }
845 return thing;
846}
847
848Creature *LuaScriptInterface::getCreature(lua_State *L, int32_t arg) {
849 if (isUserdata(L, arg)) {
850 return getUserdata<Creature>(L, arg);
851 }
852 return g_game.getCreatureByID(getNumber<uint32_t>(L, arg));
853}
854
855Player *LuaScriptInterface::getPlayer(lua_State *L, int32_t arg) {
856 if (isUserdata(L, arg)) {
857 return getUserdata<Player>(L, arg);
858 }
859 return g_game.getPlayerByID(getNumber<uint32_t>(L, arg));
860}
861
862std::string LuaScriptInterface::getFieldString(lua_State *L, int32_t arg,
863 const std::string &key) {
864 lua_getfield(L, arg, key.c_str());
865 return getString(L, -1);
866}
867
868LuaDataType LuaScriptInterface::getUserdataType(lua_State *L, int32_t arg) {
869 if (lua_getmetatable(L, arg) == 0) {
870 return LuaData_Unknown;
871 }
872 lua_rawgeti(L, -1, 't');
873
874 LuaDataType type = getNumber<LuaDataType>(L, -1);
875 lua_pop(L, 2);
876
877 return type;
878}
879
880// Push
881void LuaScriptInterface::pushBoolean(lua_State *L, bool value) {
882 lua_pushboolean(L, value ? 1 : 0);
883}
884
885void LuaScriptInterface::pushCombatDamage(lua_State *L,
886 const CombatDamage &damage) {
887 lua_pushnumber(L, damage.primary.value);
888 lua_pushnumber(L, damage.primary.type);
889 lua_pushnumber(L, damage.secondary.value);
890 lua_pushnumber(L, damage.secondary.type);
891 lua_pushnumber(L, damage.origin);
892}
893
894void LuaScriptInterface::pushInstantSpell(lua_State *L,
895 const InstantSpell &spell) {
896 lua_createtable(L, 0, 6);
897
898 setField(L, "name", spell.getName());
899 setField(L, "words", spell.getWords());
900 setField(L, "level", spell.getLevel());
901 setField(L, "mlevel", spell.getMagicLevel());
902 setField(L, "mana", spell.getMana());
903 setField(L, "manapercent", spell.getManaPercent());
904
905 setMetatable(L, -1, "Spell");
906}
907
908void LuaScriptInterface::pushPosition(lua_State *L, const Position &position,
909 int32_t stackpos /* = 0*/) {
910 lua_createtable(L, 0, 4);
911
912 setField(L, "x", position.x);
913 setField(L, "y", position.y);
914 setField(L, "z", position.z);
915 setField(L, "stackpos", stackpos);
916
917 setMetatable(L, -1, "Position");
918}
919
920void LuaScriptInterface::pushOutfit(lua_State *L, const Outfit_t &outfit) {
921 lua_createtable(L, 0, 12);
922 setField(L, "lookType", outfit.lookType);
923 setField(L, "lookTypeEx", outfit.lookTypeEx);
924 setField(L, "lookHead", outfit.lookHead);
925 setField(L, "lookBody", outfit.lookBody);
926 setField(L, "lookLegs", outfit.lookLegs);
927 setField(L, "lookFeet", outfit.lookFeet);
928 setField(L, "lookAddons", outfit.lookAddons);
929 setField(L, "lookMount", outfit.lookMount);
930 setField(L, "lookWings", outfit.lookWings);
931 setField(L, "lookAura", outfit.lookAura);
932 setField(L, "lookShader", outfit.lookShader);
933 setField(L, "lookRuneEffect", outfit.lookRuneEffect);
934}
935
936void LuaScriptInterface::pushLoot(lua_State *L,
937 const std::vector<LootBlock> &lootList) {
938 lua_createtable(L, lootList.size(), 0);
939
940 int index = 0;
941 for (const auto &lootBlock : lootList) {
942 lua_createtable(L, 0, 7);
943
944 setField(L, "itemId", lootBlock.id);
945 setField(L, "chance", lootBlock.chance);
946 setField(L, "subType", lootBlock.subType);
947 setField(L, "maxCount", lootBlock.countmax);
948 setField(L, "actionId", lootBlock.actionId);
949 setField(L, "text", lootBlock.text);
950
951 pushLoot(L, lootBlock.childLoot);
952 lua_setfield(L, -2, "childLoot");
953
954 lua_rawseti(L, -2, ++index);
955 }
956}
957
958#define registerEnum(value) \
959 { \
960 std::string enumName = #value; \
961 registerGlobalVariable(enumName.substr(enumName.find_last_of(':') + 1), \
962 value); \
963 }
964#define registerEnumIn(tableName, value) \
965 { \
966 std::string enumName = #value; \
967 registerVariable(tableName, \
968 enumName.substr(enumName.find_last_of(':') + 1), value); \
969 }
970
971void LuaScriptInterface::registerFunctions() {
972 // doPlayerAddItem(uid, itemid, <optional: default: 1> count/subtype)
973 // doPlayerAddItem(cid, itemid, <optional: default: 1> count, <optional:
974 // default: 1> canDropOnMap, <optional: default: 1>subtype) Returns uid of the
975 // created item
976 lua_register(luaState, "doPlayerAddItem",
977 LuaScriptInterface::luaDoPlayerAddItem);
978
979 // doSetCreatureLight(cid, lightLevel, lightColor, time)
980 lua_register(luaState, "doSetCreatureLight",
981 LuaScriptInterface::luaDoSetCreatureLight);
982
983 // isValidUID(uid)
984 lua_register(luaState, "isValidUID", LuaScriptInterface::luaIsValidUID);
985
986 // isDepot(uid)
987 lua_register(luaState, "isDepot", LuaScriptInterface::luaIsDepot);
988
989 // isMovable(uid)
990 lua_register(luaState, "isMovable", LuaScriptInterface::luaIsMoveable);
991
992 // doAddContainerItem(uid, itemid, <optional> count/subtype)
993 lua_register(luaState, "doAddContainerItem",
994 LuaScriptInterface::luaDoAddContainerItem);
995
996 // getDepotId(uid)
997 lua_register(luaState, "getDepotId", LuaScriptInterface::luaGetDepotId);
998
999 // getWorldTime()
1000 lua_register(luaState, "getWorldTime", LuaScriptInterface::luaGetWorldTime);
1001
1002 // getWorldLight()
1003 lua_register(luaState, "getWorldLight", LuaScriptInterface::luaGetWorldLight);
1004
1005 // getWorldUpTime()
1006 lua_register(luaState, "getWorldUpTime",
1007 LuaScriptInterface::luaGetWorldUpTime);
1008
1009 // createCombatArea( {area}, <optional> {extArea} )
1010 lua_register(luaState, "createCombatArea",
1011 LuaScriptInterface::luaCreateCombatArea);
1012
1013 // doAreaCombat(cid, type, pos, area, min, max, effect)
1014 lua_register(luaState, "doAreaCombat", LuaScriptInterface::luaDoAreaCombat);
1015
1016 // doTargetCombat(cid, target, type, min, max, effect)
1017 lua_register(luaState, "doTargetCombat",
1018 LuaScriptInterface::luaDoTargetCombat);
1019
1020 // doChallengeCreature(cid, target)
1021 lua_register(luaState, "doChallengeCreature",
1022 LuaScriptInterface::luaDoChallengeCreature);
1023
1024 // addEvent(callback, delay, ...)
1025 lua_register(luaState, "addEvent", LuaScriptInterface::luaAddEvent);
1026
1027 // stopEvent(eventid)
1028 lua_register(luaState, "stopEvent", LuaScriptInterface::luaStopEvent);
1029
1030 // saveServer()
1031 lua_register(luaState, "saveServer", LuaScriptInterface::luaSaveServer);
1032
1033 // cleanMap()
1034 lua_register(luaState, "cleanMap", LuaScriptInterface::luaCleanMap);
1035
1036 // debugPrint(text)
1037 lua_register(luaState, "debugPrint", LuaScriptInterface::luaDebugPrint);
1038
1039 // isInWar(cid, target)
1040 lua_register(luaState, "isInWar", LuaScriptInterface::luaIsInWar);
1041
1042 // getWaypointPosition(name)
1043 lua_register(luaState, "getWaypointPositionByName",
1044 LuaScriptInterface::luaGetWaypointPositionByName);
1045
1046 // sendChannelMessage(channelId, type, message)
1047 lua_register(luaState, "sendChannelMessage",
1048 LuaScriptInterface::luaSendChannelMessage);
1049
1050 // sendGuildChannelMessage(guildId, type, message)
1051 lua_register(luaState, "sendGuildChannelMessage",
1052 LuaScriptInterface::luaSendGuildChannelMessage);
1053
1054#ifndef LUAJIT_VERSION
1055 // bit operations for Lua, based on bitlib project release 24
1056 // bit.bnot, bit.band, bit.bor, bit.bxor, bit.lshift, bit.rshift
1057 luaL_register(luaState, "bit", LuaScriptInterface::luaBitReg);
1058#endif
1059
1060 // configManager table
1061 luaL_register(luaState, "configManager",
1062 LuaScriptInterface::luaConfigManagerTable);
1063
1064 // db table
1065 luaL_register(luaState, "db", LuaScriptInterface::luaDatabaseTable);
1066
1067 // result table
1068 luaL_register(luaState, "result", LuaScriptInterface::luaResultTable);
1069
1070 /* New functions */
1071 // registerClass(className, baseClass, newFunction)
1072 // registerTable(tableName)
1073 // registerMethod(className, functionName, function)
1074 // registerMetaMethod(className, functionName, function)
1075 // registerGlobalMethod(functionName, function)
1076 // registerVariable(tableName, name, value)
1077 // registerGlobalVariable(name, value)
1078 // registerEnum(value)
1079 // registerEnumIn(tableName, value)
1080
1081 // Enums
1082 registerEnum(ACCOUNT_TYPE_NORMAL) registerEnum(ACCOUNT_TYPE_TUTOR)
1083 registerEnum(ACCOUNT_TYPE_SENIORTUTOR) registerEnum(
1084 ACCOUNT_TYPE_GAMEMASTER) registerEnum(ACCOUNT_TYPE_GOD)
1085
1086 registerEnum(BUG_CATEGORY_MAP) registerEnum(BUG_CATEGORY_TYPO) registerEnum(
1087 BUG_CATEGORY_TECHNICAL) registerEnum(BUG_CATEGORY_OTHER)
1088
1089 registerEnum(CALLBACK_PARAM_LEVELMAGICVALUE) registerEnum(
1090 CALLBACK_PARAM_SKILLVALUE)
1091 registerEnum(CALLBACK_PARAM_TARGETTILE) registerEnum(
1092 CALLBACK_PARAM_TARGETCREATURE)
1093
1094 registerEnum(COMBAT_FORMULA_UNDEFINED) registerEnum(
1095 COMBAT_FORMULA_LEVELMAGIC)
1096 registerEnum(COMBAT_FORMULA_SKILL) registerEnum(
1097 COMBAT_FORMULA_DAMAGE)
1098
1099 registerEnum(DIRECTION_NORTH) registerEnum(
1100 DIRECTION_EAST) registerEnum(DIRECTION_SOUTH)
1101 registerEnum(DIRECTION_WEST) registerEnum(
1102 DIRECTION_SOUTHWEST) registerEnum(DIRECTION_SOUTHEAST)
1103 registerEnum(DIRECTION_NORTHWEST) registerEnum(
1104 DIRECTION_NORTHEAST)
1105
1106 registerEnum(COMBAT_NONE) registerEnum(
1107 COMBAT_PHYSICALDAMAGE)
1108 registerEnum(COMBAT_ENERGYDAMAGE)
1109 registerEnum(
1110 COMBAT_EARTHDAMAGE)
1111 registerEnum(
1112 COMBAT_FIREDAMAGE)
1113 registerEnum(
1114 COMBAT_UNDEFINEDDAMAGE)
1115 registerEnum(
1116 COMBAT_LIFEDRAIN)
1117 registerEnum(
1118 COMBAT_MANADRAIN)
1119 registerEnum(
1120 COMBAT_HEALING)
1121 registerEnum(
1122 COMBAT_DROWNDAMAGE)
1123 registerEnum(
1124 COMBAT_ICEDAMAGE)
1125 registerEnum(
1126 COMBAT_HOLYDAMAGE)
1127 registerEnum(
1128 COMBAT_DEATHDAMAGE)
1129
1130 registerEnum(
1131 COMBAT_PARAM_TYPE)
1132 registerEnum(
1133 COMBAT_PARAM_EFFECT)
1134 registerEnum(
1135 COMBAT_PARAM_DISTANCEEFFECT)
1136 registerEnum(
1137 COMBAT_PARAM_BLOCKSHIELD)
1138 registerEnum(
1139 COMBAT_PARAM_BLOCKARMOR)
1140 registerEnum(
1141 COMBAT_PARAM_TARGETCASTERORTOPMOST)
1142 registerEnum(
1143 COMBAT_PARAM_CREATEITEM)
1144 registerEnum(
1145 COMBAT_PARAM_AGGRESSIVE)
1146 registerEnum(
1147 COMBAT_PARAM_DISPEL)
1148 registerEnum(
1149 COMBAT_PARAM_USECHARGES)
1150
1151 registerEnum(
1152 CONDITION_NONE)
1153 registerEnum(CONDITION_POISON) registerEnum(CONDITION_FIRE) registerEnum(CONDITION_ENERGY) registerEnum(CONDITION_BLEEDING) registerEnum(
1154 CONDITION_HASTE)
1155 registerEnum(CONDITION_PARALYZE) registerEnum(CONDITION_OUTFIT) registerEnum(CONDITION_INVISIBLE) registerEnum(CONDITION_LIGHT) registerEnum(CONDITION_MANASHIELD) registerEnum(CONDITION_INFIGHT) registerEnum(CONDITION_DRUNK)
1156 registerEnum(
1157 CONDITION_EXHAUST_WEAPON)
1158 registerEnum(CONDITION_REGENERATION) registerEnum(CONDITION_SOUL) registerEnum(CONDITION_DROWN) registerEnum(CONDITION_MUTED) registerEnum(CONDITION_CHANNELMUTEDTICKS) registerEnum(CONDITION_YELLTICKS) registerEnum(CONDITION_ATTRIBUTES) registerEnum(CONDITION_FREEZING) registerEnum(CONDITION_DAZZLED) registerEnum(CONDITION_CURSED) registerEnum(CONDITION_EXHAUST_COMBAT)
1159 registerEnum(CONDITION_EXHAUST_HEAL) registerEnum(CONDITION_PACIFIED) registerEnum(
1160 CONDITION_SPELLCOOLDOWN)
1161 registerEnum(
1162 CONDITION_SPELLGROUPCOOLDOWN)
1163
1164 registerEnum(
1165 CONDITIONID_DEFAULT) registerEnum(CONDITIONID_COMBAT) registerEnum(CONDITIONID_HEAD) registerEnum(CONDITIONID_NECKLACE) registerEnum(CONDITIONID_BACKPACK)
1166 registerEnum(
1167 CONDITIONID_ARMOR)
1168 registerEnum(
1169 CONDITIONID_RIGHT) registerEnum(CONDITIONID_LEFT) registerEnum(CONDITIONID_LEGS) registerEnum(CONDITIONID_FEET) registerEnum(CONDITIONID_RING) registerEnum(CONDITIONID_AMMO)
1170
1171 registerEnum(CONDITION_PARAM_OWNER) registerEnum(CONDITION_PARAM_TICKS) registerEnum(CONDITION_PARAM_HEALTHGAIN) registerEnum(CONDITION_PARAM_HEALTHTICKS) registerEnum(CONDITION_PARAM_MANAGAIN) registerEnum(CONDITION_PARAM_MANATICKS) registerEnum(CONDITION_PARAM_DELAYED) registerEnum(CONDITION_PARAM_SPEED) registerEnum(
1172 CONDITION_PARAM_LIGHT_LEVEL) registerEnum(CONDITION_PARAM_LIGHT_COLOR) registerEnum(CONDITION_PARAM_SOULGAIN) registerEnum(CONDITION_PARAM_SOULTICKS) registerEnum(CONDITION_PARAM_MINVALUE) registerEnum(CONDITION_PARAM_MAXVALUE) registerEnum(CONDITION_PARAM_STARTVALUE) registerEnum(CONDITION_PARAM_TICKINTERVAL) registerEnum(CONDITION_PARAM_FORCEUPDATE) registerEnum(CONDITION_PARAM_SKILL_MELEE) registerEnum(CONDITION_PARAM_SKILL_FIST) registerEnum(CONDITION_PARAM_SKILL_CLUB) registerEnum(CONDITION_PARAM_SKILL_SWORD) registerEnum(CONDITION_PARAM_SKILL_AXE)
1173 registerEnum(CONDITION_PARAM_SKILL_DISTANCE) registerEnum(CONDITION_PARAM_SKILL_SHIELD) registerEnum(CONDITION_PARAM_SKILL_FISHING) registerEnum(CONDITION_PARAM_STAT_MAXHITPOINTS) registerEnum(CONDITION_PARAM_STAT_MAXMANAPOINTS) registerEnum(
1174 CONDITION_PARAM_STAT_MAGICPOINTS)
1175 registerEnum(
1176 CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT)
1177 registerEnum(CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT) registerEnum(CONDITION_PARAM_STAT_MAGICPOINTSPERCENT) registerEnum(CONDITION_PARAM_PERIODICDAMAGE) registerEnum(
1178 CONDITION_PARAM_SKILL_MELEEPERCENT)
1179 registerEnum(
1180 CONDITION_PARAM_SKILL_FISTPERCENT)
1181 registerEnum(
1182 CONDITION_PARAM_SKILL_CLUBPERCENT)
1183 registerEnum(
1184 CONDITION_PARAM_SKILL_SWORDPERCENT)
1185 registerEnum(CONDITION_PARAM_SKILL_AXEPERCENT) registerEnum(CONDITION_PARAM_SKILL_DISTANCEPERCENT) registerEnum(CONDITION_PARAM_SKILL_SHIELDPERCENT)
1186 registerEnum(
1187 CONDITION_PARAM_SKILL_FISHINGPERCENT)
1188 registerEnum(
1189 CONDITION_PARAM_BUFF_SPELL)
1190 registerEnum(CONDITION_PARAM_SUBID) registerEnum(CONDITION_PARAM_FIELD) registerEnum(CONDITION_PARAM_DISABLE_DEFENSE) registerEnum(
1191 CONDITION_PARAM_SPECIALSKILL_CRITICALHITCHANCE)
1192 registerEnum(
1193 CONDITION_PARAM_SPECIALSKILL_CRITICALHITAMOUNT)
1194 registerEnum(
1195 CONDITION_PARAM_SPECIALSKILL_LIFELEECHCHANCE) registerEnum(CONDITION_PARAM_SPECIALSKILL_LIFELEECHAMOUNT) registerEnum(CONDITION_PARAM_SPECIALSKILL_MANALEECHCHANCE) registerEnum(CONDITION_PARAM_SPECIALSKILL_MANALEECHAMOUNT)
1196 registerEnum(
1197 CONDITION_PARAM_AGGRESSIVE)
1198
1199 registerEnum(
1200 CONST_ME_NONE)
1201 registerEnum(CONST_ME_DRAWBLOOD) registerEnum(CONST_ME_LOSEENERGY) registerEnum(CONST_ME_POFF)
1202 registerEnum(
1203 CONST_ME_BLOCKHIT) registerEnum(CONST_ME_EXPLOSIONAREA) registerEnum(CONST_ME_EXPLOSIONHIT) registerEnum(CONST_ME_FIREAREA) registerEnum(CONST_ME_YELLOW_RINGS) registerEnum(CONST_ME_GREEN_RINGS) registerEnum(CONST_ME_HITAREA) registerEnum(CONST_ME_TELEPORT) registerEnum(CONST_ME_ENERGYHIT) registerEnum(CONST_ME_MAGIC_BLUE)
1204 registerEnum(CONST_ME_MAGIC_RED) registerEnum(
1205 CONST_ME_MAGIC_GREEN) registerEnum(CONST_ME_HITBYFIRE) registerEnum(CONST_ME_HITBYPOISON) registerEnum(CONST_ME_MORTAREA) registerEnum(CONST_ME_SOUND_GREEN) registerEnum(CONST_ME_SOUND_RED) registerEnum(CONST_ME_POISONAREA)
1206 registerEnum(CONST_ME_SOUND_YELLOW) registerEnum(
1207 CONST_ME_SOUND_PURPLE)
1208 registerEnum(CONST_ME_SOUND_BLUE) registerEnum(CONST_ME_SOUND_WHITE) registerEnum(CONST_ME_BUBBLES)
1209 registerEnum(
1210 CONST_ME_CRAPS)
1211 registerEnum(
1212 CONST_ME_GIFT_WRAPS)
1213 registerEnum(
1214 CONST_ME_FIREWORK_YELLOW) registerEnum(CONST_ME_FIREWORK_RED) registerEnum(CONST_ME_FIREWORK_BLUE) registerEnum(CONST_ME_STUN) registerEnum(CONST_ME_SLEEP) registerEnum(CONST_ME_WATERCREATURE) registerEnum(CONST_ME_GROUNDSHAKER) registerEnum(CONST_ME_HEARTS) registerEnum(CONST_ME_FIREATTACK)
1215 registerEnum(CONST_ME_ENERGYAREA)
1216 registerEnum(CONST_ME_SMALLCLOUDS) registerEnum(CONST_ME_HOLYDAMAGE) registerEnum(CONST_ME_BIGCLOUDS)
1217 registerEnum(
1218 CONST_ME_ICEAREA)
1219 registerEnum(
1220 CONST_ME_ICETORNADO) registerEnum(CONST_ME_ICEATTACK) registerEnum(CONST_ME_STONES) registerEnum(CONST_ME_SMALLPLANTS) registerEnum(CONST_ME_CARNIPHILA) registerEnum(CONST_ME_PURPLEENERGY) registerEnum(CONST_ME_YELLOWENERGY)
1221 registerEnum(CONST_ME_HOLYAREA) registerEnum(
1222 CONST_ME_BIGPLANTS)
1223 registerEnum(CONST_ME_CAKE) registerEnum(CONST_ME_GIANTICE)
1224 registerEnum(
1225 CONST_ME_WATERSPLASH)
1226 registerEnum(
1227 CONST_ME_PLANTATTACK) registerEnum(CONST_ME_TUTORIALARROW) registerEnum(CONST_ME_TUTORIALSQUARE)
1228 registerEnum(
1229 CONST_ME_MIRRORHORIZONTAL)
1230 registerEnum(CONST_ME_MIRRORVERTICAL) registerEnum(CONST_ME_SKULLHORIZONTAL) registerEnum(CONST_ME_SKULLVERTICAL)
1231 registerEnum(CONST_ME_ASSASSIN) registerEnum(
1232 CONST_ME_STEPSHORIZONTAL)
1233 registerEnum(
1234 CONST_ME_BLOODYSTEPS)
1235 registerEnum(CONST_ME_STEPSVERTICAL) registerEnum(CONST_ME_YALAHARIGHOST) registerEnum(CONST_ME_BATS) registerEnum(CONST_ME_SMOKE) registerEnum(
1236 CONST_ME_INSECTS)
1237 registerEnum(
1238 CONST_ME_DRAGONHEAD) registerEnum(CONST_ME_ORCSHAMAN)
1239 registerEnum(CONST_ME_ORCSHAMAN_FIRE) registerEnum(
1240 CONST_ME_THUNDER) registerEnum(CONST_ME_FERUMBRAS) registerEnum(CONST_ME_CONFETTI_HORIZONTAL) registerEnum(CONST_ME_CONFETTI_VERTICAL)
1241 registerEnum(CONST_ME_BLACKSMOKE) registerEnum(CONST_ME_REDSMOKE) registerEnum(CONST_ME_YELLOWSMOKE) registerEnum(CONST_ME_GREENSMOKE) registerEnum(
1242 CONST_ME_PURPLESMOKE)
1243 registerEnum(
1244 CONST_ME_EARLY_THUNDER)
1245 registerEnum(
1246 CONST_ME_RAGIAZ_BONECAPSULE)
1247 registerEnum(CONST_ME_CRITICAL_DAMAGE) registerEnum(
1248 CONST_ME_PLUNGING_FISH)
1249
1250 registerEnum(CONST_ANI_NONE) registerEnum(CONST_ANI_SPEAR) registerEnum(CONST_ANI_BOLT) registerEnum(CONST_ANI_ARROW) registerEnum(CONST_ANI_FIRE)
1251 registerEnum(
1252 CONST_ANI_ENERGY)
1253 registerEnum(
1254 CONST_ANI_POISONARROW) registerEnum(CONST_ANI_BURSTARROW) registerEnum(CONST_ANI_THROWINGSTAR) registerEnum(CONST_ANI_THROWINGKNIFE) registerEnum(CONST_ANI_SMALLSTONE) registerEnum(CONST_ANI_DEATH) registerEnum(CONST_ANI_LARGEROCK) registerEnum(CONST_ANI_SNOWBALL) registerEnum(CONST_ANI_POWERBOLT) registerEnum(CONST_ANI_POISON) registerEnum(CONST_ANI_INFERNALBOLT)
1255 registerEnum(
1256 CONST_ANI_HUNTINGSPEAR)
1257 registerEnum(
1258 CONST_ANI_ENCHANTEDSPEAR)
1259 registerEnum(CONST_ANI_REDSTAR) registerEnum(
1260 CONST_ANI_GREENSTAR)
1261 registerEnum(CONST_ANI_ROYALSPEAR) registerEnum(CONST_ANI_SNIPERARROW) registerEnum(CONST_ANI_ONYXARROW) registerEnum(CONST_ANI_PIERCINGBOLT) registerEnum(CONST_ANI_WHIRLWINDSWORD) registerEnum(
1262 CONST_ANI_WHIRLWINDAXE) registerEnum(CONST_ANI_WHIRLWINDCLUB) registerEnum(CONST_ANI_ETHEREALSPEAR) registerEnum(CONST_ANI_ICE) registerEnum(CONST_ANI_EARTH) registerEnum(CONST_ANI_HOLY)
1263 registerEnum(
1264 CONST_ANI_SUDDENDEATH)
1265 registerEnum(
1266 CONST_ANI_FLASHARROW)
1267 registerEnum(CONST_ANI_FLAMMINGARROW)
1268 registerEnum(
1269 CONST_ANI_SHIVERARROW)
1270 registerEnum(
1271 CONST_ANI_ENERGYBALL) registerEnum(CONST_ANI_SMALLICE) registerEnum(CONST_ANI_SMALLHOLY)
1272 registerEnum(CONST_ANI_SMALLEARTH) registerEnum(CONST_ANI_EARTHARROW) registerEnum(CONST_ANI_EXPLOSION) registerEnum(CONST_ANI_CAKE) registerEnum(CONST_ANI_TARSALARROW)
1273 registerEnum(
1274 CONST_ANI_VORTEXBOLT)
1275 registerEnum(CONST_ANI_PRISMATICBOLT) registerEnum(CONST_ANI_CRYSTALLINEARROW)
1276 registerEnum(
1277 CONST_ANI_DRILLBOLT)
1278 registerEnum(CONST_ANI_ENVENOMEDARROW) registerEnum(CONST_ANI_GLOOTHSPEAR)
1279 registerEnum(CONST_ANI_SIMPLEARROW) registerEnum(
1280 CONST_ANI_WEAPONTYPE)
1281
1282 registerEnum(CONST_PROP_BLOCKSOLID) registerEnum(
1283 CONST_PROP_HASHEIGHT)
1284 registerEnum(
1285 CONST_PROP_BLOCKPROJECTILE)
1286 registerEnum(CONST_PROP_BLOCKPATH) registerEnum(CONST_PROP_ISVERTICAL) registerEnum(
1287 CONST_PROP_ISHORIZONTAL) registerEnum(CONST_PROP_MOVEABLE) registerEnum(CONST_PROP_IMMOVABLEBLOCKSOLID) registerEnum(CONST_PROP_IMMOVABLEBLOCKPATH)
1288 registerEnum(CONST_PROP_IMMOVABLENOFIELDBLOCKPATH) registerEnum(
1289 CONST_PROP_NOFIELDBLOCKPATH)
1290 registerEnum(CONST_PROP_SUPPORTHANGABLE)
1291
1292 registerEnum(CONST_SLOT_HEAD) registerEnum(CONST_SLOT_NECKLACE) registerEnum(CONST_SLOT_BACKPACK) registerEnum(CONST_SLOT_ARMOR) registerEnum(CONST_SLOT_RIGHT)
1293 registerEnum(
1294 CONST_SLOT_LEFT)
1295 registerEnum(CONST_SLOT_LEGS) registerEnum(
1296 CONST_SLOT_FEET)
1297 registerEnum(CONST_SLOT_RING) registerEnum(CONST_SLOT_AMMO)
1298
1299 registerEnum(
1300 CREATURE_EVENT_NONE)
1301 registerEnum(CREATURE_EVENT_LOGIN)
1302 registerEnum(
1303 CREATURE_EVENT_LOGOUT)
1304 registerEnum(CREATURE_EVENT_THINK) registerEnum(CREATURE_EVENT_PREPAREDEATH) registerEnum(
1305 CREATURE_EVENT_DEATH) registerEnum(CREATURE_EVENT_KILL) registerEnum(CREATURE_EVENT_ADVANCE)
1306 registerEnum(
1307 CREATURE_EVENT_MODALWINDOW) registerEnum(CREATURE_EVENT_TEXTEDIT) registerEnum(CREATURE_EVENT_HEALTHCHANGE)
1308 registerEnum(
1309 CREATURE_EVENT_MANACHANGE)
1310 registerEnum(
1311 CREATURE_EVENT_EXTENDED_OPCODE)
1312
1313 registerEnum(GAME_STATE_STARTUP) registerEnum(
1314 GAME_STATE_INIT) registerEnum(GAME_STATE_NORMAL)
1315 registerEnum(
1316 GAME_STATE_CLOSED) registerEnum(GAME_STATE_SHUTDOWN)
1317 registerEnum(GAME_STATE_CLOSING) registerEnum(
1318 GAME_STATE_MAINTAIN)
1319
1320 registerEnum(MESSAGE_STATUS_CONSOLE_BLUE) registerEnum(MESSAGE_STATUS_CONSOLE_RED) registerEnum(MESSAGE_STATUS_DEFAULT) registerEnum(
1321 MESSAGE_STATUS_WARNING) registerEnum(MESSAGE_EVENT_ADVANCE)
1322 registerEnum(
1323 MESSAGE_STATUS_SMALL)
1324 registerEnum(
1325 MESSAGE_INFO_DESCR)
1326 registerEnum(
1327 MESSAGE_DAMAGE_DEALT) registerEnum(MESSAGE_DAMAGE_RECEIVED) registerEnum(MESSAGE_HEALED) registerEnum(MESSAGE_EXPERIENCE) registerEnum(MESSAGE_DAMAGE_OTHERS)
1328 registerEnum(MESSAGE_HEALED_OTHERS) registerEnum(MESSAGE_EXPERIENCE_OTHERS) registerEnum(MESSAGE_EVENT_DEFAULT) registerEnum(MESSAGE_GUILD) registerEnum(
1329 MESSAGE_PARTY_MANAGEMENT)
1330 registerEnum(MESSAGE_PARTY)
1331 registerEnum(
1332 MESSAGE_EVENT_ORANGE) registerEnum(MESSAGE_STATUS_CONSOLE_ORANGE) registerEnum(MESSAGE_LOOT)
1333
1334 registerEnum(
1335 CREATURETYPE_PLAYER) registerEnum(CREATURETYPE_MONSTER)
1336 registerEnum(
1337 CREATURETYPE_NPC) registerEnum(CREATURETYPE_SUMMON_OWN) registerEnum(CREATURETYPE_SUMMON_OTHERS)
1338
1339 registerEnum(
1340 CLIENTOS_LINUX)
1341 registerEnum(
1342 CLIENTOS_WINDOWS)
1343 registerEnum(CLIENTOS_FLASH) registerEnum(CLIENTOS_OTCLIENT_LINUX) registerEnum(CLIENTOS_OTCLIENT_WINDOWS) registerEnum(
1344 CLIENTOS_OTCLIENT_MAC)
1345
1346 registerEnum(
1347 FIGHTMODE_ATTACK)
1348 registerEnum(
1349 FIGHTMODE_BALANCED)
1350 registerEnum(
1351 FIGHTMODE_DEFENSE)
1352
1353 registerEnum(
1354 ITEM_ATTRIBUTE_NONE) registerEnum(ITEM_ATTRIBUTE_ACTIONID) registerEnum(ITEM_ATTRIBUTE_UNIQUEID) registerEnum(ITEM_ATTRIBUTE_DESCRIPTION) registerEnum(ITEM_ATTRIBUTE_TEXT) registerEnum(ITEM_ATTRIBUTE_DATE)
1355 registerEnum(
1356 ITEM_ATTRIBUTE_WRITER)
1357 registerEnum(
1358 ITEM_ATTRIBUTE_NAME)
1359 registerEnum(ITEM_ATTRIBUTE_ARTICLE) registerEnum(
1360 ITEM_ATTRIBUTE_PLURALNAME) registerEnum(ITEM_ATTRIBUTE_WEIGHT) registerEnum(ITEM_ATTRIBUTE_ATTACK)
1361 registerEnum(
1362 ITEM_ATTRIBUTE_DEFENSE) registerEnum(ITEM_ATTRIBUTE_EXTRADEFENSE) registerEnum(ITEM_ATTRIBUTE_ARMOR)
1363 registerEnum(
1364 ITEM_ATTRIBUTE_HITCHANCE) registerEnum(ITEM_ATTRIBUTE_SHOOTRANGE)
1365 registerEnum(ITEM_ATTRIBUTE_OWNER) registerEnum(ITEM_ATTRIBUTE_DURATION) registerEnum(
1366 ITEM_ATTRIBUTE_DECAYSTATE) registerEnum(ITEM_ATTRIBUTE_CORPSEOWNER)
1367 registerEnum(ITEM_ATTRIBUTE_CHARGES) registerEnum(
1368 ITEM_ATTRIBUTE_FLUIDTYPE) registerEnum(ITEM_ATTRIBUTE_DOORID)
1369
1370 registerEnum(ITEM_TYPE_DEPOT) registerEnum(ITEM_TYPE_MAILBOX) registerEnum(
1371 ITEM_TYPE_TRASHHOLDER)
1372 registerEnum(
1373 ITEM_TYPE_CONTAINER) registerEnum(ITEM_TYPE_DOOR)
1374 registerEnum(
1375 ITEM_TYPE_MAGICFIELD) registerEnum(ITEM_TYPE_TELEPORT)
1376 registerEnum(
1377 ITEM_TYPE_BED)
1378 registerEnum(ITEM_TYPE_KEY) registerEnum(
1379 ITEM_TYPE_RUNE)
1380
1381 registerEnum(ITEM_BAG) registerEnum(
1382 ITEM_SHOPPING_BAG) registerEnum(ITEM_GOLD_COIN) registerEnum(ITEM_PLATINUM_COIN) registerEnum(ITEM_CRYSTAL_COIN) registerEnum(ITEM_AMULETOFLOSS) registerEnum(ITEM_PARCEL) registerEnum(ITEM_LABEL) registerEnum(ITEM_FIREFIELD_PVP_FULL) registerEnum(ITEM_FIREFIELD_PVP_MEDIUM)
1383 registerEnum(ITEM_FIREFIELD_PVP_SMALL)
1384 registerEnum(
1385 ITEM_FIREFIELD_PERSISTENT_FULL)
1386 registerEnum(ITEM_FIREFIELD_PERSISTENT_MEDIUM) registerEnum(ITEM_FIREFIELD_PERSISTENT_SMALL) registerEnum(ITEM_FIREFIELD_NOPVP) registerEnum(
1387 ITEM_POISONFIELD_PVP) registerEnum(ITEM_POISONFIELD_PERSISTENT) registerEnum(ITEM_POISONFIELD_NOPVP) registerEnum(ITEM_ENERGYFIELD_PVP)
1388 registerEnum(ITEM_ENERGYFIELD_PERSISTENT) registerEnum(ITEM_ENERGYFIELD_NOPVP) registerEnum(ITEM_MAGICWALL) registerEnum(
1389 ITEM_MAGICWALL_PERSISTENT) registerEnum(ITEM_MAGICWALL_SAFE) registerEnum(ITEM_WILDGROWTH) registerEnum(ITEM_WILDGROWTH_PERSISTENT)
1390 registerEnum(
1391 ITEM_WILDGROWTH_SAFE)
1392
1393 registerEnum(
1394 PlayerFlag_CannotUseCombat)
1395 registerEnum(
1396 PlayerFlag_CannotAttackPlayer) registerEnum(PlayerFlag_CannotAttackMonster) registerEnum(PlayerFlag_CannotBeAttacked)
1397 registerEnum(PlayerFlag_CanConvinceAll) registerEnum(PlayerFlag_CanSummonAll) registerEnum(
1398 PlayerFlag_CanIllusionAll) registerEnum(PlayerFlag_CanSenseInvisibility)
1399 registerEnum(PlayerFlag_IgnoredByMonsters) registerEnum(PlayerFlag_NotGainInFight) registerEnum(
1400 PlayerFlag_HasInfiniteMana) registerEnum(PlayerFlag_HasInfiniteSoul) registerEnum(PlayerFlag_HasNoExhaustion)
1401 registerEnum(PlayerFlag_CannotUseSpells)
1402 registerEnum(PlayerFlag_CannotPickupItem) registerEnum(PlayerFlag_CanAlwaysLogin) registerEnum(
1403 PlayerFlag_CanBroadcast) registerEnum(PlayerFlag_CanEditHouses)
1404 registerEnum(PlayerFlag_CannotBeBanned) registerEnum(
1405 PlayerFlag_CannotBePushed) registerEnum(PlayerFlag_HasInfiniteCapacity)
1406 registerEnum(
1407 PlayerFlag_CanPushAllCreatures) registerEnum(PlayerFlag_CanTalkRedPrivate)
1408 registerEnum(PlayerFlag_CanTalkRedChannel) registerEnum(
1409 PlayerFlag_TalkOrangeHelpChannel) registerEnum(PlayerFlag_NotGainExperience) registerEnum(PlayerFlag_NotGainMana) registerEnum(PlayerFlag_NotGainHealth) registerEnum(PlayerFlag_NotGainSkill)
1410 registerEnum(PlayerFlag_SetMaxSpeed) registerEnum(PlayerFlag_SpecialVIP) registerEnum(PlayerFlag_NotGenerateLoot) registerEnum(PlayerFlag_CanTalkRedChannelAnonymous) registerEnum(PlayerFlag_IgnoreProtectionZone) registerEnum(
1411 PlayerFlag_IgnoreSpellCheck)
1412 registerEnum(
1413 PlayerFlag_IgnoreWeaponCheck)
1414 registerEnum(PlayerFlag_CannotBeMuted) registerEnum(
1415 PlayerFlag_IsAlwaysPremium)
1416
1417 registerEnum(
1418 PLAYERSEX_FEMALE)
1419 registerEnum(
1420 PLAYERSEX_MALE)
1421
1422 registerEnum(
1423 REPORT_REASON_NAMEINAPPROPRIATE)
1424 registerEnum(
1425 REPORT_REASON_NAMEPOORFORMATTED) registerEnum(REPORT_REASON_NAMEADVERTISING) registerEnum(REPORT_REASON_NAMEUNFITTING) registerEnum(REPORT_REASON_NAMERULEVIOLATION)
1426 registerEnum(
1427 REPORT_REASON_INSULTINGSTATEMENT)
1428 registerEnum(
1429 REPORT_REASON_SPAMMING) registerEnum(REPORT_REASON_ADVERTISINGSTATEMENT) registerEnum(REPORT_REASON_UNFITTINGSTATEMENT)
1430 registerEnum(
1431 REPORT_REASON_LANGUAGESTATEMENT)
1432 registerEnum(REPORT_REASON_DISCLOSURE) registerEnum(REPORT_REASON_RULEVIOLATION)
1433 registerEnum(
1434 REPORT_REASON_STATEMENT_BUGABUSE)
1435 registerEnum(REPORT_REASON_UNOFFICIALSOFTWARE) registerEnum(REPORT_REASON_PRETENDING) registerEnum(REPORT_REASON_HARASSINGOWNERS) registerEnum(REPORT_REASON_FALSEINFO) registerEnum(REPORT_REASON_ACCOUNTSHARING) registerEnum(REPORT_REASON_STEALINGDATA)
1436 registerEnum(
1437 REPORT_REASON_SERVICEATTACKING)
1438 registerEnum(
1439 REPORT_REASON_SERVICEAGREEMENT)
1440
1441 registerEnum(REPORT_TYPE_NAME) registerEnum(REPORT_TYPE_STATEMENT) registerEnum(REPORT_TYPE_BOT)
1442
1443 registerEnum(
1444 VOCATION_NONE)
1445
1446 registerEnum(
1447 SKILL_FIST)
1448 registerEnum(SKILL_CLUB) registerEnum(SKILL_SWORD) registerEnum(SKILL_AXE) registerEnum(SKILL_DISTANCE) registerEnum(
1449 SKILL_SHIELD) registerEnum(SKILL_FISHING) registerEnum(SKILL_MAGLEVEL) registerEnum(SKILL_LEVEL)
1450
1451 registerEnum(
1452 SPECIALSKILL_CRITICALHITCHANCE) registerEnum(SPECIALSKILL_CRITICALHITAMOUNT) registerEnum(SPECIALSKILL_LIFELEECHCHANCE)
1453 registerEnum(
1454 SPECIALSKILL_LIFELEECHAMOUNT) registerEnum(SPECIALSKILL_MANALEECHCHANCE) registerEnum(SPECIALSKILL_MANALEECHAMOUNT)
1455
1456 registerEnum(ARCHETYPE_NONE) registerEnum(
1457 ARCHETYPE_WARFARE) registerEnum(ARCHETYPE_ARCHERY) registerEnum(ARCHETYPE_PROTECTION) registerEnum(ARCHETYPE_SHADOW) registerEnum(ARCHETYPE_WIZARDRY) registerEnum(ARCHETYPE_HOLY) registerEnum(ARCHETYPE_WITCHCRAFT) registerEnum(ARCHETYPE_SPIRITUAL)
1458
1459 registerEnum(
1460 ARCHETYPE_RESOURCE_AETHER)
1461
1462 registerEnum(
1463 SKULL_NONE)
1464 registerEnum(SKULL_YELLOW) registerEnum(SKULL_GREEN) registerEnum(
1465 SKULL_WHITE) registerEnum(SKULL_RED) registerEnum(SKULL_BLACK) registerEnum(SKULL_ORANGE)
1466
1467 registerEnum(
1468 TALKTYPE_SAY)
1469 registerEnum(TALKTYPE_WHISPER) registerEnum(
1470 TALKTYPE_YELL) registerEnum(TALKTYPE_PRIVATE_FROM)
1471 registerEnum(TALKTYPE_PRIVATE_TO) registerEnum(
1472 TALKTYPE_CHANNEL_Y)
1473 registerEnum(
1474 TALKTYPE_CHANNEL_O)
1475 registerEnum(
1476 TALKTYPE_PRIVATE_NP)
1477 registerEnum(
1478 TALKTYPE_PRIVATE_PN)
1479 registerEnum(
1480 TALKTYPE_BROADCAST) registerEnum(TALKTYPE_CHANNEL_R1) registerEnum(TALKTYPE_PRIVATE_RED_FROM) registerEnum(TALKTYPE_PRIVATE_RED_TO) registerEnum(TALKTYPE_MONSTER_SAY)
1481 registerEnum(
1482 TALKTYPE_MONSTER_YELL)
1483 registerEnum(
1484 TALKTYPE_CHANNEL_R2)
1485
1486 registerEnum(
1487 TEXTCOLOR_BLUE)
1488 registerEnum(
1489 TEXTCOLOR_LIGHTGREEN) registerEnum(TEXTCOLOR_LIGHTBLUE) registerEnum(TEXTCOLOR_MAYABLUE)
1490 registerEnum(
1491 TEXTCOLOR_DARKRED)
1492 registerEnum(
1493 TEXTCOLOR_LIGHTGREY)
1494 registerEnum(TEXTCOLOR_SKYBLUE) registerEnum(TEXTCOLOR_PURPLE)
1495 registerEnum(TEXTCOLOR_ELECTRICPURPLE) registerEnum(TEXTCOLOR_RED) registerEnum(TEXTCOLOR_PASTELRED) registerEnum(TEXTCOLOR_ORANGE)
1496 registerEnum(
1497 TEXTCOLOR_YELLOW) registerEnum(TEXTCOLOR_WHITE_EXP) registerEnum(TEXTCOLOR_NONE)
1498
1499 registerEnum(
1500 TILESTATE_NONE) registerEnum(TILESTATE_PROTECTIONZONE) registerEnum(TILESTATE_NOPVPZONE) registerEnum(TILESTATE_NOLOGOUT) registerEnum(TILESTATE_PVPZONE) registerEnum(TILESTATE_FLOORCHANGE) registerEnum(TILESTATE_FLOORCHANGE_DOWN) registerEnum(TILESTATE_FLOORCHANGE_NORTH)
1501 registerEnum(TILESTATE_FLOORCHANGE_SOUTH) registerEnum(TILESTATE_FLOORCHANGE_EAST) registerEnum(TILESTATE_FLOORCHANGE_WEST)
1502 registerEnum(TILESTATE_TELEPORT) registerEnum(TILESTATE_MAGICFIELD) registerEnum(TILESTATE_MAILBOX) registerEnum(TILESTATE_TRASHHOLDER) registerEnum(TILESTATE_BED) registerEnum(TILESTATE_DEPOT) registerEnum(TILESTATE_BLOCKSOLID) registerEnum(TILESTATE_BLOCKPATH) registerEnum(TILESTATE_IMMOVABLEBLOCKSOLID) registerEnum(TILESTATE_IMMOVABLEBLOCKPATH) registerEnum(TILESTATE_IMMOVABLENOFIELDBLOCKPATH) registerEnum(TILESTATE_NOFIELDBLOCKPATH) registerEnum(TILESTATE_FLOORCHANGE_SOUTH_ALT) registerEnum(TILESTATE_FLOORCHANGE_EAST_ALT) registerEnum(
1503 TILESTATE_SUPPORTS_HANGABLE)
1504
1505 registerEnum(WEAPON_NONE) registerEnum(WEAPON_SWORD) registerEnum(WEAPON_CLUB) registerEnum(WEAPON_AXE) registerEnum(WEAPON_SHIELD) registerEnum(WEAPON_DISTANCE) registerEnum(WEAPON_WAND) registerEnum(
1506 WEAPON_AMMO)
1507
1508 registerEnum(
1509 WORLD_TYPE_NO_PVP)
1510 registerEnum(
1511 WORLD_TYPE_PVP)
1512 registerEnum(
1513 WORLD_TYPE_PVP_ENFORCED)
1514
1515 // Use with container:addItem, container:addItemEx and possibly other
1516 // functions.
1517 registerEnum(FLAG_NOLIMIT) registerEnum(FLAG_IGNOREBLOCKITEM)
1518 registerEnum(FLAG_IGNOREBLOCKCREATURE) registerEnum(FLAG_CHILDISOWNER)
1519 registerEnum(FLAG_PATHFINDING)
1520 registerEnum(FLAG_IGNOREFIELDDAMAGE)
1521 registerEnum(FLAG_IGNORENOTMOVEABLE)
1522 registerEnum(FLAG_IGNOREAUTOSTACK)
1523
1524 // Use with itemType:getSlotPosition
1525 registerEnum(SLOTP_WHEREEVER) registerEnum(SLOTP_HEAD)
1526 registerEnum(SLOTP_NECKLACE) registerEnum(SLOTP_BACKPACK)
1527 registerEnum(SLOTP_ARMOR) registerEnum(SLOTP_RIGHT)
1528 registerEnum(SLOTP_LEFT) registerEnum(SLOTP_LEGS)
1529 registerEnum(SLOTP_FEET) registerEnum(SLOTP_RING)
1530 registerEnum(SLOTP_AMMO) registerEnum(SLOTP_DEPOT)
1531 registerEnum(SLOTP_TWO_HAND)
1532
1533 // Use with combat functions
1534 registerEnum(ORIGIN_NONE) registerEnum(ORIGIN_CONDITION)
1535 registerEnum(ORIGIN_SPELL) registerEnum(ORIGIN_MELEE)
1536 registerEnum(ORIGIN_RANGED)
1537
1538 // Use with house:getAccessList, house:setAccessList
1539 registerEnum(GUEST_LIST) registerEnum(SUBOWNER_LIST)
1540
1541 // Use with npc:setSpeechBubble
1542 registerEnum(SPEECHBUBBLE_NONE) registerEnum(SPEECHBUBBLE_NORMAL)
1543 registerEnum(SPEECHBUBBLE_TRADE) registerEnum(SPEECHBUBBLE_QUEST)
1544 registerEnum(SPEECHBUBBLE_QUESTTRADER)
1545
1546 // Use with player:addMapMark
1547 registerEnum(MAPMARK_TICK) registerEnum(MAPMARK_QUESTION)
1548 registerEnum(MAPMARK_EXCLAMATION) registerEnum(MAPMARK_STAR)
1549 registerEnum(MAPMARK_CROSS) registerEnum(MAPMARK_TEMPLE)
1550 registerEnum(MAPMARK_KISS) registerEnum(MAPMARK_SHOVEL)
1551 registerEnum(MAPMARK_SWORD) registerEnum(MAPMARK_FLAG)
1552 registerEnum(MAPMARK_LOCK) registerEnum(MAPMARK_BAG)
1553 registerEnum(MAPMARK_SKULL) registerEnum(
1554 MAPMARK_DOLLAR) registerEnum(MAPMARK_REDNORTH)
1555 registerEnum(MAPMARK_REDSOUTH) registerEnum(
1556 MAPMARK_REDEAST)
1557 registerEnum(MAPMARK_REDWEST)
1558 registerEnum(MAPMARK_GREENNORTH)
1559 registerEnum(MAPMARK_GREENSOUTH)
1560
1561 // Use with Game.getReturnMessage
1562 registerEnum(RETURNVALUE_NOERROR) registerEnum(RETURNVALUE_NOTPOSSIBLE) registerEnum(
1563 RETURNVALUE_NOTENOUGHROOM) registerEnum(RETURNVALUE_PLAYERISPZLOCKED)
1564 registerEnum(RETURNVALUE_PLAYERISNOTINVITED) registerEnum(RETURNVALUE_CANNOTTHROW) registerEnum(
1565 RETURNVALUE_THEREISNOWAY) registerEnum(RETURNVALUE_DESTINATIONOUTOFREACH)
1566 registerEnum(RETURNVALUE_CREATUREBLOCK) registerEnum(RETURNVALUE_NOTMOVEABLE) registerEnum(
1567 RETURNVALUE_DROPTWOHANDEDITEM) registerEnum(RETURNVALUE_BOTHHANDSNEEDTOBEFREE)
1568 registerEnum(RETURNVALUE_CANONLYUSEONEWEAPON) registerEnum(
1569 RETURNVALUE_NEEDEXCHANGE) registerEnum(RETURNVALUE_CANNOTBEDRESSED)
1570 registerEnum(RETURNVALUE_PUTTHISOBJECTINYOURHAND) registerEnum(
1571 RETURNVALUE_PUTTHISOBJECTINBOTHHANDS) registerEnum(RETURNVALUE_TOOFARAWAY) registerEnum(RETURNVALUE_FIRSTGODOWNSTAIRS) registerEnum(RETURNVALUE_FIRSTGOUPSTAIRS) registerEnum(RETURNVALUE_CONTAINERNOTENOUGHROOM) registerEnum(RETURNVALUE_NOTENOUGHCAPACITY) registerEnum(RETURNVALUE_CANNOTPICKUP) registerEnum(RETURNVALUE_THISISIMPOSSIBLE) registerEnum(RETURNVALUE_DEPOTISFULL) registerEnum(RETURNVALUE_CREATUREDOESNOTEXIST) registerEnum(RETURNVALUE_CANNOTUSETHISOBJECT) registerEnum(RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE) registerEnum(RETURNVALUE_NOTREQUIREDLEVELTOUSERUNE) registerEnum(RETURNVALUE_YOUAREALREADYTRADING) registerEnum(RETURNVALUE_THISPLAYERISALREADYTRADING) registerEnum(RETURNVALUE_YOUMAYNOTLOGOUTDURINGAFIGHT) registerEnum(RETURNVALUE_DIRECTPLAYERSHOOT) registerEnum(RETURNVALUE_NOTENOUGHLEVEL) registerEnum(RETURNVALUE_NOTENOUGHMAGICLEVEL) registerEnum(RETURNVALUE_NOTENOUGHMANA) registerEnum(RETURNVALUE_NOTENOUGHSOUL) registerEnum(RETURNVALUE_YOUAREEXHAUSTED) registerEnum(RETURNVALUE_YOUCANNOTUSEOBJECTSTHATFAST) registerEnum(RETURNVALUE_PLAYERISNOTREACHABLE) registerEnum(RETURNVALUE_CANONLYUSETHISRUNEONCREATURES)
1572 registerEnum(RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE) registerEnum(RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER) registerEnum(RETURNVALUE_YOUMAYNOTATTACKAPERSONINPROTECTIONZONE) registerEnum(RETURNVALUE_YOUMAYNOTATTACKAPERSONWHILEINPROTECTIONZONE) registerEnum(RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE) registerEnum(RETURNVALUE_YOUCANONLYUSEITONCREATURES) registerEnum(RETURNVALUE_CREATUREISNOTREACHABLE) registerEnum(RETURNVALUE_TURNSECUREMODETOATTACKUNMARKEDPLAYERS) registerEnum(RETURNVALUE_YOUNEEDPREMIUMACCOUNT) registerEnum(
1573 RETURNVALUE_YOUNEEDTOLEARNTHISSPELL) registerEnum(RETURNVALUE_YOURVOCATIONCANNOTUSETHISSPELL) registerEnum(RETURNVALUE_YOUNEEDAWEAPONTOUSETHISSPELL) registerEnum(RETURNVALUE_PLAYERISPZLOCKEDLEAVEPVPZONE) registerEnum(RETURNVALUE_PLAYERISPZLOCKEDENTERPVPZONE) registerEnum(RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE) registerEnum(RETURNVALUE_YOUCANNOTLOGOUTHERE) registerEnum(RETURNVALUE_YOUNEEDAMAGICITEMTOCASTSPELL) registerEnum(RETURNVALUE_CANNOTCONJUREITEMHERE) registerEnum(RETURNVALUE_YOUNEEDTOSPLITYOURSPEARS) registerEnum(RETURNVALUE_NAMEISTOOAMBIGUOUS) registerEnum(RETURNVALUE_CANONLYUSEONESHIELD) registerEnum(RETURNVALUE_NOPARTYMEMBERSINRANGE) registerEnum(RETURNVALUE_YOUARENOTTHEOWNER) registerEnum(RETURNVALUE_TRADEPLAYERFARAWAY) registerEnum(RETURNVALUE_YOUDONTOWNTHISHOUSE) registerEnum(RETURNVALUE_TRADEPLAYERALREADYOWNSAHOUSE) registerEnum(RETURNVALUE_TRADEPLAYERHIGHESTBIDDER) registerEnum(RETURNVALUE_YOUCANNOTTRADETHISHOUSE) registerEnum(RETURNVALUE_YOUDONTHAVEREQUIREDPROFESSION)
1574
1575 registerEnum(RELOAD_TYPE_ALL) registerEnum(
1576 RELOAD_TYPE_ACTIONS) registerEnum(RELOAD_TYPE_AURAS) registerEnum(RELOAD_TYPE_CHAT)
1577 registerEnum(RELOAD_TYPE_CONFIG) registerEnum(RELOAD_TYPE_CREATURESCRIPTS) registerEnum(
1578 RELOAD_TYPE_EVENTS) registerEnum(RELOAD_TYPE_GLOBAL)
1579 registerEnum(RELOAD_TYPE_GLOBALEVENTS) registerEnum(
1580 RELOAD_TYPE_ITEMS) registerEnum(RELOAD_TYPE_MONSTERS)
1581 registerEnum(RELOAD_TYPE_MOUNTS) registerEnum(RELOAD_TYPE_MOVEMENTS) registerEnum(
1582 RELOAD_TYPE_NPCS) registerEnum(RELOAD_TYPE_QUESTS) registerEnum(RELOAD_TYPE_RAIDS)
1583 registerEnum(RELOAD_TYPE_SCRIPTS) registerEnum(
1584 RELOAD_TYPE_SHADERS) registerEnum(RELOAD_TYPE_SPELLS)
1585 registerEnum(RELOAD_TYPE_TALKACTIONS) registerEnum(
1586 RELOAD_TYPE_WEAPONS) registerEnum(RELOAD_TYPE_WINGS)
1587 registerEnum(RELOAD_TYPE_RUNEEFFECTS)
1588 registerEnum(RELOAD_TYPE_OUTFITS)
1589
1590 registerEnum(ZONE_PROTECTION) registerEnum(
1591 ZONE_NOPVP)
1592 registerEnum(ZONE_PVP) registerEnum(
1593 ZONE_NOLOGOUT) registerEnum(ZONE_NORMAL)
1594
1595 registerEnum(
1596 MAX_LOOTCHANCE)
1597
1598 registerEnum(
1599 SPELL_INSTANT) registerEnum(SPELL_RUNE)
1600
1601 registerEnum(
1602 MONSTERS_EVENT_THINK)
1603 registerEnum(
1604 MONSTERS_EVENT_APPEAR)
1605 registerEnum(
1606 MONSTERS_EVENT_DISAPPEAR)
1607 registerEnum(
1608 MONSTERS_EVENT_MOVE)
1609 registerEnum(
1610 MONSTERS_EVENT_SAY)
1611
1612 // _G
1613 registerGlobalVariable("INDEX_WHEREEVER", INDEX_WHEREEVER);
1614 registerGlobalBoolean("VIRTUAL_PARENT", true);
1615
1616 registerGlobalMethod("isType", LuaScriptInterface::luaIsType);
1617 registerGlobalMethod("rawgetmetatable",
1618 LuaScriptInterface::luaRawGetMetatable);
1619
1620 // configKeys
1621 registerTable("configKeys");
1622
1623 registerEnumIn("configKeys", ConfigManager::ALLOW_CHANGEOUTFIT) registerEnumIn(
1624 "configKeys",
1625 ConfigManager::
1626 ONE_PLAYER_ON_ACCOUNT) registerEnumIn("configKeys",
1627 ConfigManager::
1628 AIMBOT_HOTKEY_ENABLED)
1629 registerEnumIn("configKeys", ConfigManager::REMOVE_RUNE_CHARGES) registerEnumIn("configKeys", ConfigManager::
1630 REMOVE_WEAPON_AMMO) registerEnumIn("configKeys", ConfigManager::REMOVE_WEAPON_CHARGES) registerEnumIn("configKeys", ConfigManager::REMOVE_POTION_CHARGES) registerEnumIn("configKeys", ConfigManager::EXPERIENCE_FROM_PLAYERS) registerEnumIn("configKeys",
1631 ConfigManager::FREE_PREMIUM) registerEnumIn("configKeys", ConfigManager::REPLACE_KICK_ON_LOGIN) registerEnumIn("configKeys", ConfigManager::
1632 ALLOW_CLONES) registerEnumIn("configKeys", ConfigManager::BIND_ONLY_GLOBAL_ADDRESS) registerEnumIn("configKeys", ConfigManager::OPTIMIZE_DATABASE) registerEnumIn("configKeys", ConfigManager::MARKET_PREMIUM) registerEnumIn("configKeys",
1633 ConfigManager::EMOTE_SPELLS) registerEnumIn("configKeys", ConfigManager::
1634 STAMINA_SYSTEM) registerEnumIn("configKeys", ConfigManager::WARN_UNSAFE_SCRIPTS) registerEnumIn("configKeys", ConfigManager::CONVERT_UNSAFE_SCRIPTS) registerEnumIn("configKeys",
1635 ConfigManager::
1636 CLASSIC_EQUIPMENT_SLOTS) registerEnumIn("configKeys", ConfigManager::CLASSIC_ATTACK_SPEED) registerEnumIn("configKeys",
1637 ConfigManager::
1638 SERVER_SAVE_NOTIFY_MESSAGE) registerEnumIn("configKeys",
1639 ConfigManager::
1640 SERVER_SAVE_NOTIFY_DURATION) registerEnumIn("configKeys",
1641 ConfigManager::
1642 SERVER_SAVE_CLEAN_MAP) registerEnumIn("configKeys", ConfigManager::SERVER_SAVE_CLOSE) registerEnumIn("configKeys", ConfigManager::SERVER_SAVE_SHUTDOWN) registerEnumIn("configKeys",
1643 ConfigManager::
1644 ONLINE_OFFLINE_CHARLIST)
1645
1646 registerEnumIn("configKeys", ConfigManager::MAP_NAME) registerEnumIn(
1647 "configKeys", ConfigManager::HOUSE_RENT_PERIOD)
1648 registerEnumIn("configKeys", ConfigManager::SERVER_NAME) registerEnumIn(
1649 "configKeys",
1650 ConfigManager::
1651 OWNER_NAME) registerEnumIn("configKeys", ConfigManager::OWNER_EMAIL)
1652 registerEnumIn("configKeys", ConfigManager::URL) registerEnumIn(
1653 "configKeys",
1654 ConfigManager::
1655 LOCATION) registerEnumIn("configKeys",
1656 ConfigManager::IP)
1657 registerEnumIn("configKeys", ConfigManager::MOTD) registerEnumIn(
1658 "configKeys",
1659 ConfigManager::
1660 WORLD_TYPE) registerEnumIn("configKeys", ConfigManager::MYSQL_HOST)
1661 registerEnumIn(
1662 "configKeys",
1663 ConfigManager::
1664 MYSQL_USER) registerEnumIn("configKeys", ConfigManager::MYSQL_PASS)
1665 registerEnumIn("configKeys", ConfigManager::MYSQL_DB) registerEnumIn(
1666 "configKeys",
1667 ConfigManager::
1668 MYSQL_SOCK) registerEnumIn("configKeys", ConfigManager::DEFAULT_PRIORITY)
1669 registerEnumIn(
1670 "configKeys", ConfigManager::MAP_AUTHOR)
1671
1672 registerEnumIn(
1673 "configKeys", ConfigManager::SQL_PORT)
1674 registerEnumIn("configKeys", ConfigManager::MAX_PLAYERS) registerEnumIn("configKeys", ConfigManager::PZ_LOCKED) registerEnumIn("configKeys", ConfigManager::DEFAULT_DESPAWNRANGE) registerEnumIn("configKeys", ConfigManager::DEFAULT_DESPAWNRADIUS) registerEnumIn("configKeys", ConfigManager::RATE_EXPERIENCE) registerEnumIn("configKeys",
1675 ConfigManager::RATE_SKILL) registerEnumIn("configKeys", ConfigManager::RATE_LOOT) registerEnumIn("configKeys", ConfigManager::
1676 RATE_MAGIC) registerEnumIn("configKeys", ConfigManager::RATE_SPAWN) registerEnumIn("configKeys", ConfigManager::HOUSE_PRICE) registerEnumIn("configKeys", ConfigManager::KILLS_TO_RED) registerEnumIn("configKeys",
1677 ConfigManager::
1678 KILLS_TO_BLACK) registerEnumIn("configKeys", ConfigManager::
1679 MAX_MESSAGEBUFFER) registerEnumIn("configKeys", ConfigManager::
1680 ACTIONS_DELAY_INTERVAL) registerEnumIn("configKeys",
1681 ConfigManager::
1682 EX_ACTIONS_DELAY_INTERVAL)
1683 registerEnumIn("configKeys", ConfigManager::KICK_AFTER_MINUTES) registerEnumIn(
1684 "configKeys",
1685 ConfigManager::
1686 PROTECTION_LEVEL) registerEnumIn("configKeys",
1687 ConfigManager::
1688 DEATH_LOSE_PERCENT)
1689 registerEnumIn("configKeys", ConfigManager::STATUSQUERY_TIMEOUT) registerEnumIn(
1690 "configKeys",
1691 ConfigManager::
1692 FRAG_TIME) registerEnumIn("configKeys", ConfigManager::WHITE_SKULL_TIME)
1693 registerEnumIn(
1694 "configKeys",
1695 ConfigManager::
1696 GAME_PORT) registerEnumIn("configKeys", ConfigManager::
1697 LOGIN_PORT)
1698 registerEnumIn(
1699 "confi"
1700 "gKey"
1701 "s",
1702 ConfigManager::
1703 STATUS_PORT)
1704 registerEnumIn(
1705 "c"
1706 "o"
1707 "n"
1708 "f"
1709 "i"
1710 "g"
1711 "K"
1712 "e"
1713 "y"
1714 "s",
1715 ConfigManager::
1716 STAIRHOP_DELAY)
1717 registerEnumIn(
1718 "configKe"
1719 "ys",
1720 ConfigManager::
1721 MARKET_OFFER_DURATION)
1722 registerEnumIn(
1723 "conf"
1724 "igKe"
1725 "ys",
1726 ConfigManager::
1727 CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES)
1728 registerEnumIn(
1729 "configKeys",
1730 ConfigManager::
1731 MAX_MARKET_OFFERS_AT_A_TIME_PER_PLAYER)
1732 registerEnumIn(
1733 "configKeys",
1734 ConfigManager::
1735 EXP_FROM_PLAYERS_LEVEL_RANGE)
1736 registerEnumIn(
1737 "configKeys",
1738 ConfigManager::
1739 MAX_PACKETS_PER_SECOND)
1740
1741 // os
1742 registerMethod("os", "mtime", LuaScriptInterface::luaSystemTime);
1743
1744 // table
1745 registerMethod("table", "create", LuaScriptInterface::luaTableCreate);
1746
1747 // Game
1748 registerTable("Game");
1749
1750 registerMethod("Game", "getSpectators",
1751 LuaScriptInterface::luaGameGetSpectators);
1752 registerMethod("Game", "getPlayers", LuaScriptInterface::luaGameGetPlayers);
1753 registerMethod("Game", "loadMap", LuaScriptInterface::luaGameLoadMap);
1754
1755 registerMethod("Game", "getExperienceStage",
1756 LuaScriptInterface::luaGameGetExperienceStage);
1757 registerMethod("Game", "getMonsterCount",
1758 LuaScriptInterface::luaGameGetMonsterCount);
1759 registerMethod("Game", "getPlayerCount",
1760 LuaScriptInterface::luaGameGetPlayerCount);
1761 registerMethod("Game", "getNpcCount", LuaScriptInterface::luaGameGetNpcCount);
1762 registerMethod("Game", "getMonsterTypes",
1763 LuaScriptInterface::luaGameGetMonsterTypes);
1764
1765 registerMethod("Game", "getShaderNameByID",
1766 LuaScriptInterface::luaPlayerGetShaderNameByID);
1767
1768 registerMethod("Game", "getTowns", LuaScriptInterface::luaGameGetTowns);
1769 registerMethod("Game", "getHouses", LuaScriptInterface::luaGameGetHouses);
1770
1771 registerMethod("Game", "getGameState",
1772 LuaScriptInterface::luaGameGetGameState);
1773 registerMethod("Game", "setGameState",
1774 LuaScriptInterface::luaGameSetGameState);
1775
1776 registerMethod("Game", "getWorldType",
1777 LuaScriptInterface::luaGameGetWorldType);
1778 registerMethod("Game", "setWorldType",
1779 LuaScriptInterface::luaGameSetWorldType);
1780
1781 registerMethod("Game", "getReturnMessage",
1782 LuaScriptInterface::luaGameGetReturnMessage);
1783
1784 registerMethod("Game", "createItem", LuaScriptInterface::luaGameCreateItem);
1785 registerMethod("Game", "createContainer",
1786 LuaScriptInterface::luaGameCreateContainer);
1787 registerMethod("Game", "createMonster",
1788 LuaScriptInterface::luaGameCreateMonster);
1789 registerMethod("Game", "createNpc", LuaScriptInterface::luaGameCreateNpc);
1790 registerMethod("Game", "createTile", LuaScriptInterface::luaGameCreateTile);
1791 registerMethod("Game", "createMonsterType",
1792 LuaScriptInterface::luaGameCreateMonsterType);
1793
1794 registerMethod("Game", "startRaid", LuaScriptInterface::luaGameStartRaid);
1795
1796 registerMethod("Game", "getClientVersion",
1797 LuaScriptInterface::luaGameGetClientVersion);
1798
1799 registerMethod("Game", "reload", LuaScriptInterface::luaGameReload);
1800
1801 // Variant
1802 registerClass("Variant", "", LuaScriptInterface::luaVariantCreate);
1803
1804 registerMethod("Variant", "getNumber",
1805 LuaScriptInterface::luaVariantGetNumber);
1806 registerMethod("Variant", "getString",
1807 LuaScriptInterface::luaVariantGetString);
1808 registerMethod("Variant", "getPosition",
1809 LuaScriptInterface::luaVariantGetPosition);
1810
1811 // Position
1812 registerClass("Position", "", LuaScriptInterface::luaPositionCreate);
1813 registerMetaMethod("Position", "__add", LuaScriptInterface::luaPositionAdd);
1814 registerMetaMethod("Position", "__sub", LuaScriptInterface::luaPositionSub);
1815 registerMetaMethod("Position", "__eq",
1816 LuaScriptInterface::luaPositionCompare);
1817
1818 registerMethod("Position", "getDistance",
1819 LuaScriptInterface::luaPositionGetDistance);
1820 registerMethod("Position", "isSightClear",
1821 LuaScriptInterface::luaPositionIsSightClear);
1822
1823 registerMethod("Position", "sendMagicEffect",
1824 LuaScriptInterface::luaPositionSendMagicEffect);
1825 registerMethod("Position", "sendDistanceEffect",
1826 LuaScriptInterface::luaPositionSendDistanceEffect);
1827
1828 // Tile
1829 registerClass("Tile", "", LuaScriptInterface::luaTileCreate);
1830 registerMetaMethod("Tile", "__eq", LuaScriptInterface::luaUserdataCompare);
1831
1832 registerMethod("Tile", "getPosition", LuaScriptInterface::luaTileGetPosition);
1833 registerMethod("Tile", "getGround", LuaScriptInterface::luaTileGetGround);
1834 registerMethod("Tile", "getThing", LuaScriptInterface::luaTileGetThing);
1835 registerMethod("Tile", "getThingCount",
1836 LuaScriptInterface::luaTileGetThingCount);
1837 registerMethod("Tile", "getTopVisibleThing",
1838 LuaScriptInterface::luaTileGetTopVisibleThing);
1839
1840 registerMethod("Tile", "getTopTopItem",
1841 LuaScriptInterface::luaTileGetTopTopItem);
1842 registerMethod("Tile", "getTopDownItem",
1843 LuaScriptInterface::luaTileGetTopDownItem);
1844 registerMethod("Tile", "getFieldItem",
1845 LuaScriptInterface::luaTileGetFieldItem);
1846
1847 registerMethod("Tile", "getItemById", LuaScriptInterface::luaTileGetItemById);
1848 registerMethod("Tile", "getItemByType",
1849 LuaScriptInterface::luaTileGetItemByType);
1850 registerMethod("Tile", "getItemByTopOrder",
1851 LuaScriptInterface::luaTileGetItemByTopOrder);
1852 registerMethod("Tile", "getItemCountById",
1853 LuaScriptInterface::luaTileGetItemCountById);
1854
1855 registerMethod("Tile", "getBottomCreature",
1856 LuaScriptInterface::luaTileGetBottomCreature);
1857 registerMethod("Tile", "getTopCreature",
1858 LuaScriptInterface::luaTileGetTopCreature);
1859 registerMethod("Tile", "getBottomVisibleCreature",
1860 LuaScriptInterface::luaTileGetBottomVisibleCreature);
1861 registerMethod("Tile", "getTopVisibleCreature",
1862 LuaScriptInterface::luaTileGetTopVisibleCreature);
1863
1864 registerMethod("Tile", "getItems", LuaScriptInterface::luaTileGetItems);
1865 registerMethod("Tile", "getItemCount",
1866 LuaScriptInterface::luaTileGetItemCount);
1867 registerMethod("Tile", "getDownItemCount",
1868 LuaScriptInterface::luaTileGetDownItemCount);
1869 registerMethod("Tile", "getTopItemCount",
1870 LuaScriptInterface::luaTileGetTopItemCount);
1871
1872 registerMethod("Tile", "getCreatures",
1873 LuaScriptInterface::luaTileGetCreatures);
1874 registerMethod("Tile", "getCreatureCount",
1875 LuaScriptInterface::luaTileGetCreatureCount);
1876
1877 registerMethod("Tile", "getThingIndex",
1878 LuaScriptInterface::luaTileGetThingIndex);
1879
1880 registerMethod("Tile", "hasProperty", LuaScriptInterface::luaTileHasProperty);
1881 registerMethod("Tile", "hasFlag", LuaScriptInterface::luaTileHasFlag);
1882
1883 registerMethod("Tile", "queryAdd", LuaScriptInterface::luaTileQueryAdd);
1884 registerMethod("Tile", "addItem", LuaScriptInterface::luaTileAddItem);
1885 registerMethod("Tile", "addItemEx", LuaScriptInterface::luaTileAddItemEx);
1886
1887 registerMethod("Tile", "getHouse", LuaScriptInterface::luaTileGetHouse);
1888
1889 // NetworkMessage
1890 registerClass("NetworkMessage", "",
1891 LuaScriptInterface::luaNetworkMessageCreate);
1892 registerMetaMethod("NetworkMessage", "__eq",
1893 LuaScriptInterface::luaUserdataCompare);
1894 registerMetaMethod("NetworkMessage", "__gc",
1895 LuaScriptInterface::luaNetworkMessageDelete);
1896 registerMethod("NetworkMessage", "delete",
1897 LuaScriptInterface::luaNetworkMessageDelete);
1898
1899 registerMethod("NetworkMessage", "getByte",
1900 LuaScriptInterface::luaNetworkMessageGetByte);
1901 registerMethod("NetworkMessage", "getU16",
1902 LuaScriptInterface::luaNetworkMessageGetU16);
1903 registerMethod("NetworkMessage", "getU32",
1904 LuaScriptInterface::luaNetworkMessageGetU32);
1905 registerMethod("NetworkMessage", "getU64",
1906 LuaScriptInterface::luaNetworkMessageGetU64);
1907 registerMethod("NetworkMessage", "getString",
1908 LuaScriptInterface::luaNetworkMessageGetString);
1909 registerMethod("NetworkMessage", "getPosition",
1910 LuaScriptInterface::luaNetworkMessageGetPosition);
1911
1912 registerMethod("NetworkMessage", "addByte",
1913 LuaScriptInterface::luaNetworkMessageAddByte);
1914 registerMethod("NetworkMessage", "addU16",
1915 LuaScriptInterface::luaNetworkMessageAddU16);
1916 registerMethod("NetworkMessage", "addU32",
1917 LuaScriptInterface::luaNetworkMessageAddU32);
1918 registerMethod("NetworkMessage", "addU64",
1919 LuaScriptInterface::luaNetworkMessageAddU64);
1920 registerMethod("NetworkMessage", "addString",
1921 LuaScriptInterface::luaNetworkMessageAddString);
1922 registerMethod("NetworkMessage", "addPosition",
1923 LuaScriptInterface::luaNetworkMessageAddPosition);
1924 registerMethod("NetworkMessage", "addDouble",
1925 LuaScriptInterface::luaNetworkMessageAddDouble);
1926 registerMethod("NetworkMessage", "addItem",
1927 LuaScriptInterface::luaNetworkMessageAddItem);
1928 registerMethod("NetworkMessage", "addItemId",
1929 LuaScriptInterface::luaNetworkMessageAddItemId);
1930
1931 registerMethod("NetworkMessage", "reset",
1932 LuaScriptInterface::luaNetworkMessageReset);
1933 registerMethod("NetworkMessage", "skipBytes",
1934 LuaScriptInterface::luaNetworkMessageSkipBytes);
1935 registerMethod("NetworkMessage", "sendToPlayer",
1936 LuaScriptInterface::luaNetworkMessageSendToPlayer);
1937
1938 // ModalWindow
1939 registerClass("ModalWindow", "", LuaScriptInterface::luaModalWindowCreate);
1940 registerMetaMethod("ModalWindow", "__eq",
1941 LuaScriptInterface::luaUserdataCompare);
1942 registerMetaMethod("ModalWindow", "__gc",
1943 LuaScriptInterface::luaModalWindowDelete);
1944 registerMethod("ModalWindow", "delete",
1945 LuaScriptInterface::luaModalWindowDelete);
1946
1947 registerMethod("ModalWindow", "getId",
1948 LuaScriptInterface::luaModalWindowGetId);
1949 registerMethod("ModalWindow", "getTitle",
1950 LuaScriptInterface::luaModalWindowGetTitle);
1951 registerMethod("ModalWindow", "getMessage",
1952 LuaScriptInterface::luaModalWindowGetMessage);
1953
1954 registerMethod("ModalWindow", "setTitle",
1955 LuaScriptInterface::luaModalWindowSetTitle);
1956 registerMethod("ModalWindow", "setMessage",
1957 LuaScriptInterface::luaModalWindowSetMessage);
1958
1959 registerMethod("ModalWindow", "getButtonCount",
1960 LuaScriptInterface::luaModalWindowGetButtonCount);
1961 registerMethod("ModalWindow", "getChoiceCount",
1962 LuaScriptInterface::luaModalWindowGetChoiceCount);
1963
1964 registerMethod("ModalWindow", "addButton",
1965 LuaScriptInterface::luaModalWindowAddButton);
1966 registerMethod("ModalWindow", "addChoice",
1967 LuaScriptInterface::luaModalWindowAddChoice);
1968
1969 registerMethod("ModalWindow", "getDefaultEnterButton",
1970 LuaScriptInterface::luaModalWindowGetDefaultEnterButton);
1971 registerMethod("ModalWindow", "setDefaultEnterButton",
1972 LuaScriptInterface::luaModalWindowSetDefaultEnterButton);
1973
1974 registerMethod("ModalWindow", "getDefaultEscapeButton",
1975 LuaScriptInterface::luaModalWindowGetDefaultEscapeButton);
1976 registerMethod("ModalWindow", "setDefaultEscapeButton",
1977 LuaScriptInterface::luaModalWindowSetDefaultEscapeButton);
1978
1979 registerMethod("ModalWindow", "hasPriority",
1980 LuaScriptInterface::luaModalWindowHasPriority);
1981 registerMethod("ModalWindow", "setPriority",
1982 LuaScriptInterface::luaModalWindowSetPriority);
1983
1984 registerMethod("ModalWindow", "sendToPlayer",
1985 LuaScriptInterface::luaModalWindowSendToPlayer);
1986
1987 // Item
1988 registerClass("Item", "", LuaScriptInterface::luaItemCreate);
1989 registerMetaMethod("Item", "__eq", LuaScriptInterface::luaUserdataCompare);
1990
1991 registerMethod("Item", "isItem", LuaScriptInterface::luaItemIsItem);
1992
1993 registerMethod("Item", "getParent", LuaScriptInterface::luaItemGetParent);
1994 registerMethod("Item", "getTopParent",
1995 LuaScriptInterface::luaItemGetTopParent);
1996
1997 registerMethod("Item", "getId", LuaScriptInterface::luaItemGetId);
1998
1999 registerMethod("Item", "clone", LuaScriptInterface::luaItemClone);
2000 registerMethod("Item", "split", LuaScriptInterface::luaItemSplit);
2001 registerMethod("Item", "remove", LuaScriptInterface::luaItemRemove);
2002
2003 registerMethod("Item", "getUniqueId", LuaScriptInterface::luaItemGetUniqueId);
2004 registerMethod("Item", "getActionId", LuaScriptInterface::luaItemGetActionId);
2005 registerMethod("Item", "setActionId", LuaScriptInterface::luaItemSetActionId);
2006
2007 registerMethod("Item", "getCount", LuaScriptInterface::luaItemGetCount);
2008 registerMethod("Item", "getCharges", LuaScriptInterface::luaItemGetCharges);
2009 registerMethod("Item", "getFluidType",
2010 LuaScriptInterface::luaItemGetFluidType);
2011 registerMethod("Item", "getWeight", LuaScriptInterface::luaItemGetWeight);
2012
2013 registerMethod("Item", "getSubType", LuaScriptInterface::luaItemGetSubType);
2014
2015 registerMethod("Item", "getName", LuaScriptInterface::luaItemGetName);
2016 registerMethod("Item", "getPluralName",
2017 LuaScriptInterface::luaItemGetPluralName);
2018 registerMethod("Item", "getArticle", LuaScriptInterface::luaItemGetArticle);
2019
2020 registerMethod("Item", "getPosition", LuaScriptInterface::luaItemGetPosition);
2021 registerMethod("Item", "getTile", LuaScriptInterface::luaItemGetTile);
2022
2023 registerMethod("Item", "hasAttribute",
2024 LuaScriptInterface::luaItemHasAttribute);
2025 registerMethod("Item", "getAttribute",
2026 LuaScriptInterface::luaItemGetAttribute);
2027 registerMethod("Item", "setAttribute",
2028 LuaScriptInterface::luaItemSetAttribute);
2029 registerMethod("Item", "removeAttribute",
2030 LuaScriptInterface::luaItemRemoveAttribute);
2031 registerMethod("Item", "getCustomAttribute",
2032 LuaScriptInterface::luaItemGetCustomAttribute);
2033 registerMethod("Item", "setCustomAttribute",
2034 LuaScriptInterface::luaItemSetCustomAttribute);
2035 registerMethod("Item", "removeCustomAttribute",
2036 LuaScriptInterface::luaItemRemoveCustomAttribute);
2037
2038 registerMethod("Item", "moveTo", LuaScriptInterface::luaItemMoveTo);
2039 registerMethod("Item", "transform", LuaScriptInterface::luaItemTransform);
2040 registerMethod("Item", "decay", LuaScriptInterface::luaItemDecay);
2041
2042 registerMethod("Item", "getDescription",
2043 LuaScriptInterface::luaItemGetDescription);
2044
2045 registerMethod("Item", "hasProperty", LuaScriptInterface::luaItemHasProperty);
2046 registerMethod("Item", "isLoadedFromMap",
2047 LuaScriptInterface::luaItemIsLoadedFromMap);
2048
2049 // Container
2050 registerClass("Container", "Item", LuaScriptInterface::luaContainerCreate);
2051 registerMetaMethod("Container", "__eq",
2052 LuaScriptInterface::luaUserdataCompare);
2053
2054 registerMethod("Container", "getSize",
2055 LuaScriptInterface::luaContainerGetSize);
2056 registerMethod("Container", "getCapacity",
2057 LuaScriptInterface::luaContainerGetCapacity);
2058 registerMethod("Container", "getEmptySlots",
2059 LuaScriptInterface::luaContainerGetEmptySlots);
2060 registerMethod("Container", "getContentDescription",
2061 LuaScriptInterface::luaContainerGetContentDescription);
2062 registerMethod("Container", "getItemHoldingCount",
2063 LuaScriptInterface::luaContainerGetItemHoldingCount);
2064 registerMethod("Container", "getItemCountById",
2065 LuaScriptInterface::luaContainerGetItemCountById);
2066
2067 registerMethod("Container", "getItem",
2068 LuaScriptInterface::luaContainerGetItem);
2069 registerMethod("Container", "hasItem",
2070 LuaScriptInterface::luaContainerHasItem);
2071 registerMethod("Container", "addItem",
2072 LuaScriptInterface::luaContainerAddItem);
2073 registerMethod("Container", "addItemEx",
2074 LuaScriptInterface::luaContainerAddItemEx);
2075 registerMethod("Container", "getCorpseOwner",
2076 LuaScriptInterface::luaContainerGetCorpseOwner);
2077
2078 // Teleport
2079 registerClass("Teleport", "Item", LuaScriptInterface::luaTeleportCreate);
2080 registerMetaMethod("Teleport", "__eq",
2081 LuaScriptInterface::luaUserdataCompare);
2082
2083 registerMethod("Teleport", "getDestination",
2084 LuaScriptInterface::luaTeleportGetDestination);
2085 registerMethod("Teleport", "setDestination",
2086 LuaScriptInterface::luaTeleportSetDestination);
2087
2088 // Creature
2089 registerClass("Creature", "", LuaScriptInterface::luaCreatureCreate);
2090 registerMetaMethod("Creature", "__eq",
2091 LuaScriptInterface::luaUserdataCompare);
2092
2093 registerMethod("Creature", "getEvents",
2094 LuaScriptInterface::luaCreatureGetEvents);
2095 registerMethod("Creature", "registerEvent",
2096 LuaScriptInterface::luaCreatureRegisterEvent);
2097 registerMethod("Creature", "unregisterEvent",
2098 LuaScriptInterface::luaCreatureUnregisterEvent);
2099
2100 registerMethod("Creature", "isRemoved",
2101 LuaScriptInterface::luaCreatureIsRemoved);
2102 registerMethod("Creature", "isCreature",
2103 LuaScriptInterface::luaCreatureIsCreature);
2104 registerMethod("Creature", "isInGhostMode",
2105 LuaScriptInterface::luaCreatureIsInGhostMode);
2106 registerMethod("Creature", "isHealthHidden",
2107 LuaScriptInterface::luaCreatureIsHealthHidden);
2108 registerMethod("Creature", "isImmune",
2109 LuaScriptInterface::luaCreatureIsImmune);
2110
2111 registerMethod("Creature", "canSee", LuaScriptInterface::luaCreatureCanSee);
2112 registerMethod("Creature", "canSeeCreature",
2113 LuaScriptInterface::luaCreatureCanSeeCreature);
2114
2115 registerMethod("Creature", "getParent",
2116 LuaScriptInterface::luaCreatureGetParent);
2117
2118 registerMethod("Creature", "getId", LuaScriptInterface::luaCreatureGetId);
2119 registerMethod("Creature", "getName", LuaScriptInterface::luaCreatureGetName);
2120
2121 registerMethod("Creature", "getTarget",
2122 LuaScriptInterface::luaCreatureGetTarget);
2123 registerMethod("Creature", "setTarget",
2124 LuaScriptInterface::luaCreatureSetTarget);
2125
2126 registerMethod("Creature", "getFollowCreature",
2127 LuaScriptInterface::luaCreatureGetFollowCreature);
2128 registerMethod("Creature", "setFollowCreature",
2129 LuaScriptInterface::luaCreatureSetFollowCreature);
2130
2131 registerMethod("Creature", "getMaster",
2132 LuaScriptInterface::luaCreatureGetMaster);
2133 registerMethod("Creature", "setMaster",
2134 LuaScriptInterface::luaCreatureSetMaster);
2135
2136 registerMethod("Creature", "getLight",
2137 LuaScriptInterface::luaCreatureGetLight);
2138 registerMethod("Creature", "setLight",
2139 LuaScriptInterface::luaCreatureSetLight);
2140
2141 registerMethod("Creature", "getSpeed",
2142 LuaScriptInterface::luaCreatureGetSpeed);
2143 registerMethod("Creature", "getBaseSpeed",
2144 LuaScriptInterface::luaCreatureGetBaseSpeed);
2145 registerMethod("Creature", "changeSpeed",
2146 LuaScriptInterface::luaCreatureChangeSpeed);
2147
2148 registerMethod("Creature", "setDropLoot",
2149 LuaScriptInterface::luaCreatureSetDropLoot);
2150 registerMethod("Creature", "setSkillLoss",
2151 LuaScriptInterface::luaCreatureSetSkillLoss);
2152
2153 registerMethod("Creature", "getPosition",
2154 LuaScriptInterface::luaCreatureGetPosition);
2155 registerMethod("Creature", "getTile", LuaScriptInterface::luaCreatureGetTile);
2156 registerMethod("Creature", "getDirection",
2157 LuaScriptInterface::luaCreatureGetDirection);
2158 registerMethod("Creature", "setDirection",
2159 LuaScriptInterface::luaCreatureSetDirection);
2160
2161 registerMethod("Creature", "getHealth",
2162 LuaScriptInterface::luaCreatureGetHealth);
2163 registerMethod("Creature", "setHealth",
2164 LuaScriptInterface::luaCreatureSetHealth);
2165 registerMethod("Creature", "addHealth",
2166 LuaScriptInterface::luaCreatureAddHealth);
2167 registerMethod("Creature", "getMaxHealth",
2168 LuaScriptInterface::luaCreatureGetMaxHealth);
2169 registerMethod("Creature", "setMaxHealth",
2170 LuaScriptInterface::luaCreatureSetMaxHealth);
2171 registerMethod("Creature", "setHiddenHealth",
2172 LuaScriptInterface::luaCreatureSetHiddenHealth);
2173
2174 registerMethod("Creature", "getSkull",
2175 LuaScriptInterface::luaCreatureGetSkull);
2176 registerMethod("Creature", "setSkull",
2177 LuaScriptInterface::luaCreatureSetSkull);
2178
2179 registerMethod("Creature", "getOutfit",
2180 LuaScriptInterface::luaCreatureGetOutfit);
2181 registerMethod("Creature", "setOutfit",
2182 LuaScriptInterface::luaCreatureSetOutfit);
2183
2184 registerMethod("Creature", "getCondition",
2185 LuaScriptInterface::luaCreatureGetCondition);
2186 registerMethod("Creature", "addCondition",
2187 LuaScriptInterface::luaCreatureAddCondition);
2188 registerMethod("Creature", "removeCondition",
2189 LuaScriptInterface::luaCreatureRemoveCondition);
2190 registerMethod("Creature", "hasCondition",
2191 LuaScriptInterface::luaCreatureHasCondition);
2192
2193 registerMethod("Creature", "remove", LuaScriptInterface::luaCreatureRemove);
2194 registerMethod("Creature", "teleportTo",
2195 LuaScriptInterface::luaCreatureTeleportTo);
2196 registerMethod("Creature", "say", LuaScriptInterface::luaCreatureSay);
2197
2198 registerMethod("Creature", "getDamageMap",
2199 LuaScriptInterface::luaCreatureGetDamageMap);
2200
2201 registerMethod("Creature", "getSummons",
2202 LuaScriptInterface::luaCreatureGetSummons);
2203
2204 registerMethod("Creature", "getDescription",
2205 LuaScriptInterface::luaCreatureGetDescription);
2206
2207 registerMethod("Creature", "getPathTo",
2208 LuaScriptInterface::luaCreatureGetPathTo);
2209 registerMethod("Creature", "move", LuaScriptInterface::luaCreatureMove);
2210
2211 registerMethod("Creature", "getZone", LuaScriptInterface::luaCreatureGetZone);
2212
2213 // Player
2214 registerClass("Player", "Creature", LuaScriptInterface::luaPlayerCreate);
2215 registerMetaMethod("Player", "__eq", LuaScriptInterface::luaUserdataCompare);
2216
2217 registerMethod("Player", "isPlayer", LuaScriptInterface::luaPlayerIsPlayer);
2218
2219 registerMethod("Player", "getGuid", LuaScriptInterface::luaPlayerGetGuid);
2220 registerMethod("Player", "getIp", LuaScriptInterface::luaPlayerGetIp);
2221 registerMethod("Player", "getAccountId",
2222 LuaScriptInterface::luaPlayerGetAccountId);
2223 registerMethod("Player", "getLastLoginSaved",
2224 LuaScriptInterface::luaPlayerGetLastLoginSaved);
2225 registerMethod("Player", "getLastLogout",
2226 LuaScriptInterface::luaPlayerGetLastLogout);
2227
2228 registerMethod("Player", "getAccountType",
2229 LuaScriptInterface::luaPlayerGetAccountType);
2230 registerMethod("Player", "setAccountType",
2231 LuaScriptInterface::luaPlayerSetAccountType);
2232
2233 registerMethod("Player", "getCapacity",
2234 LuaScriptInterface::luaPlayerGetCapacity);
2235 registerMethod("Player", "setCapacity",
2236 LuaScriptInterface::luaPlayerSetCapacity);
2237
2238 registerMethod("Player", "getFreeCapacity",
2239 LuaScriptInterface::luaPlayerGetFreeCapacity);
2240
2241 registerMethod("Player", "getDepotChest",
2242 LuaScriptInterface::luaPlayerGetDepotChest);
2243 registerMethod("Player", "getInbox", LuaScriptInterface::luaPlayerGetInbox);
2244
2245 registerMethod("Player", "getSkullTime",
2246 LuaScriptInterface::luaPlayerGetSkullTime);
2247 registerMethod("Player", "setSkullTime",
2248 LuaScriptInterface::luaPlayerSetSkullTime);
2249 registerMethod("Player", "getDeathPenalty",
2250 LuaScriptInterface::luaPlayerGetDeathPenalty);
2251
2252 registerMethod("Player", "getExperience",
2253 LuaScriptInterface::luaPlayerGetExperience);
2254 registerMethod("Player", "addExperience",
2255 LuaScriptInterface::luaPlayerAddExperience);
2256 registerMethod("Player", "removeExperience",
2257 LuaScriptInterface::luaPlayerRemoveExperience);
2258 registerMethod("Player", "getLevel", LuaScriptInterface::luaPlayerGetLevel);
2259
2260 registerMethod("Player", "getMagicLevel",
2261 LuaScriptInterface::luaPlayerGetMagicLevel);
2262 registerMethod("Player", "getBaseMagicLevel",
2263 LuaScriptInterface::luaPlayerGetBaseMagicLevel);
2264 registerMethod("Player", "getMana", LuaScriptInterface::luaPlayerGetMana);
2265 registerMethod("Player", "addMana", LuaScriptInterface::luaPlayerAddMana);
2266 registerMethod("Player", "getMaxMana",
2267 LuaScriptInterface::luaPlayerGetMaxMana);
2268 registerMethod("Player", "setMaxMana",
2269 LuaScriptInterface::luaPlayerSetMaxMana);
2270 registerMethod("Player", "getManaSpent",
2271 LuaScriptInterface::luaPlayerGetManaSpent);
2272 registerMethod("Player", "addManaSpent",
2273 LuaScriptInterface::luaPlayerAddManaSpent);
2274
2275 registerMethod("Player", "getBaseMaxHealth",
2276 LuaScriptInterface::luaPlayerGetBaseMaxHealth);
2277 registerMethod("Player", "getBaseMaxMana",
2278 LuaScriptInterface::luaPlayerGetBaseMaxMana);
2279
2280 registerMethod("Player", "getSkillLevel",
2281 LuaScriptInterface::luaPlayerGetSkillLevel);
2282 registerMethod("Player", "getEffectiveSkillLevel",
2283 LuaScriptInterface::luaPlayerGetEffectiveSkillLevel);
2284 registerMethod("Player", "getSkillPercent",
2285 LuaScriptInterface::luaPlayerGetSkillPercent);
2286 registerMethod("Player", "getSkillTries",
2287 LuaScriptInterface::luaPlayerGetSkillTries);
2288 registerMethod("Player", "addSkillTries",
2289 LuaScriptInterface::luaPlayerAddSkillTries);
2290 registerMethod("Player", "getSpecialSkill",
2291 LuaScriptInterface::luaPlayerGetSpecialSkill);
2292 registerMethod("Player", "addSpecialSkill",
2293 LuaScriptInterface::luaPlayerAddSpecialSkill);
2294
2295 registerMethod("Player", "addOfflineTrainingTime",
2296 LuaScriptInterface::luaPlayerAddOfflineTrainingTime);
2297 registerMethod("Player", "getOfflineTrainingTime",
2298 LuaScriptInterface::luaPlayerGetOfflineTrainingTime);
2299 registerMethod("Player", "removeOfflineTrainingTime",
2300 LuaScriptInterface::luaPlayerRemoveOfflineTrainingTime);
2301
2302 registerMethod("Player", "addOfflineTrainingTries",
2303 LuaScriptInterface::luaPlayerAddOfflineTrainingTries);
2304
2305 registerMethod("Player", "getOfflineTrainingSkill",
2306 LuaScriptInterface::luaPlayerGetOfflineTrainingSkill);
2307 registerMethod("Player", "setOfflineTrainingSkill",
2308 LuaScriptInterface::luaPlayerSetOfflineTrainingSkill);
2309
2310 registerMethod("Player", "getItemCount",
2311 LuaScriptInterface::luaPlayerGetItemCount);
2312 registerMethod("Player", "getItemById",
2313 LuaScriptInterface::luaPlayerGetItemById);
2314
2315 registerMethod("Player", "getVocation",
2316 LuaScriptInterface::luaPlayerGetVocation);
2317 registerMethod("Player", "setVocation",
2318 LuaScriptInterface::luaPlayerSetVocation);
2319
2320 registerMethod("Player", "getSex", LuaScriptInterface::luaPlayerGetSex);
2321 registerMethod("Player", "setSex", LuaScriptInterface::luaPlayerSetSex);
2322
2323 registerMethod("Player", "getTown", LuaScriptInterface::luaPlayerGetTown);
2324 registerMethod("Player", "setTown", LuaScriptInterface::luaPlayerSetTown);
2325
2326 registerMethod("Player", "getGuild", LuaScriptInterface::luaPlayerGetGuild);
2327 registerMethod("Player", "setGuild", LuaScriptInterface::luaPlayerSetGuild);
2328
2329 registerMethod("Player", "getGuildLevel",
2330 LuaScriptInterface::luaPlayerGetGuildLevel);
2331 registerMethod("Player", "setGuildLevel",
2332 LuaScriptInterface::luaPlayerSetGuildLevel);
2333
2334 registerMethod("Player", "getGuildNick",
2335 LuaScriptInterface::luaPlayerGetGuildNick);
2336 registerMethod("Player", "setGuildNick",
2337 LuaScriptInterface::luaPlayerSetGuildNick);
2338
2339 registerMethod("Player", "getGroup", LuaScriptInterface::luaPlayerGetGroup);
2340 registerMethod("Player", "setGroup", LuaScriptInterface::luaPlayerSetGroup);
2341
2342 registerMethod("Player", "getStamina",
2343 LuaScriptInterface::luaPlayerGetStamina);
2344 registerMethod("Player", "setStamina",
2345 LuaScriptInterface::luaPlayerSetStamina);
2346
2347 registerMethod("Player", "getSoul", LuaScriptInterface::luaPlayerGetSoul);
2348 registerMethod("Player", "addSoul", LuaScriptInterface::luaPlayerAddSoul);
2349 registerMethod("Player", "getMaxSoul",
2350 LuaScriptInterface::luaPlayerGetMaxSoul);
2351
2352 registerMethod("Player", "getBankBalance",
2353 LuaScriptInterface::luaPlayerGetBankBalance);
2354 registerMethod("Player", "setBankBalance",
2355 LuaScriptInterface::luaPlayerSetBankBalance);
2356
2357 registerMethod("Player", "getStorageValue",
2358 LuaScriptInterface::luaPlayerGetStorageValue);
2359 registerMethod("Player", "setStorageValue",
2360 LuaScriptInterface::luaPlayerSetStorageValue);
2361
2362 registerMethod("Player", "addItem", LuaScriptInterface::luaPlayerAddItem);
2363 registerMethod("Player", "addItemEx", LuaScriptInterface::luaPlayerAddItemEx);
2364 registerMethod("Player", "removeItem",
2365 LuaScriptInterface::luaPlayerRemoveItem);
2366
2367 registerMethod("Player", "getMoney", LuaScriptInterface::luaPlayerGetMoney);
2368 registerMethod("Player", "addMoney", LuaScriptInterface::luaPlayerAddMoney);
2369 registerMethod("Player", "removeMoney",
2370 LuaScriptInterface::luaPlayerRemoveMoney);
2371
2372 registerMethod("Player", "showTextDialog",
2373 LuaScriptInterface::luaPlayerShowTextDialog);
2374
2375 registerMethod("Player", "sendTextMessage",
2376 LuaScriptInterface::luaPlayerSendTextMessage);
2377 registerMethod("Player", "sendChannelMessage",
2378 LuaScriptInterface::luaPlayerSendChannelMessage);
2379 registerMethod("Player", "sendPrivateMessage",
2380 LuaScriptInterface::luaPlayerSendPrivateMessage);
2381 registerMethod("Player", "channelSay",
2382 LuaScriptInterface::luaPlayerChannelSay);
2383 registerMethod("Player", "openChannel",
2384 LuaScriptInterface::luaPlayerOpenChannel);
2385
2386 registerMethod("Player", "getSlotItem",
2387 LuaScriptInterface::luaPlayerGetSlotItem);
2388
2389 registerMethod("Player", "getParty", LuaScriptInterface::luaPlayerGetParty);
2390
2391 registerMethod("Player", "addOutfit", LuaScriptInterface::luaPlayerAddOutfit);
2392 registerMethod("Player", "addOutfitAddon",
2393 LuaScriptInterface::luaPlayerAddOutfitAddon);
2394 registerMethod("Player", "removeOutfit",
2395 LuaScriptInterface::luaPlayerRemoveOutfit);
2396 registerMethod("Player", "removeOutfitAddon",
2397 LuaScriptInterface::luaPlayerRemoveOutfitAddon);
2398 registerMethod("Player", "hasOutfit", LuaScriptInterface::luaPlayerHasOutfit);
2399 registerMethod("Player", "canWearOutfit",
2400 LuaScriptInterface::luaPlayerCanWearOutfit);
2401 registerMethod("Player", "sendOutfitWindow",
2402 LuaScriptInterface::luaPlayerSendOutfitWindow);
2403
2404 registerMethod("Player", "addMount", LuaScriptInterface::luaPlayerAddMount);
2405 registerMethod("Player", "removeMount",
2406 LuaScriptInterface::luaPlayerRemoveMount);
2407 registerMethod("Player", "hasMount", LuaScriptInterface::luaPlayerHasMount);
2408
2409 registerMethod("Player", "getPremiumDays",
2410 LuaScriptInterface::luaPlayerGetPremiumDays);
2411 registerMethod("Player", "addPremiumDays",
2412 LuaScriptInterface::luaPlayerAddPremiumDays);
2413 registerMethod("Player", "removePremiumDays",
2414 LuaScriptInterface::luaPlayerRemovePremiumDays);
2415
2416 registerMethod("Player", "hasBlessing",
2417 LuaScriptInterface::luaPlayerHasBlessing);
2418 registerMethod("Player", "addBlessing",
2419 LuaScriptInterface::luaPlayerAddBlessing);
2420 registerMethod("Player", "removeBlessing",
2421 LuaScriptInterface::luaPlayerRemoveBlessing);
2422
2423 registerMethod("Player", "canLearnSpell",
2424 LuaScriptInterface::luaPlayerCanLearnSpell);
2425 registerMethod("Player", "learnSpell",
2426 LuaScriptInterface::luaPlayerLearnSpell);
2427 registerMethod("Player", "forgetSpell",
2428 LuaScriptInterface::luaPlayerForgetSpell);
2429 registerMethod("Player", "hasLearnedSpell",
2430 LuaScriptInterface::luaPlayerHasLearnedSpell);
2431
2432 registerMethod("Player", "sendTutorial",
2433 LuaScriptInterface::luaPlayerSendTutorial);
2434 registerMethod("Player", "addMapMark",
2435 LuaScriptInterface::luaPlayerAddMapMark);
2436
2437 registerMethod("Player", "save", LuaScriptInterface::luaPlayerSave);
2438 registerMethod("Player", "popupFYI", LuaScriptInterface::luaPlayerPopupFYI);
2439
2440 registerMethod("Player", "isPzLocked",
2441 LuaScriptInterface::luaPlayerIsPzLocked);
2442
2443 registerMethod("Player", "getClient", LuaScriptInterface::luaPlayerGetClient);
2444
2445 registerMethod("Player", "getHouse", LuaScriptInterface::luaPlayerGetHouse);
2446 registerMethod("Player", "sendHouseWindow",
2447 LuaScriptInterface::luaPlayerSendHouseWindow);
2448 registerMethod("Player", "setEditHouse",
2449 LuaScriptInterface::luaPlayerSetEditHouse);
2450
2451 registerMethod("Player", "setGhostMode",
2452 LuaScriptInterface::luaPlayerSetGhostMode);
2453
2454 registerMethod("Player", "getContainerId",
2455 LuaScriptInterface::luaPlayerGetContainerId);
2456 registerMethod("Player", "getContainerById",
2457 LuaScriptInterface::luaPlayerGetContainerById);
2458 registerMethod("Player", "getContainerIndex",
2459 LuaScriptInterface::luaPlayerGetContainerIndex);
2460
2461 registerMethod("Player", "getInstantSpells",
2462 LuaScriptInterface::luaPlayerGetInstantSpells);
2463 registerMethod("Player", "canCast", LuaScriptInterface::luaPlayerCanCast);
2464
2465 registerMethod("Player", "hasChaseMode",
2466 LuaScriptInterface::luaPlayerHasChaseMode);
2467 registerMethod("Player", "hasSecureMode",
2468 LuaScriptInterface::luaPlayerHasSecureMode);
2469 registerMethod("Player", "getFightMode",
2470 LuaScriptInterface::luaPlayerGetFightMode);
2471 registerMethod("Player", "getAttackSpeed",
2472 LuaScriptInterface::luaPlayerGetAttackSpeed);
2473 registerMethod("Player", "setAttackSpeed",
2474 LuaScriptInterface::luaPlayerSetAttackSpeed);
2475 registerMethod("Player", "addAura", LuaScriptInterface::luaPlayerAddAura);
2476 registerMethod("Player", "addWings", LuaScriptInterface::luaPlayerAddWings);
2477 registerMethod("Player", "addShader", LuaScriptInterface::luaPlayerAddShader);
2478 registerMethod("Player", "addRuneEffect", LuaScriptInterface::luaPlayerAddRuneEffect);
2479 registerMethod("Player", "getCurrentRuneEffect", LuaScriptInterface::luaPlayerGetCurrentRuneEffect);
2480 registerMethod("Player", "setCurrentRuneEffect", LuaScriptInterface::luaPlayerSetCurrentRuneEffect);
2481
2482 // Monster
2483 registerClass("Monster", "Creature", LuaScriptInterface::luaMonsterCreate);
2484 registerMetaMethod("Monster", "__eq", LuaScriptInterface::luaUserdataCompare);
2485
2486 registerMethod("Monster", "isMonster",
2487 LuaScriptInterface::luaMonsterIsMonster);
2488
2489 registerMethod("Monster", "getType", LuaScriptInterface::luaMonsterGetType);
2490
2491 registerMethod("Monster", "getSpawnPosition",
2492 LuaScriptInterface::luaMonsterGetSpawnPosition);
2493 registerMethod("Monster", "isInSpawnRange",
2494 LuaScriptInterface::luaMonsterIsInSpawnRange);
2495
2496 registerMethod("Monster", "isIdle", LuaScriptInterface::luaMonsterIsIdle);
2497 registerMethod("Monster", "setIdle", LuaScriptInterface::luaMonsterSetIdle);
2498
2499 registerMethod("Monster", "isTarget", LuaScriptInterface::luaMonsterIsTarget);
2500 registerMethod("Monster", "isOpponent",
2501 LuaScriptInterface::luaMonsterIsOpponent);
2502 registerMethod("Monster", "isFriend", LuaScriptInterface::luaMonsterIsFriend);
2503
2504 registerMethod("Monster", "addFriend",
2505 LuaScriptInterface::luaMonsterAddFriend);
2506 registerMethod("Monster", "removeFriend",
2507 LuaScriptInterface::luaMonsterRemoveFriend);
2508 registerMethod("Monster", "getFriendList",
2509 LuaScriptInterface::luaMonsterGetFriendList);
2510 registerMethod("Monster", "getFriendCount",
2511 LuaScriptInterface::luaMonsterGetFriendCount);
2512
2513 registerMethod("Monster", "addTarget",
2514 LuaScriptInterface::luaMonsterAddTarget);
2515 registerMethod("Monster", "removeTarget",
2516 LuaScriptInterface::luaMonsterRemoveTarget);
2517 registerMethod("Monster", "getTargetList",
2518 LuaScriptInterface::luaMonsterGetTargetList);
2519 registerMethod("Monster", "getTargetCount",
2520 LuaScriptInterface::luaMonsterGetTargetCount);
2521
2522 registerMethod("Monster", "selectTarget",
2523 LuaScriptInterface::luaMonsterSelectTarget);
2524 registerMethod("Monster", "searchTarget",
2525 LuaScriptInterface::luaMonsterSearchTarget);
2526 registerMethod("Monster", "setName", LuaScriptInterface::luaMonsterSetName);
2527
2528 // Npc
2529 registerClass("Npc", "Creature", LuaScriptInterface::luaNpcCreate);
2530 registerMetaMethod("Npc", "__eq", LuaScriptInterface::luaUserdataCompare);
2531
2532 registerMethod("Npc", "isNpc", LuaScriptInterface::luaNpcIsNpc);
2533
2534 registerMethod("Npc", "setMasterPos", LuaScriptInterface::luaNpcSetMasterPos);
2535
2536 registerMethod("Npc", "getSpeechBubble",
2537 LuaScriptInterface::luaNpcGetSpeechBubble);
2538 registerMethod("Npc", "setSpeechBubble",
2539 LuaScriptInterface::luaNpcSetSpeechBubble);
2540
2541 // Guild
2542 registerClass("Guild", "", LuaScriptInterface::luaGuildCreate);
2543 registerMetaMethod("Guild", "__eq", LuaScriptInterface::luaUserdataCompare);
2544
2545 registerMethod("Guild", "getId", LuaScriptInterface::luaGuildGetId);
2546 registerMethod("Guild", "getName", LuaScriptInterface::luaGuildGetName);
2547 registerMethod("Guild", "getMembersOnline",
2548 LuaScriptInterface::luaGuildGetMembersOnline);
2549
2550 registerMethod("Guild", "addRank", LuaScriptInterface::luaGuildAddRank);
2551 registerMethod("Guild", "getRankById",
2552 LuaScriptInterface::luaGuildGetRankById);
2553 registerMethod("Guild", "getRankByLevel",
2554 LuaScriptInterface::luaGuildGetRankByLevel);
2555
2556 registerMethod("Guild", "getMotd", LuaScriptInterface::luaGuildGetMotd);
2557 registerMethod("Guild", "setMotd", LuaScriptInterface::luaGuildSetMotd);
2558
2559 // Group
2560 registerClass("Group", "", LuaScriptInterface::luaGroupCreate);
2561 registerMetaMethod("Group", "__eq", LuaScriptInterface::luaUserdataCompare);
2562
2563 registerMethod("Group", "getId", LuaScriptInterface::luaGroupGetId);
2564 registerMethod("Group", "getName", LuaScriptInterface::luaGroupGetName);
2565 registerMethod("Group", "getFlags", LuaScriptInterface::luaGroupGetFlags);
2566 registerMethod("Group", "getAccess", LuaScriptInterface::luaGroupGetAccess);
2567 registerMethod("Group", "getMaxDepotItems",
2568 LuaScriptInterface::luaGroupGetMaxDepotItems);
2569 registerMethod("Group", "getMaxVipEntries",
2570 LuaScriptInterface::luaGroupGetMaxVipEntries);
2571 registerMethod("Group", "hasFlag", LuaScriptInterface::luaGroupHasFlag);
2572
2573 // Vocation
2574 registerClass("Vocation", "", LuaScriptInterface::luaVocationCreate);
2575 registerMetaMethod("Vocation", "__eq",
2576 LuaScriptInterface::luaUserdataCompare);
2577
2578 registerMethod("Vocation", "getId", LuaScriptInterface::luaVocationGetId);
2579 registerMethod("Vocation", "getClientId",
2580 LuaScriptInterface::luaVocationGetClientId);
2581 registerMethod("Vocation", "getName", LuaScriptInterface::luaVocationGetName);
2582 registerMethod("Vocation", "getDescription",
2583 LuaScriptInterface::luaVocationGetDescription);
2584
2585 registerMethod("Vocation", "getRequiredSkillTries",
2586 LuaScriptInterface::luaVocationGetRequiredSkillTries);
2587 registerMethod("Vocation", "getRequiredManaSpent",
2588 LuaScriptInterface::luaVocationGetRequiredManaSpent);
2589
2590 registerMethod("Vocation", "getCapacityGain",
2591 LuaScriptInterface::luaVocationGetCapacityGain);
2592
2593 registerMethod("Vocation", "getHealthGain",
2594 LuaScriptInterface::luaVocationGetHealthGain);
2595 registerMethod("Vocation", "getHealthGainTicks",
2596 LuaScriptInterface::luaVocationGetHealthGainTicks);
2597 registerMethod("Vocation", "getHealthGainAmount",
2598 LuaScriptInterface::luaVocationGetHealthGainAmount);
2599
2600 registerMethod("Vocation", "getManaGain",
2601 LuaScriptInterface::luaVocationGetManaGain);
2602 registerMethod("Vocation", "getManaGainTicks",
2603 LuaScriptInterface::luaVocationGetManaGainTicks);
2604 registerMethod("Vocation", "getManaGainAmount",
2605 LuaScriptInterface::luaVocationGetManaGainAmount);
2606
2607 registerMethod("Vocation", "getMaxSoul",
2608 LuaScriptInterface::luaVocationGetMaxSoul);
2609 registerMethod("Vocation", "getSoulGainTicks",
2610 LuaScriptInterface::luaVocationGetSoulGainTicks);
2611
2612 registerMethod("Vocation", "getAttackSpeed",
2613 LuaScriptInterface::luaVocationGetAttackSpeed);
2614 registerMethod("Vocation", "getBaseSpeed",
2615 LuaScriptInterface::luaVocationGetBaseSpeed);
2616
2617 registerMethod("Vocation", "getDemotion",
2618 LuaScriptInterface::luaVocationGetDemotion);
2619 registerMethod("Vocation", "getPromotion",
2620 LuaScriptInterface::luaVocationGetPromotion);
2621
2622 // Town
2623 registerClass("Town", "", LuaScriptInterface::luaTownCreate);
2624 registerMetaMethod("Town", "__eq", LuaScriptInterface::luaUserdataCompare);
2625
2626 registerMethod("Town", "getId", LuaScriptInterface::luaTownGetId);
2627 registerMethod("Town", "getName", LuaScriptInterface::luaTownGetName);
2628 registerMethod("Town", "getTemplePosition",
2629 LuaScriptInterface::luaTownGetTemplePosition);
2630
2631 // House
2632 registerClass("House", "", LuaScriptInterface::luaHouseCreate);
2633 registerMetaMethod("House", "__eq", LuaScriptInterface::luaUserdataCompare);
2634
2635 registerMethod("House", "getId", LuaScriptInterface::luaHouseGetId);
2636 registerMethod("House", "getName", LuaScriptInterface::luaHouseGetName);
2637 registerMethod("House", "getTown", LuaScriptInterface::luaHouseGetTown);
2638 registerMethod("House", "getExitPosition",
2639 LuaScriptInterface::luaHouseGetExitPosition);
2640 registerMethod("House", "getRent", LuaScriptInterface::luaHouseGetRent);
2641
2642 registerMethod("House", "getOwnerGuid",
2643 LuaScriptInterface::luaHouseGetOwnerGuid);
2644 registerMethod("House", "setOwnerGuid",
2645 LuaScriptInterface::luaHouseSetOwnerGuid);
2646 registerMethod("House", "startTrade", LuaScriptInterface::luaHouseStartTrade);
2647
2648 registerMethod("House", "getBeds", LuaScriptInterface::luaHouseGetBeds);
2649 registerMethod("House", "getBedCount",
2650 LuaScriptInterface::luaHouseGetBedCount);
2651
2652 registerMethod("House", "getDoors", LuaScriptInterface::luaHouseGetDoors);
2653 registerMethod("House", "getDoorCount",
2654 LuaScriptInterface::luaHouseGetDoorCount);
2655 registerMethod("House", "getDoorIdByPosition",
2656 LuaScriptInterface::luaHouseGetDoorIdByPosition);
2657
2658 registerMethod("House", "getTiles", LuaScriptInterface::luaHouseGetTiles);
2659 registerMethod("House", "getItems", LuaScriptInterface::luaHouseGetItems);
2660 registerMethod("House", "getTileCount",
2661 LuaScriptInterface::luaHouseGetTileCount);
2662
2663 registerMethod("House", "canEditAccessList",
2664 LuaScriptInterface::luaHouseCanEditAccessList);
2665 registerMethod("House", "getAccessList",
2666 LuaScriptInterface::luaHouseGetAccessList);
2667 registerMethod("House", "setAccessList",
2668 LuaScriptInterface::luaHouseSetAccessList);
2669
2670 registerMethod("House", "kickPlayer", LuaScriptInterface::luaHouseKickPlayer);
2671
2672 // ItemType
2673 registerClass("ItemType", "", LuaScriptInterface::luaItemTypeCreate);
2674 registerMetaMethod("ItemType", "__eq",
2675 LuaScriptInterface::luaUserdataCompare);
2676
2677 registerMethod("ItemType", "isCorpse",
2678 LuaScriptInterface::luaItemTypeIsCorpse);
2679 registerMethod("ItemType", "isDoor", LuaScriptInterface::luaItemTypeIsDoor);
2680 registerMethod("ItemType", "isContainer",
2681 LuaScriptInterface::luaItemTypeIsContainer);
2682 registerMethod("ItemType", "isFluidContainer",
2683 LuaScriptInterface::luaItemTypeIsFluidContainer);
2684 registerMethod("ItemType", "isMovable",
2685 LuaScriptInterface::luaItemTypeIsMovable);
2686 registerMethod("ItemType", "isRune", LuaScriptInterface::luaItemTypeIsRune);
2687 registerMethod("ItemType", "isStackable",
2688 LuaScriptInterface::luaItemTypeIsStackable);
2689 registerMethod("ItemType", "isReadable",
2690 LuaScriptInterface::luaItemTypeIsReadable);
2691 registerMethod("ItemType", "isWritable",
2692 LuaScriptInterface::luaItemTypeIsWritable);
2693 registerMethod("ItemType", "isBlocking",
2694 LuaScriptInterface::luaItemTypeIsBlocking);
2695 registerMethod("ItemType", "isGroundTile",
2696 LuaScriptInterface::luaItemTypeIsGroundTile);
2697 registerMethod("ItemType", "isMagicField",
2698 LuaScriptInterface::luaItemTypeIsMagicField);
2699 registerMethod("ItemType", "isUseable",
2700 LuaScriptInterface::luaItemTypeIsUseable);
2701 registerMethod("ItemType", "isPickupable",
2702 LuaScriptInterface::luaItemTypeIsPickupable);
2703
2704 registerMethod("ItemType", "getType", LuaScriptInterface::luaItemTypeGetType);
2705 registerMethod("ItemType", "getId", LuaScriptInterface::luaItemTypeGetId);
2706 registerMethod("ItemType", "getClientId",
2707 LuaScriptInterface::luaItemTypeGetClientId);
2708 registerMethod("ItemType", "getName", LuaScriptInterface::luaItemTypeGetName);
2709 registerMethod("ItemType", "getPluralName",
2710 LuaScriptInterface::luaItemTypeGetPluralName);
2711 registerMethod("ItemType", "getArticle",
2712 LuaScriptInterface::luaItemTypeGetArticle);
2713 registerMethod("ItemType", "getDescription",
2714 LuaScriptInterface::luaItemTypeGetDescription);
2715 registerMethod("ItemType", "getSlotPosition",
2716 LuaScriptInterface::luaItemTypeGetSlotPosition);
2717
2718 registerMethod("ItemType", "getCharges",
2719 LuaScriptInterface::luaItemTypeGetCharges);
2720 registerMethod("ItemType", "getFluidSource",
2721 LuaScriptInterface::luaItemTypeGetFluidSource);
2722 registerMethod("ItemType", "getCapacity",
2723 LuaScriptInterface::luaItemTypeGetCapacity);
2724 registerMethod("ItemType", "getWeight",
2725 LuaScriptInterface::luaItemTypeGetWeight);
2726
2727 registerMethod("ItemType", "getHitChance",
2728 LuaScriptInterface::luaItemTypeGetHitChance);
2729 registerMethod("ItemType", "getShootRange",
2730 LuaScriptInterface::luaItemTypeGetShootRange);
2731
2732 registerMethod("ItemType", "getAttack",
2733 LuaScriptInterface::luaItemTypeGetAttack);
2734 registerMethod("ItemType", "getDefense",
2735 LuaScriptInterface::luaItemTypeGetDefense);
2736 registerMethod("ItemType", "getExtraDefense",
2737 LuaScriptInterface::luaItemTypeGetExtraDefense);
2738 registerMethod("ItemType", "getArmor",
2739 LuaScriptInterface::luaItemTypeGetArmor);
2740 registerMethod("ItemType", "getWeaponType",
2741 LuaScriptInterface::luaItemTypeGetWeaponType);
2742
2743 registerMethod("ItemType", "getElementType",
2744 LuaScriptInterface::luaItemTypeGetElementType);
2745 registerMethod("ItemType", "getElementDamage",
2746 LuaScriptInterface::luaItemTypeGetElementDamage);
2747
2748 registerMethod("ItemType", "getTransformEquipId",
2749 LuaScriptInterface::luaItemTypeGetTransformEquipId);
2750 registerMethod("ItemType", "getTransformDeEquipId",
2751 LuaScriptInterface::luaItemTypeGetTransformDeEquipId);
2752 registerMethod("ItemType", "getDestroyId",
2753 LuaScriptInterface::luaItemTypeGetDestroyId);
2754 registerMethod("ItemType", "getDecayId",
2755 LuaScriptInterface::luaItemTypeGetDecayId);
2756 registerMethod("ItemType", "getRequiredLevel",
2757 LuaScriptInterface::luaItemTypeGetRequiredLevel);
2758 registerMethod("ItemType", "getAmmoType",
2759 LuaScriptInterface::luaItemTypeGetAmmoType);
2760 registerMethod("ItemType", "getCorpseType",
2761 LuaScriptInterface::luaItemTypeGetCorpseType);
2762
2763 registerMethod("ItemType", "hasSubType",
2764 LuaScriptInterface::luaItemTypeHasSubType);
2765
2766 // Combat
2767 registerClass("Combat", "", LuaScriptInterface::luaCombatCreate);
2768 registerMetaMethod("Combat", "__eq", LuaScriptInterface::luaUserdataCompare);
2769
2770 registerMethod("Combat", "setParameter",
2771 LuaScriptInterface::luaCombatSetParameter);
2772 registerMethod("Combat", "setFormula",
2773 LuaScriptInterface::luaCombatSetFormula);
2774
2775 registerMethod("Combat", "setArea", LuaScriptInterface::luaCombatSetArea);
2776 registerMethod("Combat", "addCondition",
2777 LuaScriptInterface::luaCombatAddCondition);
2778 registerMethod("Combat", "clearConditions",
2779 LuaScriptInterface::luaCombatClearConditions);
2780 registerMethod("Combat", "setCallback",
2781 LuaScriptInterface::luaCombatSetCallback);
2782 registerMethod("Combat", "setOrigin", LuaScriptInterface::luaCombatSetOrigin);
2783
2784 registerMethod("Combat", "execute", LuaScriptInterface::luaCombatExecute);
2785
2786 // Condition
2787 registerClass("Condition", "", LuaScriptInterface::luaConditionCreate);
2788 registerMetaMethod("Condition", "__eq",
2789 LuaScriptInterface::luaUserdataCompare);
2790 registerMetaMethod("Condition", "__gc",
2791 LuaScriptInterface::luaConditionDelete);
2792 registerMethod("Condition", "delete", LuaScriptInterface::luaConditionDelete);
2793
2794 registerMethod("Condition", "getId", LuaScriptInterface::luaConditionGetId);
2795 registerMethod("Condition", "getSubId",
2796 LuaScriptInterface::luaConditionGetSubId);
2797 registerMethod("Condition", "getType",
2798 LuaScriptInterface::luaConditionGetType);
2799 registerMethod("Condition", "getIcons",
2800 LuaScriptInterface::luaConditionGetIcons);
2801 registerMethod("Condition", "getEndTime",
2802 LuaScriptInterface::luaConditionGetEndTime);
2803
2804 registerMethod("Condition", "clone", LuaScriptInterface::luaConditionClone);
2805
2806 registerMethod("Condition", "getTicks",
2807 LuaScriptInterface::luaConditionGetTicks);
2808 registerMethod("Condition", "setTicks",
2809 LuaScriptInterface::luaConditionSetTicks);
2810
2811 registerMethod("Condition", "setParameter",
2812 LuaScriptInterface::luaConditionSetParameter);
2813 registerMethod("Condition", "setFormula",
2814 LuaScriptInterface::luaConditionSetFormula);
2815 registerMethod("Condition", "setOutfit",
2816 LuaScriptInterface::luaConditionSetOutfit);
2817
2818 registerMethod("Condition", "addDamage",
2819 LuaScriptInterface::luaConditionAddDamage);
2820
2821 // MonsterType
2822 registerClass("MonsterType", "", LuaScriptInterface::luaMonsterTypeCreate);
2823 registerMetaMethod("MonsterType", "__eq",
2824 LuaScriptInterface::luaUserdataCompare);
2825
2826 registerMethod("MonsterType", "isAttackable",
2827 LuaScriptInterface::luaMonsterTypeIsAttackable);
2828 registerMethod("MonsterType", "isConvinceable",
2829 LuaScriptInterface::luaMonsterTypeIsConvinceable);
2830 registerMethod("MonsterType", "isSummonable",
2831 LuaScriptInterface::luaMonsterTypeIsSummonable);
2832 registerMethod("MonsterType", "isIllusionable",
2833 LuaScriptInterface::luaMonsterTypeIsIllusionable);
2834 registerMethod("MonsterType", "isHostile",
2835 LuaScriptInterface::luaMonsterTypeIsHostile);
2836 registerMethod("MonsterType", "isPushable",
2837 LuaScriptInterface::luaMonsterTypeIsPushable);
2838 registerMethod("MonsterType", "isHealthHidden",
2839 LuaScriptInterface::luaMonsterTypeIsHealthHidden);
2840 registerMethod("MonsterType", "isBoss",
2841 LuaScriptInterface::luaMonsterTypeIsBoss);
2842
2843 registerMethod("MonsterType", "canPushItems",
2844 LuaScriptInterface::luaMonsterTypeCanPushItems);
2845 registerMethod("MonsterType", "canPushCreatures",
2846 LuaScriptInterface::luaMonsterTypeCanPushCreatures);
2847
2848 registerMethod("MonsterType", "name", LuaScriptInterface::luaMonsterTypeName);
2849
2850 registerMethod("MonsterType", "nameDescription",
2851 LuaScriptInterface::luaMonsterTypeNameDescription);
2852
2853 registerMethod("MonsterType", "health",
2854 LuaScriptInterface::luaMonsterTypeHealth);
2855 registerMethod("MonsterType", "maxHealth",
2856 LuaScriptInterface::luaMonsterTypeMaxHealth);
2857 registerMethod("MonsterType", "runHealth",
2858 LuaScriptInterface::luaMonsterTypeRunHealth);
2859 registerMethod("MonsterType", "experience",
2860 LuaScriptInterface::luaMonsterTypeExperience);
2861 registerMethod("MonsterType", "skull",
2862 LuaScriptInterface::luaMonsterTypeSkull);
2863
2864 registerMethod("MonsterType", "combatImmunities",
2865 LuaScriptInterface::luaMonsterTypeCombatImmunities);
2866 registerMethod("MonsterType", "conditionImmunities",
2867 LuaScriptInterface::luaMonsterTypeConditionImmunities);
2868
2869 registerMethod("MonsterType", "getAttackList",
2870 LuaScriptInterface::luaMonsterTypeGetAttackList);
2871 registerMethod("MonsterType", "addAttack",
2872 LuaScriptInterface::luaMonsterTypeAddAttack);
2873
2874 registerMethod("MonsterType", "getDefenseList",
2875 LuaScriptInterface::luaMonsterTypeGetDefenseList);
2876 registerMethod("MonsterType", "addDefense",
2877 LuaScriptInterface::luaMonsterTypeAddDefense);
2878
2879 registerMethod("MonsterType", "getElementList",
2880 LuaScriptInterface::luaMonsterTypeGetElementList);
2881 registerMethod("MonsterType", "addElement",
2882 LuaScriptInterface::luaMonsterTypeAddElement);
2883
2884 registerMethod("MonsterType", "getVoices",
2885 LuaScriptInterface::luaMonsterTypeGetVoices);
2886 registerMethod("MonsterType", "addVoice",
2887 LuaScriptInterface::luaMonsterTypeAddVoice);
2888
2889 registerMethod("MonsterType", "getLoot",
2890 LuaScriptInterface::luaMonsterTypeGetLoot);
2891 registerMethod("MonsterType", "addLoot",
2892 LuaScriptInterface::luaMonsterTypeAddLoot);
2893
2894 registerMethod("MonsterType", "getCreatureEvents",
2895 LuaScriptInterface::luaMonsterTypeGetCreatureEvents);
2896 registerMethod("MonsterType", "registerEvent",
2897 LuaScriptInterface::luaMonsterTypeRegisterEvent);
2898
2899 registerMethod("MonsterType", "eventType",
2900 LuaScriptInterface::luaMonsterTypeEventType);
2901 registerMethod("MonsterType", "onThink",
2902 LuaScriptInterface::luaMonsterTypeEventOnCallback);
2903 registerMethod("MonsterType", "onAppear",
2904 LuaScriptInterface::luaMonsterTypeEventOnCallback);
2905 registerMethod("MonsterType", "onDisappear",
2906 LuaScriptInterface::luaMonsterTypeEventOnCallback);
2907 registerMethod("MonsterType", "onMove",
2908 LuaScriptInterface::luaMonsterTypeEventOnCallback);
2909 registerMethod("MonsterType", "onSay",
2910 LuaScriptInterface::luaMonsterTypeEventOnCallback);
2911
2912 registerMethod("MonsterType", "getSummonList",
2913 LuaScriptInterface::luaMonsterTypeGetSummonList);
2914 registerMethod("MonsterType", "addSummon",
2915 LuaScriptInterface::luaMonsterTypeAddSummon);
2916
2917 registerMethod("MonsterType", "maxSummons",
2918 LuaScriptInterface::luaMonsterTypeMaxSummons);
2919
2920 registerMethod("MonsterType", "armor",
2921 LuaScriptInterface::luaMonsterTypeArmor);
2922 registerMethod("MonsterType", "defense",
2923 LuaScriptInterface::luaMonsterTypeDefense);
2924 registerMethod("MonsterType", "outfit",
2925 LuaScriptInterface::luaMonsterTypeOutfit);
2926 registerMethod("MonsterType", "race", LuaScriptInterface::luaMonsterTypeRace);
2927 registerMethod("MonsterType", "corpseId",
2928 LuaScriptInterface::luaMonsterTypeCorpseId);
2929 registerMethod("MonsterType", "manaCost",
2930 LuaScriptInterface::luaMonsterTypeManaCost);
2931 registerMethod("MonsterType", "baseSpeed",
2932 LuaScriptInterface::luaMonsterTypeBaseSpeed);
2933 registerMethod("MonsterType", "light",
2934 LuaScriptInterface::luaMonsterTypeLight);
2935
2936 registerMethod("MonsterType", "staticAttackChance",
2937 LuaScriptInterface::luaMonsterTypeStaticAttackChance);
2938 registerMethod("MonsterType", "targetDistance",
2939 LuaScriptInterface::luaMonsterTypeTargetDistance);
2940 registerMethod("MonsterType", "yellChance",
2941 LuaScriptInterface::luaMonsterTypeYellChance);
2942 registerMethod("MonsterType", "yellSpeedTicks",
2943 LuaScriptInterface::luaMonsterTypeYellSpeedTicks);
2944 registerMethod("MonsterType", "changeTargetChance",
2945 LuaScriptInterface::luaMonsterTypeChangeTargetChance);
2946 registerMethod("MonsterType", "changeTargetSpeed",
2947 LuaScriptInterface::luaMonsterTypeChangeTargetSpeed);
2948
2949 // Loot
2950 registerClass("Loot", "", LuaScriptInterface::luaCreateLoot);
2951 registerMetaMethod("Loot", "__gc", LuaScriptInterface::luaDeleteLoot);
2952 registerMethod("Loot", "delete", LuaScriptInterface::luaDeleteLoot);
2953
2954 registerMethod("Loot", "setId", LuaScriptInterface::luaLootSetId);
2955 registerMethod("Loot", "setMaxCount", LuaScriptInterface::luaLootSetMaxCount);
2956 registerMethod("Loot", "setSubType", LuaScriptInterface::luaLootSetSubType);
2957 registerMethod("Loot", "setChance", LuaScriptInterface::luaLootSetChance);
2958 registerMethod("Loot", "setActionId", LuaScriptInterface::luaLootSetActionId);
2959 registerMethod("Loot", "setDescription",
2960 LuaScriptInterface::luaLootSetDescription);
2961 registerMethod("Loot", "addChildLoot",
2962 LuaScriptInterface::luaLootAddChildLoot);
2963
2964 // MonsterSpell
2965 registerClass("MonsterSpell", "", LuaScriptInterface::luaCreateMonsterSpell);
2966 registerMetaMethod("MonsterSpell", "__gc",
2967 LuaScriptInterface::luaDeleteMonsterSpell);
2968 registerMethod("MonsterSpell", "delete",
2969 LuaScriptInterface::luaDeleteMonsterSpell);
2970
2971 registerMethod("MonsterSpell", "setType",
2972 LuaScriptInterface::luaMonsterSpellSetType);
2973 registerMethod("MonsterSpell", "setScriptName",
2974 LuaScriptInterface::luaMonsterSpellSetScriptName);
2975 registerMethod("MonsterSpell", "setChance",
2976 LuaScriptInterface::luaMonsterSpellSetChance);
2977 registerMethod("MonsterSpell", "setInterval",
2978 LuaScriptInterface::luaMonsterSpellSetInterval);
2979 registerMethod("MonsterSpell", "setRange",
2980 LuaScriptInterface::luaMonsterSpellSetRange);
2981 registerMethod("MonsterSpell", "setCombatValue",
2982 LuaScriptInterface::luaMonsterSpellSetCombatValue);
2983 registerMethod("MonsterSpell", "setCombatType",
2984 LuaScriptInterface::luaMonsterSpellSetCombatType);
2985 registerMethod("MonsterSpell", "setAttackValue",
2986 LuaScriptInterface::luaMonsterSpellSetAttackValue);
2987 registerMethod("MonsterSpell", "setNeedTarget",
2988 LuaScriptInterface::luaMonsterSpellSetNeedTarget);
2989 registerMethod("MonsterSpell", "setCombatLength",
2990 LuaScriptInterface::luaMonsterSpellSetCombatLength);
2991 registerMethod("MonsterSpell", "setCombatSpread",
2992 LuaScriptInterface::luaMonsterSpellSetCombatSpread);
2993 registerMethod("MonsterSpell", "setCombatRadius",
2994 LuaScriptInterface::luaMonsterSpellSetCombatRadius);
2995 registerMethod("MonsterSpell", "setConditionType",
2996 LuaScriptInterface::luaMonsterSpellSetConditionType);
2997 registerMethod("MonsterSpell", "setConditionDamage",
2998 LuaScriptInterface::luaMonsterSpellSetConditionDamage);
2999 registerMethod("MonsterSpell", "setConditionSpeedChange",
3000 LuaScriptInterface::luaMonsterSpellSetConditionSpeedChange);
3001 registerMethod("MonsterSpell", "setConditionDuration",
3002 LuaScriptInterface::luaMonsterSpellSetConditionDuration);
3003 registerMethod("MonsterSpell", "setConditionTickInterval",
3004 LuaScriptInterface::luaMonsterSpellSetConditionTickInterval);
3005 registerMethod("MonsterSpell", "setCombatShootEffect",
3006 LuaScriptInterface::luaMonsterSpellSetCombatShootEffect);
3007 registerMethod("MonsterSpell", "setCombatEffect",
3008 LuaScriptInterface::luaMonsterSpellSetCombatEffect);
3009
3010 // Party
3011 registerClass("Party", "", LuaScriptInterface::luaPartyCreate);
3012 registerMetaMethod("Party", "__eq", LuaScriptInterface::luaUserdataCompare);
3013
3014 registerMethod("Party", "disband", LuaScriptInterface::luaPartyDisband);
3015
3016 registerMethod("Party", "getLeader", LuaScriptInterface::luaPartyGetLeader);
3017 registerMethod("Party", "setLeader", LuaScriptInterface::luaPartySetLeader);
3018
3019 registerMethod("Party", "getMembers", LuaScriptInterface::luaPartyGetMembers);
3020 registerMethod("Party", "getMemberCount",
3021 LuaScriptInterface::luaPartyGetMemberCount);
3022
3023 registerMethod("Party", "getInvitees",
3024 LuaScriptInterface::luaPartyGetInvitees);
3025 registerMethod("Party", "getInviteeCount",
3026 LuaScriptInterface::luaPartyGetInviteeCount);
3027
3028 registerMethod("Party", "addInvite", LuaScriptInterface::luaPartyAddInvite);
3029 registerMethod("Party", "removeInvite",
3030 LuaScriptInterface::luaPartyRemoveInvite);
3031
3032 registerMethod("Party", "addMember", LuaScriptInterface::luaPartyAddMember);
3033 registerMethod("Party", "removeMember",
3034 LuaScriptInterface::luaPartyRemoveMember);
3035
3036 registerMethod("Party", "isSharedExperienceActive",
3037 LuaScriptInterface::luaPartyIsSharedExperienceActive);
3038 registerMethod("Party", "isSharedExperienceEnabled",
3039 LuaScriptInterface::luaPartyIsSharedExperienceEnabled);
3040 registerMethod("Party", "shareExperience",
3041 LuaScriptInterface::luaPartyShareExperience);
3042 registerMethod("Party", "setSharedExperience",
3043 LuaScriptInterface::luaPartySetSharedExperience);
3044
3045 // Spells
3046 registerClass("Spell", "", LuaScriptInterface::luaSpellCreate);
3047 registerMetaMethod("Spell", "__eq", LuaScriptInterface::luaUserdataCompare);
3048
3049 registerMethod("Spell", "onCastSpell",
3050 LuaScriptInterface::luaSpellOnCastSpell);
3051 registerMethod("Spell", "register", LuaScriptInterface::luaSpellRegister);
3052 registerMethod("Spell", "name", LuaScriptInterface::luaSpellName);
3053 registerMethod("Spell", "id", LuaScriptInterface::luaSpellId);
3054 registerMethod("Spell", "group", LuaScriptInterface::luaSpellGroup);
3055 registerMethod("Spell", "cooldown", LuaScriptInterface::luaSpellCooldown);
3056 registerMethod("Spell", "groupCooldown",
3057 LuaScriptInterface::luaSpellGroupCooldown);
3058 registerMethod("Spell", "level", LuaScriptInterface::luaSpellLevel);
3059 registerMethod("Spell", "magicLevel", LuaScriptInterface::luaSpellMagicLevel);
3060 registerMethod("Spell", "mana", LuaScriptInterface::luaSpellMana);
3061 registerMethod("Spell", "manaPercent",
3062 LuaScriptInterface::luaSpellManaPercent);
3063 registerMethod("Spell", "soul", LuaScriptInterface::luaSpellSoul);
3064 registerMethod("Spell", "range", LuaScriptInterface::luaSpellRange);
3065 registerMethod("Spell", "isPremium", LuaScriptInterface::luaSpellPremium);
3066 registerMethod("Spell", "isEnabled", LuaScriptInterface::luaSpellEnabled);
3067 registerMethod("Spell", "needTarget", LuaScriptInterface::luaSpellNeedTarget);
3068 registerMethod("Spell", "needWeapon", LuaScriptInterface::luaSpellNeedWeapon);
3069 registerMethod("Spell", "needLearn", LuaScriptInterface::luaSpellNeedLearn);
3070 registerMethod("Spell", "isSelfTarget",
3071 LuaScriptInterface::luaSpellSelfTarget);
3072 registerMethod("Spell", "isBlocking", LuaScriptInterface::luaSpellBlocking);
3073 registerMethod("Spell", "isAggressive",
3074 LuaScriptInterface::luaSpellAggressive);
3075 registerMethod("Spell", "vocation", LuaScriptInterface::luaSpellVocation);
3076
3077 // only for InstantSpell
3078 registerMethod("Spell", "words", LuaScriptInterface::luaSpellWords);
3079 registerMethod("Spell", "needDirection",
3080 LuaScriptInterface::luaSpellNeedDirection);
3081 registerMethod("Spell", "hasParams", LuaScriptInterface::luaSpellHasParams);
3082 registerMethod("Spell", "hasPlayerNameParam",
3083 LuaScriptInterface::luaSpellHasPlayerNameParam);
3084 registerMethod("Spell", "needCasterTargetOrDirection",
3085 LuaScriptInterface::luaSpellNeedCasterTargetOrDirection);
3086 registerMethod("Spell", "isBlockingWalls",
3087 LuaScriptInterface::luaSpellIsBlockingWalls);
3088
3089 // only for RuneSpells
3090 registerMethod("Spell", "runeId", LuaScriptInterface::luaSpellRuneId);
3091 registerMethod("Spell", "charges", LuaScriptInterface::luaSpellCharges);
3092 registerMethod("Spell", "allowFarUse",
3093 LuaScriptInterface::luaSpellAllowFarUse);
3094 registerMethod("Spell", "blockWalls", LuaScriptInterface::luaSpellBlockWalls);
3095 registerMethod("Spell", "checkFloor", LuaScriptInterface::luaSpellCheckFloor);
3096
3097 // Action
3098 registerClass("Action", "", LuaScriptInterface::luaCreateAction);
3099 registerMethod("Action", "onUse", LuaScriptInterface::luaActionOnUse);
3100 registerMethod("Action", "register", LuaScriptInterface::luaActionRegister);
3101 registerMethod("Action", "id", LuaScriptInterface::luaActionItemId);
3102 registerMethod("Action", "aid", LuaScriptInterface::luaActionActionId);
3103 registerMethod("Action", "uid", LuaScriptInterface::luaActionUniqueId);
3104 registerMethod("Action", "allowFarUse",
3105 LuaScriptInterface::luaActionAllowFarUse);
3106 registerMethod("Action", "blockWalls",
3107 LuaScriptInterface::luaActionBlockWalls);
3108 registerMethod("Action", "checkFloor",
3109 LuaScriptInterface::luaActionCheckFloor);
3110
3111 // TalkAction
3112 registerClass("TalkAction", "", LuaScriptInterface::luaCreateTalkaction);
3113 registerMethod("TalkAction", "onSay", LuaScriptInterface::luaTalkactionOnSay);
3114 registerMethod("TalkAction", "register",
3115 LuaScriptInterface::luaTalkactionRegister);
3116 registerMethod("TalkAction", "separator",
3117 LuaScriptInterface::luaTalkactionSeparator);
3118
3119 // CreatureEvent
3120 registerClass("CreatureEvent", "",
3121 LuaScriptInterface::luaCreateCreatureEvent);
3122 registerMethod("CreatureEvent", "type",
3123 LuaScriptInterface::luaCreatureEventType);
3124 registerMethod("CreatureEvent", "register",
3125 LuaScriptInterface::luaCreatureEventRegister);
3126 registerMethod("CreatureEvent", "onLogin",
3127 LuaScriptInterface::luaCreatureEventOnCallback);
3128 registerMethod("CreatureEvent", "onLogout",
3129 LuaScriptInterface::luaCreatureEventOnCallback);
3130 registerMethod("CreatureEvent", "onThink",
3131 LuaScriptInterface::luaCreatureEventOnCallback);
3132 registerMethod("CreatureEvent", "onPrepareDeath",
3133 LuaScriptInterface::luaCreatureEventOnCallback);
3134 registerMethod("CreatureEvent", "onDeath",
3135 LuaScriptInterface::luaCreatureEventOnCallback);
3136 registerMethod("CreatureEvent", "onKill",
3137 LuaScriptInterface::luaCreatureEventOnCallback);
3138 registerMethod("CreatureEvent", "onAdvance",
3139 LuaScriptInterface::luaCreatureEventOnCallback);
3140 registerMethod("CreatureEvent", "onModalWindow",
3141 LuaScriptInterface::luaCreatureEventOnCallback);
3142 registerMethod("CreatureEvent", "onTextEdit",
3143 LuaScriptInterface::luaCreatureEventOnCallback);
3144 registerMethod("CreatureEvent", "onHealthChange",
3145 LuaScriptInterface::luaCreatureEventOnCallback);
3146 registerMethod("CreatureEvent", "onManaChange",
3147 LuaScriptInterface::luaCreatureEventOnCallback);
3148 registerMethod("CreatureEvent", "onExtendedOpcode",
3149 LuaScriptInterface::luaCreatureEventOnCallback);
3150
3151 // MoveEvent
3152 registerClass("MoveEvent", "", LuaScriptInterface::luaCreateMoveEvent);
3153 registerMethod("MoveEvent", "type", LuaScriptInterface::luaMoveEventType);
3154 registerMethod("MoveEvent", "register",
3155 LuaScriptInterface::luaMoveEventRegister);
3156 registerMethod("MoveEvent", "level", LuaScriptInterface::luaMoveEventLevel);
3157 registerMethod("MoveEvent", "magicLevel",
3158 LuaScriptInterface::luaMoveEventMagLevel);
3159 registerMethod("MoveEvent", "slot", LuaScriptInterface::luaMoveEventSlot);
3160 registerMethod("MoveEvent", "id", LuaScriptInterface::luaMoveEventItemId);
3161 registerMethod("MoveEvent", "aid", LuaScriptInterface::luaMoveEventActionId);
3162 registerMethod("MoveEvent", "uid", LuaScriptInterface::luaMoveEventUniqueId);
3163 registerMethod("MoveEvent", "position",
3164 LuaScriptInterface::luaMoveEventPosition);
3165 registerMethod("MoveEvent", "premium",
3166 LuaScriptInterface::luaMoveEventPremium);
3167 registerMethod("MoveEvent", "vocation",
3168 LuaScriptInterface::luaMoveEventVocation);
3169 registerMethod("MoveEvent", "onEquip",
3170 LuaScriptInterface::luaMoveEventOnCallback);
3171 registerMethod("MoveEvent", "onDeEquip",
3172 LuaScriptInterface::luaMoveEventOnCallback);
3173 registerMethod("MoveEvent", "onStepIn",
3174 LuaScriptInterface::luaMoveEventOnCallback);
3175 registerMethod("MoveEvent", "onStepOut",
3176 LuaScriptInterface::luaMoveEventOnCallback);
3177 registerMethod("MoveEvent", "onAddItem",
3178 LuaScriptInterface::luaMoveEventOnCallback);
3179 registerMethod("MoveEvent", "onRemoveItem",
3180 LuaScriptInterface::luaMoveEventOnCallback);
3181
3182 // GlobalEvent
3183 registerClass("GlobalEvent", "", LuaScriptInterface::luaCreateGlobalEvent);
3184 registerMethod("GlobalEvent", "type", LuaScriptInterface::luaGlobalEventType);
3185 registerMethod("GlobalEvent", "register",
3186 LuaScriptInterface::luaGlobalEventRegister);
3187 registerMethod("GlobalEvent", "time", LuaScriptInterface::luaGlobalEventTime);
3188 registerMethod("GlobalEvent", "interval",
3189 LuaScriptInterface::luaGlobalEventInterval);
3190 registerMethod("GlobalEvent", "onThink",
3191 LuaScriptInterface::luaGlobalEventOnCallback);
3192 registerMethod("GlobalEvent", "onTime",
3193 LuaScriptInterface::luaGlobalEventOnCallback);
3194 registerMethod("GlobalEvent", "onStartup",
3195 LuaScriptInterface::luaGlobalEventOnCallback);
3196 registerMethod("GlobalEvent", "onShutdown",
3197 LuaScriptInterface::luaGlobalEventOnCallback);
3198 registerMethod("GlobalEvent", "onRecord",
3199 LuaScriptInterface::luaGlobalEventOnCallback);
3200
3201 // Weapon
3202 registerClass("Weapon", "", LuaScriptInterface::luaCreateWeapon);
3203 registerMethod("Weapon", "action", LuaScriptInterface::luaWeaponAction);
3204 registerMethod("Weapon", "register", LuaScriptInterface::luaWeaponRegister);
3205 registerMethod("Weapon", "id", LuaScriptInterface::luaWeaponId);
3206 registerMethod("Weapon", "level", LuaScriptInterface::luaWeaponLevel);
3207 registerMethod("Weapon", "magicLevel",
3208 LuaScriptInterface::luaWeaponMagicLevel);
3209 registerMethod("Weapon", "mana", LuaScriptInterface::luaWeaponMana);
3210 registerMethod("Weapon", "manaPercent",
3211 LuaScriptInterface::luaWeaponManaPercent);
3212 registerMethod("Weapon", "health", LuaScriptInterface::luaWeaponHealth);
3213 registerMethod("Weapon", "healthPercent",
3214 LuaScriptInterface::luaWeaponHealthPercent);
3215 registerMethod("Weapon", "soul", LuaScriptInterface::luaWeaponSoul);
3216 registerMethod("Weapon", "breakChance",
3217 LuaScriptInterface::luaWeaponBreakChance);
3218 registerMethod("Weapon", "premium", LuaScriptInterface::luaWeaponPremium);
3219 registerMethod("Weapon", "wieldUnproperly",
3220 LuaScriptInterface::luaWeaponUnproperly);
3221 registerMethod("Weapon", "vocation", LuaScriptInterface::luaWeaponVocation);
3222 registerMethod("Weapon", "onUseWeapon",
3223 LuaScriptInterface::luaWeaponOnUseWeapon);
3224 registerMethod("Weapon", "element", LuaScriptInterface::luaWeaponElement);
3225 registerMethod("Weapon", "attack", LuaScriptInterface::luaWeaponAttack);
3226 registerMethod("Weapon", "defense", LuaScriptInterface::luaWeaponDefense);
3227 registerMethod("Weapon", "range", LuaScriptInterface::luaWeaponRange);
3228 registerMethod("Weapon", "charges", LuaScriptInterface::luaWeaponCharges);
3229 registerMethod("Weapon", "duration", LuaScriptInterface::luaWeaponDuration);
3230 registerMethod("Weapon", "decayTo", LuaScriptInterface::luaWeaponDecayTo);
3231 registerMethod("Weapon", "transformEquipTo",
3232 LuaScriptInterface::luaWeaponTransformEquipTo);
3233 registerMethod("Weapon", "transformDeEquipTo",
3234 LuaScriptInterface::luaWeaponTransformDeEquipTo);
3235 registerMethod("Weapon", "slotType", LuaScriptInterface::luaWeaponSlotType);
3236 registerMethod("Weapon", "hitChance", LuaScriptInterface::luaWeaponHitChance);
3237 registerMethod("Weapon", "extraElement",
3238 LuaScriptInterface::luaWeaponExtraElement);
3239
3240 // exclusively for distance weapons
3241 registerMethod("Weapon", "ammoType", LuaScriptInterface::luaWeaponAmmoType);
3242 registerMethod("Weapon", "maxHitChance",
3243 LuaScriptInterface::luaWeaponMaxHitChance);
3244
3245 // exclusively for wands
3246 registerMethod("Weapon", "damage", LuaScriptInterface::luaWeaponWandDamage);
3247
3248 // exclusively for wands & distance weapons
3249 registerMethod("Weapon", "shootType", LuaScriptInterface::luaWeaponShootType);
3250}
3251
3252#undef registerEnum
3253#undef registerEnumIn
3254
3255void LuaScriptInterface::registerClass(
3256 const std::string &className, const std::string &baseClass,
3257 lua_CFunction newFunction /* = nullptr*/) {
3258 // className = {}
3259 lua_newtable(luaState);
3260 lua_pushvalue(luaState, -1);
3261 lua_setglobal(luaState, className.c_str());
3262 int methods = lua_gettop(luaState);
3263
3264 // methodsTable = {}
3265 lua_newtable(luaState);
3266 int methodsTable = lua_gettop(luaState);
3267
3268 if (newFunction) {
3269 // className.__call = newFunction
3270 lua_pushcfunction(luaState, newFunction);
3271 lua_setfield(luaState, methodsTable, "__call");
3272 }
3273
3274 uint32_t parents = 0;
3275 if (!baseClass.empty()) {
3276 lua_getglobal(luaState, baseClass.c_str());
3277 lua_rawgeti(luaState, -1, 'p');
3278 parents = getNumber<uint32_t>(luaState, -1) + 1;
3279 lua_pop(luaState, 1);
3280 lua_setfield(luaState, methodsTable, "__index");
3281 }
3282
3283 // setmetatable(className, methodsTable)
3284 lua_setmetatable(luaState, methods);
3285
3286 // className.metatable = {}
3287 luaL_newmetatable(luaState, className.c_str());
3288 int metatable = lua_gettop(luaState);
3289
3290 // className.metatable.__metatable = className
3291 lua_pushvalue(luaState, methods);
3292 lua_setfield(luaState, metatable, "__metatable");
3293
3294 // className.metatable.__index = className
3295 lua_pushvalue(luaState, methods);
3296 lua_setfield(luaState, metatable, "__index");
3297
3298 // className.metatable['h'] = hash
3299 lua_pushnumber(luaState, std::hash<std::string>()(className));
3300 lua_rawseti(luaState, metatable, 'h');
3301
3302 // className.metatable['p'] = parents
3303 lua_pushnumber(luaState, parents);
3304 lua_rawseti(luaState, metatable, 'p');
3305
3306 // className.metatable['t'] = type
3307 if (className == "Item") {
3308 lua_pushnumber(luaState, LuaData_Item);
3309 } else if (className == "Container") {
3310 lua_pushnumber(luaState, LuaData_Container);
3311 } else if (className == "Teleport") {
3312 lua_pushnumber(luaState, LuaData_Teleport);
3313 } else if (className == "Player") {
3314 lua_pushnumber(luaState, LuaData_Player);
3315 } else if (className == "Monster") {
3316 lua_pushnumber(luaState, LuaData_Monster);
3317 } else if (className == "Npc") {
3318 lua_pushnumber(luaState, LuaData_Npc);
3319 } else if (className == "Tile") {
3320 lua_pushnumber(luaState, LuaData_Tile);
3321 } else {
3322 lua_pushnumber(luaState, LuaData_Unknown);
3323 }
3324 lua_rawseti(luaState, metatable, 't');
3325
3326 // pop className, className.metatable
3327 lua_pop(luaState, 2);
3328}
3329
3330void LuaScriptInterface::registerTable(const std::string &tableName) {
3331 // _G[tableName] = {}
3332 lua_newtable(luaState);
3333 lua_setglobal(luaState, tableName.c_str());
3334}
3335
3336void LuaScriptInterface::registerMethod(const std::string &globalName,
3337 const std::string &methodName,
3338 lua_CFunction func) {
3339 // globalName.methodName = func
3340 lua_getglobal(luaState, globalName.c_str());
3341 lua_pushcfunction(luaState, func);
3342 lua_setfield(luaState, -2, methodName.c_str());
3343
3344 // pop globalName
3345 lua_pop(luaState, 1);
3346}
3347
3348void LuaScriptInterface::registerMetaMethod(const std::string &className,
3349 const std::string &methodName,
3350 lua_CFunction func) {
3351 // className.metatable.methodName = func
3352 luaL_getmetatable(luaState, className.c_str());
3353 lua_pushcfunction(luaState, func);
3354 lua_setfield(luaState, -2, methodName.c_str());
3355
3356 // pop className.metatable
3357 lua_pop(luaState, 1);
3358}
3359
3360void LuaScriptInterface::registerGlobalMethod(const std::string &functionName,
3361 lua_CFunction func) {
3362 // _G[functionName] = func
3363 lua_pushcfunction(luaState, func);
3364 lua_setglobal(luaState, functionName.c_str());
3365}
3366
3367void LuaScriptInterface::registerVariable(const std::string &tableName,
3368 const std::string &name,
3369 lua_Number value) {
3370 // tableName.name = value
3371 lua_getglobal(luaState, tableName.c_str());
3372 setField(luaState, name.c_str(), value);
3373
3374 // pop tableName
3375 lua_pop(luaState, 1);
3376}
3377
3378void LuaScriptInterface::registerGlobalVariable(const std::string &name,
3379 lua_Number value) {
3380 // _G[name] = value
3381 lua_pushnumber(luaState, value);
3382 lua_setglobal(luaState, name.c_str());
3383}
3384
3385void LuaScriptInterface::registerGlobalBoolean(const std::string &name,
3386 bool value) {
3387 // _G[name] = value
3388 pushBoolean(luaState, value);
3389 lua_setglobal(luaState, name.c_str());
3390}
3391
3392int LuaScriptInterface::luaDoPlayerAddItem(lua_State *L) {
3393 // doPlayerAddItem(cid, itemid, <optional: default: 1> count/subtype,
3394 // <optional: default: 1> canDropOnMap) doPlayerAddItem(cid, itemid,
3395 // <optional: default: 1> count, <optional: default: 1> canDropOnMap,
3396 // <optional: default: 1>subtype)
3397 Player *player = getPlayer(L, 1);
3398 if (!player) {
3399 reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
3400 pushBoolean(L, false);
3401 return 1;
3402 }
3403
3404 uint16_t itemId = getNumber<uint16_t>(L, 2);
3405 int32_t count = getNumber<int32_t>(L, 3, 1);
3406 bool canDropOnMap = getBoolean(L, 4, true);
3407 uint16_t subType = getNumber<uint16_t>(L, 5, 1);
3408
3409 const ItemType &it = Item::items[itemId];
3410 int32_t itemCount;
3411
3412 auto parameters = lua_gettop(L);
3413 if (parameters > 4) {
3414 // subtype already supplied, count then is the amount
3415 itemCount = std::max<int32_t>(1, count);
3416 } else if (it.hasSubType()) {
3417 if (it.stackable) {
3418 itemCount =
3419 static_cast<int32_t>(std::ceil(static_cast<float>(count) / 100));
3420 } else {
3421 itemCount = 1;
3422 }
3423 subType = count;
3424 } else {
3425 itemCount = std::max<int32_t>(1, count);
3426 }
3427
3428 while (itemCount > 0) {
3429 uint16_t stackCount = subType;
3430 if (it.stackable && stackCount > 100) {
3431 stackCount = 100;
3432 }
3433
3434 Item *newItem = Item::CreateItem(itemId, stackCount);
3435 if (!newItem) {
3436 reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND));
3437 pushBoolean(L, false);
3438 return 1;
3439 }
3440
3441 if (it.stackable) {
3442 subType -= stackCount;
3443 }
3444
3445 ReturnValue ret =
3446 g_game.internalPlayerAddItem(player, newItem, canDropOnMap);
3447 if (ret != RETURNVALUE_NOERROR) {
3448 delete newItem;
3449 pushBoolean(L, false);
3450 return 1;
3451 }
3452
3453 if (--itemCount == 0) {
3454 if (newItem->getParent()) {
3455 uint32_t uid = getScriptEnv()->addThing(newItem);
3456 lua_pushnumber(L, uid);
3457 return 1;
3458 } else {
3459 // stackable item stacked with existing object, newItem will be released
3460 pushBoolean(L, false);
3461 return 1;
3462 }
3463 }
3464 }
3465
3466 pushBoolean(L, false);
3467 return 1;
3468}
3469
3470int LuaScriptInterface::luaDebugPrint(lua_State *L) {
3471 // debugPrint(text)
3472 reportErrorFunc(getString(L, -1));
3473 return 0;
3474}
3475
3476int LuaScriptInterface::luaGetWorldTime(lua_State *L) {
3477 // getWorldTime()
3478 uint32_t time = g_game.getLightHour();
3479 lua_pushnumber(L, time);
3480 return 1;
3481}
3482
3483int LuaScriptInterface::luaGetWorldLight(lua_State *L) {
3484 // getWorldLight()
3485 LightInfo lightInfo = g_game.getWorldLightInfo();
3486 lua_pushnumber(L, lightInfo.level);
3487 lua_pushnumber(L, lightInfo.color);
3488 return 2;
3489}
3490
3491int LuaScriptInterface::luaGetWorldUpTime(lua_State *L) {
3492 // getWorldUpTime()
3493 uint64_t uptime = (OTSYS_TIME() - ProtocolStatus::start) / 1000;
3494 lua_pushnumber(L, uptime);
3495 return 1;
3496}
3497
3498bool LuaScriptInterface::getArea(lua_State *L, std::list<uint32_t> &list,
3499 uint32_t &rows) {
3500 lua_pushnil(L);
3501 for (rows = 0; lua_next(L, -2) != 0; ++rows) {
3502 if (!isTable(L, -1)) {
3503 return false;
3504 }
3505
3506 lua_pushnil(L);
3507 while (lua_next(L, -2) != 0) {
3508 if (!isNumber(L, -1)) {
3509 return false;
3510 }
3511 list.push_back(getNumber<uint32_t>(L, -1));
3512 lua_pop(L, 1);
3513 }
3514
3515 lua_pop(L, 1);
3516 }
3517
3518 lua_pop(L, 1);
3519 return (rows != 0);
3520}
3521
3522int LuaScriptInterface::luaCreateCombatArea(lua_State *L) {
3523 // createCombatArea( {area}, <optional> {extArea} )
3524 ScriptEnvironment *env = getScriptEnv();
3525 if (env->getScriptId() != EVENT_ID_LOADING) {
3526 reportErrorFunc("This function can only be used while loading the script.");
3527 pushBoolean(L, false);
3528 return 1;
3529 }
3530
3531 uint32_t areaId =
3532 g_luaEnvironment.createAreaObject(env->getScriptInterface());
3533 AreaCombat *area = g_luaEnvironment.getAreaObject(areaId);
3534
3535 int parameters = lua_gettop(L);
3536 if (parameters >= 2) {
3537 uint32_t rowsExtArea;
3538 std::list<uint32_t> listExtArea;
3539 if (!isTable(L, 2) || !getArea(L, listExtArea, rowsExtArea)) {
3540 reportErrorFunc("Invalid extended area table.");
3541 pushBoolean(L, false);
3542 return 1;
3543 }
3544 area->setupExtArea(listExtArea, rowsExtArea);
3545 }
3546
3547 uint32_t rowsArea = 0;
3548 std::list<uint32_t> listArea;
3549 if (!isTable(L, 1) || !getArea(L, listArea, rowsArea)) {
3550 reportErrorFunc("Invalid area table.");
3551 pushBoolean(L, false);
3552 return 1;
3553 }
3554
3555 area->setupArea(listArea, rowsArea);
3556 lua_pushnumber(L, areaId);
3557 return 1;
3558}
3559
3560int LuaScriptInterface::luaDoAreaCombat(lua_State *L) {
3561 // doAreaCombat(cid, type, pos, area, min, max, effect[, origin =
3562 // ORIGIN_SPELL])
3563 Creature *creature = getCreature(L, 1);
3564 if (!creature && (!isNumber(L, 1) || getNumber<uint32_t>(L, 1) != 0)) {
3565 reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
3566 pushBoolean(L, false);
3567 return 1;
3568 }
3569
3570 uint32_t areaId = getNumber<uint32_t>(L, 4);
3571 const AreaCombat *area = g_luaEnvironment.getAreaObject(areaId);
3572 if (area || areaId == 0) {
3573 CombatType_t combatType = getNumber<CombatType_t>(L, 2);
3574
3575 CombatParams params;
3576 params.combatType = combatType;
3577 params.impactEffect = getNumber<uint16_t>(L, 7);
3578
3579 CombatDamage damage;
3580 damage.origin = getNumber<CombatOrigin>(L, 8, ORIGIN_SPELL);
3581 damage.primary.type = combatType;
3582 damage.primary.value =
3583 normal_random(getNumber<int32_t>(L, 6), getNumber<int32_t>(L, 5));
3584
3585 Combat::doAreaCombat(creature, getPosition(L, 3), area, damage, params);
3586 pushBoolean(L, true);
3587 } else {
3588 reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND));
3589 pushBoolean(L, false);
3590 }
3591 return 1;
3592}
3593
3594int LuaScriptInterface::luaDoTargetCombat(lua_State *L) {
3595 // doTargetCombat(cid, target, type, min, max, effect[, origin =
3596 // ORIGIN_SPELL])
3597 Creature *creature = getCreature(L, 1);
3598 if (!creature && (!isNumber(L, 1) || getNumber<uint32_t>(L, 1) != 0)) {
3599 reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
3600 pushBoolean(L, false);
3601 return 1;
3602 }
3603
3604 Creature *target = getCreature(L, 2);
3605 if (!target) {
3606 reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
3607 pushBoolean(L, false);
3608 return 1;
3609 }
3610
3611 CombatType_t combatType = getNumber<CombatType_t>(L, 3);
3612
3613 CombatParams params;
3614 params.combatType = combatType;
3615 params.impactEffect = getNumber<uint16_t>(L, 6);
3616
3617 CombatDamage damage;
3618 damage.origin = getNumber<CombatOrigin>(L, 7, ORIGIN_SPELL);
3619 damage.primary.type = combatType;
3620 damage.primary.value =
3621 normal_random(getNumber<int32_t>(L, 4), getNumber<int32_t>(L, 5));
3622
3623 Combat::doTargetCombat(creature, target, damage, params);
3624 pushBoolean(L, true);
3625 return 1;
3626}
3627
3628int LuaScriptInterface::luaDoChallengeCreature(lua_State *L) {
3629 // doChallengeCreature(cid, target)
3630 Creature *creature = getCreature(L, 1);
3631 if (!creature) {
3632 reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
3633 pushBoolean(L, false);
3634 return 1;
3635 }
3636
3637 Creature *target = getCreature(L, 2);
3638 if (!target) {
3639 reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
3640 pushBoolean(L, false);
3641 return 1;
3642 }
3643
3644 target->challengeCreature(creature);
3645 pushBoolean(L, true);
3646 return 1;
3647}
3648
3649int LuaScriptInterface::luaIsValidUID(lua_State *L) {
3650 // isValidUID(uid)
3651 pushBoolean(L, getScriptEnv()->getThingByUID(getNumber<uint32_t>(L, -1)) !=
3652 nullptr);
3653 return 1;
3654}
3655
3656int LuaScriptInterface::luaIsDepot(lua_State *L) {
3657 // isDepot(uid)
3658 Container *container =
3659 getScriptEnv()->getContainerByUID(getNumber<uint32_t>(L, -1));
3660 pushBoolean(L, container && container->getDepotLocker());
3661 return 1;
3662}
3663
3664int LuaScriptInterface::luaIsMoveable(lua_State *L) {
3665 // isMoveable(uid)
3666 // isMovable(uid)
3667 Thing *thing = getScriptEnv()->getThingByUID(getNumber<uint32_t>(L, -1));
3668 pushBoolean(L, thing && thing->isPushable());
3669 return 1;
3670}
3671
3672int LuaScriptInterface::luaDoAddContainerItem(lua_State *L) {
3673 // doAddContainerItem(uid, itemid, <optional> count/subtype)
3674 uint32_t uid = getNumber<uint32_t>(L, 1);
3675
3676 ScriptEnvironment *env = getScriptEnv();
3677 Container *container = env->getContainerByUID(uid);
3678 if (!container) {
3679 reportErrorFunc(getErrorDesc(LUA_ERROR_CONTAINER_NOT_FOUND));
3680 pushBoolean(L, false);
3681 return 1;
3682 }
3683
3684 uint16_t itemId = getNumber<uint16_t>(L, 2);
3685 const ItemType &it = Item::items[itemId];
3686
3687 int32_t itemCount = 1;
3688 int32_t subType = 1;
3689 uint32_t count = getNumber<uint32_t>(L, 3, 1);
3690
3691 if (it.hasSubType()) {
3692 if (it.stackable) {
3693 itemCount =
3694 static_cast<int32_t>(std::ceil(static_cast<float>(count) / 100));
3695 }
3696
3697 subType = count;
3698 } else {
3699 itemCount = std::max<int32_t>(1, count);
3700 }
3701
3702 while (itemCount > 0) {
3703 int32_t stackCount = std::min<int32_t>(100, subType);
3704 Item *newItem = Item::CreateItem(itemId, stackCount);
3705 if (!newItem) {
3706 reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND));
3707 pushBoolean(L, false);
3708 return 1;
3709 }
3710
3711 if (it.stackable) {
3712 subType -= stackCount;
3713 }
3714
3715 ReturnValue ret = g_game.internalAddItem(container, newItem);
3716 if (ret != RETURNVALUE_NOERROR) {
3717 delete newItem;
3718 pushBoolean(L, false);
3719 return 1;
3720 }
3721
3722 if (--itemCount == 0) {
3723 if (newItem->getParent()) {
3724 lua_pushnumber(L, env->addThing(newItem));
3725 } else {
3726 // stackable item stacked with existing object, newItem will be released
3727 pushBoolean(L, false);
3728 }
3729 return 1;
3730 }
3731 }
3732
3733 pushBoolean(L, false);
3734 return 1;
3735}
3736
3737int LuaScriptInterface::luaGetDepotId(lua_State *L) {
3738 // getDepotId(uid)
3739 uint32_t uid = getNumber<uint32_t>(L, -1);
3740
3741 Container *container = getScriptEnv()->getContainerByUID(uid);
3742 if (!container) {
3743 reportErrorFunc(getErrorDesc(LUA_ERROR_CONTAINER_NOT_FOUND));
3744 pushBoolean(L, false);
3745 return 1;
3746 }
3747
3748 DepotLocker *depotLocker = container->getDepotLocker();
3749 if (!depotLocker) {
3750 reportErrorFunc("Depot not found");
3751 pushBoolean(L, false);
3752 return 1;
3753 }
3754
3755 lua_pushnumber(L, depotLocker->getDepotId());
3756 return 1;
3757}
3758
3759int LuaScriptInterface::luaDoSetCreatureLight(lua_State *L) {
3760 // doSetCreatureLight(cid, lightLevel, lightColor, time)
3761 Creature *creature = getCreature(L, 1);
3762 if (!creature) {
3763 reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
3764 pushBoolean(L, false);
3765 return 1;
3766 }
3767
3768 uint16_t level = getNumber<uint16_t>(L, 2);
3769 uint16_t color = getNumber<uint16_t>(L, 3);
3770 uint32_t time = getNumber<uint32_t>(L, 4);
3771 Condition *condition = Condition::createCondition(
3772 CONDITIONID_COMBAT, CONDITION_LIGHT, time, level | (color << 8));
3773 creature->addCondition(condition);
3774 pushBoolean(L, true);
3775 return 1;
3776}
3777
3778int LuaScriptInterface::luaAddEvent(lua_State *L) {
3779 // addEvent(callback, delay, ...)
3780 lua_State *globalState = g_luaEnvironment.getLuaState();
3781 if (!globalState) {
3782 reportErrorFunc("No valid script interface!");
3783 pushBoolean(L, false);
3784 return 1;
3785 } else if (globalState != L) {
3786 lua_xmove(L, globalState, lua_gettop(L));
3787 }
3788
3789 int parameters = lua_gettop(globalState);
3790 if (!isFunction(globalState, -parameters)) { //-parameters means the first
3791 // parameter from left to right
3792 reportErrorFunc("callback parameter should be a function.");
3793 pushBoolean(L, false);
3794 return 1;
3795 }
3796
3797 if (g_config.getBoolean(ConfigManager::WARN_UNSAFE_SCRIPTS) ||
3798 g_config.getBoolean(ConfigManager::CONVERT_UNSAFE_SCRIPTS)) {
3799 std::vector<std::pair<int32_t, LuaDataType>> indexes;
3800 for (int i = 3; i <= parameters; ++i) {
3801 if (lua_getmetatable(globalState, i) == 0) {
3802 continue;
3803 }
3804 lua_rawgeti(L, -1, 't');
3805
3806 LuaDataType type = getNumber<LuaDataType>(L, -1);
3807 if (type != LuaData_Unknown && type != LuaData_Tile) {
3808 indexes.push_back({i, type});
3809 }
3810 lua_pop(globalState, 2);
3811 }
3812
3813 if (!indexes.empty()) {
3814 if (g_config.getBoolean(ConfigManager::WARN_UNSAFE_SCRIPTS)) {
3815 bool plural = indexes.size() > 1;
3816
3817 std::string warningString = "Argument";
3818 if (plural) {
3819 warningString += 's';
3820 }
3821
3822 for (const auto &entry : indexes) {
3823 if (entry == indexes.front()) {
3824 warningString += ' ';
3825 } else if (entry == indexes.back()) {
3826 warningString += " and ";
3827 } else {
3828 warningString += ", ";
3829 }
3830 warningString += '#';
3831 warningString += std::to_string(entry.first);
3832 }
3833
3834 if (plural) {
3835 warningString += " are unsafe";
3836 } else {
3837 warningString += " is unsafe";
3838 }
3839
3840 reportErrorFunc(warningString);
3841 }
3842
3843 if (g_config.getBoolean(ConfigManager::CONVERT_UNSAFE_SCRIPTS)) {
3844 for (const auto &entry : indexes) {
3845 switch (entry.second) {
3846 case LuaData_Item:
3847 case LuaData_Container:
3848 case LuaData_Teleport: {
3849 lua_getglobal(globalState, "Item");
3850 lua_getfield(globalState, -1, "getUniqueId");
3851 break;
3852 }
3853 case LuaData_Player:
3854 case LuaData_Monster:
3855 case LuaData_Npc: {
3856 lua_getglobal(globalState, "Creature");
3857 lua_getfield(globalState, -1, "getId");
3858 break;
3859 }
3860 default:
3861 break;
3862 }
3863 lua_replace(globalState, -2);
3864 lua_pushvalue(globalState, entry.first);
3865 lua_call(globalState, 1, 1);
3866 lua_replace(globalState, entry.first);
3867 }
3868 }
3869 }
3870 }
3871
3872 LuaTimerEventDesc eventDesc;
3873 for (int i = 0; i < parameters - 2;
3874 ++i) { //-2 because addEvent needs at least two parameters
3875 eventDesc.parameters.push_back(luaL_ref(globalState, LUA_REGISTRYINDEX));
3876 }
3877
3878 uint32_t delay = std::max<uint32_t>(100, getNumber<uint32_t>(globalState, 2));
3879 lua_pop(globalState, 1);
3880
3881 eventDesc.function = luaL_ref(globalState, LUA_REGISTRYINDEX);
3882 eventDesc.scriptId = getScriptEnv()->getScriptId();
3883
3884 auto &lastTimerEventId = g_luaEnvironment.lastEventTimerId;
3885 eventDesc.eventId = g_scheduler.addEvent(createSchedulerTask(
3886 delay, std::bind(&LuaEnvironment::executeTimerEvent, &g_luaEnvironment,
3887 lastTimerEventId)));
3888
3889 g_luaEnvironment.timerEvents.emplace(lastTimerEventId, std::move(eventDesc));
3890 lua_pushnumber(L, lastTimerEventId++);
3891 return 1;
3892}
3893
3894int LuaScriptInterface::luaStopEvent(lua_State *L) {
3895 // stopEvent(eventid)
3896 lua_State *globalState = g_luaEnvironment.getLuaState();
3897 if (!globalState) {
3898 reportErrorFunc("No valid script interface!");
3899 pushBoolean(L, false);
3900 return 1;
3901 }
3902
3903 uint32_t eventId = getNumber<uint32_t>(L, 1);
3904
3905 auto &timerEvents = g_luaEnvironment.timerEvents;
3906 auto it = timerEvents.find(eventId);
3907 if (it == timerEvents.end()) {
3908 pushBoolean(L, false);
3909 return 1;
3910 }
3911
3912 LuaTimerEventDesc timerEventDesc = std::move(it->second);
3913 timerEvents.erase(it);
3914
3915 g_scheduler.stopEvent(timerEventDesc.eventId);
3916 luaL_unref(globalState, LUA_REGISTRYINDEX, timerEventDesc.function);
3917
3918 for (auto parameter : timerEventDesc.parameters) {
3919 luaL_unref(globalState, LUA_REGISTRYINDEX, parameter);
3920 }
3921
3922 pushBoolean(L, true);
3923 return 1;
3924}
3925
3926int LuaScriptInterface::luaSaveServer(lua_State *L) {
3927 g_game.saveGameState();
3928 pushBoolean(L, true);
3929 return 1;
3930}
3931
3932int LuaScriptInterface::luaCleanMap(lua_State *L) {
3933 lua_pushnumber(L, g_game.map.clean());
3934 return 1;
3935}
3936
3937int LuaScriptInterface::luaIsInWar(lua_State *L) {
3938 // isInWar(cid, target)
3939 Player *player = getPlayer(L, 1);
3940 if (!player) {
3941 reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
3942 pushBoolean(L, false);
3943 return 1;
3944 }
3945
3946 Player *targetPlayer = getPlayer(L, 2);
3947 if (!targetPlayer) {
3948 reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
3949 pushBoolean(L, false);
3950 return 1;
3951 }
3952
3953 pushBoolean(L, player->isInWar(targetPlayer));
3954 return 1;
3955}
3956
3957int LuaScriptInterface::luaGetWaypointPositionByName(lua_State *L) {
3958 // getWaypointPositionByName(name)
3959 auto &waypoints = g_game.map.waypoints;
3960
3961 auto it = waypoints.find(getString(L, -1));
3962 if (it != waypoints.end()) {
3963 pushPosition(L, it->second);
3964 } else {
3965 pushBoolean(L, false);
3966 }
3967 return 1;
3968}
3969
3970int LuaScriptInterface::luaSendChannelMessage(lua_State *L) {
3971 // sendChannelMessage(channelId, type, message)
3972 uint32_t channelId = getNumber<uint32_t>(L, 1);
3973 ChatChannel *channel = g_chat->getChannelById(channelId);
3974 if (!channel) {
3975 pushBoolean(L, false);
3976 return 1;
3977 }
3978
3979 SpeakClasses type = getNumber<SpeakClasses>(L, 2);
3980 std::string message = getString(L, 3);
3981 channel->sendToAll(message, type);
3982 pushBoolean(L, true);
3983 return 1;
3984}
3985
3986int LuaScriptInterface::luaSendGuildChannelMessage(lua_State *L) {
3987 // sendGuildChannelMessage(guildId, type, message)
3988 uint32_t guildId = getNumber<uint32_t>(L, 1);
3989 ChatChannel *channel = g_chat->getGuildChannelById(guildId);
3990 if (!channel) {
3991 pushBoolean(L, false);
3992 return 1;
3993 }
3994
3995 SpeakClasses type = getNumber<SpeakClasses>(L, 2);
3996 std::string message = getString(L, 3);
3997 channel->sendToAll(message, type);
3998 pushBoolean(L, true);
3999 return 1;
4000}
4001
4002std::string LuaScriptInterface::escapeString(const std::string &string) {
4003 std::string s = string;
4004 replaceString(s, "\\", "\\\\");
4005 replaceString(s, "\"", "\\\"");
4006 replaceString(s, "'", "\\'");
4007 replaceString(s, "[[", "\\[[");
4008 return s;
4009}
4010
4011#ifndef LUAJIT_VERSION
4012const luaL_Reg LuaScriptInterface::luaBitReg[] = {
4013 //{"tobit", LuaScriptInterface::luaBitToBit},
4014 {"bnot", LuaScriptInterface::luaBitNot},
4015 {"band", LuaScriptInterface::luaBitAnd},
4016 {"bor", LuaScriptInterface::luaBitOr},
4017 {"bxor", LuaScriptInterface::luaBitXor},
4018 {"lshift", LuaScriptInterface::luaBitLeftShift},
4019 {"rshift", LuaScriptInterface::luaBitRightShift},
4020 //{"arshift", LuaScriptInterface::luaBitArithmeticalRightShift},
4021 //{"rol", LuaScriptInterface::luaBitRotateLeft},
4022 //{"ror", LuaScriptInterface::luaBitRotateRight},
4023 //{"bswap", LuaScriptInterface::luaBitSwapEndian},
4024 //{"tohex", LuaScriptInterface::luaBitToHex},
4025 {nullptr, nullptr}};
4026
4027int LuaScriptInterface::luaBitNot(lua_State *L) {
4028 lua_pushnumber(L, ~getNumber<uint32_t>(L, -1));
4029 return 1;
4030}
4031
4032#define MULTIOP(name, op) \
4033 int LuaScriptInterface::luaBit##name(lua_State *L) { \
4034 int n = lua_gettop(L); \
4035 uint32_t w = getNumber<uint32_t>(L, -1); \
4036 for (int i = 1; i < n; ++i) \
4037 w op getNumber<uint32_t>(L, i); \
4038 lua_pushnumber(L, w); \
4039 return 1; \
4040 }
4041
4042MULTIOP(And, &=)
4043MULTIOP(Or, |=)
4044MULTIOP(Xor, ^=)
4045
4046#define SHIFTOP(name, op) \
4047 int LuaScriptInterface::luaBit##name(lua_State *L) { \
4048 uint32_t n1 = getNumber<uint32_t>(L, 1), n2 = getNumber<uint32_t>(L, 2); \
4049 lua_pushnumber(L, (n1 op n2)); \
4050 return 1; \
4051 }
4052
4053SHIFTOP(LeftShift, <<)
4054SHIFTOP(RightShift, >>)
4055#endif
4056
4057const luaL_Reg LuaScriptInterface::luaConfigManagerTable[] = {
4058 {"getString", LuaScriptInterface::luaConfigManagerGetString},
4059 {"getNumber", LuaScriptInterface::luaConfigManagerGetNumber},
4060 {"getBoolean", LuaScriptInterface::luaConfigManagerGetBoolean},
4061 {nullptr, nullptr}};
4062
4063int LuaScriptInterface::luaConfigManagerGetString(lua_State *L) {
4064 pushString(
4065 L, g_config.getString(getNumber<ConfigManager::string_config_t>(L, -1)));
4066 return 1;
4067}
4068
4069int LuaScriptInterface::luaConfigManagerGetNumber(lua_State *L) {
4070 lua_pushnumber(
4071 L, g_config.getNumber(getNumber<ConfigManager::integer_config_t>(L, -1)));
4072 return 1;
4073}
4074
4075int LuaScriptInterface::luaConfigManagerGetBoolean(lua_State *L) {
4076 pushBoolean(L, g_config.getBoolean(
4077 getNumber<ConfigManager::boolean_config_t>(L, -1)));
4078 return 1;
4079}
4080
4081const luaL_Reg LuaScriptInterface::luaDatabaseTable[] = {
4082 {"query", LuaScriptInterface::luaDatabaseExecute},
4083 {"asyncQuery", LuaScriptInterface::luaDatabaseAsyncExecute},
4084 {"storeQuery", LuaScriptInterface::luaDatabaseStoreQuery},
4085 {"asyncStoreQuery", LuaScriptInterface::luaDatabaseAsyncStoreQuery},
4086 {"escapeString", LuaScriptInterface::luaDatabaseEscapeString},
4087 {"escapeBlob", LuaScriptInterface::luaDatabaseEscapeBlob},
4088 {"lastInsertId", LuaScriptInterface::luaDatabaseLastInsertId},
4089 {"tableExists", LuaScriptInterface::luaDatabaseTableExists},
4090 {nullptr, nullptr}};
4091
4092int LuaScriptInterface::luaDatabaseExecute(lua_State *L) {
4093 pushBoolean(L, Database::getInstance().executeQuery(getString(L, -1)));
4094 return 1;
4095}
4096
4097int LuaScriptInterface::luaDatabaseAsyncExecute(lua_State *L) {
4098 std::function<void(DBResult_ptr, bool)> callback;
4099 if (lua_gettop(L) > 1) {
4100 int32_t ref = luaL_ref(L, LUA_REGISTRYINDEX);
4101 auto scriptId = getScriptEnv()->getScriptId();
4102 callback = [ref, scriptId](DBResult_ptr, bool success) {
4103 lua_State *luaState = g_luaEnvironment.getLuaState();
4104 if (!luaState) {
4105 return;
4106 }
4107
4108 if (!LuaScriptInterface::reserveScriptEnv()) {
4109 luaL_unref(luaState, LUA_REGISTRYINDEX, ref);
4110 return;
4111 }
4112
4113 lua_rawgeti(luaState, LUA_REGISTRYINDEX, ref);
4114 pushBoolean(luaState, success);
4115 auto env = getScriptEnv();
4116 env->setScriptId(scriptId, &g_luaEnvironment);
4117 g_luaEnvironment.callFunction(1);
4118
4119 luaL_unref(luaState, LUA_REGISTRYINDEX, ref);
4120 };
4121 }
4122 g_databaseTasks.addTask(getString(L, -1), callback);
4123 return 0;
4124}
4125
4126int LuaScriptInterface::luaDatabaseStoreQuery(lua_State *L) {
4127 if (DBResult_ptr res = Database::getInstance().storeQuery(getString(L, -1))) {
4128 lua_pushnumber(L, ScriptEnvironment::addResult(res));
4129 } else {
4130 pushBoolean(L, false);
4131 }
4132 return 1;
4133}
4134
4135int LuaScriptInterface::luaDatabaseAsyncStoreQuery(lua_State *L) {
4136 std::function<void(DBResult_ptr, bool)> callback;
4137 if (lua_gettop(L) > 1) {
4138 int32_t ref = luaL_ref(L, LUA_REGISTRYINDEX);
4139 auto scriptId = getScriptEnv()->getScriptId();
4140 callback = [ref, scriptId](DBResult_ptr result, bool) {
4141 lua_State *luaState = g_luaEnvironment.getLuaState();
4142 if (!luaState) {
4143 return;
4144 }
4145
4146 if (!LuaScriptInterface::reserveScriptEnv()) {
4147 luaL_unref(luaState, LUA_REGISTRYINDEX, ref);
4148 return;
4149 }
4150
4151 lua_rawgeti(luaState, LUA_REGISTRYINDEX, ref);
4152 if (result) {
4153 lua_pushnumber(luaState, ScriptEnvironment::addResult(result));
4154 } else {
4155 pushBoolean(luaState, false);
4156 }
4157 auto env = getScriptEnv();
4158 env->setScriptId(scriptId, &g_luaEnvironment);
4159 g_luaEnvironment.callFunction(1);
4160
4161 luaL_unref(luaState, LUA_REGISTRYINDEX, ref);
4162 };
4163 }
4164 g_databaseTasks.addTask(getString(L, -1), callback, true);
4165 return 0;
4166}
4167
4168int LuaScriptInterface::luaDatabaseEscapeString(lua_State *L) {
4169 pushString(L, Database::getInstance().escapeString(getString(L, -1)));
4170 return 1;
4171}
4172
4173int LuaScriptInterface::luaDatabaseEscapeBlob(lua_State *L) {
4174 uint32_t length = getNumber<uint32_t>(L, 2);
4175 pushString(
4176 L, Database::getInstance().escapeBlob(getString(L, 1).c_str(), length));
4177 return 1;
4178}
4179
4180int LuaScriptInterface::luaDatabaseLastInsertId(lua_State *L) {
4181 lua_pushnumber(L, Database::getInstance().getLastInsertId());
4182 return 1;
4183}
4184
4185int LuaScriptInterface::luaDatabaseTableExists(lua_State *L) {
4186 pushBoolean(L, DatabaseManager::tableExists(getString(L, -1)));
4187 return 1;
4188}
4189
4190const luaL_Reg LuaScriptInterface::luaResultTable[] = {
4191 {"getNumber", LuaScriptInterface::luaResultGetNumber},
4192 {"getString", LuaScriptInterface::luaResultGetString},
4193 {"getStream", LuaScriptInterface::luaResultGetStream},
4194 {"next", LuaScriptInterface::luaResultNext},
4195 {"free", LuaScriptInterface::luaResultFree},
4196 {nullptr, nullptr}};
4197
4198int LuaScriptInterface::luaResultGetNumber(lua_State *L) {
4199 DBResult_ptr res =
4200 ScriptEnvironment::getResultByID(getNumber<uint32_t>(L, 1));
4201 if (!res) {
4202 pushBoolean(L, false);
4203 return 1;
4204 }
4205
4206 const std::string &s = getString(L, 2);
4207 lua_pushnumber(L, res->getNumber<int64_t>(s));
4208 return 1;
4209}
4210
4211int LuaScriptInterface::luaResultGetString(lua_State *L) {
4212 DBResult_ptr res =
4213 ScriptEnvironment::getResultByID(getNumber<uint32_t>(L, 1));
4214 if (!res) {
4215 pushBoolean(L, false);
4216 return 1;
4217 }
4218
4219 const std::string &s = getString(L, 2);
4220 pushString(L, res->getString(s));
4221 return 1;
4222}
4223
4224int LuaScriptInterface::luaResultGetStream(lua_State *L) {
4225 DBResult_ptr res =
4226 ScriptEnvironment::getResultByID(getNumber<uint32_t>(L, 1));
4227 if (!res) {
4228 pushBoolean(L, false);
4229 return 1;
4230 }
4231
4232 unsigned long length;
4233 const char *stream = res->getStream(getString(L, 2), length);
4234 lua_pushlstring(L, stream, length);
4235 lua_pushnumber(L, length);
4236 return 2;
4237}
4238
4239int LuaScriptInterface::luaResultNext(lua_State *L) {
4240 DBResult_ptr res =
4241 ScriptEnvironment::getResultByID(getNumber<uint32_t>(L, -1));
4242 if (!res) {
4243 pushBoolean(L, false);
4244 return 1;
4245 }
4246
4247 pushBoolean(L, res->next());
4248 return 1;
4249}
4250
4251int LuaScriptInterface::luaResultFree(lua_State *L) {
4252 pushBoolean(L, ScriptEnvironment::removeResult(getNumber<uint32_t>(L, -1)));
4253 return 1;
4254}
4255
4256// Userdata
4257int LuaScriptInterface::luaUserdataCompare(lua_State *L) {
4258 // userdataA == userdataB
4259 pushBoolean(L, getUserdata<void>(L, 1) == getUserdata<void>(L, 2));
4260 return 1;
4261}
4262
4263// _G
4264int LuaScriptInterface::luaIsType(lua_State *L) {
4265 // isType(derived, base)
4266 lua_getmetatable(L, -2);
4267 lua_getmetatable(L, -2);
4268
4269 lua_rawgeti(L, -2, 'p');
4270 uint_fast8_t parentsB = getNumber<uint_fast8_t>(L, 1);
4271
4272 lua_rawgeti(L, -3, 'h');
4273 size_t hashB = getNumber<size_t>(L, 1);
4274
4275 lua_rawgeti(L, -3, 'p');
4276 uint_fast8_t parentsA = getNumber<uint_fast8_t>(L, 1);
4277 for (uint_fast8_t i = parentsA; i < parentsB; ++i) {
4278 lua_getfield(L, -3, "__index");
4279 lua_replace(L, -4);
4280 }
4281
4282 lua_rawgeti(L, -4, 'h');
4283 size_t hashA = getNumber<size_t>(L, 1);
4284
4285 pushBoolean(L, hashA == hashB);
4286 return 1;
4287}
4288
4289int LuaScriptInterface::luaRawGetMetatable(lua_State *L) {
4290 // rawgetmetatable(metatableName)
4291 luaL_getmetatable(L, getString(L, 1).c_str());
4292 return 1;
4293}
4294
4295// os
4296int LuaScriptInterface::luaSystemTime(lua_State *L) {
4297 // os.mtime()
4298 lua_pushnumber(L, OTSYS_TIME());
4299 return 1;
4300}
4301
4302// table
4303int LuaScriptInterface::luaTableCreate(lua_State *L) {
4304 // table.create(arrayLength, keyLength)
4305 lua_createtable(L, getNumber<int32_t>(L, 1), getNumber<int32_t>(L, 2));
4306 return 1;
4307}
4308
4309// Game
4310int LuaScriptInterface::luaGameGetSpectators(lua_State *L) {
4311 // Game.getSpectators(position[, multifloor = false[, onlyPlayer = false[,
4312 // minRangeX = 0[, maxRangeX = 0[, minRangeY = 0[, maxRangeY = 0]]]]]])
4313 const Position &position = getPosition(L, 1);
4314 bool multifloor = getBoolean(L, 2, false);
4315 bool onlyPlayers = getBoolean(L, 3, false);
4316 int32_t minRangeX = getNumber<int32_t>(L, 4, 0);
4317 int32_t maxRangeX = getNumber<int32_t>(L, 5, 0);
4318 int32_t minRangeY = getNumber<int32_t>(L, 6, 0);
4319 int32_t maxRangeY = getNumber<int32_t>(L, 7, 0);
4320
4321 SpectatorVec spectators;
4322 g_game.map.getSpectators(spectators, position, multifloor, onlyPlayers,
4323 minRangeX, maxRangeX, minRangeY, maxRangeY);
4324
4325 lua_createtable(L, spectators.size(), 0);
4326
4327 int index = 0;
4328 for (Creature *creature : spectators) {
4329 pushUserdata<Creature>(L, creature);
4330 setCreatureMetatable(L, -1, creature);
4331 lua_rawseti(L, -2, ++index);
4332 }
4333 return 1;
4334}
4335
4336int LuaScriptInterface::luaGameGetPlayers(lua_State *L) {
4337 // Game.getPlayers()
4338 lua_createtable(L, g_game.getPlayersOnline(), 0);
4339
4340 int index = 0;
4341 for (const auto &playerEntry : g_game.getPlayers()) {
4342 pushUserdata<Player>(L, playerEntry.second);
4343 setMetatable(L, -1, "Player");
4344 lua_rawseti(L, -2, ++index);
4345 }
4346 return 1;
4347}
4348
4349int LuaScriptInterface::luaGameLoadMap(lua_State *L) {
4350 // Game.loadMap(path)
4351 const std::string &path = getString(L, 1);
4352 g_dispatcher.addTask(createTask([path]() {
4353 try {
4354 g_game.loadMap(path);
4355 } catch (const std::exception &e) {
4356 // FIXME: Should only catch some exceptions
4357 std::cout
4358 << "[Error - LuaScriptInterface::luaGameLoadMap] Failed to load map: "
4359 << e.what() << std::endl;
4360 }
4361 }));
4362 return 0;
4363}
4364
4365int LuaScriptInterface::luaGameGetExperienceStage(lua_State *L) {
4366 // Game.getExperienceStage(level)
4367 uint32_t level = getNumber<uint32_t>(L, 1);
4368 lua_pushnumber(L, g_game.getExperienceStage(level));
4369 return 1;
4370}
4371
4372int LuaScriptInterface::luaGameGetMonsterCount(lua_State *L) {
4373 // Game.getMonsterCount()
4374 lua_pushnumber(L, g_game.getMonstersOnline());
4375 return 1;
4376}
4377
4378int LuaScriptInterface::luaGameGetPlayerCount(lua_State *L) {
4379 // Game.getPlayerCount()
4380 lua_pushnumber(L, g_game.getPlayersOnline());
4381 return 1;
4382}
4383
4384int LuaScriptInterface::luaGameGetNpcCount(lua_State *L) {
4385 // Game.getNpcCount()
4386 lua_pushnumber(L, g_game.getNpcsOnline());
4387 return 1;
4388}
4389
4390int LuaScriptInterface::luaGameGetMonsterTypes(lua_State *L) {
4391 // Game.getMonsterTypes()
4392 auto &type = g_monsters.monsters;
4393 lua_createtable(L, type.size(), 0);
4394
4395 for (auto &mType : type) {
4396 pushUserdata<MonsterType>(L, &mType.second);
4397 setMetatable(L, -1, "MonsterType");
4398 lua_setfield(L, -2, mType.first.c_str());
4399 }
4400 return 1;
4401}
4402
4403int LuaScriptInterface::luaPlayerGetShaderNameByID(lua_State *L) {
4404 // Game.getShaderNameByID(shaderId)
4405 if (!isNumber(L, 1)) {
4406 lua_pushnil(L);
4407 return 1;
4408 }
4409
4410 uint8_t shaderId = getNumber<uint8_t>(L, 1);
4411 std::string shaderName = g_game.shaders.getShaderNameByID(shaderId);
4412
4413 lua_pushstring(L, shaderName.c_str());
4414 return 1;
4415}
4416
4417int LuaScriptInterface::luaGameGetTowns(lua_State *L) {
4418 // Game.getTowns()
4419 const auto &towns = g_game.map.towns.getTowns();
4420 lua_createtable(L, towns.size(), 0);
4421
4422 int index = 0;
4423 for (auto townEntry : towns) {
4424 pushUserdata<Town>(L, townEntry.second);
4425 setMetatable(L, -1, "Town");
4426 lua_rawseti(L, -2, ++index);
4427 }
4428 return 1;
4429}
4430
4431int LuaScriptInterface::luaGameGetHouses(lua_State *L) {
4432 // Game.getHouses()
4433 const auto &houses = g_game.map.houses.getHouses();
4434 lua_createtable(L, houses.size(), 0);
4435
4436 int index = 0;
4437 for (auto houseEntry : houses) {
4438 pushUserdata<House>(L, houseEntry.second);
4439 setMetatable(L, -1, "House");
4440 lua_rawseti(L, -2, ++index);
4441 }
4442 return 1;
4443}
4444
4445int LuaScriptInterface::luaGameGetGameState(lua_State *L) {
4446 // Game.getGameState()
4447 lua_pushnumber(L, g_game.getGameState());
4448 return 1;
4449}
4450
4451int LuaScriptInterface::luaGameSetGameState(lua_State *L) {
4452 // Game.setGameState(state)
4453 GameState_t state = getNumber<GameState_t>(L, 1);
4454 g_game.setGameState(state);
4455 pushBoolean(L, true);
4456 return 1;
4457}
4458
4459int LuaScriptInterface::luaGameGetWorldType(lua_State *L) {
4460 // Game.getWorldType()
4461 lua_pushnumber(L, g_game.getWorldType());
4462 return 1;
4463}
4464
4465int LuaScriptInterface::luaGameSetWorldType(lua_State *L) {
4466 // Game.setWorldType(type)
4467 WorldType_t type = getNumber<WorldType_t>(L, 1);
4468 g_game.setWorldType(type);
4469 pushBoolean(L, true);
4470 return 1;
4471}
4472
4473int LuaScriptInterface::luaGameGetReturnMessage(lua_State *L) {
4474 // Game.getReturnMessage(value)
4475 ReturnValue value = getNumber<ReturnValue>(L, 1);
4476 pushString(L, getReturnMessage(value));
4477 return 1;
4478}
4479
4480int LuaScriptInterface::luaGameCreateItem(lua_State *L) {
4481 // Game.createItem(itemId[, count[, position]])
4482 uint16_t count = getNumber<uint16_t>(L, 2, 1);
4483 uint16_t id;
4484 if (isNumber(L, 1)) {
4485 id = getNumber<uint16_t>(L, 1);
4486 } else {
4487 id = Item::items.getItemIdByName(getString(L, 1));
4488 if (id == 0) {
4489 lua_pushnil(L);
4490 return 1;
4491 }
4492 }
4493
4494 const ItemType &it = Item::items[id];
4495 if (it.stackable) {
4496 count = std::min<uint16_t>(count, 100);
4497 }
4498
4499 Item *item = Item::CreateItem(id, count);
4500 if (!item) {
4501 lua_pushnil(L);
4502 return 1;
4503 }
4504
4505 if (lua_gettop(L) >= 3) {
4506 const Position &position = getPosition(L, 3);
4507 Tile *tile = g_game.map.getTile(position);
4508 if (!tile) {
4509 delete item;
4510 lua_pushnil(L);
4511 return 1;
4512 }
4513
4514 g_game.internalAddItem(tile, item, INDEX_WHEREEVER, FLAG_NOLIMIT);
4515 } else {
4516 getScriptEnv()->addTempItem(item);
4517 item->setParent(VirtualCylinder::virtualCylinder);
4518 }
4519
4520 pushUserdata<Item>(L, item);
4521 setItemMetatable(L, -1, item);
4522 return 1;
4523}
4524
4525int LuaScriptInterface::luaGameCreateContainer(lua_State *L) {
4526 // Game.createContainer(itemId, size[, position])
4527 uint16_t size = getNumber<uint16_t>(L, 2);
4528 uint16_t id;
4529 if (isNumber(L, 1)) {
4530 id = getNumber<uint16_t>(L, 1);
4531 } else {
4532 id = Item::items.getItemIdByName(getString(L, 1));
4533 if (id == 0) {
4534 lua_pushnil(L);
4535 return 1;
4536 }
4537 }
4538
4539 Container *container = Item::CreateItemAsContainer(id, size);
4540 if (!container) {
4541 lua_pushnil(L);
4542 return 1;
4543 }
4544
4545 if (lua_gettop(L) >= 3) {
4546 const Position &position = getPosition(L, 3);
4547 Tile *tile = g_game.map.getTile(position);
4548 if (!tile) {
4549 delete container;
4550 lua_pushnil(L);
4551 return 1;
4552 }
4553
4554 g_game.internalAddItem(tile, container, INDEX_WHEREEVER, FLAG_NOLIMIT);
4555 } else {
4556 getScriptEnv()->addTempItem(container);
4557 container->setParent(VirtualCylinder::virtualCylinder);
4558 }
4559
4560 pushUserdata<Container>(L, container);
4561 setMetatable(L, -1, "Container");
4562 return 1;
4563}
4564
4565int LuaScriptInterface::luaGameCreateMonster(lua_State *L) {
4566 // Game.createMonster(monsterName, position[, extended = false[, force =
4567 // false]])
4568 Monster *monster = Monster::createMonster(getString(L, 1));
4569 if (!monster) {
4570 lua_pushnil(L);
4571 return 1;
4572 }
4573
4574 const Position &position = getPosition(L, 2);
4575 bool extended = getBoolean(L, 3, false);
4576 bool force = getBoolean(L, 4, false);
4577 if (g_events->eventMonsterOnSpawn(monster, position, false, true) || force) {
4578 if (g_game.placeCreature(monster, position, extended, force)) {
4579 pushUserdata<Monster>(L, monster);
4580 setMetatable(L, -1, "Monster");
4581 } else {
4582 delete monster;
4583 lua_pushnil(L);
4584 }
4585 } else {
4586 delete monster;
4587 lua_pushnil(L);
4588 }
4589 return 1;
4590}
4591
4592int LuaScriptInterface::luaGameCreateNpc(lua_State *L) {
4593 // Game.createNpc(npcName, position[, extended = false[, force = false]])
4594 Npc *npc = Npc::createNpc(getString(L, 1));
4595 if (!npc) {
4596 lua_pushnil(L);
4597 return 1;
4598 }
4599
4600 const Position &position = getPosition(L, 2);
4601 bool extended = getBoolean(L, 3, false);
4602 bool force = getBoolean(L, 4, false);
4603 if (g_game.placeCreature(npc, position, extended, force)) {
4604 pushUserdata<Npc>(L, npc);
4605 setMetatable(L, -1, "Npc");
4606 } else {
4607 delete npc;
4608 lua_pushnil(L);
4609 }
4610 return 1;
4611}
4612
4613int LuaScriptInterface::luaGameCreateTile(lua_State *L) {
4614 // Game.createTile(x, y, z[, isDynamic = false])
4615 // Game.createTile(position[, isDynamic = false])
4616 Position position;
4617 bool isDynamic;
4618 if (isTable(L, 1)) {
4619 position = getPosition(L, 1);
4620 isDynamic = getBoolean(L, 2, false);
4621 } else {
4622 position.x = getNumber<uint16_t>(L, 1);
4623 position.y = getNumber<uint16_t>(L, 2);
4624 position.z = getNumber<uint16_t>(L, 3);
4625 isDynamic = getBoolean(L, 4, false);
4626 }
4627
4628 Tile *tile = g_game.map.getTile(position);
4629 if (!tile) {
4630 if (isDynamic) {
4631 tile = new DynamicTile(position.x, position.y, position.z);
4632 } else {
4633 tile = new StaticTile(position.x, position.y, position.z);
4634 }
4635
4636 g_game.map.setTile(position, tile);
4637 }
4638
4639 pushUserdata(L, tile);
4640 setMetatable(L, -1, "Tile");
4641 return 1;
4642}
4643
4644int LuaScriptInterface::luaGameCreateMonsterType(lua_State *L) {
4645 // Game.createMonsterType(name)
4646 if (getScriptEnv()->getScriptInterface() !=
4647 &g_scripts->getScriptInterface()) {
4648 reportErrorFunc(
4649 "MonsterTypes can only be registered in the Scripts interface.");
4650 lua_pushnil(L);
4651 return 1;
4652 }
4653
4654 const std::string &name = getString(L, 1);
4655 if (name.length() == 0) {
4656 lua_pushnil(L);
4657 return 1;
4658 }
4659
4660 MonsterType *monsterType = g_monsters.getMonsterType(name, false);
4661 if (!monsterType) {
4662 monsterType = &g_monsters.monsters[asLowerCaseString(name)];
4663 monsterType->name = name;
4664 monsterType->nameDescription = "a " + name;
4665 } else {
4666 monsterType->info.lootItems.clear();
4667 monsterType->info.attackSpells.clear();
4668 monsterType->info.defenseSpells.clear();
4669 }
4670
4671 pushUserdata<MonsterType>(L, monsterType);
4672 setMetatable(L, -1, "MonsterType");
4673 return 1;
4674}
4675
4676int LuaScriptInterface::luaGameStartRaid(lua_State *L) {
4677 // Game.startRaid(raidName)
4678 const std::string &raidName = getString(L, 1);
4679
4680 Raid *raid = g_game.raids.getRaidByName(raidName);
4681 if (!raid || !raid->isLoaded()) {
4682 lua_pushnumber(L, RETURNVALUE_NOSUCHRAIDEXISTS);
4683 return 1;
4684 }
4685
4686 if (g_game.raids.getRunning()) {
4687 lua_pushnumber(L, RETURNVALUE_ANOTHERRAIDISALREADYEXECUTING);
4688 return 1;
4689 }
4690
4691 g_game.raids.setRunning(raid);
4692 raid->startRaid();
4693 lua_pushnumber(L, RETURNVALUE_NOERROR);
4694 return 1;
4695}
4696
4697int LuaScriptInterface::luaGameGetClientVersion(lua_State *L) {
4698 // Game.getClientVersion()
4699 lua_createtable(L, 0, 3);
4700 setField(L, "min", CLIENT_VERSION_MIN);
4701 setField(L, "max", CLIENT_VERSION_MAX);
4702 setField(L, "string", CLIENT_VERSION_STR);
4703 return 1;
4704}
4705
4706int LuaScriptInterface::luaGameReload(lua_State *L) {
4707 // Game.reload(reloadType)
4708 ReloadTypes_t reloadType = getNumber<ReloadTypes_t>(L, 1);
4709 if (reloadType == RELOAD_TYPE_GLOBAL) {
4710 pushBoolean(L, g_luaEnvironment.loadFile("data/global.lua") == 0);
4711 pushBoolean(L, g_scripts->loadScripts("scripts/lib", true, true));
4712 } else {
4713 pushBoolean(L, g_game.reload(reloadType));
4714 }
4715 lua_gc(g_luaEnvironment.getLuaState(), LUA_GCCOLLECT, 0);
4716 return 1;
4717}
4718
4719// Variant
4720int LuaScriptInterface::luaVariantCreate(lua_State *L) {
4721 // Variant(number or string or position or thing)
4722 LuaVariant variant;
4723 if (isUserdata(L, 2)) {
4724 if (Thing *thing = getThing(L, 2)) {
4725 variant.type = VARIANT_TARGETPOSITION;
4726 variant.pos = thing->getPosition();
4727 }
4728 } else if (isTable(L, 2)) {
4729 variant.type = VARIANT_POSITION;
4730 variant.pos = getPosition(L, 2);
4731 } else if (isNumber(L, 2)) {
4732 variant.type = VARIANT_NUMBER;
4733 variant.number = getNumber<uint32_t>(L, 2);
4734 } else if (isString(L, 2)) {
4735 variant.type = VARIANT_STRING;
4736 variant.text = getString(L, 2);
4737 }
4738 pushVariant(L, variant);
4739 return 1;
4740}
4741
4742int LuaScriptInterface::luaVariantGetNumber(lua_State *L) {
4743 // Variant:getNumber()
4744 const LuaVariant &variant = getVariant(L, 1);
4745 if (variant.type == VARIANT_NUMBER) {
4746 lua_pushnumber(L, variant.number);
4747 } else {
4748 lua_pushnumber(L, 0);
4749 }
4750 return 1;
4751}
4752
4753int LuaScriptInterface::luaVariantGetString(lua_State *L) {
4754 // Variant:getString()
4755 const LuaVariant &variant = getVariant(L, 1);
4756 if (variant.type == VARIANT_STRING) {
4757 pushString(L, variant.text);
4758 } else {
4759 pushString(L, std::string());
4760 }
4761 return 1;
4762}
4763
4764int LuaScriptInterface::luaVariantGetPosition(lua_State *L) {
4765 // Variant:getPosition()
4766 const LuaVariant &variant = getVariant(L, 1);
4767 if (variant.type == VARIANT_POSITION ||
4768 variant.type == VARIANT_TARGETPOSITION) {
4769 pushPosition(L, variant.pos);
4770 } else {
4771 pushPosition(L, Position());
4772 }
4773 return 1;
4774}
4775
4776// Position
4777int LuaScriptInterface::luaPositionCreate(lua_State *L) {
4778 // Position([x = 0[, y = 0[, z = 0[, stackpos = 0]]]])
4779 // Position([position])
4780 if (lua_gettop(L) <= 1) {
4781 pushPosition(L, Position());
4782 return 1;
4783 }
4784
4785 int32_t stackpos;
4786 if (isTable(L, 2)) {
4787 const Position &position = getPosition(L, 2, stackpos);
4788 pushPosition(L, position, stackpos);
4789 } else {
4790 uint16_t x = getNumber<uint16_t>(L, 2, 0);
4791 uint16_t y = getNumber<uint16_t>(L, 3, 0);
4792 uint8_t z = getNumber<uint8_t>(L, 4, 0);
4793 stackpos = getNumber<int32_t>(L, 5, 0);
4794
4795 pushPosition(L, Position(x, y, z), stackpos);
4796 }
4797 return 1;
4798}
4799
4800int LuaScriptInterface::luaPositionAdd(lua_State *L) {
4801 // positionValue = position + positionEx
4802 int32_t stackpos;
4803 const Position &position = getPosition(L, 1, stackpos);
4804
4805 Position positionEx;
4806 if (stackpos == 0) {
4807 positionEx = getPosition(L, 2, stackpos);
4808 } else {
4809 positionEx = getPosition(L, 2);
4810 }
4811
4812 pushPosition(L, position + positionEx, stackpos);
4813 return 1;
4814}
4815
4816int LuaScriptInterface::luaPositionSub(lua_State *L) {
4817 // positionValue = position - positionEx
4818 int32_t stackpos;
4819 const Position &position = getPosition(L, 1, stackpos);
4820
4821 Position positionEx;
4822 if (stackpos == 0) {
4823 positionEx = getPosition(L, 2, stackpos);
4824 } else {
4825 positionEx = getPosition(L, 2);
4826 }
4827
4828 pushPosition(L, position - positionEx, stackpos);
4829 return 1;
4830}
4831
4832int LuaScriptInterface::luaPositionCompare(lua_State *L) {
4833 // position == positionEx
4834 const Position &positionEx = getPosition(L, 2);
4835 const Position &position = getPosition(L, 1);
4836 pushBoolean(L, position == positionEx);
4837 return 1;
4838}
4839
4840int LuaScriptInterface::luaPositionGetDistance(lua_State *L) {
4841 // position:getDistance(positionEx)
4842 const Position &positionEx = getPosition(L, 2);
4843 const Position &position = getPosition(L, 1);
4844 lua_pushnumber(
4845 L, std::max<int32_t>(
4846 std::max<int32_t>(
4847 std::abs(Position::getDistanceX(position, positionEx)),
4848 std::abs(Position::getDistanceY(position, positionEx))),
4849 std::abs(Position::getDistanceZ(position, positionEx))));
4850 return 1;
4851}
4852
4853int LuaScriptInterface::luaPositionIsSightClear(lua_State *L) {
4854 // position:isSightClear(positionEx[, sameFloor = true])
4855 bool sameFloor = getBoolean(L, 3, true);
4856 const Position &positionEx = getPosition(L, 2);
4857 const Position &position = getPosition(L, 1);
4858 pushBoolean(L, g_game.isSightClear(position, positionEx, sameFloor));
4859 return 1;
4860}
4861
4862int LuaScriptInterface::luaPositionSendMagicEffect(lua_State *L) {
4863 // position:sendMagicEffect(magicEffect[, player = nullptr])
4864 SpectatorVec spectators;
4865 if (lua_gettop(L) >= 3) {
4866 Player *player = getPlayer(L, 3);
4867 if (player) {
4868 spectators.emplace_back(player);
4869 }
4870 }
4871
4872 MagicEffectClasses magicEffect = getNumber<MagicEffectClasses>(L, 2);
4873 const Position &position = getPosition(L, 1);
4874 if (!spectators.empty()) {
4875 Game::addMagicEffect(spectators, position, magicEffect);
4876 } else {
4877 g_game.addMagicEffect(position, magicEffect);
4878 }
4879
4880 pushBoolean(L, true);
4881 return 1;
4882}
4883
4884int LuaScriptInterface::luaPositionSendDistanceEffect(lua_State *L) {
4885 // position:sendDistanceEffect(positionEx, distanceEffect[, player = nullptr])
4886 SpectatorVec spectators;
4887 if (lua_gettop(L) >= 4) {
4888 Player *player = getPlayer(L, 4);
4889 if (player) {
4890 spectators.emplace_back(player);
4891 }
4892 }
4893
4894 ShootType_t distanceEffect = getNumber<ShootType_t>(L, 3);
4895 const Position &positionEx = getPosition(L, 2);
4896 const Position &position = getPosition(L, 1);
4897 if (!spectators.empty()) {
4898 Game::addDistanceEffect(spectators, position, positionEx, distanceEffect);
4899 } else {
4900 g_game.addDistanceEffect(position, positionEx, distanceEffect);
4901 }
4902
4903 pushBoolean(L, true);
4904 return 1;
4905}
4906
4907// Tile
4908int LuaScriptInterface::luaTileCreate(lua_State *L) {
4909 // Tile(x, y, z)
4910 // Tile(position)
4911 Tile *tile;
4912 if (isTable(L, 2)) {
4913 tile = g_game.map.getTile(getPosition(L, 2));
4914 } else {
4915 uint8_t z = getNumber<uint8_t>(L, 4);
4916 uint16_t y = getNumber<uint16_t>(L, 3);
4917 uint16_t x = getNumber<uint16_t>(L, 2);
4918 tile = g_game.map.getTile(x, y, z);
4919 }
4920
4921 if (tile) {
4922 pushUserdata<Tile>(L, tile);
4923 setMetatable(L, -1, "Tile");
4924 } else {
4925 lua_pushnil(L);
4926 }
4927 return 1;
4928}
4929
4930int LuaScriptInterface::luaTileGetPosition(lua_State *L) {
4931 // tile:getPosition()
4932 Tile *tile = getUserdata<Tile>(L, 1);
4933 if (tile) {
4934 pushPosition(L, tile->getPosition());
4935 } else {
4936 lua_pushnil(L);
4937 }
4938 return 1;
4939}
4940
4941int LuaScriptInterface::luaTileGetGround(lua_State *L) {
4942 // tile:getGround()
4943 Tile *tile = getUserdata<Tile>(L, 1);
4944 if (tile && tile->getGround()) {
4945 pushUserdata<Item>(L, tile->getGround());
4946 setItemMetatable(L, -1, tile->getGround());
4947 } else {
4948 lua_pushnil(L);
4949 }
4950 return 1;
4951}
4952
4953int LuaScriptInterface::luaTileGetThing(lua_State *L) {
4954 // tile:getThing(index)
4955 int32_t index = getNumber<int32_t>(L, 2);
4956 Tile *tile = getUserdata<Tile>(L, 1);
4957 if (!tile) {
4958 lua_pushnil(L);
4959 return 1;
4960 }
4961
4962 Thing *thing = tile->getThing(index);
4963 if (!thing) {
4964 lua_pushnil(L);
4965 return 1;
4966 }
4967
4968 if (Creature *creature = thing->getCreature()) {
4969 pushUserdata<Creature>(L, creature);
4970 setCreatureMetatable(L, -1, creature);
4971 } else if (Item *item = thing->getItem()) {
4972 pushUserdata<Item>(L, item);
4973 setItemMetatable(L, -1, item);
4974 } else {
4975 lua_pushnil(L);
4976 }
4977 return 1;
4978}
4979
4980int LuaScriptInterface::luaTileGetThingCount(lua_State *L) {
4981 // tile:getThingCount()
4982 Tile *tile = getUserdata<Tile>(L, 1);
4983 if (tile) {
4984 lua_pushnumber(L, tile->getThingCount());
4985 } else {
4986 lua_pushnil(L);
4987 }
4988 return 1;
4989}
4990
4991int LuaScriptInterface::luaTileGetTopVisibleThing(lua_State *L) {
4992 // tile:getTopVisibleThing(creature)
4993 Creature *creature = getCreature(L, 2);
4994 Tile *tile = getUserdata<Tile>(L, 1);
4995 if (!tile) {
4996 lua_pushnil(L);
4997 return 1;
4998 }
4999
5000 Thing *thing = tile->getTopVisibleThing(creature);
5001 if (!thing) {
5002 lua_pushnil(L);
5003 return 1;
5004 }
5005
5006 if (Creature *visibleCreature = thing->getCreature()) {
5007 pushUserdata<Creature>(L, visibleCreature);
5008 setCreatureMetatable(L, -1, visibleCreature);
5009 } else if (Item *visibleItem = thing->getItem()) {
5010 pushUserdata<Item>(L, visibleItem);
5011 setItemMetatable(L, -1, visibleItem);
5012 } else {
5013 lua_pushnil(L);
5014 }
5015 return 1;
5016}
5017
5018int LuaScriptInterface::luaTileGetTopTopItem(lua_State *L) {
5019 // tile:getTopTopItem()
5020 Tile *tile = getUserdata<Tile>(L, 1);
5021 if (!tile) {
5022 lua_pushnil(L);
5023 return 1;
5024 }
5025
5026 Item *item = tile->getTopTopItem();
5027 if (item) {
5028 pushUserdata<Item>(L, item);
5029 setItemMetatable(L, -1, item);
5030 } else {
5031 lua_pushnil(L);
5032 }
5033 return 1;
5034}
5035
5036int LuaScriptInterface::luaTileGetTopDownItem(lua_State *L) {
5037 // tile:getTopDownItem()
5038 Tile *tile = getUserdata<Tile>(L, 1);
5039 if (!tile) {
5040 lua_pushnil(L);
5041 return 1;
5042 }
5043
5044 Item *item = tile->getTopDownItem();
5045 if (item) {
5046 pushUserdata<Item>(L, item);
5047 setItemMetatable(L, -1, item);
5048 } else {
5049 lua_pushnil(L);
5050 }
5051 return 1;
5052}
5053
5054int LuaScriptInterface::luaTileGetFieldItem(lua_State *L) {
5055 // tile:getFieldItem()
5056 Tile *tile = getUserdata<Tile>(L, 1);
5057 if (!tile) {
5058 lua_pushnil(L);
5059 return 1;
5060 }
5061
5062 Item *item = tile->getFieldItem();
5063 if (item) {
5064 pushUserdata<Item>(L, item);
5065 setItemMetatable(L, -1, item);
5066 } else {
5067 lua_pushnil(L);
5068 }
5069 return 1;
5070}
5071
5072int LuaScriptInterface::luaTileGetItemById(lua_State *L) {
5073 // tile:getItemById(itemId[, subType = -1])
5074 Tile *tile = getUserdata<Tile>(L, 1);
5075 if (!tile) {
5076 lua_pushnil(L);
5077 return 1;
5078 }
5079
5080 uint16_t itemId;
5081 if (isNumber(L, 2)) {
5082 itemId = getNumber<uint16_t>(L, 2);
5083 } else {
5084 itemId = Item::items.getItemIdByName(getString(L, 2));
5085 if (itemId == 0) {
5086 lua_pushnil(L);
5087 return 1;
5088 }
5089 }
5090 int32_t subType = getNumber<int32_t>(L, 3, -1);
5091
5092 Item *item = g_game.findItemOfType(tile, itemId, false, subType);
5093 if (item) {
5094 pushUserdata<Item>(L, item);
5095 setItemMetatable(L, -1, item);
5096 } else {
5097 lua_pushnil(L);
5098 }
5099 return 1;
5100}
5101
5102int LuaScriptInterface::luaTileGetItemByType(lua_State *L) {
5103 // tile:getItemByType(itemType)
5104 Tile *tile = getUserdata<Tile>(L, 1);
5105 if (!tile) {
5106 lua_pushnil(L);
5107 return 1;
5108 }
5109
5110 bool found;
5111
5112 ItemTypes_t itemType = getNumber<ItemTypes_t>(L, 2);
5113 switch (itemType) {
5114 case ITEM_TYPE_TELEPORT:
5115 found = tile->hasFlag(TILESTATE_TELEPORT);
5116 break;
5117 case ITEM_TYPE_MAGICFIELD:
5118 found = tile->hasFlag(TILESTATE_MAGICFIELD);
5119 break;
5120 case ITEM_TYPE_MAILBOX:
5121 found = tile->hasFlag(TILESTATE_MAILBOX);
5122 break;
5123 case ITEM_TYPE_TRASHHOLDER:
5124 found = tile->hasFlag(TILESTATE_TRASHHOLDER);
5125 break;
5126 case ITEM_TYPE_BED:
5127 found = tile->hasFlag(TILESTATE_BED);
5128 break;
5129 case ITEM_TYPE_DEPOT:
5130 found = tile->hasFlag(TILESTATE_DEPOT);
5131 break;
5132 default:
5133 found = true;
5134 break;
5135 }
5136
5137 if (!found) {
5138 lua_pushnil(L);
5139 return 1;
5140 }
5141
5142 if (Item *item = tile->getGround()) {
5143 const ItemType &it = Item::items[item->getID()];
5144 if (it.type == itemType) {
5145 pushUserdata<Item>(L, item);
5146 setItemMetatable(L, -1, item);
5147 return 1;
5148 }
5149 }
5150
5151 if (const TileItemVector *items = tile->getItemList()) {
5152 for (Item *item : *items) {
5153 const ItemType &it = Item::items[item->getID()];
5154 if (it.type == itemType) {
5155 pushUserdata<Item>(L, item);
5156 setItemMetatable(L, -1, item);
5157 return 1;
5158 }
5159 }
5160 }
5161
5162 lua_pushnil(L);
5163 return 1;
5164}
5165
5166int LuaScriptInterface::luaTileGetItemByTopOrder(lua_State *L) {
5167 // tile:getItemByTopOrder(topOrder)
5168 Tile *tile = getUserdata<Tile>(L, 1);
5169 if (!tile) {
5170 lua_pushnil(L);
5171 return 1;
5172 }
5173
5174 int32_t topOrder = getNumber<int32_t>(L, 2);
5175
5176 Item *item = tile->getItemByTopOrder(topOrder);
5177 if (!item) {
5178 lua_pushnil(L);
5179 return 1;
5180 }
5181
5182 pushUserdata<Item>(L, item);
5183 setItemMetatable(L, -1, item);
5184 return 1;
5185}
5186
5187int LuaScriptInterface::luaTileGetItemCountById(lua_State *L) {
5188 // tile:getItemCountById(itemId[, subType = -1])
5189 Tile *tile = getUserdata<Tile>(L, 1);
5190 if (!tile) {
5191 lua_pushnil(L);
5192 return 1;
5193 }
5194
5195 int32_t subType = getNumber<int32_t>(L, 3, -1);
5196
5197 uint16_t itemId;
5198 if (isNumber(L, 2)) {
5199 itemId = getNumber<uint16_t>(L, 2);
5200 } else {
5201 itemId = Item::items.getItemIdByName(getString(L, 2));
5202 if (itemId == 0) {
5203 lua_pushnil(L);
5204 return 1;
5205 }
5206 }
5207
5208 lua_pushnumber(L, tile->getItemTypeCount(itemId, subType));
5209 return 1;
5210}
5211
5212int LuaScriptInterface::luaTileGetBottomCreature(lua_State *L) {
5213 // tile:getBottomCreature()
5214 Tile *tile = getUserdata<Tile>(L, 1);
5215 if (!tile) {
5216 lua_pushnil(L);
5217 return 1;
5218 }
5219
5220 const Creature *creature = tile->getBottomCreature();
5221 if (!creature) {
5222 lua_pushnil(L);
5223 return 1;
5224 }
5225
5226 pushUserdata<const Creature>(L, creature);
5227 setCreatureMetatable(L, -1, creature);
5228 return 1;
5229}
5230
5231int LuaScriptInterface::luaTileGetTopCreature(lua_State *L) {
5232 // tile:getTopCreature()
5233 Tile *tile = getUserdata<Tile>(L, 1);
5234 if (!tile) {
5235 lua_pushnil(L);
5236 return 1;
5237 }
5238
5239 Creature *creature = tile->getTopCreature();
5240 if (!creature) {
5241 lua_pushnil(L);
5242 return 1;
5243 }
5244
5245 pushUserdata<Creature>(L, creature);
5246 setCreatureMetatable(L, -1, creature);
5247 return 1;
5248}
5249
5250int LuaScriptInterface::luaTileGetBottomVisibleCreature(lua_State *L) {
5251 // tile:getBottomVisibleCreature(creature)
5252 Tile *tile = getUserdata<Tile>(L, 1);
5253 if (!tile) {
5254 lua_pushnil(L);
5255 return 1;
5256 }
5257
5258 Creature *creature = getCreature(L, 2);
5259 if (!creature) {
5260 lua_pushnil(L);
5261 return 1;
5262 }
5263
5264 const Creature *visibleCreature = tile->getBottomVisibleCreature(creature);
5265 if (visibleCreature) {
5266 pushUserdata<const Creature>(L, visibleCreature);
5267 setCreatureMetatable(L, -1, visibleCreature);
5268 } else {
5269 lua_pushnil(L);
5270 }
5271 return 1;
5272}
5273
5274int LuaScriptInterface::luaTileGetTopVisibleCreature(lua_State *L) {
5275 // tile:getTopVisibleCreature(creature)
5276 Tile *tile = getUserdata<Tile>(L, 1);
5277 if (!tile) {
5278 lua_pushnil(L);
5279 return 1;
5280 }
5281
5282 Creature *creature = getCreature(L, 2);
5283 if (!creature) {
5284 lua_pushnil(L);
5285 return 1;
5286 }
5287
5288 Creature *visibleCreature = tile->getTopVisibleCreature(creature);
5289 if (visibleCreature) {
5290 pushUserdata<Creature>(L, visibleCreature);
5291 setCreatureMetatable(L, -1, visibleCreature);
5292 } else {
5293 lua_pushnil(L);
5294 }
5295 return 1;
5296}
5297
5298int LuaScriptInterface::luaTileGetItems(lua_State *L) {
5299 // tile:getItems()
5300 Tile *tile = getUserdata<Tile>(L, 1);
5301 if (!tile) {
5302 lua_pushnil(L);
5303 return 1;
5304 }
5305
5306 TileItemVector *itemVector = tile->getItemList();
5307 if (!itemVector) {
5308 lua_pushnil(L);
5309 return 1;
5310 }
5311
5312 lua_createtable(L, itemVector->size(), 0);
5313
5314 int index = 0;
5315 for (Item *item : *itemVector) {
5316 pushUserdata<Item>(L, item);
5317 setItemMetatable(L, -1, item);
5318 lua_rawseti(L, -2, ++index);
5319 }
5320 return 1;
5321}
5322
5323int LuaScriptInterface::luaTileGetItemCount(lua_State *L) {
5324 // tile:getItemCount()
5325 Tile *tile = getUserdata<Tile>(L, 1);
5326 if (!tile) {
5327 lua_pushnil(L);
5328 return 1;
5329 }
5330
5331 lua_pushnumber(L, tile->getItemCount());
5332 return 1;
5333}
5334
5335int LuaScriptInterface::luaTileGetDownItemCount(lua_State *L) {
5336 // tile:getDownItemCount()
5337 Tile *tile = getUserdata<Tile>(L, 1);
5338 if (tile) {
5339 lua_pushnumber(L, tile->getDownItemCount());
5340 } else {
5341 lua_pushnil(L);
5342 }
5343 return 1;
5344}
5345
5346int LuaScriptInterface::luaTileGetTopItemCount(lua_State *L) {
5347 // tile:getTopItemCount()
5348 Tile *tile = getUserdata<Tile>(L, 1);
5349 if (!tile) {
5350 lua_pushnil(L);
5351 return 1;
5352 }
5353
5354 lua_pushnumber(L, tile->getTopItemCount());
5355 return 1;
5356}
5357
5358int LuaScriptInterface::luaTileGetCreatures(lua_State *L) {
5359 // tile:getCreatures()
5360 Tile *tile = getUserdata<Tile>(L, 1);
5361 if (!tile) {
5362 lua_pushnil(L);
5363 return 1;
5364 }
5365
5366 CreatureVector *creatureVector = tile->getCreatures();
5367 if (!creatureVector) {
5368 lua_pushnil(L);
5369 return 1;
5370 }
5371
5372 lua_createtable(L, creatureVector->size(), 0);
5373
5374 int index = 0;
5375 for (Creature *creature : *creatureVector) {
5376 pushUserdata<Creature>(L, creature);
5377 setCreatureMetatable(L, -1, creature);
5378 lua_rawseti(L, -2, ++index);
5379 }
5380 return 1;
5381}
5382
5383int LuaScriptInterface::luaTileGetCreatureCount(lua_State *L) {
5384 // tile:getCreatureCount()
5385 Tile *tile = getUserdata<Tile>(L, 1);
5386 if (!tile) {
5387 lua_pushnil(L);
5388 return 1;
5389 }
5390
5391 lua_pushnumber(L, tile->getCreatureCount());
5392 return 1;
5393}
5394
5395int LuaScriptInterface::luaTileHasProperty(lua_State *L) {
5396 // tile:hasProperty(property[, item])
5397 Tile *tile = getUserdata<Tile>(L, 1);
5398 if (!tile) {
5399 lua_pushnil(L);
5400 return 1;
5401 }
5402
5403 Item *item;
5404 if (lua_gettop(L) >= 3) {
5405 item = getUserdata<Item>(L, 3);
5406 } else {
5407 item = nullptr;
5408 }
5409
5410 ITEMPROPERTY property = getNumber<ITEMPROPERTY>(L, 2);
5411 if (item) {
5412 pushBoolean(L, tile->hasProperty(item, property));
5413 } else {
5414 pushBoolean(L, tile->hasProperty(property));
5415 }
5416 return 1;
5417}
5418
5419int LuaScriptInterface::luaTileGetThingIndex(lua_State *L) {
5420 // tile:getThingIndex(thing)
5421 Tile *tile = getUserdata<Tile>(L, 1);
5422 if (!tile) {
5423 lua_pushnil(L);
5424 return 1;
5425 }
5426
5427 Thing *thing = getThing(L, 2);
5428 if (thing) {
5429 lua_pushnumber(L, tile->getThingIndex(thing));
5430 } else {
5431 lua_pushnil(L);
5432 }
5433 return 1;
5434}
5435
5436int LuaScriptInterface::luaTileHasFlag(lua_State *L) {
5437 // tile:hasFlag(flag)
5438 Tile *tile = getUserdata<Tile>(L, 1);
5439 if (tile) {
5440 tileflags_t flag = getNumber<tileflags_t>(L, 2);
5441 pushBoolean(L, tile->hasFlag(flag));
5442 } else {
5443 lua_pushnil(L);
5444 }
5445 return 1;
5446}
5447
5448int LuaScriptInterface::luaTileQueryAdd(lua_State *L) {
5449 // tile:queryAdd(thing[, flags])
5450 Tile *tile = getUserdata<Tile>(L, 1);
5451 if (!tile) {
5452 lua_pushnil(L);
5453 return 1;
5454 }
5455
5456 Thing *thing = getThing(L, 2);
5457 if (thing) {
5458 uint32_t flags = getNumber<uint32_t>(L, 3, 0);
5459 lua_pushnumber(L, tile->queryAdd(0, *thing, 1, flags));
5460 } else {
5461 lua_pushnil(L);
5462 }
5463 return 1;
5464}
5465
5466int LuaScriptInterface::luaTileAddItem(lua_State *L) {
5467 // tile:addItem(itemId[, count/subType = 1[, flags = 0]])
5468 Tile *tile = getUserdata<Tile>(L, 1);
5469 if (!tile) {
5470 lua_pushnil(L);
5471 return 1;
5472 }
5473
5474 uint16_t itemId;
5475 if (isNumber(L, 2)) {
5476 itemId = getNumber<uint16_t>(L, 2);
5477 } else {
5478 itemId = Item::items.getItemIdByName(getString(L, 2));
5479 if (itemId == 0) {
5480 lua_pushnil(L);
5481 return 1;
5482 }
5483 }
5484
5485 uint32_t subType = getNumber<uint32_t>(L, 3, 1);
5486
5487 Item *item = Item::CreateItem(itemId, std::min<uint32_t>(subType, 100));
5488 if (!item) {
5489 lua_pushnil(L);
5490 return 1;
5491 }
5492
5493 uint32_t flags = getNumber<uint32_t>(L, 4, 0);
5494
5495 ReturnValue ret = g_game.internalAddItem(tile, item, INDEX_WHEREEVER, flags);
5496 if (ret == RETURNVALUE_NOERROR) {
5497 pushUserdata<Item>(L, item);
5498 setItemMetatable(L, -1, item);
5499 } else {
5500 delete item;
5501 lua_pushnil(L);
5502 }
5503 return 1;
5504}
5505
5506int LuaScriptInterface::luaTileAddItemEx(lua_State *L) {
5507 // tile:addItemEx(item[, flags = 0])
5508 Item *item = getUserdata<Item>(L, 2);
5509 if (!item) {
5510 lua_pushnil(L);
5511 return 1;
5512 }
5513
5514 Tile *tile = getUserdata<Tile>(L, 1);
5515 if (!tile) {
5516 lua_pushnil(L);
5517 return 1;
5518 }
5519
5520 if (item->getParent() != VirtualCylinder::virtualCylinder) {
5521 reportErrorFunc("Item already has a parent");
5522 lua_pushnil(L);
5523 return 1;
5524 }
5525
5526 uint32_t flags = getNumber<uint32_t>(L, 3, 0);
5527 ReturnValue ret = g_game.internalAddItem(tile, item, INDEX_WHEREEVER, flags);
5528 if (ret == RETURNVALUE_NOERROR) {
5529 ScriptEnvironment::removeTempItem(item);
5530 }
5531 lua_pushnumber(L, ret);
5532 return 1;
5533}
5534
5535int LuaScriptInterface::luaTileGetHouse(lua_State *L) {
5536 // tile:getHouse()
5537 Tile *tile = getUserdata<Tile>(L, 1);
5538 if (!tile) {
5539 lua_pushnil(L);
5540 return 1;
5541 }
5542
5543 if (HouseTile *houseTile = dynamic_cast<HouseTile *>(tile)) {
5544 pushUserdata<House>(L, houseTile->getHouse());
5545 setMetatable(L, -1, "House");
5546 } else {
5547 lua_pushnil(L);
5548 }
5549 return 1;
5550}
5551
5552// NetworkMessage
5553int LuaScriptInterface::luaNetworkMessageCreate(lua_State *L) {
5554 // NetworkMessage()
5555 pushUserdata<NetworkMessage>(L, new NetworkMessage);
5556 setMetatable(L, -1, "NetworkMessage");
5557 return 1;
5558}
5559
5560int LuaScriptInterface::luaNetworkMessageDelete(lua_State *L) {
5561 NetworkMessage **messagePtr = getRawUserdata<NetworkMessage>(L, 1);
5562 if (messagePtr && *messagePtr) {
5563 delete *messagePtr;
5564 *messagePtr = nullptr;
5565 }
5566 return 0;
5567}
5568
5569int LuaScriptInterface::luaNetworkMessageGetByte(lua_State *L) {
5570 // networkMessage:getByte()
5571 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5572 if (message) {
5573 lua_pushnumber(L, message->getByte());
5574 } else {
5575 lua_pushnil(L);
5576 }
5577 return 1;
5578}
5579
5580int LuaScriptInterface::luaNetworkMessageGetU16(lua_State *L) {
5581 // networkMessage:getU16()
5582 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5583 if (message) {
5584 lua_pushnumber(L, message->get<uint16_t>());
5585 } else {
5586 lua_pushnil(L);
5587 }
5588 return 1;
5589}
5590
5591int LuaScriptInterface::luaNetworkMessageGetU32(lua_State *L) {
5592 // networkMessage:getU32()
5593 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5594 if (message) {
5595 lua_pushnumber(L, message->get<uint32_t>());
5596 } else {
5597 lua_pushnil(L);
5598 }
5599 return 1;
5600}
5601
5602int LuaScriptInterface::luaNetworkMessageGetU64(lua_State *L) {
5603 // networkMessage:getU64()
5604 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5605 if (message) {
5606 lua_pushnumber(L, message->get<uint64_t>());
5607 } else {
5608 lua_pushnil(L);
5609 }
5610 return 1;
5611}
5612
5613int LuaScriptInterface::luaNetworkMessageGetString(lua_State *L) {
5614 // networkMessage:getString()
5615 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5616 if (message) {
5617 pushString(L, message->getString());
5618 } else {
5619 lua_pushnil(L);
5620 }
5621 return 1;
5622}
5623
5624int LuaScriptInterface::luaNetworkMessageGetPosition(lua_State *L) {
5625 // networkMessage:getPosition()
5626 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5627 if (message) {
5628 pushPosition(L, message->getPosition());
5629 } else {
5630 lua_pushnil(L);
5631 }
5632 return 1;
5633}
5634
5635int LuaScriptInterface::luaNetworkMessageAddByte(lua_State *L) {
5636 // networkMessage:addByte(number)
5637 uint8_t number = getNumber<uint8_t>(L, 2);
5638 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5639 if (message) {
5640 message->addByte(number);
5641 pushBoolean(L, true);
5642 } else {
5643 lua_pushnil(L);
5644 }
5645 return 1;
5646}
5647
5648int LuaScriptInterface::luaNetworkMessageAddU16(lua_State *L) {
5649 // networkMessage:addU16(number)
5650 uint16_t number = getNumber<uint16_t>(L, 2);
5651 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5652 if (message) {
5653 message->add<uint16_t>(number);
5654 pushBoolean(L, true);
5655 } else {
5656 lua_pushnil(L);
5657 }
5658 return 1;
5659}
5660
5661int LuaScriptInterface::luaNetworkMessageAddU32(lua_State *L) {
5662 // networkMessage:addU32(number)
5663 uint32_t number = getNumber<uint32_t>(L, 2);
5664 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5665 if (message) {
5666 message->add<uint32_t>(number);
5667 pushBoolean(L, true);
5668 } else {
5669 lua_pushnil(L);
5670 }
5671 return 1;
5672}
5673
5674int LuaScriptInterface::luaNetworkMessageAddU64(lua_State *L) {
5675 // networkMessage:addU64(number)
5676 uint64_t number = getNumber<uint64_t>(L, 2);
5677 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5678 if (message) {
5679 message->add<uint64_t>(number);
5680 pushBoolean(L, true);
5681 } else {
5682 lua_pushnil(L);
5683 }
5684 return 1;
5685}
5686
5687int LuaScriptInterface::luaNetworkMessageAddString(lua_State *L) {
5688 // networkMessage:addString(string)
5689 const std::string &string = getString(L, 2);
5690 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5691 if (message) {
5692 message->addString(string);
5693 pushBoolean(L, true);
5694 } else {
5695 lua_pushnil(L);
5696 }
5697 return 1;
5698}
5699
5700int LuaScriptInterface::luaNetworkMessageAddPosition(lua_State *L) {
5701 // networkMessage:addPosition(position)
5702 const Position &position = getPosition(L, 2);
5703 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5704 if (message) {
5705 message->addPosition(position);
5706 pushBoolean(L, true);
5707 } else {
5708 lua_pushnil(L);
5709 }
5710 return 1;
5711}
5712
5713int LuaScriptInterface::luaNetworkMessageAddDouble(lua_State *L) {
5714 // networkMessage:addDouble(number)
5715 double number = getNumber<double>(L, 2);
5716 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5717 if (message) {
5718 message->addDouble(number);
5719 pushBoolean(L, true);
5720 } else {
5721 lua_pushnil(L);
5722 }
5723 return 1;
5724}
5725
5726int LuaScriptInterface::luaNetworkMessageAddItem(lua_State *L) {
5727 // networkMessage:addItem(item)
5728 Item *item = getUserdata<Item>(L, 2);
5729 if (!item) {
5730 reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND));
5731 lua_pushnil(L);
5732 return 1;
5733 }
5734
5735 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5736 if (message) {
5737 message->addItem(item);
5738 pushBoolean(L, true);
5739 } else {
5740 lua_pushnil(L);
5741 }
5742 return 1;
5743}
5744
5745int LuaScriptInterface::luaNetworkMessageAddItemId(lua_State *L) {
5746 // networkMessage:addItemId(itemId)
5747 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5748 if (!message) {
5749 lua_pushnil(L);
5750 return 1;
5751 }
5752
5753 uint16_t itemId;
5754 if (isNumber(L, 2)) {
5755 itemId = getNumber<uint16_t>(L, 2);
5756 } else {
5757 itemId = Item::items.getItemIdByName(getString(L, 2));
5758 if (itemId == 0) {
5759 lua_pushnil(L);
5760 return 1;
5761 }
5762 }
5763
5764 message->addItemId(itemId);
5765 pushBoolean(L, true);
5766 return 1;
5767}
5768
5769int LuaScriptInterface::luaNetworkMessageReset(lua_State *L) {
5770 // networkMessage:reset()
5771 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5772 if (message) {
5773 message->reset();
5774 pushBoolean(L, true);
5775 } else {
5776 lua_pushnil(L);
5777 }
5778 return 1;
5779}
5780
5781int LuaScriptInterface::luaNetworkMessageSkipBytes(lua_State *L) {
5782 // networkMessage:skipBytes(number)
5783 int16_t number = getNumber<int16_t>(L, 2);
5784 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5785 if (message) {
5786 message->skipBytes(number);
5787 pushBoolean(L, true);
5788 } else {
5789 lua_pushnil(L);
5790 }
5791 return 1;
5792}
5793
5794int LuaScriptInterface::luaNetworkMessageSendToPlayer(lua_State *L) {
5795 // networkMessage:sendToPlayer(player)
5796 NetworkMessage *message = getUserdata<NetworkMessage>(L, 1);
5797 if (!message) {
5798 lua_pushnil(L);
5799 return 1;
5800 }
5801
5802 Player *player = getPlayer(L, 2);
5803 if (player) {
5804 player->sendNetworkMessage(*message);
5805 pushBoolean(L, true);
5806 } else {
5807 reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
5808 lua_pushnil(L);
5809 }
5810 return 1;
5811}
5812
5813// ModalWindow
5814int LuaScriptInterface::luaModalWindowCreate(lua_State *L) {
5815 // ModalWindow(id, title, message)
5816 const std::string &message = getString(L, 4);
5817 const std::string &title = getString(L, 3);
5818 uint32_t id = getNumber<uint32_t>(L, 2);
5819
5820 pushUserdata<ModalWindow>(L, new ModalWindow(id, title, message));
5821 setMetatable(L, -1, "ModalWindow");
5822 return 1;
5823}
5824
5825int LuaScriptInterface::luaModalWindowDelete(lua_State *L) {
5826 ModalWindow **windowPtr = getRawUserdata<ModalWindow>(L, 1);
5827 if (windowPtr && *windowPtr) {
5828 delete *windowPtr;
5829 *windowPtr = nullptr;
5830 }
5831 return 0;
5832}
5833
5834int LuaScriptInterface::luaModalWindowGetId(lua_State *L) {
5835 // modalWindow:getId()
5836 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5837 if (window) {
5838 lua_pushnumber(L, window->id);
5839 } else {
5840 lua_pushnil(L);
5841 }
5842 return 1;
5843}
5844
5845int LuaScriptInterface::luaModalWindowGetTitle(lua_State *L) {
5846 // modalWindow:getTitle()
5847 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5848 if (window) {
5849 pushString(L, window->title);
5850 } else {
5851 lua_pushnil(L);
5852 }
5853 return 1;
5854}
5855
5856int LuaScriptInterface::luaModalWindowGetMessage(lua_State *L) {
5857 // modalWindow:getMessage()
5858 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5859 if (window) {
5860 pushString(L, window->message);
5861 } else {
5862 lua_pushnil(L);
5863 }
5864 return 1;
5865}
5866
5867int LuaScriptInterface::luaModalWindowSetTitle(lua_State *L) {
5868 // modalWindow:setTitle(text)
5869 const std::string &text = getString(L, 2);
5870 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5871 if (window) {
5872 window->title = text;
5873 pushBoolean(L, true);
5874 } else {
5875 lua_pushnil(L);
5876 }
5877 return 1;
5878}
5879
5880int LuaScriptInterface::luaModalWindowSetMessage(lua_State *L) {
5881 // modalWindow:setMessage(text)
5882 const std::string &text = getString(L, 2);
5883 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5884 if (window) {
5885 window->message = text;
5886 pushBoolean(L, true);
5887 } else {
5888 lua_pushnil(L);
5889 }
5890 return 1;
5891}
5892
5893int LuaScriptInterface::luaModalWindowGetButtonCount(lua_State *L) {
5894 // modalWindow:getButtonCount()
5895 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5896 if (window) {
5897 lua_pushnumber(L, window->buttons.size());
5898 } else {
5899 lua_pushnil(L);
5900 }
5901 return 1;
5902}
5903
5904int LuaScriptInterface::luaModalWindowGetChoiceCount(lua_State *L) {
5905 // modalWindow:getChoiceCount()
5906 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5907 if (window) {
5908 lua_pushnumber(L, window->choices.size());
5909 } else {
5910 lua_pushnil(L);
5911 }
5912 return 1;
5913}
5914
5915int LuaScriptInterface::luaModalWindowAddButton(lua_State *L) {
5916 // modalWindow:addButton(id, text)
5917 const std::string &text = getString(L, 3);
5918 uint8_t id = getNumber<uint8_t>(L, 2);
5919 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5920 if (window) {
5921 window->buttons.emplace_back(text, id);
5922 pushBoolean(L, true);
5923 } else {
5924 lua_pushnil(L);
5925 }
5926 return 1;
5927}
5928
5929int LuaScriptInterface::luaModalWindowAddChoice(lua_State *L) {
5930 // modalWindow:addChoice(id, text)
5931 const std::string &text = getString(L, 3);
5932 uint8_t id = getNumber<uint8_t>(L, 2);
5933 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5934 if (window) {
5935 window->choices.emplace_back(text, id);
5936 pushBoolean(L, true);
5937 } else {
5938 lua_pushnil(L);
5939 }
5940 return 1;
5941}
5942
5943int LuaScriptInterface::luaModalWindowGetDefaultEnterButton(lua_State *L) {
5944 // modalWindow:getDefaultEnterButton()
5945 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5946 if (window) {
5947 lua_pushnumber(L, window->defaultEnterButton);
5948 } else {
5949 lua_pushnil(L);
5950 }
5951 return 1;
5952}
5953
5954int LuaScriptInterface::luaModalWindowSetDefaultEnterButton(lua_State *L) {
5955 // modalWindow:setDefaultEnterButton(buttonId)
5956 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5957 if (window) {
5958 window->defaultEnterButton = getNumber<uint8_t>(L, 2);
5959 pushBoolean(L, true);
5960 } else {
5961 lua_pushnil(L);
5962 }
5963 return 1;
5964}
5965
5966int LuaScriptInterface::luaModalWindowGetDefaultEscapeButton(lua_State *L) {
5967 // modalWindow:getDefaultEscapeButton()
5968 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5969 if (window) {
5970 lua_pushnumber(L, window->defaultEscapeButton);
5971 } else {
5972 lua_pushnil(L);
5973 }
5974 return 1;
5975}
5976
5977int LuaScriptInterface::luaModalWindowSetDefaultEscapeButton(lua_State *L) {
5978 // modalWindow:setDefaultEscapeButton(buttonId)
5979 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5980 if (window) {
5981 window->defaultEscapeButton = getNumber<uint8_t>(L, 2);
5982 pushBoolean(L, true);
5983 } else {
5984 lua_pushnil(L);
5985 }
5986 return 1;
5987}
5988
5989int LuaScriptInterface::luaModalWindowHasPriority(lua_State *L) {
5990 // modalWindow:hasPriority()
5991 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
5992 if (window) {
5993 pushBoolean(L, window->priority);
5994 } else {
5995 lua_pushnil(L);
5996 }
5997 return 1;
5998}
5999
6000int LuaScriptInterface::luaModalWindowSetPriority(lua_State *L) {
6001 // modalWindow:setPriority(priority)
6002 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
6003 if (window) {
6004 window->priority = getBoolean(L, 2);
6005 pushBoolean(L, true);
6006 } else {
6007 lua_pushnil(L);
6008 }
6009 return 1;
6010}
6011
6012int LuaScriptInterface::luaModalWindowSendToPlayer(lua_State *L) {
6013 // modalWindow:sendToPlayer(player)
6014 Player *player = getPlayer(L, 2);
6015 if (!player) {
6016 lua_pushnil(L);
6017 return 1;
6018 }
6019
6020 ModalWindow *window = getUserdata<ModalWindow>(L, 1);
6021 if (window) {
6022 if (!player->hasModalWindowOpen(window->id)) {
6023 player->sendModalWindow(*window);
6024 }
6025 pushBoolean(L, true);
6026 } else {
6027 lua_pushnil(L);
6028 }
6029 return 1;
6030}
6031
6032// Item
6033int LuaScriptInterface::luaItemCreate(lua_State *L) {
6034 // Item(uid)
6035 uint32_t id = getNumber<uint32_t>(L, 2);
6036
6037 Item *item = getScriptEnv()->getItemByUID(id);
6038 if (item) {
6039 pushUserdata<Item>(L, item);
6040 setItemMetatable(L, -1, item);
6041 } else {
6042 lua_pushnil(L);
6043 }
6044 return 1;
6045}
6046
6047int LuaScriptInterface::luaItemIsItem(lua_State *L) {
6048 // item:isItem()
6049 pushBoolean(L, getUserdata<const Item>(L, 1) != nullptr);
6050 return 1;
6051}
6052
6053int LuaScriptInterface::luaItemGetParent(lua_State *L) {
6054 // item:getParent()
6055 Item *item = getUserdata<Item>(L, 1);
6056 if (!item) {
6057 lua_pushnil(L);
6058 return 1;
6059 }
6060
6061 Cylinder *parent = item->getParent();
6062 if (!parent) {
6063 lua_pushnil(L);
6064 return 1;
6065 }
6066
6067 pushCylinder(L, parent);
6068 return 1;
6069}
6070
6071int LuaScriptInterface::luaItemGetTopParent(lua_State *L) {
6072 // item:getTopParent()
6073 Item *item = getUserdata<Item>(L, 1);
6074 if (!item) {
6075 lua_pushnil(L);
6076 return 1;
6077 }
6078
6079 Cylinder *topParent = item->getTopParent();
6080 if (!topParent) {
6081 lua_pushnil(L);
6082 return 1;
6083 }
6084
6085 pushCylinder(L, topParent);
6086 return 1;
6087}
6088
6089int LuaScriptInterface::luaItemGetId(lua_State *L) {
6090 // item:getId()
6091 Item *item = getUserdata<Item>(L, 1);
6092 if (item) {
6093 lua_pushnumber(L, item->getID());
6094 } else {
6095 lua_pushnil(L);
6096 }
6097 return 1;
6098}
6099
6100int LuaScriptInterface::luaItemClone(lua_State *L) {
6101 // item:clone()
6102 Item *item = getUserdata<Item>(L, 1);
6103 if (!item) {
6104 lua_pushnil(L);
6105 return 1;
6106 }
6107
6108 Item *clone = item->clone();
6109 if (!clone) {
6110 lua_pushnil(L);
6111 return 1;
6112 }
6113
6114 getScriptEnv()->addTempItem(clone);
6115 clone->setParent(VirtualCylinder::virtualCylinder);
6116
6117 pushUserdata<Item>(L, clone);
6118 setItemMetatable(L, -1, clone);
6119 return 1;
6120}
6121
6122int LuaScriptInterface::luaItemSplit(lua_State *L) {
6123 // item:split([count = 1])
6124 Item **itemPtr = getRawUserdata<Item>(L, 1);
6125 if (!itemPtr) {
6126 lua_pushnil(L);
6127 return 1;
6128 }
6129
6130 Item *item = *itemPtr;
6131 if (!item || !item->isStackable()) {
6132 lua_pushnil(L);
6133 return 1;
6134 }
6135
6136 uint16_t count =
6137 std::min<uint16_t>(getNumber<uint16_t>(L, 2, 1), item->getItemCount());
6138 uint16_t diff = item->getItemCount() - count;
6139
6140 Item *splitItem = item->clone();
6141 if (!splitItem) {
6142 lua_pushnil(L);
6143 return 1;
6144 }
6145
6146 splitItem->setItemCount(count);
6147
6148 ScriptEnvironment *env = getScriptEnv();
6149 uint32_t uid = env->addThing(item);
6150
6151 Item *newItem = g_game.transformItem(item, item->getID(), diff);
6152 if (item->isRemoved()) {
6153 env->removeItemByUID(uid);
6154 }
6155
6156 if (newItem && newItem != item) {
6157 env->insertItem(uid, newItem);
6158 }
6159
6160 *itemPtr = newItem;
6161
6162 splitItem->setParent(VirtualCylinder::virtualCylinder);
6163 env->addTempItem(splitItem);
6164
6165 pushUserdata<Item>(L, splitItem);
6166 setItemMetatable(L, -1, splitItem);
6167 return 1;
6168}
6169
6170int LuaScriptInterface::luaItemRemove(lua_State *L) {
6171 // item:remove([count = -1])
6172 Item *item = getUserdata<Item>(L, 1);
6173 if (item) {
6174 int32_t count = getNumber<int32_t>(L, 2, -1);
6175 pushBoolean(L,
6176 g_game.internalRemoveItem(item, count) == RETURNVALUE_NOERROR);
6177 } else {
6178 lua_pushnil(L);
6179 }
6180 return 1;
6181}
6182
6183int LuaScriptInterface::luaItemGetUniqueId(lua_State *L) {
6184 // item:getUniqueId()
6185 Item *item = getUserdata<Item>(L, 1);
6186 if (item) {
6187 uint32_t uniqueId = item->getUniqueId();
6188 if (uniqueId == 0) {
6189 uniqueId = getScriptEnv()->addThing(item);
6190 }
6191 lua_pushnumber(L, uniqueId);
6192 } else {
6193 lua_pushnil(L);
6194 }
6195 return 1;
6196}
6197
6198int LuaScriptInterface::luaItemGetActionId(lua_State *L) {
6199 // item:getActionId()
6200 Item *item = getUserdata<Item>(L, 1);
6201 if (item) {
6202 lua_pushnumber(L, item->getActionId());
6203 } else {
6204 lua_pushnil(L);
6205 }
6206 return 1;
6207}
6208
6209int LuaScriptInterface::luaItemSetActionId(lua_State *L) {
6210 // item:setActionId(actionId)
6211 uint16_t actionId = getNumber<uint16_t>(L, 2);
6212 Item *item = getUserdata<Item>(L, 1);
6213 if (item) {
6214 item->setActionId(actionId);
6215 pushBoolean(L, true);
6216 } else {
6217 lua_pushnil(L);
6218 }
6219 return 1;
6220}
6221
6222int LuaScriptInterface::luaItemGetCount(lua_State *L) {
6223 // item:getCount()
6224 Item *item = getUserdata<Item>(L, 1);
6225 if (item) {
6226 lua_pushnumber(L, item->getItemCount());
6227 } else {
6228 lua_pushnil(L);
6229 }
6230 return 1;
6231}
6232
6233int LuaScriptInterface::luaItemGetCharges(lua_State *L) {
6234 // item:getCharges()
6235 Item *item = getUserdata<Item>(L, 1);
6236 if (item) {
6237 lua_pushnumber(L, item->getCharges());
6238 } else {
6239 lua_pushnil(L);
6240 }
6241 return 1;
6242}
6243
6244int LuaScriptInterface::luaItemGetFluidType(lua_State *L) {
6245 // item:getFluidType()
6246 Item *item = getUserdata<Item>(L, 1);
6247 if (item) {
6248 lua_pushnumber(L, item->getFluidType());
6249 } else {
6250 lua_pushnil(L);
6251 }
6252 return 1;
6253}
6254
6255int LuaScriptInterface::luaItemGetWeight(lua_State *L) {
6256 // item:getWeight()
6257 Item *item = getUserdata<Item>(L, 1);
6258 if (item) {
6259 lua_pushnumber(L, item->getWeight());
6260 } else {
6261 lua_pushnil(L);
6262 }
6263 return 1;
6264}
6265
6266int LuaScriptInterface::luaItemGetSubType(lua_State *L) {
6267 // item:getSubType()
6268 Item *item = getUserdata<Item>(L, 1);
6269 if (item) {
6270 lua_pushnumber(L, item->getSubType());
6271 } else {
6272 lua_pushnil(L);
6273 }
6274 return 1;
6275}
6276
6277int LuaScriptInterface::luaItemGetName(lua_State *L) {
6278 // item:getName()
6279 Item *item = getUserdata<Item>(L, 1);
6280 if (item) {
6281 pushString(L, item->getName());
6282 } else {
6283 lua_pushnil(L);
6284 }
6285 return 1;
6286}
6287
6288int LuaScriptInterface::luaItemGetPluralName(lua_State *L) {
6289 // item:getPluralName()
6290 Item *item = getUserdata<Item>(L, 1);
6291 if (item) {
6292 pushString(L, item->getPluralName());
6293 } else {
6294 lua_pushnil(L);
6295 }
6296 return 1;
6297}
6298
6299int LuaScriptInterface::luaItemGetArticle(lua_State *L) {
6300 // item:getArticle()
6301 Item *item = getUserdata<Item>(L, 1);
6302 if (item) {
6303 pushString(L, item->getArticle());
6304 } else {
6305 lua_pushnil(L);
6306 }
6307 return 1;
6308}
6309
6310int LuaScriptInterface::luaItemGetPosition(lua_State *L) {
6311 // item:getPosition()
6312 Item *item = getUserdata<Item>(L, 1);
6313 if (item) {
6314 pushPosition(L, item->getPosition());
6315 } else {
6316 lua_pushnil(L);
6317 }
6318 return 1;
6319}
6320
6321int LuaScriptInterface::luaItemGetTile(lua_State *L) {
6322 // item:getTile()
6323 Item *item = getUserdata<Item>(L, 1);
6324 if (!item) {
6325 lua_pushnil(L);
6326 return 1;
6327 }
6328
6329 Tile *tile = item->getTile();
6330 if (tile) {
6331 pushUserdata<Tile>(L, tile);
6332 setMetatable(L, -1, "Tile");
6333 } else {
6334 lua_pushnil(L);
6335 }
6336 return 1;
6337}
6338
6339int LuaScriptInterface::luaItemHasAttribute(lua_State *L) {
6340 // item:hasAttribute(key)
6341 Item *item = getUserdata<Item>(L, 1);
6342 if (!item) {
6343 lua_pushnil(L);
6344 return 1;
6345 }
6346
6347 itemAttrTypes attribute;
6348 if (isNumber(L, 2)) {
6349 attribute = getNumber<itemAttrTypes>(L, 2);
6350 } else if (isString(L, 2)) {
6351 attribute = stringToItemAttribute(getString(L, 2));
6352 } else {
6353 attribute = ITEM_ATTRIBUTE_NONE;
6354 }
6355
6356 pushBoolean(L, item->hasAttribute(attribute));
6357 return 1;
6358}
6359
6360int LuaScriptInterface::luaItemGetAttribute(lua_State *L) {
6361 // item:getAttribute(key)
6362 Item *item = getUserdata<Item>(L, 1);
6363 if (!item) {
6364 lua_pushnil(L);
6365 return 1;
6366 }
6367
6368 itemAttrTypes attribute;
6369 if (isNumber(L, 2)) {
6370 attribute = getNumber<itemAttrTypes>(L, 2);
6371 } else if (isString(L, 2)) {
6372 attribute = stringToItemAttribute(getString(L, 2));
6373 } else {
6374 attribute = ITEM_ATTRIBUTE_NONE;
6375 }
6376
6377 if (ItemAttributes::isIntAttrType(attribute)) {
6378 lua_pushnumber(L, item->getIntAttr(attribute));
6379 } else if (ItemAttributes::isStrAttrType(attribute)) {
6380 pushString(L, item->getStrAttr(attribute));
6381 } else {
6382 lua_pushnil(L);
6383 }
6384 return 1;
6385}
6386
6387int LuaScriptInterface::luaItemSetAttribute(lua_State *L) {
6388 // item:setAttribute(key, value)
6389 Item *item = getUserdata<Item>(L, 1);
6390 if (!item) {
6391 lua_pushnil(L);
6392 return 1;
6393 }
6394
6395 itemAttrTypes attribute;
6396 if (isNumber(L, 2)) {
6397 attribute = getNumber<itemAttrTypes>(L, 2);
6398 } else if (isString(L, 2)) {
6399 attribute = stringToItemAttribute(getString(L, 2));
6400 } else {
6401 attribute = ITEM_ATTRIBUTE_NONE;
6402 }
6403
6404 if (ItemAttributes::isIntAttrType(attribute)) {
6405 if (attribute == ITEM_ATTRIBUTE_UNIQUEID) {
6406 reportErrorFunc("Attempt to set protected key \"uid\"");
6407 pushBoolean(L, false);
6408 return 1;
6409 }
6410
6411 item->setIntAttr(attribute, getNumber<int32_t>(L, 3));
6412 pushBoolean(L, true);
6413 } else if (ItemAttributes::isStrAttrType(attribute)) {
6414 item->setStrAttr(attribute, getString(L, 3));
6415 pushBoolean(L, true);
6416 } else {
6417 lua_pushnil(L);
6418 }
6419 return 1;
6420}
6421
6422int LuaScriptInterface::luaItemRemoveAttribute(lua_State *L) {
6423 // item:removeAttribute(key)
6424 Item *item = getUserdata<Item>(L, 1);
6425 if (!item) {
6426 lua_pushnil(L);
6427 return 1;
6428 }
6429
6430 itemAttrTypes attribute;
6431 if (isNumber(L, 2)) {
6432 attribute = getNumber<itemAttrTypes>(L, 2);
6433 } else if (isString(L, 2)) {
6434 attribute = stringToItemAttribute(getString(L, 2));
6435 } else {
6436 attribute = ITEM_ATTRIBUTE_NONE;
6437 }
6438
6439 bool ret = attribute != ITEM_ATTRIBUTE_UNIQUEID;
6440 if (ret) {
6441 item->removeAttribute(attribute);
6442 } else {
6443 reportErrorFunc("Attempt to erase protected key \"uid\"");
6444 }
6445 pushBoolean(L, ret);
6446 return 1;
6447}
6448
6449int LuaScriptInterface::luaItemGetCustomAttribute(lua_State *L) {
6450 // item:getCustomAttribute(key)
6451 Item *item = getUserdata<Item>(L, 1);
6452 if (!item) {
6453 lua_pushnil(L);
6454 return 1;
6455 }
6456
6457 const ItemAttributes::CustomAttribute *attr;
6458 if (isNumber(L, 2)) {
6459 attr = item->getCustomAttribute(getNumber<int64_t>(L, 2));
6460 } else if (isString(L, 2)) {
6461 attr = item->getCustomAttribute(getString(L, 2));
6462 } else {
6463 lua_pushnil(L);
6464 return 1;
6465 }
6466
6467 if (attr) {
6468 attr->pushToLua(L);
6469 } else {
6470 lua_pushnil(L);
6471 }
6472 return 1;
6473}
6474
6475int LuaScriptInterface::luaItemSetCustomAttribute(lua_State *L) {
6476 // item:setCustomAttribute(key, value)
6477 Item *item = getUserdata<Item>(L, 1);
6478 if (!item) {
6479 lua_pushnil(L);
6480 return 1;
6481 }
6482
6483 std::string key;
6484 if (isNumber(L, 2)) {
6485 key = boost::lexical_cast<std::string>(getNumber<int64_t>(L, 2));
6486 } else if (isString(L, 2)) {
6487 key = getString(L, 2);
6488 } else {
6489 lua_pushnil(L);
6490 return 1;
6491 }
6492
6493 ItemAttributes::CustomAttribute val;
6494 if (isNumber(L, 3)) {
6495 double tmp = getNumber<double>(L, 3);
6496 if (std::floor(tmp) < tmp) {
6497 val.set<double>(tmp);
6498 } else {
6499 val.set<int64_t>(tmp);
6500 }
6501 } else if (isString(L, 3)) {
6502 val.set<std::string>(getString(L, 3));
6503 } else if (isBoolean(L, 3)) {
6504 val.set<bool>(getBoolean(L, 3));
6505 } else {
6506 lua_pushnil(L);
6507 return 1;
6508 }
6509
6510 item->setCustomAttribute(key, val);
6511 pushBoolean(L, true);
6512 return 1;
6513}
6514
6515int LuaScriptInterface::luaItemRemoveCustomAttribute(lua_State *L) {
6516 // item:removeCustomAttribute(key)
6517 Item *item = getUserdata<Item>(L, 1);
6518 if (!item) {
6519 lua_pushnil(L);
6520 return 1;
6521 }
6522
6523 if (isNumber(L, 2)) {
6524 pushBoolean(L, item->removeCustomAttribute(getNumber<int64_t>(L, 2)));
6525 } else if (isString(L, 2)) {
6526 pushBoolean(L, item->removeCustomAttribute(getString(L, 2)));
6527 } else {
6528 lua_pushnil(L);
6529 }
6530 return 1;
6531}
6532
6533int LuaScriptInterface::luaItemMoveTo(lua_State *L) {
6534 // item:moveTo(position or cylinder[, flags])
6535 Item **itemPtr = getRawUserdata<Item>(L, 1);
6536 if (!itemPtr) {
6537 lua_pushnil(L);
6538 return 1;
6539 }
6540
6541 Item *item = *itemPtr;
6542 if (!item || item->isRemoved()) {
6543 lua_pushnil(L);
6544 return 1;
6545 }
6546
6547 Cylinder *toCylinder;
6548 if (isUserdata(L, 2)) {
6549 const LuaDataType type = getUserdataType(L, 2);
6550 switch (type) {
6551 case LuaData_Container:
6552 toCylinder = getUserdata<Container>(L, 2);
6553 break;
6554 case LuaData_Player:
6555 toCylinder = getUserdata<Player>(L, 2);
6556 break;
6557 case LuaData_Tile:
6558 toCylinder = getUserdata<Tile>(L, 2);
6559 break;
6560 default:
6561 toCylinder = nullptr;
6562 break;
6563 }
6564 } else {
6565 toCylinder = g_game.map.getTile(getPosition(L, 2));
6566 }
6567
6568 if (!toCylinder) {
6569 lua_pushnil(L);
6570 return 1;
6571 }
6572
6573 if (item->getParent() == toCylinder) {
6574 pushBoolean(L, true);
6575 return 1;
6576 }
6577
6578 uint32_t flags = getNumber<uint32_t>(L, 3,
6579 FLAG_NOLIMIT | FLAG_IGNOREBLOCKITEM |
6580 FLAG_IGNOREBLOCKCREATURE |
6581 FLAG_IGNORENOTMOVEABLE);
6582
6583 if (item->getParent() == VirtualCylinder::virtualCylinder) {
6584 pushBoolean(L, g_game.internalAddItem(toCylinder, item, INDEX_WHEREEVER,
6585 flags) == RETURNVALUE_NOERROR);
6586 } else {
6587 Item *moveItem = nullptr;
6588 ReturnValue ret =
6589 g_game.internalMoveItem(item->getParent(), toCylinder, INDEX_WHEREEVER,
6590 item, item->getItemCount(), &moveItem, flags);
6591 if (moveItem) {
6592 *itemPtr = moveItem;
6593 }
6594 pushBoolean(L, ret == RETURNVALUE_NOERROR);
6595 }
6596 return 1;
6597}
6598
6599int LuaScriptInterface::luaItemTransform(lua_State *L) {
6600 // item:transform(itemId[, count/subType = -1])
6601 Item **itemPtr = getRawUserdata<Item>(L, 1);
6602 if (!itemPtr) {
6603 lua_pushnil(L);
6604 return 1;
6605 }
6606
6607 Item *&item = *itemPtr;
6608 if (!item) {
6609 lua_pushnil(L);
6610 return 1;
6611 }
6612
6613 uint16_t itemId;
6614 if (isNumber(L, 2)) {
6615 itemId = getNumber<uint16_t>(L, 2);
6616 } else {
6617 itemId = Item::items.getItemIdByName(getString(L, 2));
6618 if (itemId == 0) {
6619 lua_pushnil(L);
6620 return 1;
6621 }
6622 }
6623
6624 int32_t subType = getNumber<int32_t>(L, 3, -1);
6625 if (item->getID() == itemId &&
6626 (subType == -1 || subType == item->getSubType())) {
6627 pushBoolean(L, true);
6628 return 1;
6629 }
6630
6631 const ItemType &it = Item::items[itemId];
6632 if (it.stackable) {
6633 subType = std::min<int32_t>(subType, 100);
6634 }
6635
6636 ScriptEnvironment *env = getScriptEnv();
6637 uint32_t uid = env->addThing(item);
6638
6639 Item *newItem = g_game.transformItem(item, itemId, subType);
6640 if (item->isRemoved()) {
6641 env->removeItemByUID(uid);
6642 }
6643
6644 if (newItem && newItem != item) {
6645 env->insertItem(uid, newItem);
6646 }
6647
6648 item = newItem;
6649 pushBoolean(L, true);
6650 return 1;
6651}
6652
6653int LuaScriptInterface::luaItemDecay(lua_State *L) {
6654 // item:decay(decayId)
6655 Item *item = getUserdata<Item>(L, 1);
6656 if (item) {
6657 if (isNumber(L, 2)) {
6658 item->setDecayTo(getNumber<int32_t>(L, 2));
6659 }
6660
6661 g_game.startDecay(item);
6662 pushBoolean(L, true);
6663 } else {
6664 lua_pushnil(L);
6665 }
6666 return 1;
6667}
6668
6669int LuaScriptInterface::luaItemGetDescription(lua_State *L) {
6670 // item:getDescription(distance)
6671 Item *item = getUserdata<Item>(L, 1);
6672 if (item) {
6673 int32_t distance = getNumber<int32_t>(L, 2);
6674 pushString(L, item->getDescription(distance));
6675 } else {
6676 lua_pushnil(L);
6677 }
6678 return 1;
6679}
6680
6681int LuaScriptInterface::luaItemHasProperty(lua_State *L) {
6682 // item:hasProperty(property)
6683 Item *item = getUserdata<Item>(L, 1);
6684 if (item) {
6685 ITEMPROPERTY property = getNumber<ITEMPROPERTY>(L, 2);
6686 pushBoolean(L, item->hasProperty(property));
6687 } else {
6688 lua_pushnil(L);
6689 }
6690 return 1;
6691}
6692
6693int LuaScriptInterface::luaItemIsLoadedFromMap(lua_State *L) {
6694 // item:isLoadedFromMap()
6695 Item *item = getUserdata<Item>(L, 1);
6696 if (item) {
6697 pushBoolean(L, item->isLoadedFromMap());
6698 } else {
6699 lua_pushnil(L);
6700 }
6701 return 1;
6702}
6703
6704// Container
6705int LuaScriptInterface::luaContainerCreate(lua_State *L) {
6706 // Container(uid)
6707 uint32_t id = getNumber<uint32_t>(L, 2);
6708
6709 Container *container = getScriptEnv()->getContainerByUID(id);
6710 if (container) {
6711 pushUserdata(L, container);
6712 setMetatable(L, -1, "Container");
6713 } else {
6714 lua_pushnil(L);
6715 }
6716 return 1;
6717}
6718
6719int LuaScriptInterface::luaContainerGetSize(lua_State *L) {
6720 // container:getSize()
6721 Container *container = getUserdata<Container>(L, 1);
6722 if (container) {
6723 lua_pushnumber(L, container->size());
6724 } else {
6725 lua_pushnil(L);
6726 }
6727 return 1;
6728}
6729
6730int LuaScriptInterface::luaContainerGetCapacity(lua_State *L) {
6731 // container:getCapacity()
6732 Container *container = getUserdata<Container>(L, 1);
6733 if (container) {
6734 lua_pushnumber(L, container->capacity());
6735 } else {
6736 lua_pushnil(L);
6737 }
6738 return 1;
6739}
6740
6741int LuaScriptInterface::luaContainerGetEmptySlots(lua_State *L) {
6742 // container:getEmptySlots([recursive = false])
6743 Container *container = getUserdata<Container>(L, 1);
6744 if (!container) {
6745 lua_pushnil(L);
6746 return 1;
6747 }
6748
6749 uint32_t slots = container->capacity() - container->size();
6750 bool recursive = getBoolean(L, 2, false);
6751 if (recursive) {
6752 for (ContainerIterator it = container->iterator(); it.hasNext();
6753 it.advance()) {
6754 if (Container *tmpContainer = (*it)->getContainer()) {
6755 slots += tmpContainer->capacity() - tmpContainer->size();
6756 }
6757 }
6758 }
6759 lua_pushnumber(L, slots);
6760 return 1;
6761}
6762
6763int LuaScriptInterface::luaContainerGetItemHoldingCount(lua_State *L) {
6764 // container:getItemHoldingCount()
6765 Container *container = getUserdata<Container>(L, 1);
6766 if (container) {
6767 lua_pushnumber(L, container->getItemHoldingCount());
6768 } else {
6769 lua_pushnil(L);
6770 }
6771 return 1;
6772}
6773
6774int LuaScriptInterface::luaContainerGetItem(lua_State *L) {
6775 // container:getItem(index)
6776 Container *container = getUserdata<Container>(L, 1);
6777 if (!container) {
6778 lua_pushnil(L);
6779 return 1;
6780 }
6781
6782 uint32_t index = getNumber<uint32_t>(L, 2);
6783 Item *item = container->getItemByIndex(index);
6784 if (item) {
6785 pushUserdata<Item>(L, item);
6786 setItemMetatable(L, -1, item);
6787 } else {
6788 lua_pushnil(L);
6789 }
6790 return 1;
6791}
6792
6793int LuaScriptInterface::luaContainerHasItem(lua_State *L) {
6794 // container:hasItem(item)
6795 Item *item = getUserdata<Item>(L, 2);
6796 Container *container = getUserdata<Container>(L, 1);
6797 if (container) {
6798 pushBoolean(L, container->isHoldingItem(item));
6799 } else {
6800 lua_pushnil(L);
6801 }
6802 return 1;
6803}
6804
6805int LuaScriptInterface::luaContainerAddItem(lua_State *L) {
6806 // container:addItem(itemId[, count/subType = 1[, index = INDEX_WHEREEVER[,
6807 // flags = 0]]])
6808 Container *container = getUserdata<Container>(L, 1);
6809 if (!container) {
6810 lua_pushnil(L);
6811 return 1;
6812 }
6813
6814 uint16_t itemId;
6815 if (isNumber(L, 2)) {
6816 itemId = getNumber<uint16_t>(L, 2);
6817 } else {
6818 itemId = Item::items.getItemIdByName(getString(L, 2));
6819 if (itemId == 0) {
6820 lua_pushnil(L);
6821 return 1;
6822 }
6823 }
6824
6825 uint32_t count = getNumber<uint32_t>(L, 3, 1);
6826 const ItemType &it = Item::items[itemId];
6827 if (it.stackable) {
6828 count = std::min<uint16_t>(count, 100);
6829 }
6830
6831 Item *item = Item::CreateItem(itemId, count);
6832 if (!item) {
6833 lua_pushnil(L);
6834 return 1;
6835 }
6836
6837 int32_t index = getNumber<int32_t>(L, 4, INDEX_WHEREEVER);
6838 uint32_t flags = getNumber<uint32_t>(L, 5, 0);
6839
6840 ReturnValue ret = g_game.internalAddItem(container, item, index, flags);
6841 if (ret == RETURNVALUE_NOERROR) {
6842 pushUserdata<Item>(L, item);
6843 setItemMetatable(L, -1, item);
6844 } else {
6845 delete item;
6846 lua_pushnil(L);
6847 }
6848 return 1;
6849}
6850
6851int LuaScriptInterface::luaContainerAddItemEx(lua_State *L) {
6852 // container:addItemEx(item[, index = INDEX_WHEREEVER[, flags = 0]])
6853 Item *item = getUserdata<Item>(L, 2);
6854 if (!item) {
6855 lua_pushnil(L);
6856 return 1;
6857 }
6858
6859 Container *container = getUserdata<Container>(L, 1);
6860 if (!container) {
6861 lua_pushnil(L);
6862 return 1;
6863 }
6864
6865 if (item->getParent() != VirtualCylinder::virtualCylinder) {
6866 reportErrorFunc("Item already has a parent");
6867 lua_pushnil(L);
6868 return 1;
6869 }
6870
6871 int32_t index = getNumber<int32_t>(L, 3, INDEX_WHEREEVER);
6872 uint32_t flags = getNumber<uint32_t>(L, 4, 0);
6873 ReturnValue ret = g_game.internalAddItem(container, item, index, flags);
6874 if (ret == RETURNVALUE_NOERROR) {
6875 ScriptEnvironment::removeTempItem(item);
6876 }
6877 lua_pushnumber(L, ret);
6878 return 1;
6879}
6880
6881int LuaScriptInterface::luaContainerGetCorpseOwner(lua_State *L) {
6882 // container:getCorpseOwner()
6883 Container *container = getUserdata<Container>(L, 1);
6884 if (container) {
6885 lua_pushnumber(L, container->getCorpseOwner());
6886 } else {
6887 lua_pushnil(L);
6888 }
6889 return 1;
6890}
6891
6892int LuaScriptInterface::luaContainerGetItemCountById(lua_State *L) {
6893 // container:getItemCountById(itemId[, subType = -1])
6894 Container *container = getUserdata<Container>(L, 1);
6895 if (!container) {
6896 lua_pushnil(L);
6897 return 1;
6898 }
6899
6900 uint16_t itemId;
6901 if (isNumber(L, 2)) {
6902 itemId = getNumber<uint16_t>(L, 2);
6903 } else {
6904 itemId = Item::items.getItemIdByName(getString(L, 2));
6905 if (itemId == 0) {
6906 lua_pushnil(L);
6907 return 1;
6908 }
6909 }
6910
6911 int32_t subType = getNumber<int32_t>(L, 3, -1);
6912 lua_pushnumber(L, container->getItemTypeCount(itemId, subType));
6913 return 1;
6914}
6915
6916int LuaScriptInterface::luaContainerGetContentDescription(lua_State *L) {
6917 // container:getContentDescription()
6918 Container *container = getUserdata<Container>(L, 1);
6919 if (container) {
6920 pushString(L, container->getContentDescription());
6921 } else {
6922 lua_pushnil(L);
6923 }
6924 return 1;
6925}
6926
6927// Teleport
6928int LuaScriptInterface::luaTeleportCreate(lua_State *L) {
6929 // Teleport(uid)
6930 uint32_t id = getNumber<uint32_t>(L, 2);
6931
6932 Item *item = getScriptEnv()->getItemByUID(id);
6933 if (item && item->getTeleport()) {
6934 pushUserdata(L, item);
6935 setMetatable(L, -1, "Teleport");
6936 } else {
6937 lua_pushnil(L);
6938 }
6939 return 1;
6940}
6941
6942int LuaScriptInterface::luaTeleportGetDestination(lua_State *L) {
6943 // teleport:getDestination()
6944 Teleport *teleport = getUserdata<Teleport>(L, 1);
6945 if (teleport) {
6946 pushPosition(L, teleport->getDestPos());
6947 } else {
6948 lua_pushnil(L);
6949 }
6950 return 1;
6951}
6952
6953int LuaScriptInterface::luaTeleportSetDestination(lua_State *L) {
6954 // teleport:setDestination(position)
6955 Teleport *teleport = getUserdata<Teleport>(L, 1);
6956 if (teleport) {
6957 teleport->setDestPos(getPosition(L, 2));
6958 pushBoolean(L, true);
6959 } else {
6960 lua_pushnil(L);
6961 }
6962 return 1;
6963}
6964
6965// Creature
6966int LuaScriptInterface::luaCreatureCreate(lua_State *L) {
6967 // Creature(id or name or userdata)
6968 Creature *creature;
6969 if (isNumber(L, 2)) {
6970 creature = g_game.getCreatureByID(getNumber<uint32_t>(L, 2));
6971 } else if (isString(L, 2)) {
6972 creature = g_game.getCreatureByName(getString(L, 2));
6973 } else if (isUserdata(L, 2)) {
6974 LuaDataType type = getUserdataType(L, 2);
6975 if (type != LuaData_Player && type != LuaData_Monster &&
6976 type != LuaData_Npc) {
6977 lua_pushnil(L);
6978 return 1;
6979 }
6980 creature = getUserdata<Creature>(L, 2);
6981 } else {
6982 creature = nullptr;
6983 }
6984
6985 if (creature) {
6986 pushUserdata<Creature>(L, creature);
6987 setCreatureMetatable(L, -1, creature);
6988 } else {
6989 lua_pushnil(L);
6990 }
6991 return 1;
6992}
6993
6994int LuaScriptInterface::luaCreatureGetEvents(lua_State *L) {
6995 // creature:getEvents(type)
6996 Creature *creature = getUserdata<Creature>(L, 1);
6997 if (!creature) {
6998 lua_pushnil(L);
6999 return 1;
7000 }
7001
7002 CreatureEventType_t eventType = getNumber<CreatureEventType_t>(L, 2);
7003 const auto &eventList = creature->getCreatureEvents(eventType);
7004 lua_createtable(L, eventList.size(), 0);
7005
7006 int index = 0;
7007 for (CreatureEvent *event : eventList) {
7008 pushString(L, event->getName());
7009 lua_rawseti(L, -2, ++index);
7010 }
7011 return 1;
7012}
7013
7014int LuaScriptInterface::luaCreatureRegisterEvent(lua_State *L) {
7015 // creature:registerEvent(name)
7016 Creature *creature = getUserdata<Creature>(L, 1);
7017 if (creature) {
7018 const std::string &name = getString(L, 2);
7019 pushBoolean(L, creature->registerCreatureEvent(name));
7020 } else {
7021 lua_pushnil(L);
7022 }
7023 return 1;
7024}
7025
7026int LuaScriptInterface::luaCreatureUnregisterEvent(lua_State *L) {
7027 // creature:unregisterEvent(name)
7028 const std::string &name = getString(L, 2);
7029 Creature *creature = getUserdata<Creature>(L, 1);
7030 if (creature) {
7031 pushBoolean(L, creature->unregisterCreatureEvent(name));
7032 } else {
7033 lua_pushnil(L);
7034 }
7035 return 1;
7036}
7037
7038int LuaScriptInterface::luaCreatureIsRemoved(lua_State *L) {
7039 // creature:isRemoved()
7040 const Creature *creature = getUserdata<const Creature>(L, 1);
7041 if (creature) {
7042 pushBoolean(L, creature->isRemoved());
7043 } else {
7044 lua_pushnil(L);
7045 }
7046 return 1;
7047}
7048
7049int LuaScriptInterface::luaCreatureIsCreature(lua_State *L) {
7050 // creature:isCreature()
7051 pushBoolean(L, getUserdata<const Creature>(L, 1) != nullptr);
7052 return 1;
7053}
7054
7055int LuaScriptInterface::luaCreatureIsInGhostMode(lua_State *L) {
7056 // creature:isInGhostMode()
7057 const Creature *creature = getUserdata<const Creature>(L, 1);
7058 if (creature) {
7059 pushBoolean(L, creature->isInGhostMode());
7060 } else {
7061 lua_pushnil(L);
7062 }
7063 return 1;
7064}
7065
7066int LuaScriptInterface::luaCreatureIsHealthHidden(lua_State *L) {
7067 // creature:isHealthHidden()
7068 const Creature *creature = getUserdata<const Creature>(L, 1);
7069 if (creature) {
7070 pushBoolean(L, creature->isHealthHidden());
7071 } else {
7072 lua_pushnil(L);
7073 }
7074 return 1;
7075}
7076
7077int LuaScriptInterface::luaCreatureCanSee(lua_State *L) {
7078 // creature:canSee(position)
7079 const Creature *creature = getUserdata<const Creature>(L, 1);
7080 if (creature) {
7081 const Position &position = getPosition(L, 2);
7082 pushBoolean(L, creature->canSee(position));
7083 } else {
7084 lua_pushnil(L);
7085 }
7086 return 1;
7087}
7088
7089int LuaScriptInterface::luaCreatureCanSeeCreature(lua_State *L) {
7090 // creature:canSeeCreature(creature)
7091 const Creature *creature = getUserdata<const Creature>(L, 1);
7092 if (creature) {
7093 const Creature *otherCreature = getCreature(L, 2);
7094 pushBoolean(L, creature->canSeeCreature(otherCreature));
7095 } else {
7096 lua_pushnil(L);
7097 }
7098 return 1;
7099}
7100
7101int LuaScriptInterface::luaCreatureGetParent(lua_State *L) {
7102 // creature:getParent()
7103 Creature *creature = getUserdata<Creature>(L, 1);
7104 if (!creature) {
7105 lua_pushnil(L);
7106 return 1;
7107 }
7108
7109 Cylinder *parent = creature->getParent();
7110 if (!parent) {
7111 lua_pushnil(L);
7112 return 1;
7113 }
7114
7115 pushCylinder(L, parent);
7116 return 1;
7117}
7118
7119int LuaScriptInterface::luaCreatureGetId(lua_State *L) {
7120 // creature:getId()
7121 const Creature *creature = getUserdata<const Creature>(L, 1);
7122 if (creature) {
7123 lua_pushnumber(L, creature->getID());
7124 } else {
7125 lua_pushnil(L);
7126 }
7127 return 1;
7128}
7129
7130int LuaScriptInterface::luaCreatureGetName(lua_State *L) {
7131 // creature:getName()
7132 const Creature *creature = getUserdata<const Creature>(L, 1);
7133 if (creature) {
7134 pushString(L, creature->getName());
7135 } else {
7136 lua_pushnil(L);
7137 }
7138 return 1;
7139}
7140
7141int LuaScriptInterface::luaCreatureGetTarget(lua_State *L) {
7142 // creature:getTarget()
7143 Creature *creature = getUserdata<Creature>(L, 1);
7144 if (!creature) {
7145 lua_pushnil(L);
7146 return 1;
7147 }
7148
7149 Creature *target = creature->getAttackedCreature();
7150 if (target) {
7151 pushUserdata<Creature>(L, target);
7152 setCreatureMetatable(L, -1, target);
7153 } else {
7154 lua_pushnil(L);
7155 }
7156 return 1;
7157}
7158
7159int LuaScriptInterface::luaCreatureSetTarget(lua_State *L) {
7160 // creature:setTarget(target)
7161 Creature *creature = getUserdata<Creature>(L, 1);
7162 if (creature) {
7163 Creature *target = getCreature(L, 2);
7164 pushBoolean(L, creature->setAttackedCreature(target));
7165 } else {
7166 lua_pushnil(L);
7167 }
7168 return 1;
7169}
7170
7171int LuaScriptInterface::luaCreatureGetFollowCreature(lua_State *L) {
7172 // creature:getFollowCreature()
7173 Creature *creature = getUserdata<Creature>(L, 1);
7174 if (!creature) {
7175 lua_pushnil(L);
7176 return 1;
7177 }
7178
7179 Creature *followCreature = creature->getFollowCreature();
7180 if (followCreature) {
7181 pushUserdata<Creature>(L, followCreature);
7182 setCreatureMetatable(L, -1, followCreature);
7183 } else {
7184 lua_pushnil(L);
7185 }
7186 return 1;
7187}
7188
7189int LuaScriptInterface::luaCreatureSetFollowCreature(lua_State *L) {
7190 // creature:setFollowCreature(followedCreature)
7191 Creature *creature = getUserdata<Creature>(L, 1);
7192 if (creature) {
7193 Creature *followCreature = getCreature(L, 2);
7194 pushBoolean(L, creature->setFollowCreature(followCreature));
7195 } else {
7196 lua_pushnil(L);
7197 }
7198 return 1;
7199}
7200
7201int LuaScriptInterface::luaCreatureGetMaster(lua_State *L) {
7202 // creature:getMaster()
7203 Creature *creature = getUserdata<Creature>(L, 1);
7204 if (!creature) {
7205 lua_pushnil(L);
7206 return 1;
7207 }
7208
7209 Creature *master = creature->getMaster();
7210 if (!master) {
7211 lua_pushnil(L);
7212 return 1;
7213 }
7214
7215 pushUserdata<Creature>(L, master);
7216 setCreatureMetatable(L, -1, master);
7217 return 1;
7218}
7219
7220int LuaScriptInterface::luaCreatureSetMaster(lua_State *L) {
7221 // creature:setMaster(master)
7222 Creature *creature = getUserdata<Creature>(L, 1);
7223 if (!creature) {
7224 lua_pushnil(L);
7225 return 1;
7226 }
7227
7228 pushBoolean(L, creature->setMaster(getCreature(L, 2)));
7229 g_game.updateCreatureType(creature);
7230 return 1;
7231}
7232
7233int LuaScriptInterface::luaCreatureGetLight(lua_State *L) {
7234 // creature:getLight()
7235 const Creature *creature = getUserdata<const Creature>(L, 1);
7236 if (!creature) {
7237 lua_pushnil(L);
7238 return 1;
7239 }
7240
7241 LightInfo lightInfo = creature->getCreatureLight();
7242 lua_pushnumber(L, lightInfo.level);
7243 lua_pushnumber(L, lightInfo.color);
7244 return 2;
7245}
7246
7247int LuaScriptInterface::luaCreatureSetLight(lua_State *L) {
7248 // creature:setLight(color, level)
7249 Creature *creature = getUserdata<Creature>(L, 1);
7250 if (!creature) {
7251 lua_pushnil(L);
7252 return 1;
7253 }
7254
7255 LightInfo light;
7256 light.color = getNumber<uint8_t>(L, 2);
7257 light.level = getNumber<uint8_t>(L, 3);
7258 creature->setCreatureLight(light);
7259 g_game.changeLight(creature);
7260 pushBoolean(L, true);
7261 return 1;
7262}
7263
7264int LuaScriptInterface::luaCreatureGetSpeed(lua_State *L) {
7265 // creature:getSpeed()
7266 const Creature *creature = getUserdata<const Creature>(L, 1);
7267 if (creature) {
7268 lua_pushnumber(L, creature->getSpeed());
7269 } else {
7270 lua_pushnil(L);
7271 }
7272 return 1;
7273}
7274
7275int LuaScriptInterface::luaCreatureGetBaseSpeed(lua_State *L) {
7276 // creature:getBaseSpeed()
7277 const Creature *creature = getUserdata<const Creature>(L, 1);
7278 if (creature) {
7279 lua_pushnumber(L, creature->getBaseSpeed());
7280 } else {
7281 lua_pushnil(L);
7282 }
7283 return 1;
7284}
7285
7286int LuaScriptInterface::luaCreatureChangeSpeed(lua_State *L) {
7287 // creature:changeSpeed(delta)
7288 Creature *creature = getCreature(L, 1);
7289 if (!creature) {
7290 reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
7291 pushBoolean(L, false);
7292 return 1;
7293 }
7294
7295 int32_t delta = getNumber<int32_t>(L, 2);
7296 g_game.changeSpeed(creature, delta);
7297 pushBoolean(L, true);
7298 return 1;
7299}
7300
7301int LuaScriptInterface::luaCreatureSetDropLoot(lua_State *L) {
7302 // creature:setDropLoot(doDrop)
7303 Creature *creature = getUserdata<Creature>(L, 1);
7304 if (creature) {
7305 creature->setDropLoot(getBoolean(L, 2));
7306 pushBoolean(L, true);
7307 } else {
7308 lua_pushnil(L);
7309 }
7310 return 1;
7311}
7312
7313int LuaScriptInterface::luaCreatureSetSkillLoss(lua_State *L) {
7314 // creature:setSkillLoss(skillLoss)
7315 Creature *creature = getUserdata<Creature>(L, 1);
7316 if (creature) {
7317 creature->setSkillLoss(getBoolean(L, 2));
7318 pushBoolean(L, true);
7319 } else {
7320 lua_pushnil(L);
7321 }
7322 return 1;
7323}
7324
7325int LuaScriptInterface::luaCreatureGetPosition(lua_State *L) {
7326 // creature:getPosition()
7327 const Creature *creature = getUserdata<const Creature>(L, 1);
7328 if (creature) {
7329 pushPosition(L, creature->getPosition());
7330 } else {
7331 lua_pushnil(L);
7332 }
7333 return 1;
7334}
7335
7336int LuaScriptInterface::luaCreatureGetTile(lua_State *L) {
7337 // creature:getTile()
7338 Creature *creature = getUserdata<Creature>(L, 1);
7339 if (!creature) {
7340 lua_pushnil(L);
7341 return 1;
7342 }
7343
7344 Tile *tile = creature->getTile();
7345 if (tile) {
7346 pushUserdata<Tile>(L, tile);
7347 setMetatable(L, -1, "Tile");
7348 } else {
7349 lua_pushnil(L);
7350 }
7351 return 1;
7352}
7353
7354int LuaScriptInterface::luaCreatureGetDirection(lua_State *L) {
7355 // creature:getDirection()
7356 const Creature *creature = getUserdata<const Creature>(L, 1);
7357 if (creature) {
7358 lua_pushnumber(L, creature->getDirection());
7359 } else {
7360 lua_pushnil(L);
7361 }
7362 return 1;
7363}
7364
7365int LuaScriptInterface::luaCreatureSetDirection(lua_State *L) {
7366 // creature:setDirection(direction)
7367 Creature *creature = getUserdata<Creature>(L, 1);
7368 if (creature) {
7369 pushBoolean(
7370 L, g_game.internalCreatureTurn(creature, getNumber<Direction>(L, 2)));
7371 } else {
7372 lua_pushnil(L);
7373 }
7374 return 1;
7375}
7376
7377int LuaScriptInterface::luaCreatureGetHealth(lua_State *L) {
7378 // creature:getHealth()
7379 const Creature *creature = getUserdata<const Creature>(L, 1);
7380 if (creature) {
7381 lua_pushnumber(L, creature->getHealth());
7382 } else {
7383 lua_pushnil(L);
7384 }
7385 return 1;
7386}
7387
7388int LuaScriptInterface::luaCreatureSetHealth(lua_State *L) {
7389 // creature:setHealth(health)
7390 Creature *creature = getUserdata<Creature>(L, 1);
7391 if (!creature) {
7392 lua_pushnil(L);
7393 return 1;
7394 }
7395
7396 creature->health =
7397 std::min<int32_t>(getNumber<uint32_t>(L, 2), creature->healthMax);
7398 g_game.addCreatureHealth(creature);
7399
7400 Player *player = creature->getPlayer();
7401 if (player) {
7402 player->sendStats();
7403 }
7404 pushBoolean(L, true);
7405 return 1;
7406}
7407
7408int LuaScriptInterface::luaCreatureAddHealth(lua_State *L) {
7409 // creature:addHealth(healthChange)
7410 Creature *creature = getUserdata<Creature>(L, 1);
7411 if (!creature) {
7412 lua_pushnil(L);
7413 return 1;
7414 }
7415
7416 CombatDamage damage;
7417 damage.primary.value = getNumber<int32_t>(L, 2);
7418 if (damage.primary.value >= 0) {
7419 damage.primary.type = COMBAT_HEALING;
7420 } else {
7421 damage.primary.type = COMBAT_UNDEFINEDDAMAGE;
7422 }
7423 pushBoolean(L, g_game.combatChangeHealth(nullptr, creature, damage));
7424 return 1;
7425}
7426
7427int LuaScriptInterface::luaCreatureGetMaxHealth(lua_State *L) {
7428 // creature:getMaxHealth()
7429 const Creature *creature = getUserdata<const Creature>(L, 1);
7430 if (creature) {
7431 lua_pushnumber(L, creature->getMaxHealth());
7432 } else {
7433 lua_pushnil(L);
7434 }
7435 return 1;
7436}
7437
7438int LuaScriptInterface::luaCreatureSetMaxHealth(lua_State *L) {
7439 // creature:setMaxHealth(maxHealth)
7440 Creature *creature = getUserdata<Creature>(L, 1);
7441 if (!creature) {
7442 lua_pushnil(L);
7443 return 1;
7444 }
7445
7446 creature->healthMax = getNumber<uint32_t>(L, 2);
7447 creature->health = std::min<int32_t>(creature->health, creature->healthMax);
7448 g_game.addCreatureHealth(creature);
7449
7450 Player *player = creature->getPlayer();
7451 if (player) {
7452 player->sendStats();
7453 }
7454 pushBoolean(L, true);
7455 return 1;
7456}
7457
7458int LuaScriptInterface::luaCreatureSetHiddenHealth(lua_State *L) {
7459 // creature:setHiddenHealth(hide)
7460 Creature *creature = getUserdata<Creature>(L, 1);
7461 if (creature) {
7462 creature->setHiddenHealth(getBoolean(L, 2));
7463 g_game.addCreatureHealth(creature);
7464 pushBoolean(L, true);
7465 } else {
7466 lua_pushnil(L);
7467 }
7468 return 1;
7469}
7470
7471int LuaScriptInterface::luaCreatureGetSkull(lua_State *L) {
7472 // creature:getSkull()
7473 Creature *creature = getUserdata<Creature>(L, 1);
7474 if (creature) {
7475 lua_pushnumber(L, creature->getSkull());
7476 } else {
7477 lua_pushnil(L);
7478 }
7479 return 1;
7480}
7481
7482int LuaScriptInterface::luaCreatureSetSkull(lua_State *L) {
7483 // creature:setSkull(skull)
7484 Creature *creature = getUserdata<Creature>(L, 1);
7485 if (creature) {
7486 creature->setSkull(getNumber<Skulls_t>(L, 2));
7487 pushBoolean(L, true);
7488 } else {
7489 lua_pushnil(L);
7490 }
7491 return 1;
7492}
7493
7494int LuaScriptInterface::luaCreatureGetOutfit(lua_State *L) {
7495 // creature:getOutfit()
7496 const Creature *creature = getUserdata<const Creature>(L, 1);
7497 if (creature) {
7498 if (creature->isAttackPulsing) {
7499 pushOutfit(L, creature->originalOutfit);
7500 } else {
7501 pushOutfit(L, creature->getCurrentOutfit());
7502 }
7503 } else {
7504 lua_pushnil(L);
7505 }
7506 return 1;
7507}
7508
7509int LuaScriptInterface::luaCreatureSetOutfit(lua_State *L) {
7510 // creature:setOutfit(outfit)
7511 Creature *creature = getUserdata<Creature>(L, 1);
7512 if (creature) {
7513 creature->defaultOutfit = getOutfit(L, 2);
7514 g_game.internalCreatureChangeOutfit(creature, creature->defaultOutfit);
7515 pushBoolean(L, true);
7516 } else {
7517 lua_pushnil(L);
7518 }
7519 return 1;
7520}
7521
7522int LuaScriptInterface::luaCreatureGetCondition(lua_State *L) {
7523 // creature:getCondition(conditionType[, conditionId = CONDITIONID_COMBAT[,
7524 // subId = 0]])
7525 Creature *creature = getUserdata<Creature>(L, 1);
7526 if (!creature) {
7527 lua_pushnil(L);
7528 return 1;
7529 }
7530
7531 ConditionType_t conditionType = getNumber<ConditionType_t>(L, 2);
7532 ConditionId_t conditionId =
7533 getNumber<ConditionId_t>(L, 3, CONDITIONID_COMBAT);
7534 uint32_t subId = getNumber<uint32_t>(L, 4, 0);
7535
7536 Condition *condition =
7537 creature->getCondition(conditionType, conditionId, subId);
7538 if (condition) {
7539 pushUserdata<Condition>(L, condition);
7540 setWeakMetatable(L, -1, "Condition");
7541 } else {
7542 lua_pushnil(L);
7543 }
7544 return 1;
7545}
7546
7547int LuaScriptInterface::luaCreatureAddCondition(lua_State *L) {
7548 // creature:addCondition(condition[, force = false])
7549 Creature *creature = getUserdata<Creature>(L, 1);
7550 Condition *condition = getUserdata<Condition>(L, 2);
7551 if (creature && condition) {
7552 bool force = getBoolean(L, 3, false);
7553 pushBoolean(L, creature->addCondition(condition->clone(), force));
7554 } else {
7555 lua_pushnil(L);
7556 }
7557 return 1;
7558}
7559
7560int LuaScriptInterface::luaCreatureRemoveCondition(lua_State *L) {
7561 // creature:removeCondition(conditionType[, conditionId = CONDITIONID_COMBAT[,
7562 // subId = 0[, force = false]]])
7563 Creature *creature = getUserdata<Creature>(L, 1);
7564 if (!creature) {
7565 lua_pushnil(L);
7566 return 1;
7567 }
7568
7569 ConditionType_t conditionType = getNumber<ConditionType_t>(L, 2);
7570 ConditionId_t conditionId =
7571 getNumber<ConditionId_t>(L, 3, CONDITIONID_COMBAT);
7572 uint32_t subId = getNumber<uint32_t>(L, 4, 0);
7573 Condition *condition =
7574 creature->getCondition(conditionType, conditionId, subId);
7575 if (condition) {
7576 bool force = getBoolean(L, 5, false);
7577 creature->removeCondition(condition, force);
7578 pushBoolean(L, true);
7579 } else {
7580 lua_pushnil(L);
7581 }
7582 return 1;
7583}
7584
7585int LuaScriptInterface::luaCreatureHasCondition(lua_State *L) {
7586 // creature:hasCondition(conditionType[, subId = 0])
7587 Creature *creature = getUserdata<Creature>(L, 1);
7588 if (!creature) {
7589 lua_pushnil(L);
7590 return 1;
7591 }
7592
7593 ConditionType_t conditionType = getNumber<ConditionType_t>(L, 2);
7594 uint32_t subId = getNumber<uint32_t>(L, 3, 0);
7595 pushBoolean(L, creature->hasCondition(conditionType, subId));
7596 return 1;
7597}
7598
7599int LuaScriptInterface::luaCreatureIsImmune(lua_State *L) {
7600 // creature:isImmune(condition or conditionType)
7601 Creature *creature = getUserdata<Creature>(L, 1);
7602 if (!creature) {
7603 lua_pushnil(L);
7604 return 1;
7605 }
7606
7607 if (isNumber(L, 2)) {
7608 pushBoolean(L, creature->isImmune(getNumber<ConditionType_t>(L, 2)));
7609 } else if (Condition *condition = getUserdata<Condition>(L, 2)) {
7610 pushBoolean(L, creature->isImmune(condition->getType()));
7611 } else {
7612 lua_pushnil(L);
7613 }
7614 return 1;
7615}
7616
7617int LuaScriptInterface::luaCreatureRemove(lua_State *L) {
7618 // creature:remove()
7619 Creature **creaturePtr = getRawUserdata<Creature>(L, 1);
7620 if (!creaturePtr) {
7621 lua_pushnil(L);
7622 return 1;
7623 }
7624
7625 Creature *creature = *creaturePtr;
7626 if (!creature) {
7627 lua_pushnil(L);
7628 return 1;
7629 }
7630
7631 Player *player = creature->getPlayer();
7632 if (player) {
7633 player->kickPlayer(true);
7634 } else {
7635 g_game.removeCreature(creature);
7636 }
7637
7638 *creaturePtr = nullptr;
7639 pushBoolean(L, true);
7640 return 1;
7641}
7642
7643int LuaScriptInterface::luaCreatureTeleportTo(lua_State *L) {
7644 // creature:teleportTo(position[, pushMovement = false])
7645 bool pushMovement = getBoolean(L, 3, false);
7646
7647 const Position &position = getPosition(L, 2);
7648 Creature *creature = getUserdata<Creature>(L, 1);
7649 if (!creature) {
7650 lua_pushnil(L);
7651 return 1;
7652 }
7653
7654 const Position oldPosition = creature->getPosition();
7655 if (g_game.internalTeleport(creature, position, pushMovement) !=
7656 RETURNVALUE_NOERROR) {
7657 pushBoolean(L, false);
7658 return 1;
7659 }
7660
7661 if (pushMovement) {
7662 if (oldPosition.x == position.x) {
7663 if (oldPosition.y < position.y) {
7664 g_game.internalCreatureTurn(creature, DIRECTION_SOUTH);
7665 } else {
7666 g_game.internalCreatureTurn(creature, DIRECTION_NORTH);
7667 }
7668 } else if (oldPosition.x > position.x) {
7669 g_game.internalCreatureTurn(creature, DIRECTION_WEST);
7670 } else if (oldPosition.x < position.x) {
7671 g_game.internalCreatureTurn(creature, DIRECTION_EAST);
7672 }
7673 }
7674 pushBoolean(L, true);
7675 return 1;
7676}
7677
7678int LuaScriptInterface::luaCreatureSay(lua_State *L) {
7679 // creature:say(text[, type = TALKTYPE_MONSTER_SAY[, ghost = false[, target =
7680 // nullptr[, position]]]])
7681 int parameters = lua_gettop(L);
7682
7683 Position position;
7684 if (parameters >= 6) {
7685 position = getPosition(L, 6);
7686 if (!position.x || !position.y) {
7687 reportErrorFunc("Invalid position specified.");
7688 pushBoolean(L, false);
7689 return 1;
7690 }
7691 }
7692
7693 Creature *target = nullptr;
7694 if (parameters >= 5) {
7695 target = getCreature(L, 5);
7696 }
7697
7698 bool ghost = getBoolean(L, 4, false);
7699
7700 SpeakClasses type = getNumber<SpeakClasses>(L, 3, TALKTYPE_MONSTER_SAY);
7701 const std::string &text = getString(L, 2);
7702 Creature *creature = getUserdata<Creature>(L, 1);
7703 if (!creature) {
7704 lua_pushnil(L);
7705 return 1;
7706 }
7707
7708 SpectatorVec spectators;
7709 if (target) {
7710 spectators.emplace_back(target);
7711 }
7712
7713 if (position.x != 0) {
7714 pushBoolean(L, g_game.internalCreatureSay(creature, type, text, ghost,
7715 &spectators, &position));
7716 } else {
7717 pushBoolean(L, g_game.internalCreatureSay(creature, type, text, ghost,
7718 &spectators));
7719 }
7720 return 1;
7721}
7722
7723int LuaScriptInterface::luaCreatureGetDamageMap(lua_State *L) {
7724 // creature:getDamageMap()
7725 Creature *creature = getUserdata<Creature>(L, 1);
7726 if (!creature) {
7727 lua_pushnil(L);
7728 return 1;
7729 }
7730
7731 lua_createtable(L, creature->damageMap.size(), 0);
7732 for (auto damageEntry : creature->damageMap) {
7733 lua_createtable(L, 0, 2);
7734 setField(L, "total", damageEntry.second.total);
7735 setField(L, "ticks", damageEntry.second.ticks);
7736 lua_rawseti(L, -2, damageEntry.first);
7737 }
7738 return 1;
7739}
7740
7741int LuaScriptInterface::luaCreatureGetSummons(lua_State *L) {
7742 // creature:getSummons()
7743 Creature *creature = getUserdata<Creature>(L, 1);
7744 if (!creature) {
7745 lua_pushnil(L);
7746 return 1;
7747 }
7748
7749 lua_createtable(L, creature->getSummonCount(), 0);
7750
7751 int index = 0;
7752 for (Creature *summon : creature->getSummons()) {
7753 pushUserdata<Creature>(L, summon);
7754 setCreatureMetatable(L, -1, summon);
7755 lua_rawseti(L, -2, ++index);
7756 }
7757 return 1;
7758}
7759
7760int LuaScriptInterface::luaCreatureGetDescription(lua_State *L) {
7761 // creature:getDescription(distance)
7762 int32_t distance = getNumber<int32_t>(L, 2);
7763 Creature *creature = getUserdata<Creature>(L, 1);
7764 if (creature) {
7765 pushString(L, creature->getDescription(distance));
7766 } else {
7767 lua_pushnil(L);
7768 }
7769 return 1;
7770}
7771
7772int LuaScriptInterface::luaCreatureGetPathTo(lua_State *L) {
7773 // creature:getPathTo(pos[, minTargetDist = 0[, maxTargetDist = 1[,
7774 // fullPathSearch = true[, clearSight = true[, maxSearchDist = 0]]]]])
7775 Creature *creature = getUserdata<Creature>(L, 1);
7776 if (!creature) {
7777 lua_pushnil(L);
7778 return 1;
7779 }
7780
7781 const Position &position = getPosition(L, 2);
7782
7783 FindPathParams fpp;
7784 fpp.minTargetDist = getNumber<int32_t>(L, 3, 0);
7785 fpp.maxTargetDist = getNumber<int32_t>(L, 4, 1);
7786 fpp.fullPathSearch = getBoolean(L, 5, fpp.fullPathSearch);
7787 fpp.clearSight = getBoolean(L, 6, fpp.clearSight);
7788 fpp.maxSearchDist = getNumber<int32_t>(L, 7, fpp.maxSearchDist);
7789
7790 std::list<Direction> dirList;
7791 if (creature->getPathTo(position, dirList, fpp)) {
7792 lua_newtable(L);
7793
7794 int index = 0;
7795 for (Direction dir : dirList) {
7796 lua_pushnumber(L, dir);
7797 lua_rawseti(L, -2, ++index);
7798 }
7799 } else {
7800 pushBoolean(L, false);
7801 }
7802 return 1;
7803}
7804
7805int LuaScriptInterface::luaCreatureMove(lua_State *L) {
7806 // creature:move(direction)
7807 // creature:move(tile[, flags = 0])
7808 Creature *creature = getUserdata<Creature>(L, 1);
7809 if (!creature) {
7810 lua_pushnil(L);
7811 return 1;
7812 }
7813
7814 if (isNumber(L, 2)) {
7815 Direction direction = getNumber<Direction>(L, 2);
7816 if (direction > DIRECTION_LAST) {
7817 lua_pushnil(L);
7818 return 1;
7819 }
7820 lua_pushnumber(
7821 L, g_game.internalMoveCreature(creature, direction, FLAG_NOLIMIT));
7822 } else {
7823 Tile *tile = getUserdata<Tile>(L, 2);
7824 if (!tile) {
7825 lua_pushnil(L);
7826 return 1;
7827 }
7828 lua_pushnumber(L, g_game.internalMoveCreature(*creature, *tile,
7829 getNumber<uint32_t>(L, 3)));
7830 }
7831 return 1;
7832}
7833
7834int LuaScriptInterface::luaCreatureGetZone(lua_State *L) {
7835 // creature:getZone()
7836 Creature *creature = getUserdata<Creature>(L, 1);
7837 if (creature) {
7838 lua_pushnumber(L, creature->getZone());
7839 } else {
7840 lua_pushnil(L);
7841 }
7842 return 1;
7843}
7844
7845// Player
7846int LuaScriptInterface::luaPlayerCreate(lua_State *L) {
7847 // Player(id or guid or name or userdata)
7848 Player *player;
7849 if (isNumber(L, 2)) {
7850 uint32_t id = getNumber<uint32_t>(L, 2);
7851 if (id >= 0x10000000 && id <= Player::playerAutoID) {
7852 player = g_game.getPlayerByID(id);
7853 } else {
7854 player = g_game.getPlayerByGUID(id);
7855 }
7856 } else if (isString(L, 2)) {
7857 ReturnValue ret = g_game.getPlayerByNameWildcard(getString(L, 2), player);
7858 if (ret != RETURNVALUE_NOERROR) {
7859 lua_pushnil(L);
7860 lua_pushnumber(L, ret);
7861 return 2;
7862 }
7863 } else if (isUserdata(L, 2)) {
7864 if (getUserdataType(L, 2) != LuaData_Player) {
7865 lua_pushnil(L);
7866 return 1;
7867 }
7868 player = getUserdata<Player>(L, 2);
7869 } else {
7870 player = nullptr;
7871 }
7872
7873 if (player) {
7874 pushUserdata<Player>(L, player);
7875 setMetatable(L, -1, "Player");
7876 } else {
7877 lua_pushnil(L);
7878 }
7879 return 1;
7880}
7881
7882int LuaScriptInterface::luaPlayerIsPlayer(lua_State *L) {
7883 // player:isPlayer()
7884 pushBoolean(L, getUserdata<const Player>(L, 1) != nullptr);
7885 return 1;
7886}
7887
7888int LuaScriptInterface::luaPlayerGetGuid(lua_State *L) {
7889 // player:getGuid()
7890 Player *player = getUserdata<Player>(L, 1);
7891 if (player) {
7892 lua_pushnumber(L, player->getGUID());
7893 } else {
7894 lua_pushnil(L);
7895 }
7896 return 1;
7897}
7898
7899int LuaScriptInterface::luaPlayerGetIp(lua_State *L) {
7900 // player:getIp()
7901 Player *player = getUserdata<Player>(L, 1);
7902 if (player) {
7903 lua_pushnumber(L, player->getIP());
7904 } else {
7905 lua_pushnil(L);
7906 }
7907 return 1;
7908}
7909
7910int LuaScriptInterface::luaPlayerGetAccountId(lua_State *L) {
7911 // player:getAccountId()
7912 Player *player = getUserdata<Player>(L, 1);
7913 if (player) {
7914 lua_pushnumber(L, player->getAccount());
7915 } else {
7916 lua_pushnil(L);
7917 }
7918 return 1;
7919}
7920
7921int LuaScriptInterface::luaPlayerGetLastLoginSaved(lua_State *L) {
7922 // player:getLastLoginSaved()
7923 Player *player = getUserdata<Player>(L, 1);
7924 if (player) {
7925 lua_pushnumber(L, player->getLastLoginSaved());
7926 } else {
7927 lua_pushnil(L);
7928 }
7929 return 1;
7930}
7931
7932int LuaScriptInterface::luaPlayerGetLastLogout(lua_State *L) {
7933 // player:getLastLogout()
7934 Player *player = getUserdata<Player>(L, 1);
7935 if (player) {
7936 lua_pushnumber(L, player->getLastLogout());
7937 } else {
7938 lua_pushnil(L);
7939 }
7940 return 1;
7941}
7942
7943int LuaScriptInterface::luaPlayerGetAccountType(lua_State *L) {
7944 // player:getAccountType()
7945 Player *player = getUserdata<Player>(L, 1);
7946 if (player) {
7947 lua_pushnumber(L, player->getAccountType());
7948 } else {
7949 lua_pushnil(L);
7950 }
7951 return 1;
7952}
7953
7954int LuaScriptInterface::luaPlayerSetAccountType(lua_State *L) {
7955 // player:setAccountType(accountType)
7956 Player *player = getUserdata<Player>(L, 1);
7957 if (player) {
7958 player->accountType = getNumber<AccountType_t>(L, 2);
7959 IOLoginData::setAccountType(player->getAccount(), player->accountType);
7960 pushBoolean(L, true);
7961 } else {
7962 lua_pushnil(L);
7963 }
7964 return 1;
7965}
7966
7967int LuaScriptInterface::luaPlayerGetCapacity(lua_State *L) {
7968 // player:getCapacity()
7969 Player *player = getUserdata<Player>(L, 1);
7970 if (player) {
7971 lua_pushnumber(L, player->getCapacity());
7972 } else {
7973 lua_pushnil(L);
7974 }
7975 return 1;
7976}
7977
7978int LuaScriptInterface::luaPlayerSetCapacity(lua_State *L) {
7979 // player:setCapacity(capacity)
7980 Player *player = getUserdata<Player>(L, 1);
7981 if (player) {
7982 player->capacity = getNumber<uint32_t>(L, 2);
7983 player->sendStats();
7984 pushBoolean(L, true);
7985 } else {
7986 lua_pushnil(L);
7987 }
7988 return 1;
7989}
7990
7991int LuaScriptInterface::luaPlayerGetFreeCapacity(lua_State *L) {
7992 // player:getFreeCapacity()
7993 Player *player = getUserdata<Player>(L, 1);
7994 if (player) {
7995 lua_pushnumber(L, player->getFreeCapacity());
7996 } else {
7997 lua_pushnil(L);
7998 }
7999 return 1;
8000}
8001
8002int LuaScriptInterface::luaPlayerGetDepotChest(lua_State *L) {
8003 // player:getDepotChest(depotId[, autoCreate = false])
8004 Player *player = getUserdata<Player>(L, 1);
8005 if (!player) {
8006 lua_pushnil(L);
8007 return 1;
8008 }
8009
8010 uint32_t depotId = getNumber<uint32_t>(L, 2);
8011 bool autoCreate = getBoolean(L, 3, false);
8012 DepotChest *depotChest = player->getDepotChest(depotId, autoCreate);
8013 if (depotChest) {
8014 player->setLastDepotId(depotId); // FIXME: workaround for #2251
8015 pushUserdata<Item>(L, depotChest);
8016 setItemMetatable(L, -1, depotChest);
8017 } else {
8018 pushBoolean(L, false);
8019 }
8020 return 1;
8021}
8022
8023int LuaScriptInterface::luaPlayerGetInbox(lua_State *L) {
8024 // player:getInbox()
8025 Player *player = getUserdata<Player>(L, 1);
8026 if (!player) {
8027 lua_pushnil(L);
8028 return 1;
8029 }
8030
8031 Inbox *inbox = player->getInbox();
8032 if (inbox) {
8033 pushUserdata<Item>(L, inbox);
8034 setItemMetatable(L, -1, inbox);
8035 } else {
8036 pushBoolean(L, false);
8037 }
8038 return 1;
8039}
8040
8041int LuaScriptInterface::luaPlayerGetSkullTime(lua_State *L) {
8042 // player:getSkullTime()
8043 Player *player = getUserdata<Player>(L, 1);
8044 if (player) {
8045 lua_pushnumber(L, player->getSkullTicks());
8046 } else {
8047 lua_pushnil(L);
8048 }
8049 return 1;
8050}
8051
8052int LuaScriptInterface::luaPlayerSetSkullTime(lua_State *L) {
8053 // player:setSkullTime(skullTime)
8054 Player *player = getUserdata<Player>(L, 1);
8055 if (player) {
8056 player->setSkullTicks(getNumber<int64_t>(L, 2));
8057 pushBoolean(L, true);
8058 } else {
8059 lua_pushnil(L);
8060 }
8061 return 1;
8062}
8063
8064int LuaScriptInterface::luaPlayerGetDeathPenalty(lua_State *L) {
8065 // player:getDeathPenalty()
8066 Player *player = getUserdata<Player>(L, 1);
8067 if (player) {
8068 lua_pushnumber(L, player->getLostPercent() * 100);
8069 } else {
8070 lua_pushnil(L);
8071 }
8072 return 1;
8073}
8074
8075int LuaScriptInterface::luaPlayerGetExperience(lua_State *L) {
8076 // player:getExperience()
8077 Player *player = getUserdata<Player>(L, 1);
8078 if (player) {
8079 lua_pushnumber(L, player->getExperience());
8080 } else {
8081 lua_pushnil(L);
8082 }
8083 return 1;
8084}
8085
8086int LuaScriptInterface::luaPlayerAddExperience(lua_State *L) {
8087 // player:addExperience(experience[, sendText = false])
8088 Player *player = getUserdata<Player>(L, 1);
8089 if (player) {
8090 int64_t experience = getNumber<int64_t>(L, 2);
8091 bool sendText = getBoolean(L, 3, false);
8092 player->addExperience(nullptr, experience, sendText);
8093 pushBoolean(L, true);
8094 } else {
8095 lua_pushnil(L);
8096 }
8097 return 1;
8098}
8099
8100int LuaScriptInterface::luaPlayerRemoveExperience(lua_State *L) {
8101 // player:removeExperience(experience[, sendText = false])
8102 Player *player = getUserdata<Player>(L, 1);
8103 if (player) {
8104 int64_t experience = getNumber<int64_t>(L, 2);
8105 bool sendText = getBoolean(L, 3, false);
8106 player->removeExperience(experience, sendText);
8107 pushBoolean(L, true);
8108 } else {
8109 lua_pushnil(L);
8110 }
8111 return 1;
8112}
8113
8114int LuaScriptInterface::luaPlayerGetLevel(lua_State *L) {
8115 // player:getLevel()
8116 Player *player = getUserdata<Player>(L, 1);
8117 if (player) {
8118 lua_pushnumber(L, player->getLevel());
8119 } else {
8120 lua_pushnil(L);
8121 }
8122 return 1;
8123}
8124
8125int LuaScriptInterface::luaPlayerGetMagicLevel(lua_State *L) {
8126 // player:getMagicLevel()
8127 Player *player = getUserdata<Player>(L, 1);
8128 if (player) {
8129 lua_pushnumber(L, player->getMagicLevel());
8130 } else {
8131 lua_pushnil(L);
8132 }
8133 return 1;
8134}
8135
8136int LuaScriptInterface::luaPlayerGetBaseMagicLevel(lua_State *L) {
8137 // player:getBaseMagicLevel()
8138 Player *player = getUserdata<Player>(L, 1);
8139 if (player) {
8140 lua_pushnumber(L, player->getBaseMagicLevel());
8141 } else {
8142 lua_pushnil(L);
8143 }
8144 return 1;
8145}
8146
8147int LuaScriptInterface::luaPlayerGetMana(lua_State *L) {
8148 // player:getMana()
8149 const Player *player = getUserdata<const Player>(L, 1);
8150 if (player) {
8151 lua_pushnumber(L, player->getMana());
8152 } else {
8153 lua_pushnil(L);
8154 }
8155 return 1;
8156}
8157
8158int LuaScriptInterface::luaPlayerAddMana(lua_State *L) {
8159 // player:addMana(manaChange[, animationOnLoss = false])
8160 Player *player = getUserdata<Player>(L, 1);
8161 if (!player) {
8162 lua_pushnil(L);
8163 return 1;
8164 }
8165
8166 int32_t manaChange = getNumber<int32_t>(L, 2);
8167 bool animationOnLoss = getBoolean(L, 3, false);
8168 if (!animationOnLoss && manaChange < 0) {
8169 player->changeMana(manaChange);
8170 } else {
8171 CombatDamage damage;
8172 damage.primary.value = manaChange;
8173 damage.origin = ORIGIN_NONE;
8174 g_game.combatChangeMana(nullptr, player, damage);
8175 }
8176 pushBoolean(L, true);
8177 return 1;
8178}
8179
8180int LuaScriptInterface::luaPlayerGetMaxMana(lua_State *L) {
8181 // player:getMaxMana()
8182 const Player *player = getUserdata<const Player>(L, 1);
8183 if (player) {
8184 lua_pushnumber(L, player->getMaxMana());
8185 } else {
8186 lua_pushnil(L);
8187 }
8188 return 1;
8189}
8190
8191int LuaScriptInterface::luaPlayerSetMaxMana(lua_State *L) {
8192 // player:setMaxMana(maxMana)
8193 Player *player = getPlayer(L, 1);
8194 if (player) {
8195 player->manaMax = getNumber<int32_t>(L, 2);
8196 player->mana = std::min<int32_t>(player->mana, player->manaMax);
8197 player->sendStats();
8198 pushBoolean(L, true);
8199 } else {
8200 lua_pushnil(L);
8201 }
8202 return 1;
8203}
8204
8205int LuaScriptInterface::luaPlayerGetManaSpent(lua_State *L) {
8206 // player:getManaSpent()
8207 Player *player = getUserdata<Player>(L, 1);
8208 if (player) {
8209 lua_pushnumber(L, player->getSpentMana());
8210 } else {
8211 lua_pushnil(L);
8212 }
8213 return 1;
8214}
8215
8216int LuaScriptInterface::luaPlayerAddManaSpent(lua_State *L) {
8217 // player:addManaSpent(amount)
8218 Player *player = getUserdata<Player>(L, 1);
8219 if (player) {
8220 player->addManaSpent(getNumber<uint64_t>(L, 2));
8221 pushBoolean(L, true);
8222 } else {
8223 lua_pushnil(L);
8224 }
8225 return 1;
8226}
8227
8228int LuaScriptInterface::luaPlayerGetBaseMaxHealth(lua_State *L) {
8229 // player:getBaseMaxHealth()
8230 Player *player = getUserdata<Player>(L, 1);
8231 if (player) {
8232 lua_pushnumber(L, player->healthMax);
8233 } else {
8234 lua_pushnil(L);
8235 }
8236 return 1;
8237}
8238
8239int LuaScriptInterface::luaPlayerGetBaseMaxMana(lua_State *L) {
8240 // player:getBaseMaxMana()
8241 Player *player = getUserdata<Player>(L, 1);
8242 if (player) {
8243 lua_pushnumber(L, player->manaMax);
8244 } else {
8245 lua_pushnil(L);
8246 }
8247 return 1;
8248}
8249
8250int LuaScriptInterface::luaPlayerGetSkillLevel(lua_State *L) {
8251 // player:getSkillLevel(skillType)
8252 skills_t skillType = getNumber<skills_t>(L, 2);
8253 Player *player = getUserdata<Player>(L, 1);
8254 if (player && skillType <= SKILL_LAST) {
8255 lua_pushnumber(L, player->skills[skillType].level);
8256 } else {
8257 lua_pushnil(L);
8258 }
8259 return 1;
8260}
8261
8262int LuaScriptInterface::luaPlayerGetEffectiveSkillLevel(lua_State *L) {
8263 // player:getEffectiveSkillLevel(skillType)
8264 skills_t skillType = getNumber<skills_t>(L, 2);
8265 Player *player = getUserdata<Player>(L, 1);
8266 if (player && skillType <= SKILL_LAST) {
8267 lua_pushnumber(L, player->getSkillLevel(skillType));
8268 } else {
8269 lua_pushnil(L);
8270 }
8271 return 1;
8272}
8273
8274int LuaScriptInterface::luaPlayerGetSkillPercent(lua_State *L) {
8275 // player:getSkillPercent(skillType)
8276 skills_t skillType = getNumber<skills_t>(L, 2);
8277 Player *player = getUserdata<Player>(L, 1);
8278 if (player && skillType <= SKILL_LAST) {
8279 lua_pushnumber(L, player->skills[skillType].percent);
8280 } else {
8281 lua_pushnil(L);
8282 }
8283 return 1;
8284}
8285
8286int LuaScriptInterface::luaPlayerGetSkillTries(lua_State *L) {
8287 // player:getSkillTries(skillType)
8288 skills_t skillType = getNumber<skills_t>(L, 2);
8289 Player *player = getUserdata<Player>(L, 1);
8290 if (player && skillType <= SKILL_LAST) {
8291 lua_pushnumber(L, player->skills[skillType].tries);
8292 } else {
8293 lua_pushnil(L);
8294 }
8295 return 1;
8296}
8297
8298int LuaScriptInterface::luaPlayerAddSkillTries(lua_State *L) {
8299 // player:addSkillTries(skillType, tries)
8300 Player *player = getUserdata<Player>(L, 1);
8301 if (player) {
8302 skills_t skillType = getNumber<skills_t>(L, 2);
8303 uint64_t tries = getNumber<uint64_t>(L, 3);
8304 player->addSkillAdvance(skillType, tries);
8305 pushBoolean(L, true);
8306 } else {
8307 lua_pushnil(L);
8308 }
8309 return 1;
8310}
8311
8312int LuaScriptInterface::luaPlayerGetSpecialSkill(lua_State *L) {
8313 // player:getSpecialSkill(specialSkillType)
8314 SpecialSkills_t specialSkillType = getNumber<SpecialSkills_t>(L, 2);
8315 Player *player = getUserdata<Player>(L, 1);
8316 if (player && specialSkillType <= SPECIALSKILL_LAST) {
8317 lua_pushnumber(L, player->getSpecialSkill(specialSkillType));
8318 } else {
8319 lua_pushnil(L);
8320 }
8321 return 1;
8322}
8323
8324int LuaScriptInterface::luaPlayerAddSpecialSkill(lua_State *L) {
8325 // player:addSpecialSkill(specialSkillType, value)
8326 Player *player = getUserdata<Player>(L, 1);
8327 if (!player) {
8328 lua_pushnil(L);
8329 return 1;
8330 }
8331
8332 SpecialSkills_t specialSkillType = getNumber<SpecialSkills_t>(L, 2);
8333 if (specialSkillType > SPECIALSKILL_LAST) {
8334 lua_pushnil(L);
8335 return 1;
8336 }
8337
8338 player->setVarSpecialSkill(specialSkillType, getNumber<int32_t>(L, 3));
8339 player->sendSkills();
8340 pushBoolean(L, true);
8341 return 1;
8342}
8343
8344int LuaScriptInterface::luaPlayerAddOfflineTrainingTime(lua_State *L) {
8345 // player:addOfflineTrainingTime(time)
8346 Player *player = getUserdata<Player>(L, 1);
8347 if (player) {
8348 int32_t time = getNumber<int32_t>(L, 2);
8349 player->addOfflineTrainingTime(time);
8350 player->sendStats();
8351 pushBoolean(L, true);
8352 } else {
8353 lua_pushnil(L);
8354 }
8355 return 1;
8356}
8357
8358int LuaScriptInterface::luaPlayerGetOfflineTrainingTime(lua_State *L) {
8359 // player:getOfflineTrainingTime()
8360 Player *player = getUserdata<Player>(L, 1);
8361 if (player) {
8362 lua_pushnumber(L, player->getOfflineTrainingTime());
8363 } else {
8364 lua_pushnil(L);
8365 }
8366 return 1;
8367}
8368
8369int LuaScriptInterface::luaPlayerRemoveOfflineTrainingTime(lua_State *L) {
8370 // player:removeOfflineTrainingTime(time)
8371 Player *player = getUserdata<Player>(L, 1);
8372 if (player) {
8373 int32_t time = getNumber<int32_t>(L, 2);
8374 player->removeOfflineTrainingTime(time);
8375 player->sendStats();
8376 pushBoolean(L, true);
8377 } else {
8378 lua_pushnil(L);
8379 }
8380 return 1;
8381}
8382
8383int LuaScriptInterface::luaPlayerAddOfflineTrainingTries(lua_State *L) {
8384 // player:addOfflineTrainingTries(skillType, tries)
8385 Player *player = getUserdata<Player>(L, 1);
8386 if (player) {
8387 skills_t skillType = getNumber<skills_t>(L, 2);
8388 uint64_t tries = getNumber<uint64_t>(L, 3);
8389 pushBoolean(L, player->addOfflineTrainingTries(skillType, tries));
8390 } else {
8391 lua_pushnil(L);
8392 }
8393 return 1;
8394}
8395
8396int LuaScriptInterface::luaPlayerGetOfflineTrainingSkill(lua_State *L) {
8397 // player:getOfflineTrainingSkill()
8398 Player *player = getUserdata<Player>(L, 1);
8399 if (player) {
8400 lua_pushnumber(L, player->getOfflineTrainingSkill());
8401 } else {
8402 lua_pushnil(L);
8403 }
8404 return 1;
8405}
8406
8407int LuaScriptInterface::luaPlayerSetOfflineTrainingSkill(lua_State *L) {
8408 // player:setOfflineTrainingSkill(skillId)
8409 Player *player = getUserdata<Player>(L, 1);
8410 if (player) {
8411 uint32_t skillId = getNumber<uint32_t>(L, 2);
8412 player->setOfflineTrainingSkill(skillId);
8413 pushBoolean(L, true);
8414 } else {
8415 lua_pushnil(L);
8416 }
8417 return 1;
8418}
8419
8420int LuaScriptInterface::luaPlayerGetItemCount(lua_State *L) {
8421 // player:getItemCount(itemId[, subType = -1])
8422 Player *player = getUserdata<Player>(L, 1);
8423 if (!player) {
8424 lua_pushnil(L);
8425 return 1;
8426 }
8427
8428 uint16_t itemId;
8429 if (isNumber(L, 2)) {
8430 itemId = getNumber<uint16_t>(L, 2);
8431 } else {
8432 itemId = Item::items.getItemIdByName(getString(L, 2));
8433 if (itemId == 0) {
8434 lua_pushnil(L);
8435 return 1;
8436 }
8437 }
8438
8439 int32_t subType = getNumber<int32_t>(L, 3, -1);
8440 lua_pushnumber(L, player->getItemTypeCount(itemId, subType));
8441 return 1;
8442}
8443
8444int LuaScriptInterface::luaPlayerGetItemById(lua_State *L) {
8445 // player:getItemById(itemId, deepSearch[, subType = -1])
8446 Player *player = getUserdata<Player>(L, 1);
8447 if (!player) {
8448 lua_pushnil(L);
8449 return 1;
8450 }
8451
8452 uint16_t itemId;
8453 if (isNumber(L, 2)) {
8454 itemId = getNumber<uint16_t>(L, 2);
8455 } else {
8456 itemId = Item::items.getItemIdByName(getString(L, 2));
8457 if (itemId == 0) {
8458 lua_pushnil(L);
8459 return 1;
8460 }
8461 }
8462 bool deepSearch = getBoolean(L, 3);
8463 int32_t subType = getNumber<int32_t>(L, 4, -1);
8464
8465 Item *item = g_game.findItemOfType(player, itemId, deepSearch, subType);
8466 if (item) {
8467 pushUserdata<Item>(L, item);
8468 setItemMetatable(L, -1, item);
8469 } else {
8470 lua_pushnil(L);
8471 }
8472 return 1;
8473}
8474
8475int LuaScriptInterface::luaPlayerGetVocation(lua_State *L) {
8476 // player:getVocation()
8477 Player *player = getUserdata<Player>(L, 1);
8478 if (player) {
8479 pushUserdata<Vocation>(L, player->getVocation());
8480 setMetatable(L, -1, "Vocation");
8481 } else {
8482 lua_pushnil(L);
8483 }
8484 return 1;
8485}
8486
8487int LuaScriptInterface::luaPlayerSetVocation(lua_State *L) {
8488 // player:setVocation(id or name or userdata)
8489 Player *player = getUserdata<Player>(L, 1);
8490 if (!player) {
8491 lua_pushnil(L);
8492 return 1;
8493 }
8494
8495 Vocation *vocation;
8496 if (isNumber(L, 2)) {
8497 vocation = g_vocations.getVocation(getNumber<uint16_t>(L, 2));
8498 } else if (isString(L, 2)) {
8499 vocation =
8500 g_vocations.getVocation(g_vocations.getVocationId(getString(L, 2)));
8501 } else if (isUserdata(L, 2)) {
8502 vocation = getUserdata<Vocation>(L, 2);
8503 } else {
8504 vocation = nullptr;
8505 }
8506
8507 if (!vocation) {
8508 pushBoolean(L, false);
8509 return 1;
8510 }
8511
8512 player->setVocation(vocation->getId());
8513 pushBoolean(L, true);
8514 return 1;
8515}
8516
8517int LuaScriptInterface::luaPlayerGetSex(lua_State *L) {
8518 // player:getSex()
8519 Player *player = getUserdata<Player>(L, 1);
8520 if (player) {
8521 lua_pushnumber(L, player->getSex());
8522 } else {
8523 lua_pushnil(L);
8524 }
8525 return 1;
8526}
8527
8528int LuaScriptInterface::luaPlayerSetSex(lua_State *L) {
8529 // player:setSex(newSex)
8530 Player *player = getUserdata<Player>(L, 1);
8531 if (player) {
8532 PlayerSex_t newSex = getNumber<PlayerSex_t>(L, 2);
8533 player->setSex(newSex);
8534 pushBoolean(L, true);
8535 } else {
8536 lua_pushnil(L);
8537 }
8538 return 1;
8539}
8540
8541int LuaScriptInterface::luaPlayerGetTown(lua_State *L) {
8542 // player:getTown()
8543 Player *player = getUserdata<Player>(L, 1);
8544 if (player) {
8545 pushUserdata<Town>(L, player->getTown());
8546 setMetatable(L, -1, "Town");
8547 } else {
8548 lua_pushnil(L);
8549 }
8550 return 1;
8551}
8552
8553int LuaScriptInterface::luaPlayerSetTown(lua_State *L) {
8554 // player:setTown(town)
8555 Town *town = getUserdata<Town>(L, 2);
8556 if (!town) {
8557 pushBoolean(L, false);
8558 return 1;
8559 }
8560
8561 Player *player = getUserdata<Player>(L, 1);
8562 if (player) {
8563 player->setTown(town);
8564 pushBoolean(L, true);
8565 } else {
8566 lua_pushnil(L);
8567 }
8568 return 1;
8569}
8570
8571int LuaScriptInterface::luaPlayerGetGuild(lua_State *L) {
8572 // player:getGuild()
8573 Player *player = getUserdata<Player>(L, 1);
8574 if (!player) {
8575 lua_pushnil(L);
8576 return 1;
8577 }
8578
8579 Guild *guild = player->getGuild();
8580 if (!guild) {
8581 lua_pushnil(L);
8582 return 1;
8583 }
8584
8585 pushUserdata<Guild>(L, guild);
8586 setMetatable(L, -1, "Guild");
8587 return 1;
8588}
8589
8590int LuaScriptInterface::luaPlayerSetGuild(lua_State *L) {
8591 // player:setGuild(guild)
8592 Player *player = getUserdata<Player>(L, 1);
8593 if (!player) {
8594 lua_pushnil(L);
8595 return 1;
8596 }
8597
8598 player->setGuild(getUserdata<Guild>(L, 2));
8599 pushBoolean(L, true);
8600 return 1;
8601}
8602
8603int LuaScriptInterface::luaPlayerGetGuildLevel(lua_State *L) {
8604 // player:getGuildLevel()
8605 Player *player = getUserdata<Player>(L, 1);
8606 if (player && player->getGuild()) {
8607 lua_pushnumber(L, player->getGuildRank()->level);
8608 } else {
8609 lua_pushnil(L);
8610 }
8611 return 1;
8612}
8613
8614int LuaScriptInterface::luaPlayerSetGuildLevel(lua_State *L) {
8615 // player:setGuildLevel(level)
8616 uint8_t level = getNumber<uint8_t>(L, 2);
8617 Player *player = getUserdata<Player>(L, 1);
8618 if (!player || !player->getGuild()) {
8619 lua_pushnil(L);
8620 return 1;
8621 }
8622
8623 GuildRank_ptr rank = player->getGuild()->getRankByLevel(level);
8624 if (!rank) {
8625 pushBoolean(L, false);
8626 } else {
8627 player->setGuildRank(rank);
8628 pushBoolean(L, true);
8629 }
8630
8631 return 1;
8632}
8633
8634int LuaScriptInterface::luaPlayerGetGuildNick(lua_State *L) {
8635 // player:getGuildNick()
8636 Player *player = getUserdata<Player>(L, 1);
8637 if (player) {
8638 pushString(L, player->getGuildNick());
8639 } else {
8640 lua_pushnil(L);
8641 }
8642 return 1;
8643}
8644
8645int LuaScriptInterface::luaPlayerSetGuildNick(lua_State *L) {
8646 // player:setGuildNick(nick)
8647 const std::string &nick = getString(L, 2);
8648 Player *player = getUserdata<Player>(L, 1);
8649 if (player) {
8650 player->setGuildNick(nick);
8651 pushBoolean(L, true);
8652 } else {
8653 lua_pushnil(L);
8654 }
8655 return 1;
8656}
8657
8658int LuaScriptInterface::luaPlayerGetGroup(lua_State *L) {
8659 // player:getGroup()
8660 Player *player = getUserdata<Player>(L, 1);
8661 if (player) {
8662 pushUserdata<Group>(L, player->getGroup());
8663 setMetatable(L, -1, "Group");
8664 } else {
8665 lua_pushnil(L);
8666 }
8667 return 1;
8668}
8669
8670int LuaScriptInterface::luaPlayerSetGroup(lua_State *L) {
8671 // player:setGroup(group)
8672 Group *group = getUserdata<Group>(L, 2);
8673 if (!group) {
8674 pushBoolean(L, false);
8675 return 1;
8676 }
8677
8678 Player *player = getUserdata<Player>(L, 1);
8679 if (player) {
8680 player->setGroup(group);
8681 pushBoolean(L, true);
8682 } else {
8683 lua_pushnil(L);
8684 }
8685 return 1;
8686}
8687
8688int LuaScriptInterface::luaPlayerGetStamina(lua_State *L) {
8689 // player:getStamina()
8690 Player *player = getUserdata<Player>(L, 1);
8691 if (player) {
8692 lua_pushnumber(L, player->getStaminaMinutes());
8693 } else {
8694 lua_pushnil(L);
8695 }
8696 return 1;
8697}
8698
8699int LuaScriptInterface::luaPlayerSetStamina(lua_State *L) {
8700 // player:setStamina(stamina)
8701 uint16_t stamina = getNumber<uint16_t>(L, 2);
8702 Player *player = getUserdata<Player>(L, 1);
8703 if (player) {
8704 player->staminaMinutes = std::min<uint16_t>(2520, stamina);
8705 player->sendStats();
8706 pushBoolean(L, true);
8707 } else {
8708 lua_pushnil(L);
8709 }
8710 return 1;
8711}
8712
8713int LuaScriptInterface::luaPlayerGetSoul(lua_State *L) {
8714 // player:getSoul()
8715 Player *player = getUserdata<Player>(L, 1);
8716 if (player) {
8717 lua_pushnumber(L, player->getSoul());
8718 } else {
8719 lua_pushnil(L);
8720 }
8721 return 1;
8722}
8723
8724int LuaScriptInterface::luaPlayerAddSoul(lua_State *L) {
8725 // player:addSoul(soulChange)
8726 int32_t soulChange = getNumber<int32_t>(L, 2);
8727 Player *player = getUserdata<Player>(L, 1);
8728 if (player) {
8729 player->changeSoul(soulChange);
8730 pushBoolean(L, true);
8731 } else {
8732 lua_pushnil(L);
8733 }
8734 return 1;
8735}
8736
8737int LuaScriptInterface::luaPlayerGetMaxSoul(lua_State *L) {
8738 // player:getMaxSoul()
8739 Player *player = getUserdata<Player>(L, 1);
8740 if (player && player->vocation) {
8741 lua_pushnumber(L, player->vocation->getSoulMax());
8742 } else {
8743 lua_pushnil(L);
8744 }
8745 return 1;
8746}
8747
8748int LuaScriptInterface::luaPlayerGetBankBalance(lua_State *L) {
8749 // player:getBankBalance()
8750 Player *player = getUserdata<Player>(L, 1);
8751 if (player) {
8752 lua_pushnumber(L, player->getBankBalance());
8753 } else {
8754 lua_pushnil(L);
8755 }
8756 return 1;
8757}
8758
8759int LuaScriptInterface::luaPlayerSetBankBalance(lua_State *L) {
8760 // player:setBankBalance(bankBalance)
8761 Player *player = getUserdata<Player>(L, 1);
8762 if (!player) {
8763 lua_pushnil(L);
8764 return 1;
8765 }
8766
8767 int64_t balance = getNumber<int64_t>(L, 2);
8768 if (balance < 0) {
8769 reportErrorFunc("Invalid bank balance value.");
8770 lua_pushnil(L);
8771 return 1;
8772 }
8773
8774 player->setBankBalance(balance);
8775 pushBoolean(L, true);
8776 return 1;
8777}
8778
8779int LuaScriptInterface::luaPlayerGetStorageValue(lua_State *L) {
8780 // player:getStorageValue(key)
8781 Player *player = getUserdata<Player>(L, 1);
8782 if (!player) {
8783 lua_pushnil(L);
8784 return 1;
8785 }
8786
8787 uint32_t key = getNumber<uint32_t>(L, 2);
8788 int32_t value;
8789 if (player->getStorageValue(key, value)) {
8790 lua_pushnumber(L, value);
8791 } else {
8792 lua_pushnumber(L, -1);
8793 }
8794 return 1;
8795}
8796
8797int LuaScriptInterface::luaPlayerSetStorageValue(lua_State *L) {
8798 // player:setStorageValue(key, value)
8799 int32_t value = getNumber<int32_t>(L, 3);
8800 uint32_t key = getNumber<uint32_t>(L, 2);
8801 Player *player = getUserdata<Player>(L, 1);
8802 if (IS_IN_KEYRANGE(key, RESERVED_RANGE)) {
8803 std::ostringstream ss;
8804 ss << "Accessing reserved range: " << key;
8805 reportErrorFunc(ss.str());
8806 pushBoolean(L, false);
8807 return 1;
8808 }
8809
8810 if (player) {
8811 player->addStorageValue(key, value);
8812 pushBoolean(L, true);
8813 } else {
8814 lua_pushnil(L);
8815 }
8816 return 1;
8817}
8818
8819int LuaScriptInterface::luaPlayerAddItem(lua_State *L) {
8820 // player:addItem(itemId[, count = 1[, canDropOnMap = true[, subType = 1[,
8821 // slot = CONST_SLOT_WHEREEVER]]]])
8822 Player *player = getUserdata<Player>(L, 1);
8823 if (!player) {
8824 pushBoolean(L, false);
8825 return 1;
8826 }
8827
8828 uint16_t itemId;
8829 if (isNumber(L, 2)) {
8830 itemId = getNumber<uint16_t>(L, 2);
8831 } else {
8832 itemId = Item::items.getItemIdByName(getString(L, 2));
8833 if (itemId == 0) {
8834 lua_pushnil(L);
8835 return 1;
8836 }
8837 }
8838
8839 int32_t count = getNumber<int32_t>(L, 3, 1);
8840 int32_t subType = getNumber<int32_t>(L, 5, 1);
8841
8842 const ItemType &it = Item::items[itemId];
8843
8844 int32_t itemCount = 1;
8845 int parameters = lua_gettop(L);
8846 if (parameters >= 4) {
8847 itemCount = std::max<int32_t>(1, count);
8848 } else if (it.hasSubType()) {
8849 if (it.stackable) {
8850 itemCount = std::ceil(count / 100.f);
8851 }
8852
8853 subType = count;
8854 } else {
8855 itemCount = std::max<int32_t>(1, count);
8856 }
8857
8858 bool hasTable = itemCount > 1;
8859 if (hasTable) {
8860 lua_newtable(L);
8861 } else if (itemCount == 0) {
8862 lua_pushnil(L);
8863 return 1;
8864 }
8865
8866 bool canDropOnMap = getBoolean(L, 4, true);
8867 slots_t slot = getNumber<slots_t>(L, 6, CONST_SLOT_WHEREEVER);
8868 for (int32_t i = 1; i <= itemCount; ++i) {
8869 int32_t stackCount = subType;
8870 if (it.stackable) {
8871 stackCount = std::min<int32_t>(stackCount, 100);
8872 subType -= stackCount;
8873 }
8874
8875 Item *item = Item::CreateItem(itemId, stackCount);
8876 if (!item) {
8877 if (!hasTable) {
8878 lua_pushnil(L);
8879 }
8880 return 1;
8881 }
8882
8883 ReturnValue ret =
8884 g_game.internalPlayerAddItem(player, item, canDropOnMap, slot);
8885 if (ret != RETURNVALUE_NOERROR) {
8886 delete item;
8887 if (!hasTable) {
8888 lua_pushnil(L);
8889 }
8890 return 1;
8891 }
8892
8893 if (hasTable) {
8894 lua_pushnumber(L, i);
8895 pushUserdata<Item>(L, item);
8896 setItemMetatable(L, -1, item);
8897 lua_settable(L, -3);
8898 } else {
8899 pushUserdata<Item>(L, item);
8900 setItemMetatable(L, -1, item);
8901 }
8902 }
8903 return 1;
8904}
8905
8906int LuaScriptInterface::luaPlayerAddItemEx(lua_State *L) {
8907 // player:addItemEx(item[, canDropOnMap = false[, index = INDEX_WHEREEVER[,
8908 // flags = 0]]]) player:addItemEx(item[, canDropOnMap = true[, slot =
8909 // CONST_SLOT_WHEREEVER]])
8910 Item *item = getUserdata<Item>(L, 2);
8911 if (!item) {
8912 reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND));
8913 pushBoolean(L, false);
8914 return 1;
8915 }
8916
8917 Player *player = getUserdata<Player>(L, 1);
8918 if (!player) {
8919 lua_pushnil(L);
8920 return 1;
8921 }
8922
8923 if (item->getParent() != VirtualCylinder::virtualCylinder) {
8924 reportErrorFunc("Item already has a parent");
8925 pushBoolean(L, false);
8926 return 1;
8927 }
8928
8929 bool canDropOnMap = getBoolean(L, 3, false);
8930 ReturnValue returnValue;
8931 if (canDropOnMap) {
8932 slots_t slot = getNumber<slots_t>(L, 4, CONST_SLOT_WHEREEVER);
8933 returnValue = g_game.internalPlayerAddItem(player, item, true, slot);
8934 } else {
8935 int32_t index = getNumber<int32_t>(L, 4, INDEX_WHEREEVER);
8936 uint32_t flags = getNumber<uint32_t>(L, 5, 0);
8937 returnValue = g_game.internalAddItem(player, item, index, flags);
8938 }
8939
8940 if (returnValue == RETURNVALUE_NOERROR) {
8941 ScriptEnvironment::removeTempItem(item);
8942 }
8943 lua_pushnumber(L, returnValue);
8944 return 1;
8945}
8946
8947int LuaScriptInterface::luaPlayerRemoveItem(lua_State *L) {
8948 // player:removeItem(itemId, count[, subType = -1[, ignoreEquipped = false]])
8949 Player *player = getUserdata<Player>(L, 1);
8950 if (!player) {
8951 lua_pushnil(L);
8952 return 1;
8953 }
8954
8955 uint16_t itemId;
8956 if (isNumber(L, 2)) {
8957 itemId = getNumber<uint16_t>(L, 2);
8958 } else {
8959 itemId = Item::items.getItemIdByName(getString(L, 2));
8960 if (itemId == 0) {
8961 lua_pushnil(L);
8962 return 1;
8963 }
8964 }
8965
8966 uint32_t count = getNumber<uint32_t>(L, 3);
8967 int32_t subType = getNumber<int32_t>(L, 4, -1);
8968 bool ignoreEquipped = getBoolean(L, 5, false);
8969 pushBoolean(L,
8970 player->removeItemOfType(itemId, count, subType, ignoreEquipped));
8971 return 1;
8972}
8973
8974int LuaScriptInterface::luaPlayerGetMoney(lua_State *L) {
8975 // player:getMoney()
8976 Player *player = getUserdata<Player>(L, 1);
8977 if (player) {
8978 lua_pushnumber(L, player->getMoney());
8979 } else {
8980 lua_pushnil(L);
8981 }
8982 return 1;
8983}
8984
8985int LuaScriptInterface::luaPlayerAddMoney(lua_State *L) {
8986 // player:addMoney(money)
8987 uint64_t money = getNumber<uint64_t>(L, 2);
8988 Player *player = getUserdata<Player>(L, 1);
8989 if (player) {
8990 g_game.addMoney(player, money);
8991 pushBoolean(L, true);
8992 } else {
8993 lua_pushnil(L);
8994 }
8995 return 1;
8996}
8997
8998int LuaScriptInterface::luaPlayerRemoveMoney(lua_State *L) {
8999 // player:removeMoney(money)
9000 Player *player = getUserdata<Player>(L, 1);
9001 if (player) {
9002 uint64_t money = getNumber<uint64_t>(L, 2);
9003 pushBoolean(L, g_game.removeMoney(player, money));
9004 } else {
9005 lua_pushnil(L);
9006 }
9007 return 1;
9008}
9009
9010int LuaScriptInterface::luaPlayerShowTextDialog(lua_State *L) {
9011 // player:showTextDialog(id or name or userdata[, text[, canWrite[, length]]])
9012 Player *player = getUserdata<Player>(L, 1);
9013 if (!player) {
9014 lua_pushnil(L);
9015 return 1;
9016 }
9017
9018 int32_t length = getNumber<int32_t>(L, 5, -1);
9019 bool canWrite = getBoolean(L, 4, false);
9020 std::string text;
9021
9022 int parameters = lua_gettop(L);
9023 if (parameters >= 3) {
9024 text = getString(L, 3);
9025 }
9026
9027 Item *item;
9028 if (isNumber(L, 2)) {
9029 item = Item::CreateItem(getNumber<uint16_t>(L, 2));
9030 } else if (isString(L, 2)) {
9031 item = Item::CreateItem(Item::items.getItemIdByName(getString(L, 2)));
9032 } else if (isUserdata(L, 2)) {
9033 if (getUserdataType(L, 2) != LuaData_Item) {
9034 pushBoolean(L, false);
9035 return 1;
9036 }
9037
9038 item = getUserdata<Item>(L, 2);
9039 } else {
9040 item = nullptr;
9041 }
9042
9043 if (!item) {
9044 reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND));
9045 pushBoolean(L, false);
9046 return 1;
9047 }
9048
9049 if (length < 0) {
9050 length = Item::items[item->getID()].maxTextLen;
9051 }
9052
9053 if (!text.empty()) {
9054 item->setText(text);
9055 length = std::max<int32_t>(text.size(), length);
9056 }
9057
9058 item->setParent(player);
9059 player->setWriteItem(item, length);
9060 player->sendTextWindow(item, length, canWrite);
9061 pushBoolean(L, true);
9062 return 1;
9063}
9064
9065int LuaScriptInterface::luaPlayerSendTextMessage(lua_State *L) {
9066 // player:sendTextMessage(type, text[, position, primaryValue = 0,
9067 // primaryColor = TEXTCOLOR_NONE[, secondaryValue = 0, secondaryColor =
9068 // TEXTCOLOR_NONE]]) player:sendTextMessage(type, text, channelId)
9069
9070 Player *player = getUserdata<Player>(L, 1);
9071 if (!player) {
9072 lua_pushnil(L);
9073 return 1;
9074 }
9075
9076 int parameters = lua_gettop(L);
9077
9078 TextMessage message(getNumber<MessageClasses>(L, 2), getString(L, 3));
9079 if (parameters == 4) {
9080 uint16_t channelId = getNumber<uint16_t>(L, 4);
9081 ChatChannel *channel = g_chat->getChannel(*player, channelId);
9082 if (!channel || !channel->hasUser(*player)) {
9083 pushBoolean(L, false);
9084 return 1;
9085 }
9086 message.channelId = channelId;
9087 } else {
9088 if (parameters >= 6) {
9089 message.position = getPosition(L, 4);
9090 message.primary.value = getNumber<int32_t>(L, 5);
9091 message.primary.color = getNumber<TextColor_t>(L, 6);
9092 }
9093
9094 if (parameters >= 8) {
9095 message.secondary.value = getNumber<int32_t>(L, 7);
9096 message.secondary.color = getNumber<TextColor_t>(L, 8);
9097 }
9098 }
9099
9100 player->sendTextMessage(message);
9101 pushBoolean(L, true);
9102
9103 return 1;
9104}
9105
9106int LuaScriptInterface::luaPlayerSendChannelMessage(lua_State *L) {
9107 // player:sendChannelMessage(author, text, type, channelId)
9108 uint16_t channelId = getNumber<uint16_t>(L, 5);
9109 SpeakClasses type = getNumber<SpeakClasses>(L, 4);
9110 const std::string &text = getString(L, 3);
9111 const std::string &author = getString(L, 2);
9112 Player *player = getUserdata<Player>(L, 1);
9113 if (player) {
9114 player->sendChannelMessage(author, text, type, channelId);
9115 pushBoolean(L, true);
9116 } else {
9117 lua_pushnil(L);
9118 }
9119 return 1;
9120}
9121
9122int LuaScriptInterface::luaPlayerSendPrivateMessage(lua_State *L) {
9123 // player:sendPrivateMessage(speaker, text[, type])
9124 Player *player = getUserdata<Player>(L, 1);
9125 if (!player) {
9126 lua_pushnil(L);
9127 return 1;
9128 }
9129
9130 const Player *speaker = getUserdata<const Player>(L, 2);
9131 const std::string &text = getString(L, 3);
9132 SpeakClasses type = getNumber<SpeakClasses>(L, 4, TALKTYPE_PRIVATE_FROM);
9133 player->sendPrivateMessage(speaker, type, text);
9134 pushBoolean(L, true);
9135 return 1;
9136}
9137
9138int LuaScriptInterface::luaPlayerChannelSay(lua_State *L) {
9139 // player:channelSay(speaker, type, text, channelId)
9140 Player *player = getUserdata<Player>(L, 1);
9141 if (!player) {
9142 lua_pushnil(L);
9143 return 1;
9144 }
9145
9146 Creature *speaker = getCreature(L, 2);
9147 SpeakClasses type = getNumber<SpeakClasses>(L, 3);
9148 const std::string &text = getString(L, 4);
9149 uint16_t channelId = getNumber<uint16_t>(L, 5);
9150 player->sendToChannel(speaker, type, text, channelId);
9151 pushBoolean(L, true);
9152 return 1;
9153}
9154
9155int LuaScriptInterface::luaPlayerOpenChannel(lua_State *L) {
9156 // player:openChannel(channelId)
9157 uint16_t channelId = getNumber<uint16_t>(L, 2);
9158 Player *player = getUserdata<Player>(L, 1);
9159 if (player) {
9160 g_game.playerOpenChannel(player->getID(), channelId);
9161 pushBoolean(L, true);
9162 } else {
9163 lua_pushnil(L);
9164 }
9165 return 1;
9166}
9167
9168int LuaScriptInterface::luaPlayerGetSlotItem(lua_State *L) {
9169 // player:getSlotItem(slot)
9170 const Player *player = getUserdata<const Player>(L, 1);
9171 if (!player) {
9172 lua_pushnil(L);
9173 return 1;
9174 }
9175
9176 uint32_t slot = getNumber<uint32_t>(L, 2);
9177 Thing *thing = player->getThing(slot);
9178 if (!thing) {
9179 lua_pushnil(L);
9180 return 1;
9181 }
9182
9183 Item *item = thing->getItem();
9184 if (item) {
9185 pushUserdata<Item>(L, item);
9186 setItemMetatable(L, -1, item);
9187 } else {
9188 lua_pushnil(L);
9189 }
9190 return 1;
9191}
9192
9193int LuaScriptInterface::luaPlayerGetParty(lua_State *L) {
9194 // player:getParty()
9195 const Player *player = getUserdata<const Player>(L, 1);
9196 if (!player) {
9197 lua_pushnil(L);
9198 return 1;
9199 }
9200
9201 Party *party = player->getParty();
9202 if (party) {
9203 pushUserdata<Party>(L, party);
9204 setMetatable(L, -1, "Party");
9205 } else {
9206 lua_pushnil(L);
9207 }
9208 return 1;
9209}
9210
9211int LuaScriptInterface::luaPlayerAddOutfit(lua_State *L) {
9212 // player:addOutfit(lookType)
9213 Player *player = getUserdata<Player>(L, 1);
9214 if (player) {
9215 player->addOutfit(getNumber<uint16_t>(L, 2), 0);
9216 pushBoolean(L, true);
9217 } else {
9218 lua_pushnil(L);
9219 }
9220 return 1;
9221}
9222
9223int LuaScriptInterface::luaPlayerAddOutfitAddon(lua_State *L) {
9224 // player:addOutfitAddon(lookType, addon)
9225 Player *player = getUserdata<Player>(L, 1);
9226 if (player) {
9227 uint16_t lookType = getNumber<uint16_t>(L, 2);
9228 uint8_t addon = getNumber<uint8_t>(L, 3);
9229 player->addOutfit(lookType, addon);
9230 pushBoolean(L, true);
9231 } else {
9232 lua_pushnil(L);
9233 }
9234 return 1;
9235}
9236
9237int LuaScriptInterface::luaPlayerRemoveOutfit(lua_State *L) {
9238 // player:removeOutfit(lookType)
9239 Player *player = getUserdata<Player>(L, 1);
9240 if (player) {
9241 uint16_t lookType = getNumber<uint16_t>(L, 2);
9242 pushBoolean(L, player->removeOutfit(lookType));
9243 } else {
9244 lua_pushnil(L);
9245 }
9246 return 1;
9247}
9248
9249int LuaScriptInterface::luaPlayerRemoveOutfitAddon(lua_State *L) {
9250 // player:removeOutfitAddon(lookType, addon)
9251 Player *player = getUserdata<Player>(L, 1);
9252 if (player) {
9253 uint16_t lookType = getNumber<uint16_t>(L, 2);
9254 uint8_t addon = getNumber<uint8_t>(L, 3);
9255 pushBoolean(L, player->removeOutfitAddon(lookType, addon));
9256 } else {
9257 lua_pushnil(L);
9258 }
9259 return 1;
9260}
9261
9262int LuaScriptInterface::luaPlayerHasOutfit(lua_State *L) {
9263 // player:hasOutfit(lookType[, addon = 0])
9264 Player *player = getUserdata<Player>(L, 1);
9265 if (player) {
9266 uint16_t lookType = getNumber<uint16_t>(L, 2);
9267 uint8_t addon = getNumber<uint8_t>(L, 3, 0);
9268 pushBoolean(L, player->hasOutfit(lookType, addon));
9269 } else {
9270 lua_pushnil(L);
9271 }
9272 return 1;
9273}
9274
9275int LuaScriptInterface::luaPlayerCanWearOutfit(lua_State *L) {
9276 // player:canWearOutfit(lookType[, addon = 0])
9277 Player *player = getUserdata<Player>(L, 1);
9278 if (player) {
9279 uint16_t lookType = getNumber<uint16_t>(L, 2);
9280 uint8_t addon = getNumber<uint8_t>(L, 3, 0);
9281 pushBoolean(L, player->canWear(lookType, addon));
9282 } else {
9283 lua_pushnil(L);
9284 }
9285 return 1;
9286}
9287
9288int LuaScriptInterface::luaPlayerSendOutfitWindow(lua_State *L) {
9289 // player:sendOutfitWindow()
9290 Player *player = getUserdata<Player>(L, 1);
9291 if (player) {
9292 player->sendOutfitWindow();
9293 pushBoolean(L, true);
9294 } else {
9295 lua_pushnil(L);
9296 }
9297 return 1;
9298}
9299
9300int LuaScriptInterface::luaPlayerAddMount(lua_State *L) {
9301 // player:addMount(mountId or mountName)
9302 Player *player = getUserdata<Player>(L, 1);
9303 if (!player) {
9304 lua_pushnil(L);
9305 return 1;
9306 }
9307
9308 uint8_t mountId;
9309 if (isNumber(L, 2)) {
9310 mountId = getNumber<uint8_t>(L, 2);
9311 } else {
9312 Mount *mount = g_game.mounts.getMountByName(getString(L, 2));
9313 if (!mount) {
9314 lua_pushnil(L);
9315 return 1;
9316 }
9317 mountId = mount->id;
9318 }
9319 pushBoolean(L, player->tameMount(mountId));
9320 return 1;
9321}
9322
9323int LuaScriptInterface::luaPlayerRemoveMount(lua_State *L) {
9324 // player:removeMount(mountId or mountName)
9325 Player *player = getUserdata<Player>(L, 1);
9326 if (!player) {
9327 lua_pushnil(L);
9328 return 1;
9329 }
9330
9331 uint8_t mountId;
9332 if (isNumber(L, 2)) {
9333 mountId = getNumber<uint8_t>(L, 2);
9334 } else {
9335 Mount *mount = g_game.mounts.getMountByName(getString(L, 2));
9336 if (!mount) {
9337 lua_pushnil(L);
9338 return 1;
9339 }
9340 mountId = mount->id;
9341 }
9342 pushBoolean(L, player->untameMount(mountId));
9343 return 1;
9344}
9345
9346int LuaScriptInterface::luaPlayerHasMount(lua_State *L) {
9347 // player:hasMount(mountId or mountName)
9348 const Player *player = getUserdata<const Player>(L, 1);
9349 if (!player) {
9350 lua_pushnil(L);
9351 return 1;
9352 }
9353
9354 Mount *mount = nullptr;
9355 if (isNumber(L, 2)) {
9356 mount = g_game.mounts.getMountByID(getNumber<uint8_t>(L, 2));
9357 } else {
9358 mount = g_game.mounts.getMountByName(getString(L, 2));
9359 }
9360
9361 if (mount) {
9362 pushBoolean(L, player->hasMount(mount));
9363 } else {
9364 lua_pushnil(L);
9365 }
9366 return 1;
9367}
9368
9369int LuaScriptInterface::luaPlayerGetPremiumDays(lua_State *L) {
9370 // player:getPremiumDays()
9371 Player *player = getUserdata<Player>(L, 1);
9372 if (player) {
9373 lua_pushnumber(L, player->premiumDays);
9374 } else {
9375 lua_pushnil(L);
9376 }
9377 return 1;
9378}
9379
9380int LuaScriptInterface::luaPlayerAddPremiumDays(lua_State *L) {
9381 // player:addPremiumDays(days)
9382 Player *player = getUserdata<Player>(L, 1);
9383 if (!player) {
9384 lua_pushnil(L);
9385 return 1;
9386 }
9387
9388 if (player->premiumDays != std::numeric_limits<uint16_t>::max()) {
9389 uint16_t days = getNumber<uint16_t>(L, 2);
9390 int32_t addDays = std::min<int32_t>(0xFFFE - player->premiumDays, days);
9391 if (addDays > 0) {
9392 player->setPremiumDays(player->premiumDays + addDays);
9393 IOLoginData::addPremiumDays(player->getAccount(), addDays);
9394 }
9395 }
9396 pushBoolean(L, true);
9397 return 1;
9398}
9399
9400int LuaScriptInterface::luaPlayerRemovePremiumDays(lua_State *L) {
9401 // player:removePremiumDays(days)
9402 Player *player = getUserdata<Player>(L, 1);
9403 if (!player) {
9404 lua_pushnil(L);
9405 return 1;
9406 }
9407
9408 if (player->premiumDays != std::numeric_limits<uint16_t>::max()) {
9409 uint16_t days = getNumber<uint16_t>(L, 2);
9410 int32_t removeDays = std::min<int32_t>(player->premiumDays, days);
9411 if (removeDays > 0) {
9412 player->setPremiumDays(player->premiumDays - removeDays);
9413 IOLoginData::removePremiumDays(player->getAccount(), removeDays);
9414 }
9415 }
9416 pushBoolean(L, true);
9417 return 1;
9418}
9419
9420int LuaScriptInterface::luaPlayerHasBlessing(lua_State *L) {
9421 // player:hasBlessing(blessing)
9422 uint8_t blessing = getNumber<uint8_t>(L, 2) - 1;
9423 Player *player = getUserdata<Player>(L, 1);
9424 if (player) {
9425 pushBoolean(L, player->hasBlessing(blessing));
9426 } else {
9427 lua_pushnil(L);
9428 }
9429 return 1;
9430}
9431
9432int LuaScriptInterface::luaPlayerAddBlessing(lua_State *L) {
9433 // player:addBlessing(blessing)
9434 Player *player = getUserdata<Player>(L, 1);
9435 if (!player) {
9436 lua_pushnil(L);
9437 return 1;
9438 }
9439
9440 uint8_t blessing = getNumber<uint8_t>(L, 2) - 1;
9441 if (player->hasBlessing(blessing)) {
9442 pushBoolean(L, false);
9443 return 1;
9444 }
9445
9446 player->addBlessing(1 << blessing);
9447 pushBoolean(L, true);
9448 return 1;
9449}
9450
9451int LuaScriptInterface::luaPlayerRemoveBlessing(lua_State *L) {
9452 // player:removeBlessing(blessing)
9453 Player *player = getUserdata<Player>(L, 1);
9454 if (!player) {
9455 lua_pushnil(L);
9456 return 1;
9457 }
9458
9459 uint8_t blessing = getNumber<uint8_t>(L, 2) - 1;
9460 if (!player->hasBlessing(blessing)) {
9461 pushBoolean(L, false);
9462 return 1;
9463 }
9464
9465 player->removeBlessing(1 << blessing);
9466 pushBoolean(L, true);
9467 return 1;
9468}
9469
9470int LuaScriptInterface::luaPlayerCanLearnSpell(lua_State *L) {
9471 // player:canLearnSpell(spellName)
9472 const Player *player = getUserdata<const Player>(L, 1);
9473 if (!player) {
9474 lua_pushnil(L);
9475 return 1;
9476 }
9477
9478 const std::string &spellName = getString(L, 2);
9479 InstantSpell *spell = g_spells->getInstantSpellByName(spellName);
9480 if (!spell) {
9481 reportErrorFunc("Spell \"" + spellName + "\" not found");
9482 pushBoolean(L, false);
9483 return 1;
9484 }
9485
9486 if (player->hasFlag(PlayerFlag_IgnoreSpellCheck)) {
9487 pushBoolean(L, true);
9488 return 1;
9489 }
9490
9491 const auto &vocMap = spell->getVocMap();
9492 if (vocMap.count(player->getVocationId()) == 0) {
9493 pushBoolean(L, false);
9494 } else if (player->getLevel() < spell->getLevel()) {
9495 pushBoolean(L, false);
9496 } else if (player->getMagicLevel() < spell->getMagicLevel()) {
9497 pushBoolean(L, false);
9498 } else {
9499 pushBoolean(L, true);
9500 }
9501 return 1;
9502}
9503
9504int LuaScriptInterface::luaPlayerLearnSpell(lua_State *L) {
9505 // player:learnSpell(spellName)
9506 Player *player = getUserdata<Player>(L, 1);
9507 if (player) {
9508 const std::string &spellName = getString(L, 2);
9509 player->learnInstantSpell(spellName);
9510 pushBoolean(L, true);
9511 } else {
9512 lua_pushnil(L);
9513 }
9514 return 1;
9515}
9516
9517int LuaScriptInterface::luaPlayerForgetSpell(lua_State *L) {
9518 // player:forgetSpell(spellName)
9519 Player *player = getUserdata<Player>(L, 1);
9520 if (player) {
9521 const std::string &spellName = getString(L, 2);
9522 player->forgetInstantSpell(spellName);
9523 pushBoolean(L, true);
9524 } else {
9525 lua_pushnil(L);
9526 }
9527 return 1;
9528}
9529
9530int LuaScriptInterface::luaPlayerHasLearnedSpell(lua_State *L) {
9531 // player:hasLearnedSpell(spellName)
9532 Player *player = getUserdata<Player>(L, 1);
9533 if (player) {
9534 const std::string &spellName = getString(L, 2);
9535 pushBoolean(L, player->hasLearnedInstantSpell(spellName));
9536 } else {
9537 lua_pushnil(L);
9538 }
9539 return 1;
9540}
9541
9542int LuaScriptInterface::luaPlayerSendTutorial(lua_State *L) {
9543 // player:sendTutorial(tutorialId)
9544 Player *player = getUserdata<Player>(L, 1);
9545 if (player) {
9546 uint8_t tutorialId = getNumber<uint8_t>(L, 2);
9547 player->sendTutorial(tutorialId);
9548 pushBoolean(L, true);
9549 } else {
9550 lua_pushnil(L);
9551 }
9552 return 1;
9553}
9554
9555int LuaScriptInterface::luaPlayerAddMapMark(lua_State *L) {
9556 // player:addMapMark(position, type, description)
9557 Player *player = getUserdata<Player>(L, 1);
9558 if (player) {
9559 const Position &position = getPosition(L, 2);
9560 uint8_t type = getNumber<uint8_t>(L, 3);
9561 const std::string &description = getString(L, 4);
9562 player->sendAddMarker(position, type, description);
9563 pushBoolean(L, true);
9564 } else {
9565 lua_pushnil(L);
9566 }
9567 return 1;
9568}
9569
9570int LuaScriptInterface::luaPlayerSave(lua_State *L) {
9571 // player:save()
9572 Player *player = getUserdata<Player>(L, 1);
9573 if (player) {
9574 player->loginPosition = player->getPosition();
9575 pushBoolean(L, IOLoginData::savePlayer(player));
9576 } else {
9577 lua_pushnil(L);
9578 }
9579 return 1;
9580}
9581
9582int LuaScriptInterface::luaPlayerPopupFYI(lua_State *L) {
9583 // player:popupFYI(message)
9584 Player *player = getUserdata<Player>(L, 1);
9585 if (player) {
9586 const std::string &message = getString(L, 2);
9587 player->sendFYIBox(message);
9588 pushBoolean(L, true);
9589 } else {
9590 lua_pushnil(L);
9591 }
9592 return 1;
9593}
9594
9595int LuaScriptInterface::luaPlayerIsPzLocked(lua_State *L) {
9596 // player:isPzLocked()
9597 Player *player = getUserdata<Player>(L, 1);
9598 if (player) {
9599 pushBoolean(L, player->isPzLocked());
9600 } else {
9601 lua_pushnil(L);
9602 }
9603 return 1;
9604}
9605
9606int LuaScriptInterface::luaPlayerGetClient(lua_State *L) {
9607 // player:getClient()
9608 Player *player = getUserdata<Player>(L, 1);
9609 if (player) {
9610 lua_createtable(L, 0, 5);
9611 setField(L, "version", player->getProtocolVersion());
9612 setField(L, "os", player->getOperatingSystem());
9613 setField(L, "otcv8", player->getOTCv8Version());
9614 setField(L, "ping", player->getLocalPing());
9615 setField(L, "fps", player->getFPS());
9616 } else {
9617 lua_pushnil(L);
9618 }
9619 return 1;
9620}
9621
9622int LuaScriptInterface::luaPlayerGetHouse(lua_State *L) {
9623 // player:getHouse()
9624 Player *player = getUserdata<Player>(L, 1);
9625 if (!player) {
9626 lua_pushnil(L);
9627 return 1;
9628 }
9629
9630 House *house = g_game.map.houses.getHouseByPlayerId(player->getGUID());
9631 if (house) {
9632 pushUserdata<House>(L, house);
9633 setMetatable(L, -1, "House");
9634 } else {
9635 lua_pushnil(L);
9636 }
9637 return 1;
9638}
9639
9640int LuaScriptInterface::luaPlayerSendHouseWindow(lua_State *L) {
9641 // player:sendHouseWindow(house, listId)
9642 Player *player = getUserdata<Player>(L, 1);
9643 if (!player) {
9644 lua_pushnil(L);
9645 return 1;
9646 }
9647
9648 House *house = getUserdata<House>(L, 2);
9649 if (!house) {
9650 lua_pushnil(L);
9651 return 1;
9652 }
9653
9654 uint32_t listId = getNumber<uint32_t>(L, 3);
9655 player->sendHouseWindow(house, listId);
9656 pushBoolean(L, true);
9657 return 1;
9658}
9659
9660int LuaScriptInterface::luaPlayerSetEditHouse(lua_State *L) {
9661 // player:setEditHouse(house, listId)
9662 Player *player = getUserdata<Player>(L, 1);
9663 if (!player) {
9664 lua_pushnil(L);
9665 return 1;
9666 }
9667
9668 House *house = getUserdata<House>(L, 2);
9669 if (!house) {
9670 lua_pushnil(L);
9671 return 1;
9672 }
9673
9674 uint32_t listId = getNumber<uint32_t>(L, 3);
9675 player->setEditHouse(house, listId);
9676 pushBoolean(L, true);
9677 return 1;
9678}
9679
9680int LuaScriptInterface::luaPlayerSetGhostMode(lua_State *L) {
9681 // player:setGhostMode(enabled[, showEffect=true])
9682 Player *player = getUserdata<Player>(L, 1);
9683 if (!player) {
9684 lua_pushnil(L);
9685 return 1;
9686 }
9687
9688 bool enabled = getBoolean(L, 2);
9689 if (player->isInGhostMode() == enabled) {
9690 pushBoolean(L, true);
9691 return 1;
9692 }
9693
9694 bool showEffect = getBoolean(L, 3, true);
9695
9696 player->switchGhostMode();
9697
9698 Tile *tile = player->getTile();
9699 const Position &position = player->getPosition();
9700
9701 SpectatorVec spectators;
9702 g_game.map.getSpectators(spectators, position, true, true);
9703 for (Creature *spectator : spectators) {
9704 Player *tmpPlayer = spectator->getPlayer();
9705 if (tmpPlayer != player && !tmpPlayer->isAccessPlayer()) {
9706 if (enabled) {
9707 tmpPlayer->sendRemoveTileThing(
9708 position, tile->getStackposOfCreature(tmpPlayer, player));
9709 } else {
9710 tmpPlayer->sendCreatureAppear(player, position, showEffect);
9711 }
9712 } else {
9713 tmpPlayer->sendCreatureChangeVisible(player, !enabled);
9714 }
9715 }
9716
9717 if (player->isInGhostMode()) {
9718 for (const auto &it : g_game.getPlayers()) {
9719 if (!it.second->isAccessPlayer()) {
9720 it.second->notifyStatusChange(player, VIPSTATUS_OFFLINE);
9721 }
9722 }
9723 IOLoginData::updateOnlineStatus(player->getGUID(), false);
9724 } else {
9725 for (const auto &it : g_game.getPlayers()) {
9726 if (!it.second->isAccessPlayer()) {
9727 it.second->notifyStatusChange(player, VIPSTATUS_ONLINE);
9728 }
9729 }
9730 IOLoginData::updateOnlineStatus(player->getGUID(), true);
9731 }
9732 pushBoolean(L, true);
9733 return 1;
9734}
9735
9736int LuaScriptInterface::luaPlayerGetContainerId(lua_State *L) {
9737 // player:getContainerId(container)
9738 Player *player = getUserdata<Player>(L, 1);
9739 if (!player) {
9740 lua_pushnil(L);
9741 return 1;
9742 }
9743
9744 Container *container = getUserdata<Container>(L, 2);
9745 if (container) {
9746 lua_pushnumber(L, player->getContainerID(container));
9747 } else {
9748 lua_pushnil(L);
9749 }
9750 return 1;
9751}
9752
9753int LuaScriptInterface::luaPlayerGetContainerById(lua_State *L) {
9754 // player:getContainerById(id)
9755 Player *player = getUserdata<Player>(L, 1);
9756 if (!player) {
9757 lua_pushnil(L);
9758 return 1;
9759 }
9760
9761 Container *container = player->getContainerByID(getNumber<uint8_t>(L, 2));
9762 if (container) {
9763 pushUserdata<Container>(L, container);
9764 setMetatable(L, -1, "Container");
9765 } else {
9766 lua_pushnil(L);
9767 }
9768 return 1;
9769}
9770
9771int LuaScriptInterface::luaPlayerGetContainerIndex(lua_State *L) {
9772 // player:getContainerIndex(id)
9773 Player *player = getUserdata<Player>(L, 1);
9774 if (player) {
9775 lua_pushnumber(L, player->getContainerIndex(getNumber<uint8_t>(L, 2)));
9776 } else {
9777 lua_pushnil(L);
9778 }
9779 return 1;
9780}
9781
9782int LuaScriptInterface::luaPlayerGetInstantSpells(lua_State *L) {
9783 // player:getInstantSpells()
9784 Player *player = getUserdata<Player>(L, 1);
9785 if (!player) {
9786 lua_pushnil(L);
9787 return 1;
9788 }
9789
9790 std::vector<const InstantSpell *> spells;
9791 for (auto &spell : g_spells->getInstantSpells()) {
9792 if (spell.second.canCast(player)) {
9793 spells.push_back(&spell.second);
9794 }
9795 }
9796
9797 lua_createtable(L, spells.size(), 0);
9798
9799 int index = 0;
9800 for (auto spell : spells) {
9801 pushInstantSpell(L, *spell);
9802 lua_rawseti(L, -2, ++index);
9803 }
9804 return 1;
9805}
9806
9807int LuaScriptInterface::luaPlayerCanCast(lua_State *L) {
9808 // player:canCast(spell)
9809 Player *player = getUserdata<Player>(L, 1);
9810 InstantSpell *spell = getUserdata<InstantSpell>(L, 2);
9811 if (player && spell) {
9812 pushBoolean(L, spell->canCast(player));
9813 } else {
9814 lua_pushnil(L);
9815 }
9816 return 1;
9817}
9818
9819int LuaScriptInterface::luaPlayerHasChaseMode(lua_State *L) {
9820 // player:hasChaseMode()
9821 Player *player = getUserdata<Player>(L, 1);
9822 if (player) {
9823 pushBoolean(L, player->chaseMode);
9824 } else {
9825 lua_pushnil(L);
9826 }
9827 return 1;
9828}
9829
9830int LuaScriptInterface::luaPlayerHasSecureMode(lua_State *L) {
9831 // player:hasSecureMode()
9832 Player *player = getUserdata<Player>(L, 1);
9833 if (player) {
9834 pushBoolean(L, player->secureMode);
9835 } else {
9836 lua_pushnil(L);
9837 }
9838 return 1;
9839}
9840
9841int LuaScriptInterface::luaPlayerSetAttackSpeed(lua_State *L) {
9842 // player:setAttackSpeed(ms)
9843 Player *player = getUserdata<Player>(L, 1);
9844 uint32_t ms = getNumber<uint32_t>(L, 2);
9845 if (player) {
9846 player->setAttackSpeed(ms);
9847 pushBoolean(L, true);
9848 } else {
9849 lua_pushnil(L);
9850 }
9851 return 1;
9852}
9853
9854int LuaScriptInterface::luaPlayerGetAttackSpeed(lua_State *L) {
9855 // player:getAttackSpeed()
9856 Player *player = getUserdata<Player>(L, 1);
9857 if (player) {
9858 lua_pushnumber(L, player->getAttackSpeed());
9859 } else {
9860 lua_pushnil(L);
9861 }
9862 return 1;
9863}
9864
9865int LuaScriptInterface::luaPlayerGetFightMode(lua_State *L) {
9866 // player:getFightMode()
9867 Player *player = getUserdata<Player>(L, 1);
9868 if (player) {
9869 lua_pushnumber(L, player->fightMode);
9870 } else {
9871 lua_pushnil(L);
9872 }
9873 return 1;
9874}
9875
9876int LuaScriptInterface::luaPlayerAddWings(lua_State *L) {
9877 // player:addWing(wingId or wingName)
9878 Player *player = getUserdata<Player>(L, 1);
9879 if (!player) {
9880 lua_pushnil(L);
9881 return 1;
9882 }
9883
9884 uint8_t wingId;
9885 if (isNumber(L, 2)) {
9886 wingId = getNumber<uint8_t>(L, 2);
9887 } else {
9888 Wing *wing = g_game.wings.getWingByName(getString(L, 2));
9889 if (!wing) {
9890 lua_pushnil(L);
9891 return 1;
9892 }
9893 wingId = wing->id;
9894 }
9895 pushBoolean(L, player->addWing(wingId));
9896 return 1;
9897}
9898
9899int LuaScriptInterface::luaPlayerAddAura(lua_State *L) {
9900 // player:addAura(auraId or auraName)
9901 Player *player = getUserdata<Player>(L, 1);
9902 if (!player) {
9903 lua_pushnil(L);
9904 return 1;
9905 }
9906
9907 uint8_t auraId;
9908 if (isNumber(L, 2)) {
9909 auraId = getNumber<uint8_t>(L, 2);
9910 } else {
9911 Aura *aura = g_game.auras.getAuraByName(getString(L, 2));
9912 if (!aura) {
9913 lua_pushnil(L);
9914 return 1;
9915 }
9916 auraId = aura->id;
9917 }
9918 pushBoolean(L, player->addAura(auraId));
9919 return 1;
9920}
9921
9922int LuaScriptInterface::luaPlayerAddShader(lua_State *L) {
9923 // player:addShader(shaderId or shaderName)
9924 Player *player = getUserdata<Player>(L, 1);
9925 if (!player) {
9926 lua_pushnil(L);
9927 return 1;
9928 }
9929
9930 uint8_t shaderId;
9931 if (isNumber(L, 2)) {
9932 shaderId = getNumber<uint8_t>(L, 2);
9933 } else {
9934 Shader *shader = g_game.shaders.getShaderByName(getString(L, 2));
9935 if (!shader) {
9936 lua_pushnil(L);
9937 return 1;
9938 }
9939 shaderId = shader->id;
9940 }
9941 pushBoolean(L, player->addShader(shaderId));
9942 return 1;
9943}
9944
9945int LuaScriptInterface::luaPlayerAddRuneEffect(lua_State *L) {
9946 // player:addRuneEffect(runeEffectId or runeEffectName)
9947 Player *player = getUserdata<Player>(L, 1);
9948 if (!player) {
9949 lua_pushnil(L);
9950 return 1;
9951 }
9952
9953 uint8_t runeEffectId;
9954 if (isNumber(L, 2)) {
9955 runeEffectId = getNumber<uint8_t>(L, 2);
9956 } else {
9957 RuneEffect *runeEffect = g_game.runeEffects.getRuneEffectByName(getString(L, 2));
9958 if (!runeEffect) {
9959 lua_pushnil(L);
9960 return 1;
9961 }
9962 runeEffectId = runeEffect->id;
9963 }
9964 pushBoolean(L, player->addRuneEffect(runeEffectId));
9965 return 1;
9966}
9967
9968int LuaScriptInterface::luaPlayerGetCurrentRuneEffect(lua_State *L) {
9969 // player:getCurrentRuneEffect()
9970 Player *player = getUserdata<Player>(L, 1);
9971 if (!player) {
9972 lua_pushnil(L);
9973 return 1;
9974 }
9975
9976 lua_pushnumber(L, player->getCurrentRuneEffect());
9977 return 1;
9978}
9979
9980int LuaScriptInterface::luaPlayerSetCurrentRuneEffect(lua_State *L) {
9981 // player:setCurrentRuneEffect(runeEffectId)
9982 Player *player = getUserdata<Player>(L, 1);
9983 if (!player) {
9984 lua_pushnil(L);
9985 return 1;
9986 }
9987
9988 uint8_t runeEffectId = getNumber<uint8_t>(L, 2);
9989 player->setCurrentRuneEffect(runeEffectId);
9990 pushBoolean(L, true);
9991 return 1;
9992}
9993
9994// Monster
9995int LuaScriptInterface::luaMonsterCreate(lua_State *L) {
9996 // Monster(id or userdata)
9997 Monster *monster;
9998 if (isNumber(L, 2)) {
9999 monster = g_game.getMonsterByID(getNumber<uint32_t>(L, 2));
10000 } else if (isUserdata(L, 2)) {
10001 if (getUserdataType(L, 2) != LuaData_Monster) {
10002 lua_pushnil(L);
10003 return 1;
10004 }
10005 monster = getUserdata<Monster>(L, 2);
10006 } else {
10007 monster = nullptr;
10008 }
10009
10010 if (monster) {
10011 pushUserdata<Monster>(L, monster);
10012 setMetatable(L, -1, "Monster");
10013 } else {
10014 lua_pushnil(L);
10015 }
10016 return 1;
10017}
10018
10019int LuaScriptInterface::luaMonsterIsMonster(lua_State *L) {
10020 // monster:isMonster()
10021 pushBoolean(L, getUserdata<const Monster>(L, 1) != nullptr);
10022 return 1;
10023}
10024
10025int LuaScriptInterface::luaMonsterGetType(lua_State *L) {
10026 // monster:getType()
10027 const Monster *monster = getUserdata<const Monster>(L, 1);
10028 if (monster) {
10029 pushUserdata<MonsterType>(L, monster->mType);
10030 setMetatable(L, -1, "MonsterType");
10031 } else {
10032 lua_pushnil(L);
10033 }
10034 return 1;
10035}
10036
10037int LuaScriptInterface::luaMonsterGetSpawnPosition(lua_State *L) {
10038 // monster:getSpawnPosition()
10039 const Monster *monster = getUserdata<const Monster>(L, 1);
10040 if (monster) {
10041 pushPosition(L, monster->getMasterPos());
10042 } else {
10043 lua_pushnil(L);
10044 }
10045 return 1;
10046}
10047
10048int LuaScriptInterface::luaMonsterIsInSpawnRange(lua_State *L) {
10049 // monster:isInSpawnRange([position])
10050 Monster *monster = getUserdata<Monster>(L, 1);
10051 if (monster) {
10052 pushBoolean(L, monster->isInSpawnRange(lua_gettop(L) >= 2
10053 ? getPosition(L, 2)
10054 : monster->getPosition()));
10055 } else {
10056 lua_pushnil(L);
10057 }
10058 return 1;
10059}
10060
10061int LuaScriptInterface::luaMonsterIsIdle(lua_State *L) {
10062 // monster:isIdle()
10063 Monster *monster = getUserdata<Monster>(L, 1);
10064 if (monster) {
10065 pushBoolean(L, monster->getIdleStatus());
10066 } else {
10067 lua_pushnil(L);
10068 }
10069 return 1;
10070}
10071
10072int LuaScriptInterface::luaMonsterSetIdle(lua_State *L) {
10073 // monster:setIdle(idle)
10074 Monster *monster = getUserdata<Monster>(L, 1);
10075 if (!monster) {
10076 lua_pushnil(L);
10077 return 1;
10078 }
10079
10080 monster->setIdle(getBoolean(L, 2));
10081 pushBoolean(L, true);
10082 return 1;
10083}
10084
10085int LuaScriptInterface::luaMonsterIsTarget(lua_State *L) {
10086 // monster:isTarget(creature)
10087 Monster *monster = getUserdata<Monster>(L, 1);
10088 if (monster) {
10089 const Creature *creature = getCreature(L, 2);
10090 pushBoolean(L, monster->isTarget(creature));
10091 } else {
10092 lua_pushnil(L);
10093 }
10094 return 1;
10095}
10096
10097int LuaScriptInterface::luaMonsterIsOpponent(lua_State *L) {
10098 // monster:isOpponent(creature)
10099 Monster *monster = getUserdata<Monster>(L, 1);
10100 if (monster) {
10101 const Creature *creature = getCreature(L, 2);
10102 pushBoolean(L, monster->isOpponent(creature));
10103 } else {
10104 lua_pushnil(L);
10105 }
10106 return 1;
10107}
10108
10109int LuaScriptInterface::luaMonsterIsFriend(lua_State *L) {
10110 // monster:isFriend(creature)
10111 Monster *monster = getUserdata<Monster>(L, 1);
10112 if (monster) {
10113 const Creature *creature = getCreature(L, 2);
10114 pushBoolean(L, monster->isFriend(creature));
10115 } else {
10116 lua_pushnil(L);
10117 }
10118 return 1;
10119}
10120
10121int LuaScriptInterface::luaMonsterAddFriend(lua_State *L) {
10122 // monster:addFriend(creature)
10123 Monster *monster = getUserdata<Monster>(L, 1);
10124 if (monster) {
10125 Creature *creature = getCreature(L, 2);
10126 monster->addFriend(creature);
10127 pushBoolean(L, true);
10128 } else {
10129 lua_pushnil(L);
10130 }
10131 return 1;
10132}
10133
10134int LuaScriptInterface::luaMonsterRemoveFriend(lua_State *L) {
10135 // monster:removeFriend(creature)
10136 Monster *monster = getUserdata<Monster>(L, 1);
10137 if (monster) {
10138 Creature *creature = getCreature(L, 2);
10139 monster->removeFriend(creature);
10140 pushBoolean(L, true);
10141 } else {
10142 lua_pushnil(L);
10143 }
10144 return 1;
10145}
10146
10147int LuaScriptInterface::luaMonsterGetFriendList(lua_State *L) {
10148 // monster:getFriendList()
10149 Monster *monster = getUserdata<Monster>(L, 1);
10150 if (!monster) {
10151 lua_pushnil(L);
10152 return 1;
10153 }
10154
10155 const auto &friendList = monster->getFriendList();
10156 lua_createtable(L, friendList.size(), 0);
10157
10158 int index = 0;
10159 for (Creature *creature : friendList) {
10160 pushUserdata<Creature>(L, creature);
10161 setCreatureMetatable(L, -1, creature);
10162 lua_rawseti(L, -2, ++index);
10163 }
10164 return 1;
10165}
10166
10167int LuaScriptInterface::luaMonsterGetFriendCount(lua_State *L) {
10168 // monster:getFriendCount()
10169 Monster *monster = getUserdata<Monster>(L, 1);
10170 if (monster) {
10171 lua_pushnumber(L, monster->getFriendList().size());
10172 } else {
10173 lua_pushnil(L);
10174 }
10175 return 1;
10176}
10177
10178int LuaScriptInterface::luaMonsterAddTarget(lua_State *L) {
10179 // monster:addTarget(creature[, pushFront = false])
10180 Monster *monster = getUserdata<Monster>(L, 1);
10181 if (!monster) {
10182 lua_pushnil(L);
10183 return 1;
10184 }
10185
10186 Creature *creature = getCreature(L, 2);
10187 bool pushFront = getBoolean(L, 3, false);
10188 monster->addTarget(creature, pushFront);
10189 pushBoolean(L, true);
10190 return 1;
10191}
10192
10193int LuaScriptInterface::luaMonsterRemoveTarget(lua_State *L) {
10194 // monster:removeTarget(creature)
10195 Monster *monster = getUserdata<Monster>(L, 1);
10196 if (!monster) {
10197 lua_pushnil(L);
10198 return 1;
10199 }
10200
10201 monster->removeTarget(getCreature(L, 2));
10202 pushBoolean(L, true);
10203 return 1;
10204}
10205
10206int LuaScriptInterface::luaMonsterGetTargetList(lua_State *L) {
10207 // monster:getTargetList()
10208 Monster *monster = getUserdata<Monster>(L, 1);
10209 if (!monster) {
10210 lua_pushnil(L);
10211 return 1;
10212 }
10213
10214 const auto &targetList = monster->getTargetList();
10215 lua_createtable(L, targetList.size(), 0);
10216
10217 int index = 0;
10218 for (Creature *creature : targetList) {
10219 pushUserdata<Creature>(L, creature);
10220 setCreatureMetatable(L, -1, creature);
10221 lua_rawseti(L, -2, ++index);
10222 }
10223 return 1;
10224}
10225
10226int LuaScriptInterface::luaMonsterGetTargetCount(lua_State *L) {
10227 // monster:getTargetCount()
10228 Monster *monster = getUserdata<Monster>(L, 1);
10229 if (monster) {
10230 lua_pushnumber(L, monster->getTargetList().size());
10231 } else {
10232 lua_pushnil(L);
10233 }
10234 return 1;
10235}
10236
10237int LuaScriptInterface::luaMonsterSelectTarget(lua_State *L) {
10238 // monster:selectTarget(creature)
10239 Monster *monster = getUserdata<Monster>(L, 1);
10240 if (monster) {
10241 Creature *creature = getCreature(L, 2);
10242 pushBoolean(L, monster->selectTarget(creature));
10243 } else {
10244 lua_pushnil(L);
10245 }
10246 return 1;
10247}
10248
10249int LuaScriptInterface::luaMonsterSearchTarget(lua_State *L) {
10250 // monster:searchTarget([searchType = TARGETSEARCH_DEFAULT])
10251 Monster *monster = getUserdata<Monster>(L, 1);
10252 if (monster) {
10253 TargetSearchType_t searchType =
10254 getNumber<TargetSearchType_t>(L, 2, TARGETSEARCH_DEFAULT);
10255 pushBoolean(L, monster->searchTarget(searchType));
10256 } else {
10257 lua_pushnil(L);
10258 }
10259 return 1;
10260}
10261
10262int LuaScriptInterface::luaMonsterSetName(lua_State *L) {
10263 // monster:setName(name, description)
10264 std::string newDesc = getString(L, 3);
10265 std::string newName = getString(L, 2);
10266
10267 Monster *monster = getUserdata<Monster>(L, 1);
10268 if (!monster) {
10269 reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
10270 pushBoolean(L, false);
10271 return 1;
10272 }
10273 monster->setName(newName);
10274 monster->setDescription(newDesc);
10275 monster->setStrDescription(newDesc);
10276 lua_pushboolean(L, true);
10277
10278 return 1;
10279}
10280
10281// Npc
10282int LuaScriptInterface::luaNpcCreate(lua_State *L) {
10283 // Npc([id or name or userdata])
10284 Npc *npc;
10285 if (lua_gettop(L) >= 2) {
10286 if (isNumber(L, 2)) {
10287 npc = g_game.getNpcByID(getNumber<uint32_t>(L, 2));
10288 } else if (isString(L, 2)) {
10289 npc = g_game.getNpcByName(getString(L, 2));
10290 } else if (isUserdata(L, 2)) {
10291 if (getUserdataType(L, 2) != LuaData_Npc) {
10292 lua_pushnil(L);
10293 return 1;
10294 }
10295 npc = getUserdata<Npc>(L, 2);
10296 } else {
10297 npc = nullptr;
10298 }
10299 } else {
10300 npc = getScriptEnv()->getNpc();
10301 }
10302
10303 if (npc) {
10304 pushUserdata<Npc>(L, npc);
10305 setMetatable(L, -1, "Npc");
10306 } else {
10307 lua_pushnil(L);
10308 }
10309 return 1;
10310}
10311
10312int LuaScriptInterface::luaNpcIsNpc(lua_State *L) {
10313 // npc:isNpc()
10314 pushBoolean(L, getUserdata<const Npc>(L, 1) != nullptr);
10315 return 1;
10316}
10317
10318int LuaScriptInterface::luaNpcSetMasterPos(lua_State *L) {
10319 // npc:setMasterPos(pos[, radius])
10320 Npc *npc = getUserdata<Npc>(L, 1);
10321 if (!npc) {
10322 lua_pushnil(L);
10323 return 1;
10324 }
10325
10326 const Position &pos = getPosition(L, 2);
10327 int32_t radius = getNumber<int32_t>(L, 3, 1);
10328 npc->setMasterPos(pos, radius);
10329 pushBoolean(L, true);
10330 return 1;
10331}
10332
10333int LuaScriptInterface::luaNpcGetSpeechBubble(lua_State *L) {
10334 // npc:getSpeechBubble()
10335 Npc *npc = getUserdata<Npc>(L, 1);
10336 if (npc) {
10337 lua_pushnumber(L, npc->getSpeechBubble());
10338 } else {
10339 lua_pushnil(L);
10340 }
10341 return 1;
10342}
10343
10344int LuaScriptInterface::luaNpcSetSpeechBubble(lua_State *L) {
10345 // npc:setSpeechBubble(speechBubble)
10346 Npc *npc = getUserdata<Npc>(L, 1);
10347 if (npc) {
10348 npc->setSpeechBubble(getNumber<uint8_t>(L, 2));
10349 }
10350 return 0;
10351}
10352
10353// Guild
10354int LuaScriptInterface::luaGuildCreate(lua_State *L) {
10355 // Guild(id)
10356 uint32_t id = getNumber<uint32_t>(L, 2);
10357
10358 Guild *guild = g_game.getGuild(id);
10359 if (guild) {
10360 pushUserdata<Guild>(L, guild);
10361 setMetatable(L, -1, "Guild");
10362 } else {
10363 lua_pushnil(L);
10364 }
10365 return 1;
10366}
10367
10368int LuaScriptInterface::luaGuildGetId(lua_State *L) {
10369 // guild:getId()
10370 Guild *guild = getUserdata<Guild>(L, 1);
10371 if (guild) {
10372 lua_pushnumber(L, guild->getId());
10373 } else {
10374 lua_pushnil(L);
10375 }
10376 return 1;
10377}
10378
10379int LuaScriptInterface::luaGuildGetName(lua_State *L) {
10380 // guild:getName()
10381 Guild *guild = getUserdata<Guild>(L, 1);
10382 if (guild) {
10383 pushString(L, guild->getName());
10384 } else {
10385 lua_pushnil(L);
10386 }
10387 return 1;
10388}
10389
10390int LuaScriptInterface::luaGuildGetMembersOnline(lua_State *L) {
10391 // guild:getMembersOnline()
10392 const Guild *guild = getUserdata<const Guild>(L, 1);
10393 if (!guild) {
10394 lua_pushnil(L);
10395 return 1;
10396 }
10397
10398 const auto &members = guild->getMembersOnline();
10399 lua_createtable(L, members.size(), 0);
10400
10401 int index = 0;
10402 for (Player *player : members) {
10403 pushUserdata<Player>(L, player);
10404 setMetatable(L, -1, "Player");
10405 lua_rawseti(L, -2, ++index);
10406 }
10407 return 1;
10408}
10409
10410int LuaScriptInterface::luaGuildAddRank(lua_State *L) {
10411 // guild:addRank(id, name, level)
10412 Guild *guild = getUserdata<Guild>(L, 1);
10413 if (guild) {
10414 uint32_t id = getNumber<uint32_t>(L, 2);
10415 const std::string &name = getString(L, 3);
10416 uint8_t level = getNumber<uint8_t>(L, 4);
10417 guild->addRank(id, name, level);
10418 pushBoolean(L, true);
10419 } else {
10420 lua_pushnil(L);
10421 }
10422 return 1;
10423}
10424
10425int LuaScriptInterface::luaGuildGetRankById(lua_State *L) {
10426 // guild:getRankById(id)
10427 Guild *guild = getUserdata<Guild>(L, 1);
10428 if (!guild) {
10429 lua_pushnil(L);
10430 return 1;
10431 }
10432
10433 uint32_t id = getNumber<uint32_t>(L, 2);
10434 GuildRank_ptr rank = guild->getRankById(id);
10435 if (rank) {
10436 lua_createtable(L, 0, 3);
10437 setField(L, "id", rank->id);
10438 setField(L, "name", rank->name);
10439 setField(L, "level", rank->level);
10440 } else {
10441 lua_pushnil(L);
10442 }
10443 return 1;
10444}
10445
10446int LuaScriptInterface::luaGuildGetRankByLevel(lua_State *L) {
10447 // guild:getRankByLevel(level)
10448 const Guild *guild = getUserdata<const Guild>(L, 1);
10449 if (!guild) {
10450 lua_pushnil(L);
10451 return 1;
10452 }
10453
10454 uint8_t level = getNumber<uint8_t>(L, 2);
10455 GuildRank_ptr rank = guild->getRankByLevel(level);
10456 if (rank) {
10457 lua_createtable(L, 0, 3);
10458 setField(L, "id", rank->id);
10459 setField(L, "name", rank->name);
10460 setField(L, "level", rank->level);
10461 } else {
10462 lua_pushnil(L);
10463 }
10464 return 1;
10465}
10466
10467int LuaScriptInterface::luaGuildGetMotd(lua_State *L) {
10468 // guild:getMotd()
10469 Guild *guild = getUserdata<Guild>(L, 1);
10470 if (guild) {
10471 pushString(L, guild->getMotd());
10472 } else {
10473 lua_pushnil(L);
10474 }
10475 return 1;
10476}
10477
10478int LuaScriptInterface::luaGuildSetMotd(lua_State *L) {
10479 // guild:setMotd(motd)
10480 const std::string &motd = getString(L, 2);
10481 Guild *guild = getUserdata<Guild>(L, 1);
10482 if (guild) {
10483 guild->setMotd(motd);
10484 pushBoolean(L, true);
10485 } else {
10486 lua_pushnil(L);
10487 }
10488 return 1;
10489}
10490
10491// Group
10492int LuaScriptInterface::luaGroupCreate(lua_State *L) {
10493 // Group(id)
10494 uint32_t id = getNumber<uint32_t>(L, 2);
10495
10496 Group *group = g_game.groups.getGroup(id);
10497 if (group) {
10498 pushUserdata<Group>(L, group);
10499 setMetatable(L, -1, "Group");
10500 } else {
10501 lua_pushnil(L);
10502 }
10503 return 1;
10504}
10505
10506int LuaScriptInterface::luaGroupGetId(lua_State *L) {
10507 // group:getId()
10508 Group *group = getUserdata<Group>(L, 1);
10509 if (group) {
10510 lua_pushnumber(L, group->id);
10511 } else {
10512 lua_pushnil(L);
10513 }
10514 return 1;
10515}
10516
10517int LuaScriptInterface::luaGroupGetName(lua_State *L) {
10518 // group:getName()
10519 Group *group = getUserdata<Group>(L, 1);
10520 if (group) {
10521 pushString(L, group->name);
10522 } else {
10523 lua_pushnil(L);
10524 }
10525 return 1;
10526}
10527
10528int LuaScriptInterface::luaGroupGetFlags(lua_State *L) {
10529 // group:getFlags()
10530 Group *group = getUserdata<Group>(L, 1);
10531 if (group) {
10532 lua_pushnumber(L, group->flags);
10533 } else {
10534 lua_pushnil(L);
10535 }
10536 return 1;
10537}
10538
10539int LuaScriptInterface::luaGroupGetAccess(lua_State *L) {
10540 // group:getAccess()
10541 Group *group = getUserdata<Group>(L, 1);
10542 if (group) {
10543 pushBoolean(L, group->access);
10544 } else {
10545 lua_pushnil(L);
10546 }
10547 return 1;
10548}
10549
10550int LuaScriptInterface::luaGroupGetMaxDepotItems(lua_State *L) {
10551 // group:getMaxDepotItems()
10552 Group *group = getUserdata<Group>(L, 1);
10553 if (group) {
10554 lua_pushnumber(L, group->maxDepotItems);
10555 } else {
10556 lua_pushnil(L);
10557 }
10558 return 1;
10559}
10560
10561int LuaScriptInterface::luaGroupGetMaxVipEntries(lua_State *L) {
10562 // group:getMaxVipEntries()
10563 Group *group = getUserdata<Group>(L, 1);
10564 if (group) {
10565 lua_pushnumber(L, group->maxVipEntries);
10566 } else {
10567 lua_pushnil(L);
10568 }
10569 return 1;
10570}
10571
10572int LuaScriptInterface::luaGroupHasFlag(lua_State *L) {
10573 // group:hasFlag(flag)
10574 Group *group = getUserdata<Group>(L, 1);
10575 if (group) {
10576 PlayerFlags flag = getNumber<PlayerFlags>(L, 2);
10577 pushBoolean(L, (group->flags & flag) != 0);
10578 } else {
10579 lua_pushnil(L);
10580 }
10581 return 1;
10582}
10583
10584// Vocation
10585int LuaScriptInterface::luaVocationCreate(lua_State *L) {
10586 // Vocation(id or name)
10587 uint32_t id;
10588 if (isNumber(L, 2)) {
10589 id = getNumber<uint32_t>(L, 2);
10590 } else {
10591 id = g_vocations.getVocationId(getString(L, 2));
10592 }
10593
10594 Vocation *vocation = g_vocations.getVocation(id);
10595 if (vocation) {
10596 pushUserdata<Vocation>(L, vocation);
10597 setMetatable(L, -1, "Vocation");
10598 } else {
10599 lua_pushnil(L);
10600 }
10601 return 1;
10602}
10603
10604int LuaScriptInterface::luaVocationGetId(lua_State *L) {
10605 // vocation:getId()
10606 Vocation *vocation = getUserdata<Vocation>(L, 1);
10607 if (vocation) {
10608 lua_pushnumber(L, vocation->getId());
10609 } else {
10610 lua_pushnil(L);
10611 }
10612 return 1;
10613}
10614
10615int LuaScriptInterface::luaVocationGetClientId(lua_State *L) {
10616 // vocation:getClientId()
10617 Vocation *vocation = getUserdata<Vocation>(L, 1);
10618 if (vocation) {
10619 lua_pushnumber(L, vocation->getClientId());
10620 } else {
10621 lua_pushnil(L);
10622 }
10623 return 1;
10624}
10625
10626int LuaScriptInterface::luaVocationGetName(lua_State *L) {
10627 // vocation:getName()
10628 Vocation *vocation = getUserdata<Vocation>(L, 1);
10629 if (vocation) {
10630 pushString(L, vocation->getVocName());
10631 } else {
10632 lua_pushnil(L);
10633 }
10634 return 1;
10635}
10636
10637int LuaScriptInterface::luaVocationGetDescription(lua_State *L) {
10638 // vocation:getDescription()
10639 Vocation *vocation = getUserdata<Vocation>(L, 1);
10640 if (vocation) {
10641 pushString(L, vocation->getVocDescription());
10642 } else {
10643 lua_pushnil(L);
10644 }
10645 return 1;
10646}
10647
10648int LuaScriptInterface::luaVocationGetRequiredSkillTries(lua_State *L) {
10649 // vocation:getRequiredSkillTries(skillType, skillLevel)
10650 Vocation *vocation = getUserdata<Vocation>(L, 1);
10651 if (vocation) {
10652 skills_t skillType = getNumber<skills_t>(L, 2);
10653 uint16_t skillLevel = getNumber<uint16_t>(L, 3);
10654 lua_pushnumber(L, vocation->getReqSkillTries(skillType, skillLevel));
10655 } else {
10656 lua_pushnil(L);
10657 }
10658 return 1;
10659}
10660
10661int LuaScriptInterface::luaVocationGetRequiredManaSpent(lua_State *L) {
10662 // vocation:getRequiredManaSpent(magicLevel)
10663 Vocation *vocation = getUserdata<Vocation>(L, 1);
10664 if (vocation) {
10665 uint32_t magicLevel = getNumber<uint32_t>(L, 2);
10666 lua_pushnumber(L, vocation->getReqMana(magicLevel));
10667 } else {
10668 lua_pushnil(L);
10669 }
10670 return 1;
10671}
10672
10673int LuaScriptInterface::luaVocationGetCapacityGain(lua_State *L) {
10674 // vocation:getCapacityGain()
10675 Vocation *vocation = getUserdata<Vocation>(L, 1);
10676 if (vocation) {
10677 lua_pushnumber(L, vocation->getCapGain());
10678 } else {
10679 lua_pushnil(L);
10680 }
10681 return 1;
10682}
10683
10684int LuaScriptInterface::luaVocationGetHealthGain(lua_State *L) {
10685 // vocation:getHealthGain()
10686 Vocation *vocation = getUserdata<Vocation>(L, 1);
10687 if (vocation) {
10688 lua_pushnumber(L, vocation->getHPGain());
10689 } else {
10690 lua_pushnil(L);
10691 }
10692 return 1;
10693}
10694
10695int LuaScriptInterface::luaVocationGetHealthGainTicks(lua_State *L) {
10696 // vocation:getHealthGainTicks()
10697 Vocation *vocation = getUserdata<Vocation>(L, 1);
10698 if (vocation) {
10699 lua_pushnumber(L, vocation->getHealthGainTicks());
10700 } else {
10701 lua_pushnil(L);
10702 }
10703 return 1;
10704}
10705
10706int LuaScriptInterface::luaVocationGetHealthGainAmount(lua_State *L) {
10707 // vocation:getHealthGainAmount()
10708 Vocation *vocation = getUserdata<Vocation>(L, 1);
10709 if (vocation) {
10710 lua_pushnumber(L, vocation->getHealthGainAmount());
10711 } else {
10712 lua_pushnil(L);
10713 }
10714 return 1;
10715}
10716
10717int LuaScriptInterface::luaVocationGetManaGain(lua_State *L) {
10718 // vocation:getManaGain()
10719 Vocation *vocation = getUserdata<Vocation>(L, 1);
10720 if (vocation) {
10721 lua_pushnumber(L, vocation->getManaGain());
10722 } else {
10723 lua_pushnil(L);
10724 }
10725 return 1;
10726}
10727
10728int LuaScriptInterface::luaVocationGetManaGainTicks(lua_State *L) {
10729 // vocation:getManaGainTicks()
10730 Vocation *vocation = getUserdata<Vocation>(L, 1);
10731 if (vocation) {
10732 lua_pushnumber(L, vocation->getManaGainTicks());
10733 } else {
10734 lua_pushnil(L);
10735 }
10736 return 1;
10737}
10738
10739int LuaScriptInterface::luaVocationGetManaGainAmount(lua_State *L) {
10740 // vocation:getManaGainAmount()
10741 Vocation *vocation = getUserdata<Vocation>(L, 1);
10742 if (vocation) {
10743 lua_pushnumber(L, vocation->getManaGainAmount());
10744 } else {
10745 lua_pushnil(L);
10746 }
10747 return 1;
10748}
10749
10750int LuaScriptInterface::luaVocationGetMaxSoul(lua_State *L) {
10751 // vocation:getMaxSoul()
10752 Vocation *vocation = getUserdata<Vocation>(L, 1);
10753 if (vocation) {
10754 lua_pushnumber(L, vocation->getSoulMax());
10755 } else {
10756 lua_pushnil(L);
10757 }
10758 return 1;
10759}
10760
10761int LuaScriptInterface::luaVocationGetSoulGainTicks(lua_State *L) {
10762 // vocation:getSoulGainTicks()
10763 Vocation *vocation = getUserdata<Vocation>(L, 1);
10764 if (vocation) {
10765 lua_pushnumber(L, vocation->getSoulGainTicks());
10766 } else {
10767 lua_pushnil(L);
10768 }
10769 return 1;
10770}
10771
10772int LuaScriptInterface::luaVocationGetAttackSpeed(lua_State *L) {
10773 // vocation:getAttackSpeed()
10774 Vocation *vocation = getUserdata<Vocation>(L, 1);
10775 if (vocation) {
10776 lua_pushnumber(L, vocation->getAttackSpeed());
10777 } else {
10778 lua_pushnil(L);
10779 }
10780 return 1;
10781}
10782
10783int LuaScriptInterface::luaVocationGetBaseSpeed(lua_State *L) {
10784 // vocation:getBaseSpeed()
10785 Vocation *vocation = getUserdata<Vocation>(L, 1);
10786 if (vocation) {
10787 lua_pushnumber(L, vocation->getBaseSpeed());
10788 } else {
10789 lua_pushnil(L);
10790 }
10791 return 1;
10792}
10793
10794int LuaScriptInterface::luaVocationGetDemotion(lua_State *L) {
10795 // vocation:getDemotion()
10796 Vocation *vocation = getUserdata<Vocation>(L, 1);
10797 if (!vocation) {
10798 lua_pushnil(L);
10799 return 1;
10800 }
10801
10802 uint16_t fromId = vocation->getFromVocation();
10803 if (fromId == VOCATION_NONE) {
10804 lua_pushnil(L);
10805 return 1;
10806 }
10807
10808 Vocation *demotedVocation = g_vocations.getVocation(fromId);
10809 if (demotedVocation && demotedVocation != vocation) {
10810 pushUserdata<Vocation>(L, demotedVocation);
10811 setMetatable(L, -1, "Vocation");
10812 } else {
10813 lua_pushnil(L);
10814 }
10815 return 1;
10816}
10817
10818int LuaScriptInterface::luaVocationGetPromotion(lua_State *L) {
10819 // vocation:getPromotion()
10820 Vocation *vocation = getUserdata<Vocation>(L, 1);
10821 if (!vocation) {
10822 lua_pushnil(L);
10823 return 1;
10824 }
10825
10826 uint16_t promotedId = g_vocations.getPromotedVocation(vocation->getId());
10827 if (promotedId == VOCATION_NONE) {
10828 lua_pushnil(L);
10829 return 1;
10830 }
10831
10832 Vocation *promotedVocation = g_vocations.getVocation(promotedId);
10833 if (promotedVocation && promotedVocation != vocation) {
10834 pushUserdata<Vocation>(L, promotedVocation);
10835 setMetatable(L, -1, "Vocation");
10836 } else {
10837 lua_pushnil(L);
10838 }
10839 return 1;
10840}
10841
10842// Town
10843int LuaScriptInterface::luaTownCreate(lua_State *L) {
10844 // Town(id or name)
10845 Town *town;
10846 if (isNumber(L, 2)) {
10847 town = g_game.map.towns.getTown(getNumber<uint32_t>(L, 2));
10848 } else if (isString(L, 2)) {
10849 town = g_game.map.towns.getTown(getString(L, 2));
10850 } else {
10851 town = nullptr;
10852 }
10853
10854 if (town) {
10855 pushUserdata<Town>(L, town);
10856 setMetatable(L, -1, "Town");
10857 } else {
10858 lua_pushnil(L);
10859 }
10860 return 1;
10861}
10862
10863int LuaScriptInterface::luaTownGetId(lua_State *L) {
10864 // town:getId()
10865 Town *town = getUserdata<Town>(L, 1);
10866 if (town) {
10867 lua_pushnumber(L, town->getID());
10868 } else {
10869 lua_pushnil(L);
10870 }
10871 return 1;
10872}
10873
10874int LuaScriptInterface::luaTownGetName(lua_State *L) {
10875 // town:getName()
10876 Town *town = getUserdata<Town>(L, 1);
10877 if (town) {
10878 pushString(L, town->getName());
10879 } else {
10880 lua_pushnil(L);
10881 }
10882 return 1;
10883}
10884
10885int LuaScriptInterface::luaTownGetTemplePosition(lua_State *L) {
10886 // town:getTemplePosition()
10887 Town *town = getUserdata<Town>(L, 1);
10888 if (town) {
10889 pushPosition(L, town->getTemplePosition());
10890 } else {
10891 lua_pushnil(L);
10892 }
10893 return 1;
10894}
10895
10896// House
10897int LuaScriptInterface::luaHouseCreate(lua_State *L) {
10898 // House(id)
10899 House *house = g_game.map.houses.getHouse(getNumber<uint32_t>(L, 2));
10900 if (house) {
10901 pushUserdata<House>(L, house);
10902 setMetatable(L, -1, "House");
10903 } else {
10904 lua_pushnil(L);
10905 }
10906 return 1;
10907}
10908
10909int LuaScriptInterface::luaHouseGetId(lua_State *L) {
10910 // house:getId()
10911 House *house = getUserdata<House>(L, 1);
10912 if (house) {
10913 lua_pushnumber(L, house->getId());
10914 } else {
10915 lua_pushnil(L);
10916 }
10917 return 1;
10918}
10919
10920int LuaScriptInterface::luaHouseGetName(lua_State *L) {
10921 // house:getName()
10922 House *house = getUserdata<House>(L, 1);
10923 if (house) {
10924 pushString(L, house->getName());
10925 } else {
10926 lua_pushnil(L);
10927 }
10928 return 1;
10929}
10930
10931int LuaScriptInterface::luaHouseGetTown(lua_State *L) {
10932 // house:getTown()
10933 House *house = getUserdata<House>(L, 1);
10934 if (!house) {
10935 lua_pushnil(L);
10936 return 1;
10937 }
10938
10939 Town *town = g_game.map.towns.getTown(house->getTownId());
10940 if (town) {
10941 pushUserdata<Town>(L, town);
10942 setMetatable(L, -1, "Town");
10943 } else {
10944 lua_pushnil(L);
10945 }
10946 return 1;
10947}
10948
10949int LuaScriptInterface::luaHouseGetExitPosition(lua_State *L) {
10950 // house:getExitPosition()
10951 House *house = getUserdata<House>(L, 1);
10952 if (house) {
10953 pushPosition(L, house->getEntryPosition());
10954 } else {
10955 lua_pushnil(L);
10956 }
10957 return 1;
10958}
10959
10960int LuaScriptInterface::luaHouseGetRent(lua_State *L) {
10961 // house:getRent()
10962 House *house = getUserdata<House>(L, 1);
10963 if (house) {
10964 lua_pushnumber(L, house->getRent());
10965 } else {
10966 lua_pushnil(L);
10967 }
10968 return 1;
10969}
10970
10971int LuaScriptInterface::luaHouseGetOwnerGuid(lua_State *L) {
10972 // house:getOwnerGuid()
10973 House *house = getUserdata<House>(L, 1);
10974 if (house) {
10975 lua_pushnumber(L, house->getOwner());
10976 } else {
10977 lua_pushnil(L);
10978 }
10979 return 1;
10980}
10981
10982int LuaScriptInterface::luaHouseSetOwnerGuid(lua_State *L) {
10983 // house:setOwnerGuid(guid[, updateDatabase = true])
10984 House *house = getUserdata<House>(L, 1);
10985 if (house) {
10986 uint32_t guid = getNumber<uint32_t>(L, 2);
10987 bool updateDatabase = getBoolean(L, 3, true);
10988 house->setOwner(guid, updateDatabase);
10989 pushBoolean(L, true);
10990 } else {
10991 lua_pushnil(L);
10992 }
10993 return 1;
10994}
10995
10996int LuaScriptInterface::luaHouseStartTrade(lua_State *L) {
10997 // house:startTrade(player, tradePartner)
10998 House *house = getUserdata<House>(L, 1);
10999 Player *player = getUserdata<Player>(L, 2);
11000 Player *tradePartner = getUserdata<Player>(L, 3);
11001
11002 if (!player || !tradePartner || !house) {
11003 lua_pushnil(L);
11004 return 1;
11005 }
11006
11007 if (!Position::areInRange<2, 2, 0>(tradePartner->getPosition(),
11008 player->getPosition())) {
11009 lua_pushnumber(L, RETURNVALUE_TRADEPLAYERFARAWAY);
11010 return 1;
11011 }
11012
11013 if (house->getOwner() != player->getGUID()) {
11014 lua_pushnumber(L, RETURNVALUE_YOUDONTOWNTHISHOUSE);
11015 return 1;
11016 }
11017
11018 if (g_game.map.houses.getHouseByPlayerId(tradePartner->getGUID())) {
11019 lua_pushnumber(L, RETURNVALUE_TRADEPLAYERALREADYOWNSAHOUSE);
11020 return 1;
11021 }
11022
11023 if (IOLoginData::hasBiddedOnHouse(tradePartner->getGUID())) {
11024 lua_pushnumber(L, RETURNVALUE_TRADEPLAYERHIGHESTBIDDER);
11025 return 1;
11026 }
11027
11028 Item *transferItem = house->getTransferItem();
11029 if (!transferItem) {
11030 lua_pushnumber(L, RETURNVALUE_YOUCANNOTTRADETHISHOUSE);
11031 return 1;
11032 }
11033
11034 transferItem->getParent()->setParent(player);
11035 if (!g_game.internalStartTrade(player, tradePartner, transferItem)) {
11036 house->resetTransferItem();
11037 }
11038
11039 lua_pushnumber(L, RETURNVALUE_NOERROR);
11040 return 1;
11041}
11042
11043int LuaScriptInterface::luaHouseGetBeds(lua_State *L) {
11044 // house:getBeds()
11045 House *house = getUserdata<House>(L, 1);
11046 if (!house) {
11047 lua_pushnil(L);
11048 return 1;
11049 }
11050
11051 const auto &beds = house->getBeds();
11052 lua_createtable(L, beds.size(), 0);
11053
11054 int index = 0;
11055 for (BedItem *bedItem : beds) {
11056 pushUserdata<Item>(L, bedItem);
11057 setItemMetatable(L, -1, bedItem);
11058 lua_rawseti(L, -2, ++index);
11059 }
11060 return 1;
11061}
11062
11063int LuaScriptInterface::luaHouseGetBedCount(lua_State *L) {
11064 // house:getBedCount()
11065 House *house = getUserdata<House>(L, 1);
11066 if (house) {
11067 lua_pushnumber(L, house->getBedCount());
11068 } else {
11069 lua_pushnil(L);
11070 }
11071 return 1;
11072}
11073
11074int LuaScriptInterface::luaHouseGetDoors(lua_State *L) {
11075 // house:getDoors()
11076 House *house = getUserdata<House>(L, 1);
11077 if (!house) {
11078 lua_pushnil(L);
11079 return 1;
11080 }
11081
11082 const auto &doors = house->getDoors();
11083 lua_createtable(L, doors.size(), 0);
11084
11085 int index = 0;
11086 for (Door *door : doors) {
11087 pushUserdata<Item>(L, door);
11088 setItemMetatable(L, -1, door);
11089 lua_rawseti(L, -2, ++index);
11090 }
11091 return 1;
11092}
11093
11094int LuaScriptInterface::luaHouseGetDoorCount(lua_State *L) {
11095 // house:getDoorCount()
11096 House *house = getUserdata<House>(L, 1);
11097 if (house) {
11098 lua_pushnumber(L, house->getDoors().size());
11099 } else {
11100 lua_pushnil(L);
11101 }
11102 return 1;
11103}
11104
11105int LuaScriptInterface::luaHouseGetDoorIdByPosition(lua_State *L) {
11106 // house:getDoorIdByPosition(position)
11107 House *house = getUserdata<House>(L, 1);
11108 if (!house) {
11109 lua_pushnil(L);
11110 return 1;
11111 }
11112
11113 Door *door = house->getDoorByPosition(getPosition(L, 2));
11114 if (door) {
11115 lua_pushnumber(L, door->getDoorId());
11116 } else {
11117 lua_pushnil(L);
11118 }
11119 return 1;
11120}
11121
11122int LuaScriptInterface::luaHouseGetTiles(lua_State *L) {
11123 // house:getTiles()
11124 House *house = getUserdata<House>(L, 1);
11125 if (!house) {
11126 lua_pushnil(L);
11127 return 1;
11128 }
11129
11130 const auto &tiles = house->getTiles();
11131 lua_createtable(L, tiles.size(), 0);
11132
11133 int index = 0;
11134 for (Tile *tile : tiles) {
11135 pushUserdata<Tile>(L, tile);
11136 setMetatable(L, -1, "Tile");
11137 lua_rawseti(L, -2, ++index);
11138 }
11139 return 1;
11140}
11141
11142int LuaScriptInterface::luaHouseGetItems(lua_State *L) {
11143 // house:getItems()
11144 House *house = getUserdata<House>(L, 1);
11145 if (!house) {
11146 lua_pushnil(L);
11147 return 1;
11148 }
11149
11150 const auto &tiles = house->getTiles();
11151 lua_newtable(L);
11152
11153 int index = 0;
11154 for (Tile *tile : tiles) {
11155 TileItemVector *itemVector = tile->getItemList();
11156 if (itemVector) {
11157 for (Item *item : *itemVector) {
11158 pushUserdata<Item>(L, item);
11159 setItemMetatable(L, -1, item);
11160 lua_rawseti(L, -2, ++index);
11161 }
11162 }
11163 }
11164 return 1;
11165}
11166
11167int LuaScriptInterface::luaHouseGetTileCount(lua_State *L) {
11168 // house:getTileCount()
11169 House *house = getUserdata<House>(L, 1);
11170 if (house) {
11171 lua_pushnumber(L, house->getTiles().size());
11172 } else {
11173 lua_pushnil(L);
11174 }
11175 return 1;
11176}
11177
11178int LuaScriptInterface::luaHouseCanEditAccessList(lua_State *L) {
11179 // house:canEditAccessList(listId, player)
11180 House *house = getUserdata<House>(L, 1);
11181 if (!house) {
11182 lua_pushnil(L);
11183 return 1;
11184 }
11185
11186 uint32_t listId = getNumber<uint32_t>(L, 2);
11187 Player *player = getPlayer(L, 3);
11188
11189 pushBoolean(L, house->canEditAccessList(listId, player));
11190 return 1;
11191}
11192
11193int LuaScriptInterface::luaHouseGetAccessList(lua_State *L) {
11194 // house:getAccessList(listId)
11195 House *house = getUserdata<House>(L, 1);
11196 if (!house) {
11197 lua_pushnil(L);
11198 return 1;
11199 }
11200
11201 std::string list;
11202 uint32_t listId = getNumber<uint32_t>(L, 2);
11203 if (house->getAccessList(listId, list)) {
11204 pushString(L, list);
11205 } else {
11206 pushBoolean(L, false);
11207 }
11208 return 1;
11209}
11210
11211int LuaScriptInterface::luaHouseSetAccessList(lua_State *L) {
11212 // house:setAccessList(listId, list)
11213 House *house = getUserdata<House>(L, 1);
11214 if (!house) {
11215 lua_pushnil(L);
11216 return 1;
11217 }
11218
11219 uint32_t listId = getNumber<uint32_t>(L, 2);
11220 const std::string &list = getString(L, 3);
11221 house->setAccessList(listId, list);
11222 pushBoolean(L, true);
11223 return 1;
11224}
11225
11226int LuaScriptInterface::luaHouseKickPlayer(lua_State *L) {
11227 // house:kickPlayer(player, targetPlayer)
11228 House *house = getUserdata<House>(L, 1);
11229 if (!house) {
11230 lua_pushnil(L);
11231 return 1;
11232 }
11233
11234 pushBoolean(L, house->kickPlayer(getPlayer(L, 2), getPlayer(L, 3)));
11235 return 1;
11236}
11237
11238// ItemType
11239int LuaScriptInterface::luaItemTypeCreate(lua_State *L) {
11240 // ItemType(id or name)
11241 uint32_t id;
11242 if (isNumber(L, 2)) {
11243 id = getNumber<uint32_t>(L, 2);
11244 } else if (isString(L, 2)) {
11245 id = Item::items.getItemIdByName(getString(L, 2));
11246 } else {
11247 lua_pushnil(L);
11248 return 1;
11249 }
11250
11251 const ItemType &itemType = Item::items[id];
11252 pushUserdata<const ItemType>(L, &itemType);
11253 setMetatable(L, -1, "ItemType");
11254 return 1;
11255}
11256
11257int LuaScriptInterface::luaItemTypeIsCorpse(lua_State *L) {
11258 // itemType:isCorpse()
11259 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11260 if (itemType) {
11261 pushBoolean(L, itemType->corpseType != RACE_NONE);
11262 } else {
11263 lua_pushnil(L);
11264 }
11265 return 1;
11266}
11267
11268int LuaScriptInterface::luaItemTypeIsDoor(lua_State *L) {
11269 // itemType:isDoor()
11270 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11271 if (itemType) {
11272 pushBoolean(L, itemType->isDoor());
11273 } else {
11274 lua_pushnil(L);
11275 }
11276 return 1;
11277}
11278
11279int LuaScriptInterface::luaItemTypeIsContainer(lua_State *L) {
11280 // itemType:isContainer()
11281 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11282 if (itemType) {
11283 pushBoolean(L, itemType->isContainer());
11284 } else {
11285 lua_pushnil(L);
11286 }
11287 return 1;
11288}
11289
11290int LuaScriptInterface::luaItemTypeIsFluidContainer(lua_State *L) {
11291 // itemType:isFluidContainer()
11292 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11293 if (itemType) {
11294 pushBoolean(L, itemType->isFluidContainer());
11295 } else {
11296 lua_pushnil(L);
11297 }
11298 return 1;
11299}
11300
11301int LuaScriptInterface::luaItemTypeIsMovable(lua_State *L) {
11302 // itemType:isMovable()
11303 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11304 if (itemType) {
11305 pushBoolean(L, itemType->moveable);
11306 } else {
11307 lua_pushnil(L);
11308 }
11309 return 1;
11310}
11311
11312int LuaScriptInterface::luaItemTypeIsRune(lua_State *L) {
11313 // itemType:isRune()
11314 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11315 if (itemType) {
11316 pushBoolean(L, itemType->isRune());
11317 } else {
11318 lua_pushnil(L);
11319 }
11320 return 1;
11321}
11322
11323int LuaScriptInterface::luaItemTypeIsStackable(lua_State *L) {
11324 // itemType:isStackable()
11325 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11326 if (itemType) {
11327 pushBoolean(L, itemType->stackable);
11328 } else {
11329 lua_pushnil(L);
11330 }
11331 return 1;
11332}
11333
11334int LuaScriptInterface::luaItemTypeIsReadable(lua_State *L) {
11335 // itemType:isReadable()
11336 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11337 if (itemType) {
11338 pushBoolean(L, itemType->canReadText);
11339 } else {
11340 lua_pushnil(L);
11341 }
11342 return 1;
11343}
11344
11345int LuaScriptInterface::luaItemTypeIsWritable(lua_State *L) {
11346 // itemType:isWritable()
11347 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11348 if (itemType) {
11349 pushBoolean(L, itemType->canWriteText);
11350 } else {
11351 lua_pushnil(L);
11352 }
11353 return 1;
11354}
11355
11356int LuaScriptInterface::luaItemTypeIsBlocking(lua_State *L) {
11357 // itemType:isBlocking()
11358 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11359 if (itemType) {
11360 pushBoolean(L, itemType->blockProjectile || itemType->blockSolid);
11361 } else {
11362 lua_pushnil(L);
11363 }
11364 return 1;
11365}
11366
11367int LuaScriptInterface::luaItemTypeIsGroundTile(lua_State *L) {
11368 // itemType:isGroundTile()
11369 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11370 if (itemType) {
11371 pushBoolean(L, itemType->isGroundTile());
11372 } else {
11373 lua_pushnil(L);
11374 }
11375 return 1;
11376}
11377
11378int LuaScriptInterface::luaItemTypeIsMagicField(lua_State *L) {
11379 // itemType:isMagicField()
11380 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11381 if (itemType) {
11382 pushBoolean(L, itemType->isMagicField());
11383 } else {
11384 lua_pushnil(L);
11385 }
11386 return 1;
11387}
11388
11389int LuaScriptInterface::luaItemTypeIsUseable(lua_State *L) {
11390 // itemType:isUseable()
11391 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11392 if (itemType) {
11393 pushBoolean(L, itemType->isUseable());
11394 } else {
11395 lua_pushnil(L);
11396 }
11397 return 1;
11398}
11399
11400int LuaScriptInterface::luaItemTypeIsPickupable(lua_State *L) {
11401 // itemType:isPickupable()
11402 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11403 if (itemType) {
11404 pushBoolean(L, itemType->isPickupable());
11405 } else {
11406 lua_pushnil(L);
11407 }
11408 return 1;
11409}
11410
11411int LuaScriptInterface::luaItemTypeGetType(lua_State *L) {
11412 // itemType:getType()
11413 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11414 if (itemType) {
11415 lua_pushnumber(L, itemType->type);
11416 } else {
11417 lua_pushnil(L);
11418 }
11419 return 1;
11420}
11421
11422int LuaScriptInterface::luaItemTypeGetId(lua_State *L) {
11423 // itemType:getId()
11424 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11425 if (itemType) {
11426 lua_pushnumber(L, itemType->id);
11427 } else {
11428 lua_pushnil(L);
11429 }
11430 return 1;
11431}
11432
11433int LuaScriptInterface::luaItemTypeGetClientId(lua_State *L) {
11434 // itemType:getClientId()
11435 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11436 if (itemType) {
11437 lua_pushnumber(L, itemType->clientId);
11438 } else {
11439 lua_pushnil(L);
11440 }
11441 return 1;
11442}
11443
11444int LuaScriptInterface::luaItemTypeGetName(lua_State *L) {
11445 // itemType:getName()
11446 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11447 if (itemType) {
11448 pushString(L, itemType->name);
11449 } else {
11450 lua_pushnil(L);
11451 }
11452 return 1;
11453}
11454
11455int LuaScriptInterface::luaItemTypeGetPluralName(lua_State *L) {
11456 // itemType:getPluralName()
11457 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11458 if (itemType) {
11459 pushString(L, itemType->getPluralName());
11460 } else {
11461 lua_pushnil(L);
11462 }
11463 return 1;
11464}
11465
11466int LuaScriptInterface::luaItemTypeGetArticle(lua_State *L) {
11467 // itemType:getArticle()
11468 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11469 if (itemType) {
11470 pushString(L, itemType->article);
11471 } else {
11472 lua_pushnil(L);
11473 }
11474 return 1;
11475}
11476
11477int LuaScriptInterface::luaItemTypeGetDescription(lua_State *L) {
11478 // itemType:getDescription()
11479 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11480 if (itemType) {
11481 pushString(L, itemType->description);
11482 } else {
11483 lua_pushnil(L);
11484 }
11485 return 1;
11486}
11487
11488int LuaScriptInterface::luaItemTypeGetSlotPosition(lua_State *L) {
11489 // itemType:getSlotPosition()
11490 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11491 if (itemType) {
11492 lua_pushnumber(L, itemType->slotPosition);
11493 } else {
11494 lua_pushnil(L);
11495 }
11496 return 1;
11497}
11498
11499int LuaScriptInterface::luaItemTypeGetCharges(lua_State *L) {
11500 // itemType:getCharges()
11501 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11502 if (itemType) {
11503 lua_pushnumber(L, itemType->charges);
11504 } else {
11505 lua_pushnil(L);
11506 }
11507 return 1;
11508}
11509
11510int LuaScriptInterface::luaItemTypeGetFluidSource(lua_State *L) {
11511 // itemType:getFluidSource()
11512 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11513 if (itemType) {
11514 lua_pushnumber(L, itemType->fluidSource);
11515 } else {
11516 lua_pushnil(L);
11517 }
11518 return 1;
11519}
11520
11521int LuaScriptInterface::luaItemTypeGetCapacity(lua_State *L) {
11522 // itemType:getCapacity()
11523 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11524 if (itemType) {
11525 lua_pushnumber(L, itemType->maxItems);
11526 } else {
11527 lua_pushnil(L);
11528 }
11529 return 1;
11530}
11531
11532int LuaScriptInterface::luaItemTypeGetWeight(lua_State *L) {
11533 // itemType:getWeight([count = 1])
11534 uint16_t count = getNumber<uint16_t>(L, 2, 1);
11535
11536 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11537 if (!itemType) {
11538 lua_pushnil(L);
11539 return 1;
11540 }
11541
11542 uint64_t weight =
11543 static_cast<uint64_t>(itemType->weight) * std::max<int32_t>(1, count);
11544 lua_pushnumber(L, weight);
11545 return 1;
11546}
11547
11548int LuaScriptInterface::luaItemTypeGetHitChance(lua_State *L) {
11549 // itemType:getHitChance()
11550 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11551 if (itemType) {
11552 lua_pushnumber(L, itemType->hitChance);
11553 } else {
11554 lua_pushnil(L);
11555 }
11556 return 1;
11557}
11558
11559int LuaScriptInterface::luaItemTypeGetShootRange(lua_State *L) {
11560 // itemType:getShootRange()
11561 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11562 if (itemType) {
11563 lua_pushnumber(L, itemType->shootRange);
11564 } else {
11565 lua_pushnil(L);
11566 }
11567 return 1;
11568}
11569
11570int LuaScriptInterface::luaItemTypeGetAttack(lua_State *L) {
11571 // itemType:getAttack()
11572 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11573 if (itemType) {
11574 lua_pushnumber(L, itemType->attack);
11575 } else {
11576 lua_pushnil(L);
11577 }
11578 return 1;
11579}
11580
11581int LuaScriptInterface::luaItemTypeGetDefense(lua_State *L) {
11582 // itemType:getDefense()
11583 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11584 if (itemType) {
11585 lua_pushnumber(L, itemType->defense);
11586 } else {
11587 lua_pushnil(L);
11588 }
11589 return 1;
11590}
11591
11592int LuaScriptInterface::luaItemTypeGetExtraDefense(lua_State *L) {
11593 // itemType:getExtraDefense()
11594 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11595 if (itemType) {
11596 lua_pushnumber(L, itemType->extraDefense);
11597 } else {
11598 lua_pushnil(L);
11599 }
11600 return 1;
11601}
11602
11603int LuaScriptInterface::luaItemTypeGetArmor(lua_State *L) {
11604 // itemType:getArmor()
11605 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11606 if (itemType) {
11607 lua_pushnumber(L, itemType->armor);
11608 } else {
11609 lua_pushnil(L);
11610 }
11611 return 1;
11612}
11613
11614int LuaScriptInterface::luaItemTypeGetWeaponType(lua_State *L) {
11615 // itemType:getWeaponType()
11616 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11617 if (itemType) {
11618 lua_pushnumber(L, itemType->weaponType);
11619 } else {
11620 lua_pushnil(L);
11621 }
11622 return 1;
11623}
11624
11625int LuaScriptInterface::luaItemTypeGetAmmoType(lua_State *L) {
11626 // itemType:getAmmoType()
11627 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11628 if (itemType) {
11629 lua_pushnumber(L, itemType->ammoType);
11630 } else {
11631 lua_pushnil(L);
11632 }
11633 return 1;
11634}
11635
11636int LuaScriptInterface::luaItemTypeGetCorpseType(lua_State *L) {
11637 // itemType:getCorpseType()
11638 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11639 if (itemType) {
11640 lua_pushnumber(L, itemType->corpseType);
11641 } else {
11642 lua_pushnil(L);
11643 }
11644 return 1;
11645}
11646
11647int LuaScriptInterface::luaItemTypeGetElementType(lua_State *L) {
11648 // itemType:getElementType()
11649 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11650 if (!itemType) {
11651 lua_pushnil(L);
11652 return 1;
11653 }
11654
11655 auto &abilities = itemType->abilities;
11656 if (abilities) {
11657 lua_pushnumber(L, abilities->elementType);
11658 } else {
11659 lua_pushnil(L);
11660 }
11661 return 1;
11662}
11663
11664int LuaScriptInterface::luaItemTypeGetElementDamage(lua_State *L) {
11665 // itemType:getElementDamage()
11666 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11667 if (!itemType) {
11668 lua_pushnil(L);
11669 return 1;
11670 }
11671
11672 auto &abilities = itemType->abilities;
11673 if (abilities) {
11674 lua_pushnumber(L, abilities->elementDamage);
11675 } else {
11676 lua_pushnil(L);
11677 }
11678 return 1;
11679}
11680
11681int LuaScriptInterface::luaItemTypeGetTransformEquipId(lua_State *L) {
11682 // itemType:getTransformEquipId()
11683 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11684 if (itemType) {
11685 lua_pushnumber(L, itemType->transformEquipTo);
11686 } else {
11687 lua_pushnil(L);
11688 }
11689 return 1;
11690}
11691
11692int LuaScriptInterface::luaItemTypeGetTransformDeEquipId(lua_State *L) {
11693 // itemType:getTransformDeEquipId()
11694 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11695 if (itemType) {
11696 lua_pushnumber(L, itemType->transformDeEquipTo);
11697 } else {
11698 lua_pushnil(L);
11699 }
11700 return 1;
11701}
11702
11703int LuaScriptInterface::luaItemTypeGetDestroyId(lua_State *L) {
11704 // itemType:getDestroyId()
11705 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11706 if (itemType) {
11707 lua_pushnumber(L, itemType->destroyTo);
11708 } else {
11709 lua_pushnil(L);
11710 }
11711 return 1;
11712}
11713
11714int LuaScriptInterface::luaItemTypeGetDecayId(lua_State *L) {
11715 // itemType:getDecayId()
11716 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11717 if (itemType) {
11718 lua_pushnumber(L, itemType->decayTo);
11719 } else {
11720 lua_pushnil(L);
11721 }
11722 return 1;
11723}
11724
11725int LuaScriptInterface::luaItemTypeGetRequiredLevel(lua_State *L) {
11726 // itemType:getRequiredLevel()
11727 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11728 if (itemType) {
11729 lua_pushnumber(L, itemType->minReqLevel);
11730 } else {
11731 lua_pushnil(L);
11732 }
11733 return 1;
11734}
11735
11736int LuaScriptInterface::luaItemTypeHasSubType(lua_State *L) {
11737 // itemType:hasSubType()
11738 const ItemType *itemType = getUserdata<const ItemType>(L, 1);
11739 if (itemType) {
11740 pushBoolean(L, itemType->hasSubType());
11741 } else {
11742 lua_pushnil(L);
11743 }
11744 return 1;
11745}
11746
11747// Combat
11748int LuaScriptInterface::luaCombatCreate(lua_State *L) {
11749 // Combat()
11750 pushUserdata<Combat>(L, g_luaEnvironment.createCombatObject(
11751 getScriptEnv()->getScriptInterface()));
11752 setMetatable(L, -1, "Combat");
11753 return 1;
11754}
11755
11756int LuaScriptInterface::luaCombatSetParameter(lua_State *L) {
11757 // combat:setParameter(key, value)
11758 Combat *combat = getUserdata<Combat>(L, 1);
11759 if (!combat) {
11760 lua_pushnil(L);
11761 return 1;
11762 }
11763
11764 CombatParam_t key = getNumber<CombatParam_t>(L, 2);
11765 uint32_t value;
11766 if (isBoolean(L, 3)) {
11767 value = getBoolean(L, 3) ? 1 : 0;
11768 } else {
11769 value = getNumber<uint32_t>(L, 3);
11770 }
11771 combat->setParam(key, value);
11772 pushBoolean(L, true);
11773 return 1;
11774}
11775
11776int LuaScriptInterface::luaCombatSetFormula(lua_State *L) {
11777 // combat:setFormula(type, mina, minb, maxa, maxb)
11778 Combat *combat = getUserdata<Combat>(L, 1);
11779 if (!combat) {
11780 lua_pushnil(L);
11781 return 1;
11782 }
11783
11784 formulaType_t type = getNumber<formulaType_t>(L, 2);
11785 double mina = getNumber<double>(L, 3);
11786 double minb = getNumber<double>(L, 4);
11787 double maxa = getNumber<double>(L, 5);
11788 double maxb = getNumber<double>(L, 6);
11789 combat->setPlayerCombatValues(type, mina, minb, maxa, maxb);
11790 pushBoolean(L, true);
11791 return 1;
11792}
11793
11794int LuaScriptInterface::luaCombatSetArea(lua_State *L) {
11795 // combat:setArea(area)
11796 if (getScriptEnv()->getScriptId() != EVENT_ID_LOADING) {
11797 reportErrorFunc("This function can only be used while loading the script.");
11798 lua_pushnil(L);
11799 return 1;
11800 }
11801
11802 const AreaCombat *area =
11803 g_luaEnvironment.getAreaObject(getNumber<uint32_t>(L, 2));
11804 if (!area) {
11805 reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND));
11806 lua_pushnil(L);
11807 return 1;
11808 }
11809
11810 Combat *combat = getUserdata<Combat>(L, 1);
11811 if (combat) {
11812 combat->setArea(new AreaCombat(*area));
11813 pushBoolean(L, true);
11814 } else {
11815 lua_pushnil(L);
11816 }
11817 return 1;
11818}
11819
11820int LuaScriptInterface::luaCombatAddCondition(lua_State *L) {
11821 // combat:addCondition(condition)
11822 Condition *condition = getUserdata<Condition>(L, 2);
11823 Combat *combat = getUserdata<Combat>(L, 1);
11824 if (combat && condition) {
11825 combat->addCondition(condition->clone());
11826 pushBoolean(L, true);
11827 } else {
11828 lua_pushnil(L);
11829 }
11830 return 1;
11831}
11832
11833int LuaScriptInterface::luaCombatClearConditions(lua_State *L) {
11834 // combat:clearConditions()
11835 Combat *combat = getUserdata<Combat>(L, 1);
11836 if (combat) {
11837 combat->clearConditions();
11838 pushBoolean(L, true);
11839 } else {
11840 lua_pushnil(L);
11841 }
11842 return 1;
11843}
11844
11845int LuaScriptInterface::luaCombatSetCallback(lua_State *L) {
11846 // combat:setCallback(key, function)
11847 Combat *combat = getUserdata<Combat>(L, 1);
11848 if (!combat) {
11849 lua_pushnil(L);
11850 return 1;
11851 }
11852
11853 CallBackParam_t key = getNumber<CallBackParam_t>(L, 2);
11854 if (!combat->setCallback(key)) {
11855 lua_pushnil(L);
11856 return 1;
11857 }
11858
11859 CallBack *callback = combat->getCallback(key);
11860 if (!callback) {
11861 lua_pushnil(L);
11862 return 1;
11863 }
11864
11865 const std::string &function = getString(L, 3);
11866 pushBoolean(L, callback->loadCallBack(getScriptEnv()->getScriptInterface(),
11867 function));
11868 return 1;
11869}
11870
11871int LuaScriptInterface::luaCombatSetOrigin(lua_State *L) {
11872 // combat:setOrigin(origin)
11873 Combat *combat = getUserdata<Combat>(L, 1);
11874 if (combat) {
11875 combat->setOrigin(getNumber<CombatOrigin>(L, 2));
11876 pushBoolean(L, true);
11877 } else {
11878 lua_pushnil(L);
11879 }
11880 return 1;
11881}
11882
11883int LuaScriptInterface::luaCombatExecute(lua_State *L) {
11884 // combat:execute(creature, variant)
11885 Combat *combat = getUserdata<Combat>(L, 1);
11886 if (!combat) {
11887 pushBoolean(L, false);
11888 return 1;
11889 }
11890
11891 if (isUserdata(L, 2)) {
11892 LuaDataType type = getUserdataType(L, 2);
11893 if (type != LuaData_Player && type != LuaData_Monster &&
11894 type != LuaData_Npc) {
11895 pushBoolean(L, false);
11896 return 1;
11897 }
11898 }
11899
11900 Creature *creature = getCreature(L, 2);
11901
11902 const LuaVariant &variant = getVariant(L, 3);
11903 switch (variant.type) {
11904 case VARIANT_NUMBER: {
11905 Creature *target = g_game.getCreatureByID(variant.number);
11906 if (!target) {
11907 pushBoolean(L, false);
11908 return 1;
11909 }
11910
11911 if (combat->hasArea()) {
11912 combat->doCombat(creature, target->getPosition());
11913 } else {
11914 combat->doCombat(creature, target);
11915 }
11916 break;
11917 }
11918
11919 case VARIANT_POSITION: {
11920 combat->doCombat(creature, variant.pos);
11921 break;
11922 }
11923
11924 case VARIANT_TARGETPOSITION: {
11925 if (combat->hasArea()) {
11926 combat->doCombat(creature, variant.pos);
11927 } else {
11928 combat->postCombatEffects(creature, variant.pos);
11929 g_game.addMagicEffect(variant.pos, CONST_ME_POFF);
11930 }
11931 break;
11932 }
11933
11934 case VARIANT_STRING: {
11935 Player *target = g_game.getPlayerByName(variant.text);
11936 if (!target) {
11937 pushBoolean(L, false);
11938 return 1;
11939 }
11940
11941 combat->doCombat(creature, target);
11942 break;
11943 }
11944
11945 case VARIANT_NONE: {
11946 reportErrorFunc(getErrorDesc(LUA_ERROR_VARIANT_NOT_FOUND));
11947 pushBoolean(L, false);
11948 return 1;
11949 }
11950
11951 default: {
11952 break;
11953 }
11954 }
11955
11956 pushBoolean(L, true);
11957 return 1;
11958}
11959
11960// Condition
11961int LuaScriptInterface::luaConditionCreate(lua_State *L) {
11962 // Condition(conditionType[, conditionId = CONDITIONID_COMBAT])
11963 ConditionType_t conditionType = getNumber<ConditionType_t>(L, 2);
11964 ConditionId_t conditionId =
11965 getNumber<ConditionId_t>(L, 3, CONDITIONID_COMBAT);
11966
11967 Condition *condition =
11968 Condition::createCondition(conditionId, conditionType, 0, 0);
11969 if (condition) {
11970 pushUserdata<Condition>(L, condition);
11971 setMetatable(L, -1, "Condition");
11972 } else {
11973 lua_pushnil(L);
11974 }
11975 return 1;
11976}
11977
11978int LuaScriptInterface::luaConditionDelete(lua_State *L) {
11979 // condition:delete()
11980 Condition **conditionPtr = getRawUserdata<Condition>(L, 1);
11981 if (conditionPtr && *conditionPtr) {
11982 delete *conditionPtr;
11983 *conditionPtr = nullptr;
11984 }
11985 return 0;
11986}
11987
11988int LuaScriptInterface::luaConditionGetId(lua_State *L) {
11989 // condition:getId()
11990 Condition *condition = getUserdata<Condition>(L, 1);
11991 if (condition) {
11992 lua_pushnumber(L, condition->getId());
11993 } else {
11994 lua_pushnil(L);
11995 }
11996 return 1;
11997}
11998
11999int LuaScriptInterface::luaConditionGetSubId(lua_State *L) {
12000 // condition:getSubId()
12001 Condition *condition = getUserdata<Condition>(L, 1);
12002 if (condition) {
12003 lua_pushnumber(L, condition->getSubId());
12004 } else {
12005 lua_pushnil(L);
12006 }
12007 return 1;
12008}
12009
12010int LuaScriptInterface::luaConditionGetType(lua_State *L) {
12011 // condition:getType()
12012 Condition *condition = getUserdata<Condition>(L, 1);
12013 if (condition) {
12014 lua_pushnumber(L, condition->getType());
12015 } else {
12016 lua_pushnil(L);
12017 }
12018 return 1;
12019}
12020
12021int LuaScriptInterface::luaConditionGetIcons(lua_State *L) {
12022 // condition:getIcons()
12023 Condition *condition = getUserdata<Condition>(L, 1);
12024 if (condition) {
12025 lua_pushnumber(L, condition->getIcons());
12026 } else {
12027 lua_pushnil(L);
12028 }
12029 return 1;
12030}
12031
12032int LuaScriptInterface::luaConditionGetEndTime(lua_State *L) {
12033 // condition:getEndTime()
12034 Condition *condition = getUserdata<Condition>(L, 1);
12035 if (condition) {
12036 lua_pushnumber(L, condition->getEndTime());
12037 } else {
12038 lua_pushnil(L);
12039 }
12040 return 1;
12041}
12042
12043int LuaScriptInterface::luaConditionClone(lua_State *L) {
12044 // condition:clone()
12045 Condition *condition = getUserdata<Condition>(L, 1);
12046 if (condition) {
12047 pushUserdata<Condition>(L, condition->clone());
12048 setMetatable(L, -1, "Condition");
12049 } else {
12050 lua_pushnil(L);
12051 }
12052 return 1;
12053}
12054
12055int LuaScriptInterface::luaConditionGetTicks(lua_State *L) {
12056 // condition:getTicks()
12057 Condition *condition = getUserdata<Condition>(L, 1);
12058 if (condition) {
12059 lua_pushnumber(L, condition->getTicks());
12060 } else {
12061 lua_pushnil(L);
12062 }
12063 return 1;
12064}
12065
12066int LuaScriptInterface::luaConditionSetTicks(lua_State *L) {
12067 // condition:setTicks(ticks)
12068 int32_t ticks = getNumber<int32_t>(L, 2);
12069 Condition *condition = getUserdata<Condition>(L, 1);
12070 if (condition) {
12071 condition->setTicks(ticks);
12072 pushBoolean(L, true);
12073 } else {
12074 lua_pushnil(L);
12075 }
12076 return 1;
12077}
12078
12079int LuaScriptInterface::luaConditionSetParameter(lua_State *L) {
12080 // condition:setParameter(key, value)
12081 Condition *condition = getUserdata<Condition>(L, 1);
12082 if (!condition) {
12083 lua_pushnil(L);
12084 return 1;
12085 }
12086
12087 ConditionParam_t key = getNumber<ConditionParam_t>(L, 2);
12088 int32_t value;
12089 if (isBoolean(L, 3)) {
12090 value = getBoolean(L, 3) ? 1 : 0;
12091 } else {
12092 value = getNumber<int32_t>(L, 3);
12093 }
12094 condition->setParam(key, value);
12095 pushBoolean(L, true);
12096 return 1;
12097}
12098
12099int LuaScriptInterface::luaConditionSetFormula(lua_State *L) {
12100 // condition:setFormula(mina, minb, maxa, maxb)
12101 double maxb = getNumber<double>(L, 5);
12102 double maxa = getNumber<double>(L, 4);
12103 double minb = getNumber<double>(L, 3);
12104 double mina = getNumber<double>(L, 2);
12105 ConditionSpeed *condition =
12106 dynamic_cast<ConditionSpeed *>(getUserdata<Condition>(L, 1));
12107 if (condition) {
12108 condition->setFormulaVars(mina, minb, maxa, maxb);
12109 pushBoolean(L, true);
12110 } else {
12111 lua_pushnil(L);
12112 }
12113 return 1;
12114}
12115
12116int LuaScriptInterface::luaConditionSetOutfit(lua_State *L) {
12117 // condition:setOutfit(outfit)
12118 // condition:setOutfit(lookTypeEx, lookType, lookHead, lookBody, lookLegs,
12119 // lookFeet[, lookAddons[, lookMount, lookWings, lookAura, lookShader]])
12120 Outfit_t outfit;
12121 if (isTable(L, 2)) {
12122 outfit = getOutfit(L, 2);
12123 } else {
12124 outfit.lookShader = getNumber<uint16_t>(L, 12, outfit.lookShader);
12125 outfit.lookAura = getNumber<uint16_t>(L, 11, outfit.lookAura);
12126 outfit.lookWings = getNumber<uint16_t>(L, 10, outfit.lookWings);
12127 outfit.lookMount = getNumber<uint16_t>(L, 9, outfit.lookMount);
12128 outfit.lookAddons = getNumber<uint8_t>(L, 8, outfit.lookAddons);
12129 outfit.lookFeet = getNumber<uint8_t>(L, 7);
12130 outfit.lookLegs = getNumber<uint8_t>(L, 6);
12131 outfit.lookBody = getNumber<uint8_t>(L, 5);
12132 outfit.lookHead = getNumber<uint8_t>(L, 4);
12133 outfit.lookType = getNumber<uint16_t>(L, 3);
12134 outfit.lookTypeEx = getNumber<uint16_t>(L, 2);
12135 }
12136
12137 ConditionOutfit *condition =
12138 dynamic_cast<ConditionOutfit *>(getUserdata<Condition>(L, 1));
12139 if (condition) {
12140 condition->setOutfit(outfit);
12141 pushBoolean(L, true);
12142 } else {
12143 lua_pushnil(L);
12144 }
12145 return 1;
12146}
12147
12148int LuaScriptInterface::luaConditionAddDamage(lua_State *L) {
12149 // condition:addDamage(rounds, time, value)
12150 int32_t value = getNumber<int32_t>(L, 4);
12151 int32_t time = getNumber<int32_t>(L, 3);
12152 int32_t rounds = getNumber<int32_t>(L, 2);
12153 ConditionDamage *condition =
12154 dynamic_cast<ConditionDamage *>(getUserdata<Condition>(L, 1));
12155 if (condition) {
12156 pushBoolean(L, condition->addDamage(rounds, time, value));
12157 } else {
12158 lua_pushnil(L);
12159 }
12160 return 1;
12161}
12162
12163// MonsterType
12164int LuaScriptInterface::luaMonsterTypeCreate(lua_State *L) {
12165 // MonsterType(name)
12166 MonsterType *monsterType = g_monsters.getMonsterType(getString(L, 2));
12167 if (monsterType) {
12168 pushUserdata<MonsterType>(L, monsterType);
12169 setMetatable(L, -1, "MonsterType");
12170 } else {
12171 lua_pushnil(L);
12172 }
12173 return 1;
12174}
12175
12176int LuaScriptInterface::luaMonsterTypeIsAttackable(lua_State *L) {
12177 // get: monsterType:isAttackable() set: monsterType:isAttackable(bool)
12178 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12179 if (monsterType) {
12180 if (lua_gettop(L) == 1) {
12181 pushBoolean(L, monsterType->info.isAttackable);
12182 } else {
12183 monsterType->info.isAttackable = getBoolean(L, 2);
12184 pushBoolean(L, true);
12185 }
12186 } else {
12187 lua_pushnil(L);
12188 }
12189 return 1;
12190}
12191
12192int LuaScriptInterface::luaMonsterTypeIsConvinceable(lua_State *L) {
12193 // get: monsterType:isConvinceable() set: monsterType:isConvinceable(bool)
12194 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12195 if (monsterType) {
12196 if (lua_gettop(L) == 1) {
12197 pushBoolean(L, monsterType->info.isConvinceable);
12198 } else {
12199 monsterType->info.isConvinceable = getBoolean(L, 2);
12200 pushBoolean(L, true);
12201 }
12202 } else {
12203 lua_pushnil(L);
12204 }
12205 return 1;
12206}
12207
12208int LuaScriptInterface::luaMonsterTypeIsSummonable(lua_State *L) {
12209 // get: monsterType:isSummonable() set: monsterType:isSummonable(bool)
12210 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12211 if (monsterType) {
12212 if (lua_gettop(L) == 1) {
12213 pushBoolean(L, monsterType->info.isSummonable);
12214 } else {
12215 monsterType->info.isSummonable = getBoolean(L, 2);
12216 pushBoolean(L, true);
12217 }
12218 } else {
12219 lua_pushnil(L);
12220 }
12221 return 1;
12222}
12223
12224int LuaScriptInterface::luaMonsterTypeIsIllusionable(lua_State *L) {
12225 // get: monsterType:isIllusionable() set: monsterType:isIllusionable(bool)
12226 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12227 if (monsterType) {
12228 if (lua_gettop(L) == 1) {
12229 pushBoolean(L, monsterType->info.isIllusionable);
12230 } else {
12231 monsterType->info.isIllusionable = getBoolean(L, 2);
12232 pushBoolean(L, true);
12233 }
12234 } else {
12235 lua_pushnil(L);
12236 }
12237 return 1;
12238}
12239
12240int LuaScriptInterface::luaMonsterTypeIsHostile(lua_State *L) {
12241 // get: monsterType:isHostile() set: monsterType:isHostile(bool)
12242 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12243 if (monsterType) {
12244 if (lua_gettop(L) == 1) {
12245 pushBoolean(L, monsterType->info.isHostile);
12246 } else {
12247 monsterType->info.isHostile = getBoolean(L, 2);
12248 pushBoolean(L, true);
12249 }
12250 } else {
12251 lua_pushnil(L);
12252 }
12253 return 1;
12254}
12255
12256int LuaScriptInterface::luaMonsterTypeIsPushable(lua_State *L) {
12257 // get: monsterType:isPushable() set: monsterType:isPushable(bool)
12258 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12259 if (monsterType) {
12260 if (lua_gettop(L) == 1) {
12261 pushBoolean(L, monsterType->info.pushable);
12262 } else {
12263 monsterType->info.pushable = getBoolean(L, 2);
12264 pushBoolean(L, true);
12265 }
12266 } else {
12267 lua_pushnil(L);
12268 }
12269 return 1;
12270}
12271
12272int LuaScriptInterface::luaMonsterTypeIsHealthHidden(lua_State *L) {
12273 // get: monsterType:isHealthHidden() set: monsterType:isHealthHidden(bool)
12274 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12275 if (monsterType) {
12276 if (lua_gettop(L) == 1) {
12277 pushBoolean(L, monsterType->info.hiddenHealth);
12278 } else {
12279 monsterType->info.hiddenHealth = getBoolean(L, 2);
12280 pushBoolean(L, true);
12281 }
12282 } else {
12283 lua_pushnil(L);
12284 }
12285 return 1;
12286}
12287
12288int LuaScriptInterface::luaMonsterTypeIsBoss(lua_State *L) {
12289 // get: monsterType:isBoss() set: monsterType:isBoss(bool)
12290 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12291 if (monsterType) {
12292 if (lua_gettop(L) == 1) {
12293 pushBoolean(L, monsterType->info.isBoss);
12294 } else {
12295 monsterType->info.isBoss = getBoolean(L, 2);
12296 pushBoolean(L, true);
12297 }
12298 } else {
12299 lua_pushnil(L);
12300 }
12301 return 1;
12302}
12303
12304int LuaScriptInterface::luaMonsterTypeCanPushItems(lua_State *L) {
12305 // get: monsterType:canPushItems() set: monsterType:canPushItems(bool)
12306 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12307 if (monsterType) {
12308 if (lua_gettop(L) == 1) {
12309 pushBoolean(L, monsterType->info.canPushItems);
12310 } else {
12311 monsterType->info.canPushItems = getBoolean(L, 2);
12312 pushBoolean(L, true);
12313 }
12314 } else {
12315 lua_pushnil(L);
12316 }
12317 return 1;
12318}
12319
12320int LuaScriptInterface::luaMonsterTypeCanPushCreatures(lua_State *L) {
12321 // get: monsterType:canPushCreatures() set: monsterType:canPushCreatures(bool)
12322 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12323 if (monsterType) {
12324 if (lua_gettop(L) == 1) {
12325 pushBoolean(L, monsterType->info.canPushCreatures);
12326 } else {
12327 monsterType->info.canPushCreatures = getBoolean(L, 2);
12328 pushBoolean(L, true);
12329 }
12330 } else {
12331 lua_pushnil(L);
12332 }
12333 return 1;
12334}
12335
12336int32_t LuaScriptInterface::luaMonsterTypeName(lua_State *L) {
12337 // get: monsterType:name() set: monsterType:name(name)
12338 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12339 if (monsterType) {
12340 if (lua_gettop(L) == 1) {
12341 pushString(L, monsterType->name);
12342 } else {
12343 monsterType->name = getString(L, 2);
12344 pushBoolean(L, true);
12345 }
12346 } else {
12347 lua_pushnil(L);
12348 }
12349 return 1;
12350}
12351
12352int LuaScriptInterface::luaMonsterTypeNameDescription(lua_State *L) {
12353 // get: monsterType:nameDescription() set: monsterType:nameDescription(desc)
12354 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12355 if (monsterType) {
12356 if (lua_gettop(L) == 1) {
12357 pushString(L, monsterType->nameDescription);
12358 } else {
12359 monsterType->nameDescription = getString(L, 2);
12360 pushBoolean(L, true);
12361 }
12362 } else {
12363 lua_pushnil(L);
12364 }
12365 return 1;
12366}
12367
12368int LuaScriptInterface::luaMonsterTypeHealth(lua_State *L) {
12369 // get: monsterType:health() set: monsterType:health(health)
12370 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12371 if (monsterType) {
12372 if (lua_gettop(L) == 1) {
12373 lua_pushnumber(L, monsterType->info.health);
12374 } else {
12375 monsterType->info.health = getNumber<int32_t>(L, 2);
12376 pushBoolean(L, true);
12377 }
12378 } else {
12379 lua_pushnil(L);
12380 }
12381 return 1;
12382}
12383
12384int LuaScriptInterface::luaMonsterTypeMaxHealth(lua_State *L) {
12385 // get: monsterType:maxHealth() set: monsterType:maxHealth(health)
12386 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12387 if (monsterType) {
12388 if (lua_gettop(L) == 1) {
12389 lua_pushnumber(L, monsterType->info.healthMax);
12390 } else {
12391 monsterType->info.healthMax = getNumber<int32_t>(L, 2);
12392 pushBoolean(L, true);
12393 }
12394 } else {
12395 lua_pushnil(L);
12396 }
12397 return 1;
12398}
12399
12400int LuaScriptInterface::luaMonsterTypeRunHealth(lua_State *L) {
12401 // get: monsterType:runHealth() set: monsterType:runHealth(health)
12402 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12403 if (monsterType) {
12404 if (lua_gettop(L) == 1) {
12405 lua_pushnumber(L, monsterType->info.runAwayHealth);
12406 } else {
12407 monsterType->info.runAwayHealth = getNumber<int32_t>(L, 2);
12408 pushBoolean(L, true);
12409 }
12410 } else {
12411 lua_pushnil(L);
12412 }
12413 return 1;
12414}
12415
12416int LuaScriptInterface::luaMonsterTypeExperience(lua_State *L) {
12417 // get: monsterType:experience() set: monsterType:experience(exp)
12418 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12419 if (monsterType) {
12420 if (lua_gettop(L) == 1) {
12421 lua_pushnumber(L, monsterType->info.experience);
12422 } else {
12423 monsterType->info.experience = getNumber<uint64_t>(L, 2);
12424 pushBoolean(L, true);
12425 }
12426 } else {
12427 lua_pushnil(L);
12428 }
12429 return 1;
12430}
12431
12432int LuaScriptInterface::luaMonsterTypeSkull(lua_State *L) {
12433 // get: monsterType:skull() set: monsterType:skull(str/constant)
12434 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12435 if (monsterType) {
12436 if (lua_gettop(L) == 1) {
12437 lua_pushnumber(L, monsterType->info.skull);
12438 } else {
12439 if (isNumber(L, 2)) {
12440 monsterType->info.skull = getNumber<Skulls_t>(L, 2);
12441 } else {
12442 monsterType->info.skull = getSkullType(getString(L, 2));
12443 }
12444 pushBoolean(L, true);
12445 }
12446 } else {
12447 lua_pushnil(L);
12448 }
12449 return 1;
12450}
12451
12452int LuaScriptInterface::luaMonsterTypeCombatImmunities(lua_State *L) {
12453 // get: monsterType:combatImmunities() set:
12454 // monsterType:combatImmunities(immunity)
12455 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12456 if (monsterType) {
12457 if (lua_gettop(L) == 1) {
12458 lua_pushnumber(L, monsterType->info.damageImmunities);
12459 } else {
12460 std::string immunity = getString(L, 2);
12461 if (immunity == "physical") {
12462 monsterType->info.damageImmunities |= COMBAT_PHYSICALDAMAGE;
12463 pushBoolean(L, true);
12464 } else if (immunity == "energy") {
12465 monsterType->info.damageImmunities |= COMBAT_ENERGYDAMAGE;
12466 pushBoolean(L, true);
12467 } else if (immunity == "fire") {
12468 monsterType->info.damageImmunities |= COMBAT_FIREDAMAGE;
12469 pushBoolean(L, true);
12470 } else if (immunity == "poison" || immunity == "earth") {
12471 monsterType->info.damageImmunities |= COMBAT_EARTHDAMAGE;
12472 pushBoolean(L, true);
12473 } else if (immunity == "drown") {
12474 monsterType->info.damageImmunities |= COMBAT_DROWNDAMAGE;
12475 pushBoolean(L, true);
12476 } else if (immunity == "ice") {
12477 monsterType->info.damageImmunities |= COMBAT_ICEDAMAGE;
12478 pushBoolean(L, true);
12479 } else if (immunity == "holy") {
12480 monsterType->info.damageImmunities |= COMBAT_HOLYDAMAGE;
12481 pushBoolean(L, true);
12482 } else if (immunity == "death") {
12483 monsterType->info.damageImmunities |= COMBAT_DEATHDAMAGE;
12484 pushBoolean(L, true);
12485 } else if (immunity == "lifedrain") {
12486 monsterType->info.damageImmunities |= COMBAT_LIFEDRAIN;
12487 pushBoolean(L, true);
12488 } else if (immunity == "manadrain") {
12489 monsterType->info.damageImmunities |= COMBAT_MANADRAIN;
12490 pushBoolean(L, true);
12491 } else {
12492 std::cout << "[Warning - Monsters::loadMonster] Unknown immunity name "
12493 << immunity << " for monster: " << monsterType->name
12494 << std::endl;
12495 lua_pushnil(L);
12496 }
12497 }
12498 } else {
12499 lua_pushnil(L);
12500 }
12501 return 1;
12502}
12503
12504int LuaScriptInterface::luaMonsterTypeConditionImmunities(lua_State *L) {
12505 // get: monsterType:conditionImmunities() set:
12506 // monsterType:conditionImmunities(immunity)
12507 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12508 if (monsterType) {
12509 if (lua_gettop(L) == 1) {
12510 lua_pushnumber(L, monsterType->info.conditionImmunities);
12511 } else {
12512 std::string immunity = getString(L, 2);
12513 if (immunity == "physical") {
12514 monsterType->info.conditionImmunities |= CONDITION_BLEEDING;
12515 pushBoolean(L, true);
12516 } else if (immunity == "energy") {
12517 monsterType->info.conditionImmunities |= CONDITION_ENERGY;
12518 pushBoolean(L, true);
12519 } else if (immunity == "fire") {
12520 monsterType->info.conditionImmunities |= CONDITION_FIRE;
12521 pushBoolean(L, true);
12522 } else if (immunity == "poison" || immunity == "earth") {
12523 monsterType->info.conditionImmunities |= CONDITION_POISON;
12524 pushBoolean(L, true);
12525 } else if (immunity == "drown") {
12526 monsterType->info.conditionImmunities |= CONDITION_DROWN;
12527 pushBoolean(L, true);
12528 } else if (immunity == "ice") {
12529 monsterType->info.conditionImmunities |= CONDITION_FREEZING;
12530 pushBoolean(L, true);
12531 } else if (immunity == "holy") {
12532 monsterType->info.conditionImmunities |= CONDITION_DAZZLED;
12533 pushBoolean(L, true);
12534 } else if (immunity == "death") {
12535 monsterType->info.conditionImmunities |= CONDITION_CURSED;
12536 pushBoolean(L, true);
12537 } else if (immunity == "paralyze") {
12538 monsterType->info.conditionImmunities |= CONDITION_PARALYZE;
12539 pushBoolean(L, true);
12540 } else if (immunity == "outfit") {
12541 monsterType->info.conditionImmunities |= CONDITION_OUTFIT;
12542 pushBoolean(L, true);
12543 } else if (immunity == "drunk") {
12544 monsterType->info.conditionImmunities |= CONDITION_DRUNK;
12545 pushBoolean(L, true);
12546 } else if (immunity == "invisible" || immunity == "invisibility") {
12547 monsterType->info.conditionImmunities |= CONDITION_INVISIBLE;
12548 pushBoolean(L, true);
12549 } else if (immunity == "bleed") {
12550 monsterType->info.conditionImmunities |= CONDITION_BLEEDING;
12551 pushBoolean(L, true);
12552 } else {
12553 std::cout << "[Warning - Monsters::loadMonster] Unknown immunity name "
12554 << immunity << " for monster: " << monsterType->name
12555 << std::endl;
12556 lua_pushnil(L);
12557 }
12558 }
12559 } else {
12560 lua_pushnil(L);
12561 }
12562 return 1;
12563}
12564
12565int LuaScriptInterface::luaMonsterTypeGetAttackList(lua_State *L) {
12566 // monsterType:getAttackList()
12567 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12568 if (!monsterType) {
12569 lua_pushnil(L);
12570 return 1;
12571 }
12572
12573 lua_createtable(L, monsterType->info.attackSpells.size(), 0);
12574
12575 int index = 0;
12576 for (const auto &spellBlock : monsterType->info.attackSpells) {
12577 lua_createtable(L, 0, 8);
12578
12579 setField(L, "chance", spellBlock.chance);
12580 setField(L, "isCombatSpell", spellBlock.combatSpell ? 1 : 0);
12581 setField(L, "isMelee", spellBlock.isMelee ? 1 : 0);
12582 setField(L, "minCombatValue", spellBlock.minCombatValue);
12583 setField(L, "maxCombatValue", spellBlock.maxCombatValue);
12584 setField(L, "range", spellBlock.range);
12585 setField(L, "speed", spellBlock.speed);
12586 pushUserdata<CombatSpell>(L, static_cast<CombatSpell *>(spellBlock.spell));
12587 lua_setfield(L, -2, "spell");
12588
12589 lua_rawseti(L, -2, ++index);
12590 }
12591 return 1;
12592}
12593
12594int LuaScriptInterface::luaMonsterTypeAddAttack(lua_State *L) {
12595 // monsterType:addAttack(monsterspell)
12596 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12597 if (monsterType) {
12598 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 2);
12599 if (spell) {
12600 spellBlock_t sb;
12601 if (g_monsters.deserializeSpell(spell, sb, monsterType->name)) {
12602 monsterType->info.attackSpells.push_back(std::move(sb));
12603 } else {
12604 std::cout << monsterType->name << std::endl;
12605 std::cout << "[Warning - Monsters::loadMonster] Cant load spell. "
12606 << spell->name << std::endl;
12607 }
12608 } else {
12609 lua_pushnil(L);
12610 }
12611 } else {
12612 lua_pushnil(L);
12613 }
12614 return 1;
12615}
12616
12617int LuaScriptInterface::luaMonsterTypeGetDefenseList(lua_State *L) {
12618 // monsterType:getDefenseList()
12619 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12620 if (!monsterType) {
12621 lua_pushnil(L);
12622 return 1;
12623 }
12624
12625 lua_createtable(L, monsterType->info.defenseSpells.size(), 0);
12626
12627 int index = 0;
12628 for (const auto &spellBlock : monsterType->info.defenseSpells) {
12629 lua_createtable(L, 0, 8);
12630
12631 setField(L, "chance", spellBlock.chance);
12632 setField(L, "isCombatSpell", spellBlock.combatSpell ? 1 : 0);
12633 setField(L, "isMelee", spellBlock.isMelee ? 1 : 0);
12634 setField(L, "minCombatValue", spellBlock.minCombatValue);
12635 setField(L, "maxCombatValue", spellBlock.maxCombatValue);
12636 setField(L, "range", spellBlock.range);
12637 setField(L, "speed", spellBlock.speed);
12638 pushUserdata<CombatSpell>(L, static_cast<CombatSpell *>(spellBlock.spell));
12639 lua_setfield(L, -2, "spell");
12640
12641 lua_rawseti(L, -2, ++index);
12642 }
12643 return 1;
12644}
12645
12646int LuaScriptInterface::luaMonsterTypeAddDefense(lua_State *L) {
12647 // monsterType:addDefense(monsterspell)
12648 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12649 if (monsterType) {
12650 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 2);
12651 if (spell) {
12652 spellBlock_t sb;
12653 if (g_monsters.deserializeSpell(spell, sb, monsterType->name)) {
12654 monsterType->info.defenseSpells.push_back(std::move(sb));
12655 } else {
12656 std::cout << monsterType->name << std::endl;
12657 std::cout << "[Warning - Monsters::loadMonster] Cant load spell. "
12658 << spell->name << std::endl;
12659 }
12660 } else {
12661 lua_pushnil(L);
12662 }
12663 } else {
12664 lua_pushnil(L);
12665 }
12666 return 1;
12667}
12668
12669int LuaScriptInterface::luaMonsterTypeGetElementList(lua_State *L) {
12670 // monsterType:getElementList()
12671 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12672 if (!monsterType) {
12673 lua_pushnil(L);
12674 return 1;
12675 }
12676
12677 lua_createtable(L, monsterType->info.elementMap.size(), 0);
12678 for (const auto &elementEntry : monsterType->info.elementMap) {
12679 lua_pushnumber(L, elementEntry.second);
12680 lua_rawseti(L, -2, elementEntry.first);
12681 }
12682 return 1;
12683}
12684
12685int LuaScriptInterface::luaMonsterTypeAddElement(lua_State *L) {
12686 // monsterType:addElement(type, percent)
12687 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12688 if (monsterType) {
12689 CombatType_t element = getNumber<CombatType_t>(L, 2);
12690 monsterType->info.elementMap[element] = getNumber<int32_t>(L, 3);
12691 pushBoolean(L, true);
12692 } else {
12693 lua_pushnil(L);
12694 }
12695 return 1;
12696}
12697
12698int LuaScriptInterface::luaMonsterTypeGetVoices(lua_State *L) {
12699 // monsterType:getVoices()
12700 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12701 if (!monsterType) {
12702 lua_pushnil(L);
12703 return 1;
12704 }
12705
12706 int index = 0;
12707 lua_createtable(L, monsterType->info.voiceVector.size(), 0);
12708 for (const auto &voiceBlock : monsterType->info.voiceVector) {
12709 lua_createtable(L, 0, 2);
12710 setField(L, "text", voiceBlock.text);
12711 setField(L, "yellText", voiceBlock.yellText);
12712 lua_rawseti(L, -2, ++index);
12713 }
12714 return 1;
12715}
12716
12717int LuaScriptInterface::luaMonsterTypeAddVoice(lua_State *L) {
12718 // monsterType:addVoice(sentence, interval, chance, yell)
12719 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12720 if (monsterType) {
12721 voiceBlock_t voice;
12722 voice.text = getString(L, 2);
12723 monsterType->info.yellSpeedTicks = getNumber<uint32_t>(L, 3);
12724 monsterType->info.yellChance = getNumber<uint32_t>(L, 4);
12725 voice.yellText = getBoolean(L, 5);
12726 monsterType->info.voiceVector.push_back(voice);
12727 pushBoolean(L, true);
12728 } else {
12729 lua_pushnil(L);
12730 }
12731 return 1;
12732}
12733
12734int LuaScriptInterface::luaMonsterTypeGetLoot(lua_State *L) {
12735 // monsterType:getLoot()
12736 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12737 if (!monsterType) {
12738 lua_pushnil(L);
12739 return 1;
12740 }
12741
12742 pushLoot(L, monsterType->info.lootItems);
12743 return 1;
12744}
12745
12746int LuaScriptInterface::luaMonsterTypeAddLoot(lua_State *L) {
12747 // monsterType:addLoot(loot)
12748 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12749 if (monsterType) {
12750 Loot *loot = getUserdata<Loot>(L, 2);
12751 if (loot) {
12752 monsterType->loadLoot(monsterType, loot->lootBlock);
12753 pushBoolean(L, true);
12754 } else {
12755 lua_pushnil(L);
12756 }
12757 } else {
12758 lua_pushnil(L);
12759 }
12760 return 1;
12761}
12762
12763int LuaScriptInterface::luaMonsterTypeGetCreatureEvents(lua_State *L) {
12764 // monsterType:getCreatureEvents()
12765 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12766 if (!monsterType) {
12767 lua_pushnil(L);
12768 return 1;
12769 }
12770
12771 int index = 0;
12772 lua_createtable(L, monsterType->info.scripts.size(), 0);
12773 for (const std::string &creatureEvent : monsterType->info.scripts) {
12774 pushString(L, creatureEvent);
12775 lua_rawseti(L, -2, ++index);
12776 }
12777 return 1;
12778}
12779
12780int LuaScriptInterface::luaMonsterTypeRegisterEvent(lua_State *L) {
12781 // monsterType:registerEvent(name)
12782 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12783 if (monsterType) {
12784 monsterType->info.scripts.push_back(getString(L, 2));
12785 pushBoolean(L, true);
12786 } else {
12787 lua_pushnil(L);
12788 }
12789 return 1;
12790}
12791
12792int LuaScriptInterface::luaMonsterTypeEventOnCallback(lua_State *L) {
12793 // monsterType:onThink(callback)
12794 // monsterType:onAppear(callback)
12795 // monsterType:onDisappear(callback)
12796 // monsterType:onMove(callback)
12797 // monsterType:onSay(callback)
12798 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12799 if (monsterType) {
12800 if (monsterType->loadCallback(&g_scripts->getScriptInterface())) {
12801 pushBoolean(L, true);
12802 return 1;
12803 }
12804 pushBoolean(L, false);
12805 } else {
12806 lua_pushnil(L);
12807 }
12808 return 1;
12809}
12810
12811int LuaScriptInterface::luaMonsterTypeEventType(lua_State *L) {
12812 // monstertype:eventType(event)
12813 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12814 if (monsterType) {
12815 monsterType->info.eventType = getNumber<MonstersEvent_t>(L, 2);
12816 pushBoolean(L, true);
12817 } else {
12818 lua_pushnil(L);
12819 }
12820 return 1;
12821}
12822
12823int LuaScriptInterface::luaMonsterTypeGetSummonList(lua_State *L) {
12824 // monsterType:getSummonList()
12825 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12826 if (!monsterType) {
12827 lua_pushnil(L);
12828 return 1;
12829 }
12830
12831 int index = 0;
12832 lua_createtable(L, monsterType->info.summons.size(), 0);
12833 for (const auto &summonBlock : monsterType->info.summons) {
12834 lua_createtable(L, 0, 3);
12835 setField(L, "name", summonBlock.name);
12836 setField(L, "speed", summonBlock.speed);
12837 setField(L, "chance", summonBlock.chance);
12838 lua_rawseti(L, -2, ++index);
12839 }
12840 return 1;
12841}
12842
12843int LuaScriptInterface::luaMonsterTypeAddSummon(lua_State *L) {
12844 // monsterType:addSummon(name, interval, chance)
12845 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12846 if (monsterType) {
12847 summonBlock_t summon;
12848 summon.name = getString(L, 2);
12849 summon.chance = getNumber<int32_t>(L, 3);
12850 summon.speed = getNumber<int32_t>(L, 4);
12851 monsterType->info.summons.push_back(summon);
12852 pushBoolean(L, true);
12853 } else {
12854 lua_pushnil(L);
12855 }
12856 return 1;
12857}
12858
12859int LuaScriptInterface::luaMonsterTypeMaxSummons(lua_State *L) {
12860 // get: monsterType:maxSummons() set: monsterType:maxSummons(ammount)
12861 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12862 if (monsterType) {
12863 if (lua_gettop(L) == 1) {
12864 lua_pushnumber(L, monsterType->info.maxSummons);
12865 } else {
12866 monsterType->info.maxSummons = getNumber<uint32_t>(L, 2);
12867 pushBoolean(L, true);
12868 }
12869 } else {
12870 lua_pushnil(L);
12871 }
12872 return 1;
12873}
12874
12875int LuaScriptInterface::luaMonsterTypeArmor(lua_State *L) {
12876 // get: monsterType:armor() set: monsterType:armor(armor)
12877 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12878 if (monsterType) {
12879 if (lua_gettop(L) == 1) {
12880 lua_pushnumber(L, monsterType->info.armor);
12881 } else {
12882 monsterType->info.armor = getNumber<int32_t>(L, 2);
12883 pushBoolean(L, true);
12884 }
12885 } else {
12886 lua_pushnil(L);
12887 }
12888 return 1;
12889}
12890
12891int LuaScriptInterface::luaMonsterTypeDefense(lua_State *L) {
12892 // get: monsterType:defense() set: monsterType:defense(defense)
12893 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12894 if (monsterType) {
12895 if (lua_gettop(L) == 1) {
12896 lua_pushnumber(L, monsterType->info.defense);
12897 } else {
12898 monsterType->info.defense = getNumber<int32_t>(L, 2);
12899 pushBoolean(L, true);
12900 }
12901 } else {
12902 lua_pushnil(L);
12903 }
12904 return 1;
12905}
12906
12907int LuaScriptInterface::luaMonsterTypeOutfit(lua_State *L) {
12908 // get: monsterType:outfit() set: monsterType:outfit(outfit)
12909 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12910 if (monsterType) {
12911 if (lua_gettop(L) == 1) {
12912 pushOutfit(L, monsterType->info.outfit);
12913 } else {
12914 monsterType->info.outfit = getOutfit(L, 2);
12915 pushBoolean(L, true);
12916 }
12917 } else {
12918 lua_pushnil(L);
12919 }
12920 return 1;
12921}
12922
12923int LuaScriptInterface::luaMonsterTypeRace(lua_State *L) {
12924 // get: monsterType:race() set: monsterType:race(race)
12925 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12926 std::string race = getString(L, 2);
12927 if (monsterType) {
12928 if (lua_gettop(L) == 1) {
12929 lua_pushnumber(L, monsterType->info.race);
12930 } else {
12931 if (race == "venom") {
12932 monsterType->info.race = RACE_VENOM;
12933 } else if (race == "blood") {
12934 monsterType->info.race = RACE_BLOOD;
12935 } else if (race == "undead") {
12936 monsterType->info.race = RACE_UNDEAD;
12937 } else if (race == "fire") {
12938 monsterType->info.race = RACE_FIRE;
12939 } else if (race == "energy") {
12940 monsterType->info.race = RACE_ENERGY;
12941 } else {
12942 std::cout << "[Warning - Monsters::loadMonster] Unknown race type "
12943 << race << "." << std::endl;
12944 lua_pushnil(L);
12945 return 1;
12946 }
12947 pushBoolean(L, true);
12948 }
12949 } else {
12950 lua_pushnil(L);
12951 }
12952 return 1;
12953}
12954
12955int LuaScriptInterface::luaMonsterTypeCorpseId(lua_State *L) {
12956 // get: monsterType:corpseId() set: monsterType:corpseId(id)
12957 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12958 if (monsterType) {
12959 if (lua_gettop(L) == 1) {
12960 lua_pushnumber(L, monsterType->info.lookcorpse);
12961 } else {
12962 monsterType->info.lookcorpse = getNumber<uint16_t>(L, 2);
12963 lua_pushboolean(L, true);
12964 }
12965 } else {
12966 lua_pushnil(L);
12967 }
12968 return 1;
12969}
12970
12971int LuaScriptInterface::luaMonsterTypeManaCost(lua_State *L) {
12972 // get: monsterType:manaCost() set: monsterType:manaCost(mana)
12973 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12974 if (monsterType) {
12975 if (lua_gettop(L) == 1) {
12976 lua_pushnumber(L, monsterType->info.manaCost);
12977 } else {
12978 monsterType->info.manaCost = getNumber<uint32_t>(L, 2);
12979 pushBoolean(L, true);
12980 }
12981 } else {
12982 lua_pushnil(L);
12983 }
12984 return 1;
12985}
12986
12987int LuaScriptInterface::luaMonsterTypeBaseSpeed(lua_State *L) {
12988 // get: monsterType:baseSpeed() set: monsterType:baseSpeed(speed)
12989 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
12990 if (monsterType) {
12991 if (lua_gettop(L) == 1) {
12992 lua_pushnumber(L, monsterType->info.baseSpeed);
12993 } else {
12994 monsterType->info.baseSpeed = getNumber<uint32_t>(L, 2);
12995 pushBoolean(L, true);
12996 }
12997 } else {
12998 lua_pushnil(L);
12999 }
13000 return 1;
13001}
13002
13003int LuaScriptInterface::luaMonsterTypeLight(lua_State *L) {
13004 // get: monsterType:light() set: monsterType:light(color, level)
13005 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
13006 if (!monsterType) {
13007 lua_pushnil(L);
13008 return 1;
13009 }
13010 if (lua_gettop(L) == 1) {
13011 lua_pushnumber(L, monsterType->info.light.level);
13012 lua_pushnumber(L, monsterType->info.light.color);
13013 return 2;
13014 } else {
13015 monsterType->info.light.color = getNumber<uint8_t>(L, 2);
13016 monsterType->info.light.level = getNumber<uint8_t>(L, 3);
13017 pushBoolean(L, true);
13018 }
13019 return 1;
13020}
13021
13022int LuaScriptInterface::luaMonsterTypeStaticAttackChance(lua_State *L) {
13023 // get: monsterType:staticAttackChance() set:
13024 // monsterType:staticAttackChance(chance)
13025 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
13026 if (monsterType) {
13027 if (lua_gettop(L) == 1) {
13028 lua_pushnumber(L, monsterType->info.staticAttackChance);
13029 } else {
13030 monsterType->info.staticAttackChance = getNumber<uint32_t>(L, 2);
13031 pushBoolean(L, true);
13032 }
13033 } else {
13034 lua_pushnil(L);
13035 }
13036 return 1;
13037}
13038
13039int LuaScriptInterface::luaMonsterTypeTargetDistance(lua_State *L) {
13040 // get: monsterType:targetDistance() set: monsterType:targetDistance(distance)
13041 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
13042 if (monsterType) {
13043 if (lua_gettop(L) == 1) {
13044 lua_pushnumber(L, monsterType->info.targetDistance);
13045 } else {
13046 monsterType->info.targetDistance = getNumber<int32_t>(L, 2);
13047 pushBoolean(L, true);
13048 }
13049 } else {
13050 lua_pushnil(L);
13051 }
13052 return 1;
13053}
13054
13055int LuaScriptInterface::luaMonsterTypeYellChance(lua_State *L) {
13056 // get: monsterType:yellChance() set: monsterType:yellChance(chance)
13057 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
13058 if (monsterType) {
13059 if (lua_gettop(L) == 1) {
13060 lua_pushnumber(L, monsterType->info.yellChance);
13061 } else {
13062 monsterType->info.yellChance = getNumber<uint32_t>(L, 2);
13063 pushBoolean(L, true);
13064 }
13065 } else {
13066 lua_pushnil(L);
13067 }
13068 return 1;
13069}
13070
13071int LuaScriptInterface::luaMonsterTypeYellSpeedTicks(lua_State *L) {
13072 // get: monsterType:yellSpeedTicks() set: monsterType:yellSpeedTicks(rate)
13073 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
13074 if (monsterType) {
13075 if (lua_gettop(L) == 1) {
13076 lua_pushnumber(L, monsterType->info.yellSpeedTicks);
13077 } else {
13078 monsterType->info.yellSpeedTicks = getNumber<uint32_t>(L, 2);
13079 pushBoolean(L, true);
13080 }
13081 } else {
13082 lua_pushnil(L);
13083 }
13084 return 1;
13085}
13086
13087int LuaScriptInterface::luaMonsterTypeChangeTargetChance(lua_State *L) {
13088 // get: monsterType:changeTargetChance() set:
13089 // monsterType:changeTargetChance(chance)
13090 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
13091 if (monsterType) {
13092 if (lua_gettop(L) == 1) {
13093 lua_pushnumber(L, monsterType->info.changeTargetChance);
13094 } else {
13095 monsterType->info.changeTargetChance = getNumber<int32_t>(L, 2);
13096 pushBoolean(L, true);
13097 }
13098 } else {
13099 lua_pushnil(L);
13100 }
13101 return 1;
13102}
13103
13104int LuaScriptInterface::luaMonsterTypeChangeTargetSpeed(lua_State *L) {
13105 // get: monsterType:changeTargetSpeed() set:
13106 // monsterType:changeTargetSpeed(speed)
13107 MonsterType *monsterType = getUserdata<MonsterType>(L, 1);
13108 if (monsterType) {
13109 if (lua_gettop(L) == 1) {
13110 lua_pushnumber(L, monsterType->info.changeTargetSpeed);
13111 } else {
13112 monsterType->info.changeTargetSpeed = getNumber<uint32_t>(L, 2);
13113 pushBoolean(L, true);
13114 }
13115 } else {
13116 lua_pushnil(L);
13117 }
13118 return 1;
13119}
13120
13121// Loot
13122int LuaScriptInterface::luaCreateLoot(lua_State *L) {
13123 // Loot() will create a new loot item
13124 Loot *loot = new Loot();
13125 if (loot) {
13126 pushUserdata<Loot>(L, loot);
13127 setMetatable(L, -1, "Loot");
13128 } else {
13129 lua_pushnil(L);
13130 }
13131 return 1;
13132}
13133
13134int LuaScriptInterface::luaDeleteLoot(lua_State *L) {
13135 // loot:delete() loot:__gc()
13136 Loot **lootPtr = getRawUserdata<Loot>(L, 1);
13137 if (lootPtr && *lootPtr) {
13138 delete *lootPtr;
13139 *lootPtr = nullptr;
13140 }
13141 return 0;
13142}
13143
13144int LuaScriptInterface::luaLootSetId(lua_State *L) {
13145 // loot:setId(id or name)
13146 Loot *loot = getUserdata<Loot>(L, 1);
13147 if (loot) {
13148 if (isNumber(L, 2)) {
13149 loot->lootBlock.id = getNumber<uint16_t>(L, 2);
13150 } else {
13151 auto name = getString(L, 2);
13152 auto ids = Item::items.nameToItems.equal_range(asLowerCaseString(name));
13153
13154 if (ids.first == Item::items.nameToItems.cend()) {
13155 std::cout << "[Warning - Loot:setId] Unknown loot item \"" << name
13156 << "\". " << std::endl;
13157 pushBoolean(L, false);
13158 return 1;
13159 }
13160
13161 if (std::next(ids.first) != ids.second) {
13162 std::cout << "[Warning - Loot:setId] Non-unique loot item \"" << name
13163 << "\". " << std::endl;
13164 pushBoolean(L, false);
13165 return 1;
13166 }
13167
13168 loot->lootBlock.id = ids.first->second;
13169 }
13170 pushBoolean(L, true);
13171 } else {
13172 lua_pushnil(L);
13173 }
13174 return 1;
13175}
13176
13177int LuaScriptInterface::luaLootSetSubType(lua_State *L) {
13178 // loot:setSubType(type)
13179 Loot *loot = getUserdata<Loot>(L, 1);
13180 if (loot) {
13181 loot->lootBlock.subType = getNumber<uint16_t>(L, 2);
13182 pushBoolean(L, true);
13183 } else {
13184 lua_pushnil(L);
13185 }
13186 return 1;
13187}
13188
13189int LuaScriptInterface::luaLootSetChance(lua_State *L) {
13190 // loot:setChance(chance)
13191 Loot *loot = getUserdata<Loot>(L, 1);
13192 if (loot) {
13193 loot->lootBlock.chance = getNumber<uint32_t>(L, 2);
13194 pushBoolean(L, true);
13195 } else {
13196 lua_pushnil(L);
13197 }
13198 return 1;
13199}
13200
13201int LuaScriptInterface::luaLootSetMaxCount(lua_State *L) {
13202 // loot:setMaxCount(max)
13203 Loot *loot = getUserdata<Loot>(L, 1);
13204 if (loot) {
13205 loot->lootBlock.countmax = getNumber<uint32_t>(L, 2);
13206 pushBoolean(L, true);
13207 } else {
13208 lua_pushnil(L);
13209 }
13210 return 1;
13211}
13212
13213int LuaScriptInterface::luaLootSetActionId(lua_State *L) {
13214 // loot:setActionId(actionid)
13215 Loot *loot = getUserdata<Loot>(L, 1);
13216 if (loot) {
13217 loot->lootBlock.actionId = getNumber<uint32_t>(L, 2);
13218 pushBoolean(L, true);
13219 } else {
13220 lua_pushnil(L);
13221 }
13222 return 1;
13223}
13224
13225int LuaScriptInterface::luaLootSetDescription(lua_State *L) {
13226 // loot:setDescription(desc)
13227 Loot *loot = getUserdata<Loot>(L, 1);
13228 if (loot) {
13229 loot->lootBlock.text = getString(L, 2);
13230 pushBoolean(L, true);
13231 } else {
13232 lua_pushnil(L);
13233 }
13234 return 1;
13235}
13236
13237int LuaScriptInterface::luaLootAddChildLoot(lua_State *L) {
13238 // loot:addChildLoot(loot)
13239 Loot *loot = getUserdata<Loot>(L, 1);
13240 if (loot) {
13241 loot->lootBlock.childLoot.push_back(getUserdata<Loot>(L, 2)->lootBlock);
13242 } else {
13243 lua_pushnil(L);
13244 }
13245 return 1;
13246}
13247
13248// MonsterSpell
13249int LuaScriptInterface::luaCreateMonsterSpell(lua_State *L) {
13250 // MonsterSpell() will create a new Monster Spell
13251 MonsterSpell *spell = new MonsterSpell();
13252 if (spell) {
13253 pushUserdata<MonsterSpell>(L, spell);
13254 setMetatable(L, -1, "MonsterSpell");
13255 } else {
13256 lua_pushnil(L);
13257 }
13258 return 1;
13259}
13260
13261int LuaScriptInterface::luaDeleteMonsterSpell(lua_State *L) {
13262 // monsterSpell:delete() monsterSpell:__gc()
13263 MonsterSpell **monsterSpellPtr = getRawUserdata<MonsterSpell>(L, 1);
13264 if (monsterSpellPtr && *monsterSpellPtr) {
13265 delete *monsterSpellPtr;
13266 *monsterSpellPtr = nullptr;
13267 }
13268 return 0;
13269}
13270
13271int LuaScriptInterface::luaMonsterSpellSetType(lua_State *L) {
13272 // monsterSpell:setType(type)
13273 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13274 if (spell) {
13275 spell->name = getString(L, 2);
13276 pushBoolean(L, true);
13277 } else {
13278 lua_pushnil(L);
13279 }
13280 return 1;
13281}
13282
13283int LuaScriptInterface::luaMonsterSpellSetScriptName(lua_State *L) {
13284 // monsterSpell:setScriptName(name)
13285 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13286 if (spell) {
13287 spell->scriptName = getString(L, 2);
13288 pushBoolean(L, true);
13289 } else {
13290 lua_pushnil(L);
13291 }
13292 return 1;
13293}
13294
13295int LuaScriptInterface::luaMonsterSpellSetChance(lua_State *L) {
13296 // monsterSpell:setChance(chance)
13297 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13298 if (spell) {
13299 spell->chance = getNumber<uint8_t>(L, 2);
13300 pushBoolean(L, true);
13301 } else {
13302 lua_pushnil(L);
13303 }
13304 return 1;
13305}
13306
13307int LuaScriptInterface::luaMonsterSpellSetInterval(lua_State *L) {
13308 // monsterSpell:setInterval(interval)
13309 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13310 if (spell) {
13311 spell->interval = getNumber<uint16_t>(L, 2);
13312 pushBoolean(L, true);
13313 } else {
13314 lua_pushnil(L);
13315 }
13316 return 1;
13317}
13318
13319int LuaScriptInterface::luaMonsterSpellSetRange(lua_State *L) {
13320 // monsterSpell:setRange(range)
13321 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13322 if (spell) {
13323 spell->range = getNumber<uint8_t>(L, 2);
13324 pushBoolean(L, true);
13325 } else {
13326 lua_pushnil(L);
13327 }
13328 return 1;
13329}
13330
13331int LuaScriptInterface::luaMonsterSpellSetCombatValue(lua_State *L) {
13332 // monsterSpell:setCombatValue(min, max)
13333 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13334 if (spell) {
13335 spell->minCombatValue = getNumber<int32_t>(L, 2);
13336 spell->maxCombatValue = getNumber<int32_t>(L, 3);
13337 pushBoolean(L, true);
13338 } else {
13339 lua_pushnil(L);
13340 }
13341 return 1;
13342}
13343
13344int LuaScriptInterface::luaMonsterSpellSetCombatType(lua_State *L) {
13345 // monsterSpell:setCombatType(combatType_t)
13346 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13347 if (spell) {
13348 spell->combatType = getNumber<CombatType_t>(L, 2);
13349 pushBoolean(L, true);
13350 } else {
13351 lua_pushnil(L);
13352 }
13353 return 1;
13354}
13355
13356int LuaScriptInterface::luaMonsterSpellSetAttackValue(lua_State *L) {
13357 // monsterSpell:setAttackValue(attack, skill)
13358 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13359 if (spell) {
13360 spell->attack = getNumber<int32_t>(L, 2);
13361 spell->skill = getNumber<int32_t>(L, 3);
13362 pushBoolean(L, true);
13363 } else {
13364 lua_pushnil(L);
13365 }
13366 return 1;
13367}
13368
13369int LuaScriptInterface::luaMonsterSpellSetNeedTarget(lua_State *L) {
13370 // monsterSpell:setNeedTarget(bool)
13371 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13372 if (spell) {
13373 spell->needTarget = getBoolean(L, 2);
13374 pushBoolean(L, true);
13375 } else {
13376 lua_pushnil(L);
13377 }
13378 return 1;
13379}
13380
13381int LuaScriptInterface::luaMonsterSpellSetCombatLength(lua_State *L) {
13382 // monsterSpell:setCombatLength(length)
13383 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13384 if (spell) {
13385 spell->length = getNumber<int32_t>(L, 2);
13386 pushBoolean(L, true);
13387 } else {
13388 lua_pushnil(L);
13389 }
13390 return 1;
13391}
13392
13393int LuaScriptInterface::luaMonsterSpellSetCombatSpread(lua_State *L) {
13394 // monsterSpell:setCombatSpread(spread)
13395 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13396 if (spell) {
13397 spell->spread = getNumber<int32_t>(L, 2);
13398 pushBoolean(L, true);
13399 } else {
13400 lua_pushnil(L);
13401 }
13402 return 1;
13403}
13404
13405int LuaScriptInterface::luaMonsterSpellSetCombatRadius(lua_State *L) {
13406 // monsterSpell:setCombatRadius(radius)
13407 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13408 if (spell) {
13409 spell->radius = getNumber<int32_t>(L, 2);
13410 pushBoolean(L, true);
13411 } else {
13412 lua_pushnil(L);
13413 }
13414 return 1;
13415}
13416
13417int LuaScriptInterface::luaMonsterSpellSetConditionType(lua_State *L) {
13418 // monsterSpell:setConditionType(type)
13419 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13420 if (spell) {
13421 spell->conditionType = getNumber<ConditionType_t>(L, 2);
13422 pushBoolean(L, true);
13423 } else {
13424 lua_pushnil(L);
13425 }
13426 return 1;
13427}
13428
13429int LuaScriptInterface::luaMonsterSpellSetConditionDamage(lua_State *L) {
13430 // monsterSpell:setConditionDamage(min, max, start)
13431 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13432 if (spell) {
13433 spell->conditionMinDamage = getNumber<int32_t>(L, 2);
13434 spell->conditionMaxDamage = getNumber<int32_t>(L, 3);
13435 spell->conditionStartDamage = getNumber<int32_t>(L, 4);
13436 pushBoolean(L, true);
13437 } else {
13438 lua_pushnil(L);
13439 }
13440 return 1;
13441}
13442
13443int LuaScriptInterface::luaMonsterSpellSetConditionSpeedChange(lua_State *L) {
13444 // monsterSpell:setConditionSpeedChange(minSpeed[, maxSpeed])
13445 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13446 if (spell) {
13447 spell->minSpeedChange = getNumber<int32_t>(L, 2);
13448 spell->maxSpeedChange = getNumber<int32_t>(L, 3, 0);
13449 pushBoolean(L, true);
13450 } else {
13451 lua_pushnil(L);
13452 }
13453 return 1;
13454}
13455
13456int LuaScriptInterface::luaMonsterSpellSetConditionDuration(lua_State *L) {
13457 // monsterSpell:setConditionDuration(duration)
13458 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13459 if (spell) {
13460 spell->duration = getNumber<int32_t>(L, 2);
13461 pushBoolean(L, true);
13462 } else {
13463 lua_pushnil(L);
13464 }
13465 return 1;
13466}
13467
13468int LuaScriptInterface::luaMonsterSpellSetConditionTickInterval(lua_State *L) {
13469 // monsterSpell:setConditionTickInterval(interval)
13470 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13471 if (spell) {
13472 spell->tickInterval = getNumber<int32_t>(L, 2);
13473 pushBoolean(L, true);
13474 } else {
13475 lua_pushnil(L);
13476 }
13477 return 1;
13478}
13479
13480int LuaScriptInterface::luaMonsterSpellSetCombatShootEffect(lua_State *L) {
13481 // monsterSpell:setCombatShootEffect(effect)
13482 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13483 if (spell) {
13484 spell->shoot = getNumber<ShootType_t>(L, 2);
13485 pushBoolean(L, true);
13486 } else {
13487 lua_pushnil(L);
13488 }
13489 return 1;
13490}
13491
13492int LuaScriptInterface::luaMonsterSpellSetCombatEffect(lua_State *L) {
13493 // monsterSpell:setCombatEffect(effect)
13494 MonsterSpell *spell = getUserdata<MonsterSpell>(L, 1);
13495 if (spell) {
13496 spell->effect = getNumber<MagicEffectClasses>(L, 2);
13497 pushBoolean(L, true);
13498 } else {
13499 lua_pushnil(L);
13500 }
13501 return 1;
13502}
13503
13504// Party
13505int32_t LuaScriptInterface::luaPartyCreate(lua_State *L) {
13506 // Party(userdata)
13507 Player *player = getUserdata<Player>(L, 2);
13508 if (!player) {
13509 lua_pushnil(L);
13510 return 1;
13511 }
13512
13513 Party *party = player->getParty();
13514 if (!party) {
13515 party = new Party(player);
13516 g_game.updatePlayerShield(player);
13517 player->sendCreatureSkull(player);
13518 pushUserdata<Party>(L, party);
13519 setMetatable(L, -1, "Party");
13520 } else {
13521 lua_pushnil(L);
13522 }
13523 return 1;
13524}
13525
13526int LuaScriptInterface::luaPartyDisband(lua_State *L) {
13527 // party:disband()
13528 Party **partyPtr = getRawUserdata<Party>(L, 1);
13529 if (partyPtr && *partyPtr) {
13530 Party *&party = *partyPtr;
13531 party->disband();
13532 party = nullptr;
13533 pushBoolean(L, true);
13534 } else {
13535 lua_pushnil(L);
13536 }
13537 return 1;
13538}
13539
13540int LuaScriptInterface::luaPartyGetLeader(lua_State *L) {
13541 // party:getLeader()
13542 Party *party = getUserdata<Party>(L, 1);
13543 if (!party) {
13544 lua_pushnil(L);
13545 return 1;
13546 }
13547
13548 Player *leader = party->getLeader();
13549 if (leader) {
13550 pushUserdata<Player>(L, leader);
13551 setMetatable(L, -1, "Player");
13552 } else {
13553 lua_pushnil(L);
13554 }
13555 return 1;
13556}
13557
13558int LuaScriptInterface::luaPartySetLeader(lua_State *L) {
13559 // party:setLeader(player)
13560 Player *player = getPlayer(L, 2);
13561 Party *party = getUserdata<Party>(L, 1);
13562 if (party && player) {
13563 pushBoolean(L, party->passPartyLeadership(player));
13564 } else {
13565 lua_pushnil(L);
13566 }
13567 return 1;
13568}
13569
13570int LuaScriptInterface::luaPartyGetMembers(lua_State *L) {
13571 // party:getMembers()
13572 Party *party = getUserdata<Party>(L, 1);
13573 if (!party) {
13574 lua_pushnil(L);
13575 return 1;
13576 }
13577
13578 int index = 0;
13579 lua_createtable(L, party->getMemberCount(), 0);
13580 for (Player *player : party->getMembers()) {
13581 pushUserdata<Player>(L, player);
13582 setMetatable(L, -1, "Player");
13583 lua_rawseti(L, -2, ++index);
13584 }
13585 return 1;
13586}
13587
13588int LuaScriptInterface::luaPartyGetMemberCount(lua_State *L) {
13589 // party:getMemberCount()
13590 Party *party = getUserdata<Party>(L, 1);
13591 if (party) {
13592 lua_pushnumber(L, party->getMemberCount());
13593 } else {
13594 lua_pushnil(L);
13595 }
13596 return 1;
13597}
13598
13599int LuaScriptInterface::luaPartyGetInvitees(lua_State *L) {
13600 // party:getInvitees()
13601 Party *party = getUserdata<Party>(L, 1);
13602 if (party) {
13603 lua_createtable(L, party->getInvitationCount(), 0);
13604
13605 int index = 0;
13606 for (Player *player : party->getInvitees()) {
13607 pushUserdata<Player>(L, player);
13608 setMetatable(L, -1, "Player");
13609 lua_rawseti(L, -2, ++index);
13610 }
13611 } else {
13612 lua_pushnil(L);
13613 }
13614 return 1;
13615}
13616
13617int LuaScriptInterface::luaPartyGetInviteeCount(lua_State *L) {
13618 // party:getInviteeCount()
13619 Party *party = getUserdata<Party>(L, 1);
13620 if (party) {
13621 lua_pushnumber(L, party->getInvitationCount());
13622 } else {
13623 lua_pushnil(L);
13624 }
13625 return 1;
13626}
13627
13628int LuaScriptInterface::luaPartyAddInvite(lua_State *L) {
13629 // party:addInvite(player)
13630 Player *player = getPlayer(L, 2);
13631 Party *party = getUserdata<Party>(L, 1);
13632 if (party && player) {
13633 pushBoolean(L, party->invitePlayer(*player));
13634 } else {
13635 lua_pushnil(L);
13636 }
13637 return 1;
13638}
13639
13640int LuaScriptInterface::luaPartyRemoveInvite(lua_State *L) {
13641 // party:removeInvite(player)
13642 Player *player = getPlayer(L, 2);
13643 Party *party = getUserdata<Party>(L, 1);
13644 if (party && player) {
13645 pushBoolean(L, party->removeInvite(*player));
13646 } else {
13647 lua_pushnil(L);
13648 }
13649 return 1;
13650}
13651
13652int LuaScriptInterface::luaPartyAddMember(lua_State *L) {
13653 // party:addMember(player)
13654 Player *player = getPlayer(L, 2);
13655 Party *party = getUserdata<Party>(L, 1);
13656 if (party && player) {
13657 pushBoolean(L, party->joinParty(*player));
13658 } else {
13659 lua_pushnil(L);
13660 }
13661 return 1;
13662}
13663
13664int LuaScriptInterface::luaPartyRemoveMember(lua_State *L) {
13665 // party:removeMember(player)
13666 Player *player = getPlayer(L, 2);
13667 Party *party = getUserdata<Party>(L, 1);
13668 if (party && player) {
13669 pushBoolean(L, party->leaveParty(player));
13670 } else {
13671 lua_pushnil(L);
13672 }
13673 return 1;
13674}
13675
13676int LuaScriptInterface::luaPartyIsSharedExperienceActive(lua_State *L) {
13677 // party:isSharedExperienceActive()
13678 Party *party = getUserdata<Party>(L, 1);
13679 if (party) {
13680 pushBoolean(L, party->isSharedExperienceActive());
13681 } else {
13682 lua_pushnil(L);
13683 }
13684 return 1;
13685}
13686
13687int LuaScriptInterface::luaPartyIsSharedExperienceEnabled(lua_State *L) {
13688 // party:isSharedExperienceEnabled()
13689 Party *party = getUserdata<Party>(L, 1);
13690 if (party) {
13691 pushBoolean(L, party->isSharedExperienceEnabled());
13692 } else {
13693 lua_pushnil(L);
13694 }
13695 return 1;
13696}
13697
13698int LuaScriptInterface::luaPartyShareExperience(lua_State *L) {
13699 // party:shareExperience(experience)
13700 uint64_t experience = getNumber<uint64_t>(L, 2);
13701 Party *party = getUserdata<Party>(L, 1);
13702 if (party) {
13703 party->shareExperience(experience);
13704 pushBoolean(L, true);
13705 } else {
13706 lua_pushnil(L);
13707 }
13708 return 1;
13709}
13710
13711int LuaScriptInterface::luaPartySetSharedExperience(lua_State *L) {
13712 // party:setSharedExperience(active)
13713 bool active = getBoolean(L, 2);
13714 Party *party = getUserdata<Party>(L, 1);
13715 if (party) {
13716 pushBoolean(L, party->setSharedExperience(party->getLeader(), active));
13717 } else {
13718 lua_pushnil(L);
13719 }
13720 return 1;
13721}
13722
13723// Spells
13724int LuaScriptInterface::luaSpellCreate(lua_State *L) {
13725 // Spell(words, name or id) to get an existing spell
13726 // Spell(type) ex: Spell(SPELL_INSTANT) or Spell(SPELL_RUNE) to create a new
13727 // spell
13728 if (lua_gettop(L) == 1) {
13729 std::cout << "[Error - Spell::luaSpellCreate] There is no parameter set!"
13730 << std::endl;
13731 lua_pushnil(L);
13732 return 1;
13733 }
13734
13735 SpellType_t type = getNumber<SpellType_t>(L, 2);
13736
13737 if (isString(L, 2)) {
13738 std::string tmp = asLowerCaseString(getString(L, 2));
13739 if (tmp == "instant") {
13740 type = SPELL_INSTANT;
13741 } else if (tmp == "rune") {
13742 type = SPELL_RUNE;
13743 }
13744 }
13745
13746 if (type == SPELL_INSTANT) {
13747 InstantSpell *spell =
13748 new InstantSpell(getScriptEnv()->getScriptInterface());
13749 spell->fromLua = true;
13750 pushUserdata<Spell>(L, spell);
13751 setMetatable(L, -1, "Spell");
13752 spell->spellType = SPELL_INSTANT;
13753 return 1;
13754 } else if (type == SPELL_RUNE) {
13755 RuneSpell *spell = new RuneSpell(getScriptEnv()->getScriptInterface());
13756 spell->fromLua = true;
13757 pushUserdata<Spell>(L, spell);
13758 setMetatable(L, -1, "Spell");
13759 spell->spellType = SPELL_RUNE;
13760 return 1;
13761 }
13762
13763 // isNumber(L, 2) doesn't work here for some reason, maybe a bug?
13764 if (getNumber<uint32_t>(L, 2)) {
13765 InstantSpell *instant =
13766 g_spells->getInstantSpellById(getNumber<uint32_t>(L, 2));
13767 if (instant) {
13768 pushUserdata<Spell>(L, instant);
13769 setMetatable(L, -1, "Spell");
13770 return 1;
13771 }
13772 RuneSpell *rune = g_spells->getRuneSpell(getNumber<uint32_t>(L, 2));
13773 if (rune) {
13774 pushUserdata<Spell>(L, rune);
13775 setMetatable(L, -1, "Spell");
13776 return 1;
13777 }
13778 } else if (isString(L, 2)) {
13779 std::string arg = getString(L, 2);
13780 InstantSpell *instant = g_spells->getInstantSpellByName(arg);
13781 if (instant) {
13782 pushUserdata<Spell>(L, instant);
13783 setMetatable(L, -1, "Spell");
13784 return 1;
13785 }
13786 instant = g_spells->getInstantSpell(arg);
13787 if (instant) {
13788 pushUserdata<Spell>(L, instant);
13789 setMetatable(L, -1, "Spell");
13790 return 1;
13791 }
13792 RuneSpell *rune = g_spells->getRuneSpellByName(arg);
13793 if (rune) {
13794 pushUserdata<Spell>(L, rune);
13795 setMetatable(L, -1, "Spell");
13796 return 1;
13797 }
13798 }
13799 lua_pushnil(L);
13800 return 1;
13801}
13802
13803int LuaScriptInterface::luaSpellOnCastSpell(lua_State *L) {
13804 // spell:onCastSpell(callback)
13805 Spell *spell = getUserdata<Spell>(L, 1);
13806 if (spell) {
13807 if (spell->spellType == SPELL_INSTANT) {
13808 InstantSpell *instant =
13809 dynamic_cast<InstantSpell *>(getUserdata<Spell>(L, 1));
13810 if (!instant->loadCallback()) {
13811 pushBoolean(L, false);
13812 return 1;
13813 }
13814 instant->scripted = true;
13815 pushBoolean(L, true);
13816 } else if (spell->spellType == SPELL_RUNE) {
13817 RuneSpell *rune = dynamic_cast<RuneSpell *>(getUserdata<Spell>(L, 1));
13818 if (!rune->loadCallback()) {
13819 pushBoolean(L, false);
13820 return 1;
13821 }
13822 rune->scripted = true;
13823 pushBoolean(L, true);
13824 }
13825 } else {
13826 lua_pushnil(L);
13827 }
13828 return 1;
13829}
13830
13831int LuaScriptInterface::luaSpellRegister(lua_State *L) {
13832 // spell:register()
13833 Spell *spell = getUserdata<Spell>(L, 1);
13834 if (spell) {
13835 if (spell->spellType == SPELL_INSTANT) {
13836 InstantSpell *instant =
13837 dynamic_cast<InstantSpell *>(getUserdata<Spell>(L, 1));
13838 if (!instant->isScripted()) {
13839 pushBoolean(L, false);
13840 return 1;
13841 }
13842 pushBoolean(L, g_spells->registerInstantLuaEvent(instant));
13843 } else if (spell->spellType == SPELL_RUNE) {
13844 RuneSpell *rune = dynamic_cast<RuneSpell *>(getUserdata<Spell>(L, 1));
13845 if (rune->getMagicLevel() != 0 || rune->getLevel() != 0) {
13846 // Change information in the ItemType to get accurate description
13847 ItemType &iType = Item::items.getItemType(rune->getRuneItemId());
13848 iType.name = rune->getName();
13849 iType.runeMagLevel = rune->getMagicLevel();
13850 iType.runeLevel = rune->getLevel();
13851 iType.charges = rune->getCharges();
13852 }
13853 if (!rune->isScripted()) {
13854 pushBoolean(L, false);
13855 return 1;
13856 }
13857 pushBoolean(L, g_spells->registerRuneLuaEvent(rune));
13858 }
13859 } else {
13860 lua_pushnil(L);
13861 }
13862 return 1;
13863}
13864
13865int LuaScriptInterface::luaSpellName(lua_State *L) {
13866 // spell:name(name)
13867 Spell *spell = getUserdata<Spell>(L, 1);
13868 if (spell) {
13869 if (lua_gettop(L) == 1) {
13870 pushString(L, spell->getName());
13871 } else {
13872 spell->setName(getString(L, 2));
13873 pushBoolean(L, true);
13874 }
13875 } else {
13876 lua_pushnil(L);
13877 }
13878 return 1;
13879}
13880
13881int LuaScriptInterface::luaSpellId(lua_State *L) {
13882 // spell:id(id)
13883 Spell *spell = getUserdata<Spell>(L, 1);
13884 if (spell) {
13885 if (lua_gettop(L) == 1) {
13886 lua_pushnumber(L, spell->getId());
13887 } else {
13888 spell->setId(getNumber<uint8_t>(L, 2));
13889 pushBoolean(L, true);
13890 }
13891 } else {
13892 lua_pushnil(L);
13893 }
13894 return 1;
13895}
13896
13897int LuaScriptInterface::luaSpellGroup(lua_State *L) {
13898 // spell:group(primaryGroup[, secondaryGroup])
13899 Spell *spell = getUserdata<Spell>(L, 1);
13900 if (spell) {
13901 if (lua_gettop(L) == 1) {
13902 lua_pushnumber(L, spell->getGroup());
13903 lua_pushnumber(L, spell->getSecondaryGroup());
13904 return 2;
13905 } else if (lua_gettop(L) == 2) {
13906 SpellGroup_t group = getNumber<SpellGroup_t>(L, 2);
13907 if (group) {
13908 spell->setGroup(group);
13909 pushBoolean(L, true);
13910 } else if (isString(L, 2)) {
13911 group = stringToSpellGroup(getString(L, 2));
13912 if (group != SPELLGROUP_NONE) {
13913 spell->setGroup(group);
13914 } else {
13915 std::cout << "[Warning - Spell::group] Unknown group: "
13916 << getString(L, 2) << std::endl;
13917 pushBoolean(L, false);
13918 return 1;
13919 }
13920 pushBoolean(L, true);
13921 } else {
13922 std::cout << "[Warning - Spell::group] Unknown group: "
13923 << getString(L, 2) << std::endl;
13924 pushBoolean(L, false);
13925 return 1;
13926 }
13927 } else {
13928 SpellGroup_t primaryGroup = getNumber<SpellGroup_t>(L, 2);
13929 SpellGroup_t secondaryGroup = getNumber<SpellGroup_t>(L, 2);
13930 if (primaryGroup && secondaryGroup) {
13931 spell->setGroup(primaryGroup);
13932 spell->setSecondaryGroup(secondaryGroup);
13933 pushBoolean(L, true);
13934 } else if (isString(L, 2) && isString(L, 3)) {
13935 primaryGroup = stringToSpellGroup(getString(L, 2));
13936 if (primaryGroup != SPELLGROUP_NONE) {
13937 spell->setGroup(primaryGroup);
13938 } else {
13939 std::cout << "[Warning - Spell::group] Unknown primaryGroup: "
13940 << getString(L, 2) << std::endl;
13941 pushBoolean(L, false);
13942 return 1;
13943 }
13944 secondaryGroup = stringToSpellGroup(getString(L, 3));
13945 if (secondaryGroup != SPELLGROUP_NONE) {
13946 spell->setSecondaryGroup(secondaryGroup);
13947 } else {
13948 std::cout << "[Warning - Spell::group] Unknown secondaryGroup: "
13949 << getString(L, 3) << std::endl;
13950 pushBoolean(L, false);
13951 return 1;
13952 }
13953 pushBoolean(L, true);
13954 } else {
13955 std::cout << "[Warning - Spell::group] Unknown primaryGroup: "
13956 << getString(L, 2)
13957 << " or secondaryGroup: " << getString(L, 3) << std::endl;
13958 pushBoolean(L, false);
13959 return 1;
13960 }
13961 }
13962 } else {
13963 lua_pushnil(L);
13964 }
13965 return 1;
13966}
13967
13968int LuaScriptInterface::luaSpellCooldown(lua_State *L) {
13969 // spell:cooldown(cooldown)
13970 Spell *spell = getUserdata<Spell>(L, 1);
13971 if (spell) {
13972 if (lua_gettop(L) == 1) {
13973 lua_pushnumber(L, spell->getCooldown());
13974 } else {
13975 spell->setCooldown(getNumber<uint32_t>(L, 2));
13976 pushBoolean(L, true);
13977 }
13978 } else {
13979 lua_pushnil(L);
13980 }
13981 return 1;
13982}
13983
13984int LuaScriptInterface::luaSpellGroupCooldown(lua_State *L) {
13985 // spell:groupCooldown(primaryGroupCd[, secondaryGroupCd])
13986 Spell *spell = getUserdata<Spell>(L, 1);
13987 if (spell) {
13988 if (lua_gettop(L) == 1) {
13989 lua_pushnumber(L, spell->getGroupCooldown());
13990 lua_pushnumber(L, spell->getSecondaryCooldown());
13991 return 2;
13992 } else if (lua_gettop(L) == 2) {
13993 spell->setGroupCooldown(getNumber<uint32_t>(L, 2));
13994 pushBoolean(L, true);
13995 } else {
13996 spell->setGroupCooldown(getNumber<uint32_t>(L, 2));
13997 spell->setSecondaryCooldown(getNumber<uint32_t>(L, 3));
13998 pushBoolean(L, true);
13999 }
14000 } else {
14001 lua_pushnil(L);
14002 }
14003 return 1;
14004}
14005
14006int LuaScriptInterface::luaSpellLevel(lua_State *L) {
14007 // spell:level(lvl)
14008 Spell *spell = getUserdata<Spell>(L, 1);
14009 if (spell) {
14010 if (lua_gettop(L) == 1) {
14011 lua_pushnumber(L, spell->getLevel());
14012 } else {
14013 spell->setLevel(getNumber<uint32_t>(L, 2));
14014 pushBoolean(L, true);
14015 }
14016 } else {
14017 lua_pushnil(L);
14018 }
14019 return 1;
14020}
14021
14022int LuaScriptInterface::luaSpellMagicLevel(lua_State *L) {
14023 // spell:magicLevel(lvl)
14024 Spell *spell = getUserdata<Spell>(L, 1);
14025 if (spell) {
14026 if (lua_gettop(L) == 1) {
14027 lua_pushnumber(L, spell->getMagicLevel());
14028 } else {
14029 spell->setMagicLevel(getNumber<uint32_t>(L, 2));
14030 pushBoolean(L, true);
14031 }
14032 } else {
14033 lua_pushnil(L);
14034 }
14035 return 1;
14036}
14037
14038int LuaScriptInterface::luaSpellMana(lua_State *L) {
14039 // spell:mana(mana)
14040 Spell *spell = getUserdata<Spell>(L, 1);
14041 if (spell) {
14042 if (lua_gettop(L) == 1) {
14043 lua_pushnumber(L, spell->getMana());
14044 } else {
14045 spell->setMana(getNumber<uint32_t>(L, 2));
14046 pushBoolean(L, true);
14047 }
14048 } else {
14049 lua_pushnil(L);
14050 }
14051 return 1;
14052}
14053
14054int LuaScriptInterface::luaSpellManaPercent(lua_State *L) {
14055 // spell:manaPercent(percent)
14056 Spell *spell = getUserdata<Spell>(L, 1);
14057 if (spell) {
14058 if (lua_gettop(L) == 1) {
14059 lua_pushnumber(L, spell->getManaPercent());
14060 } else {
14061 spell->setManaPercent(getNumber<uint32_t>(L, 2));
14062 pushBoolean(L, true);
14063 }
14064 } else {
14065 lua_pushnil(L);
14066 }
14067 return 1;
14068}
14069
14070int LuaScriptInterface::luaSpellSoul(lua_State *L) {
14071 // spell:soul(soul)
14072 Spell *spell = getUserdata<Spell>(L, 1);
14073 if (spell) {
14074 if (lua_gettop(L) == 1) {
14075 lua_pushnumber(L, spell->getSoulCost());
14076 } else {
14077 spell->setSoulCost(getNumber<uint32_t>(L, 2));
14078 pushBoolean(L, true);
14079 }
14080 } else {
14081 lua_pushnil(L);
14082 }
14083 return 1;
14084}
14085
14086int LuaScriptInterface::luaSpellRange(lua_State *L) {
14087 // spell:range(range)
14088 Spell *spell = getUserdata<Spell>(L, 1);
14089 if (spell) {
14090 if (lua_gettop(L) == 1) {
14091 lua_pushnumber(L, spell->getRange());
14092 } else {
14093 spell->setRange(getNumber<int32_t>(L, 2));
14094 pushBoolean(L, true);
14095 }
14096 } else {
14097 lua_pushnil(L);
14098 }
14099 return 1;
14100}
14101
14102int LuaScriptInterface::luaSpellPremium(lua_State *L) {
14103 // spell:isPremium(bool)
14104 Spell *spell = getUserdata<Spell>(L, 1);
14105 if (spell) {
14106 if (lua_gettop(L) == 1) {
14107 pushBoolean(L, spell->isPremium());
14108 } else {
14109 spell->setPremium(getBoolean(L, 2));
14110 pushBoolean(L, true);
14111 }
14112 } else {
14113 lua_pushnil(L);
14114 }
14115 return 1;
14116}
14117
14118int LuaScriptInterface::luaSpellEnabled(lua_State *L) {
14119 // spell:isEnabled(bool)
14120 Spell *spell = getUserdata<Spell>(L, 1);
14121 if (spell) {
14122 if (lua_gettop(L) == 1) {
14123 pushBoolean(L, spell->isEnabled());
14124 } else {
14125 spell->setEnabled(getBoolean(L, 2));
14126 pushBoolean(L, true);
14127 }
14128 } else {
14129 lua_pushnil(L);
14130 }
14131 return 1;
14132}
14133
14134int LuaScriptInterface::luaSpellNeedTarget(lua_State *L) {
14135 // spell:needTarget(bool)
14136 Spell *spell = getUserdata<Spell>(L, 1);
14137 if (spell) {
14138 if (lua_gettop(L) == 1) {
14139 pushBoolean(L, spell->getNeedTarget());
14140 } else {
14141 spell->setNeedTarget(getBoolean(L, 2));
14142 pushBoolean(L, true);
14143 }
14144 } else {
14145 lua_pushnil(L);
14146 }
14147 return 1;
14148}
14149
14150int LuaScriptInterface::luaSpellNeedWeapon(lua_State *L) {
14151 // spell:needWeapon(bool)
14152 Spell *spell = getUserdata<Spell>(L, 1);
14153 if (spell) {
14154 if (lua_gettop(L) == 1) {
14155 pushBoolean(L, spell->getNeedWeapon());
14156 } else {
14157 spell->setNeedWeapon(getBoolean(L, 2));
14158 pushBoolean(L, true);
14159 }
14160 } else {
14161 lua_pushnil(L);
14162 }
14163 return 1;
14164}
14165
14166int LuaScriptInterface::luaSpellNeedLearn(lua_State *L) {
14167 // spell:needLearn(bool)
14168 Spell *spell = getUserdata<Spell>(L, 1);
14169 if (spell) {
14170 if (lua_gettop(L) == 1) {
14171 pushBoolean(L, spell->getNeedLearn());
14172 } else {
14173 spell->setNeedLearn(getBoolean(L, 2));
14174 pushBoolean(L, true);
14175 }
14176 } else {
14177 lua_pushnil(L);
14178 }
14179 return 1;
14180}
14181
14182int LuaScriptInterface::luaSpellSelfTarget(lua_State *L) {
14183 // spell:isSelfTarget(bool)
14184 Spell *spell = getUserdata<Spell>(L, 1);
14185 if (spell) {
14186 if (lua_gettop(L) == 1) {
14187 pushBoolean(L, spell->getSelfTarget());
14188 } else {
14189 spell->setSelfTarget(getBoolean(L, 2));
14190 pushBoolean(L, true);
14191 }
14192 } else {
14193 lua_pushnil(L);
14194 }
14195 return 1;
14196}
14197
14198int LuaScriptInterface::luaSpellBlocking(lua_State *L) {
14199 // spell:isBlocking(blockingSolid, blockingCreature)
14200 Spell *spell = getUserdata<Spell>(L, 1);
14201 if (spell) {
14202 if (lua_gettop(L) == 1) {
14203 pushBoolean(L, spell->getBlockingSolid());
14204 pushBoolean(L, spell->getBlockingCreature());
14205 return 2;
14206 } else {
14207 spell->setBlockingSolid(getBoolean(L, 2));
14208 spell->setBlockingCreature(getBoolean(L, 3));
14209 pushBoolean(L, true);
14210 }
14211 } else {
14212 lua_pushnil(L);
14213 }
14214 return 1;
14215}
14216
14217int LuaScriptInterface::luaSpellAggressive(lua_State *L) {
14218 // spell:isAggressive(bool)
14219 Spell *spell = getUserdata<Spell>(L, 1);
14220 if (spell) {
14221 if (lua_gettop(L) == 1) {
14222 pushBoolean(L, spell->getAggressive());
14223 } else {
14224 spell->setAggressive(getBoolean(L, 2));
14225 pushBoolean(L, true);
14226 }
14227 } else {
14228 lua_pushnil(L);
14229 }
14230 return 1;
14231}
14232
14233int LuaScriptInterface::luaSpellVocation(lua_State *L) {
14234 // spell:vocation(vocation)
14235 Spell *spell = getUserdata<Spell>(L, 1);
14236 if (!spell) {
14237 lua_pushnil(L);
14238 return 1;
14239 }
14240
14241 if (lua_gettop(L) == 1) {
14242 lua_createtable(L, 0, 0);
14243 int i = 0;
14244 for (auto &voc : spell->getVocMap()) {
14245 std::string name = g_vocations.getVocation(voc.first)->getVocName();
14246 pushString(L, name);
14247 lua_rawseti(L, -2, ++i);
14248 }
14249 setMetatable(L, -1, "Spell");
14250 } else {
14251 int parameters =
14252 lua_gettop(L) -
14253 1; // - 1 because self is a parameter aswell, which we want to skip ofc
14254 for (int i = 0; i < parameters; ++i) {
14255 std::vector<std::string> vocList =
14256 explodeString(getString(L, 2 + i), ";");
14257 spell->addVocMap(g_vocations.getVocationId(vocList[0]),
14258 vocList.size() > 1 ? booleanString(vocList[1]) : false);
14259 }
14260 pushBoolean(L, true);
14261 }
14262 return 1;
14263}
14264
14265// only for InstantSpells
14266int LuaScriptInterface::luaSpellWords(lua_State *L) {
14267 // spell:words(words[, separator = ""])
14268 InstantSpell *spell = dynamic_cast<InstantSpell *>(getUserdata<Spell>(L, 1));
14269 if (spell) {
14270 // if spell != SPELL_INSTANT, it means that this actually is no
14271 // InstantSpell, so we return nil
14272 if (spell->spellType != SPELL_INSTANT) {
14273 lua_pushnil(L);
14274 return 1;
14275 }
14276
14277 if (lua_gettop(L) == 1) {
14278 pushString(L, spell->getWords());
14279 pushString(L, spell->getSeparator());
14280 return 2;
14281 } else {
14282 std::string sep = "";
14283 if (lua_gettop(L) == 3) {
14284 sep = getString(L, 3);
14285 }
14286 spell->setWords(getString(L, 2));
14287 spell->setSeparator(sep);
14288 pushBoolean(L, true);
14289 }
14290 } else {
14291 lua_pushnil(L);
14292 }
14293 return 1;
14294}
14295
14296// only for InstantSpells
14297int LuaScriptInterface::luaSpellNeedDirection(lua_State *L) {
14298 // spell:needDirection(bool)
14299 InstantSpell *spell = dynamic_cast<InstantSpell *>(getUserdata<Spell>(L, 1));
14300 if (spell) {
14301 // if spell != SPELL_INSTANT, it means that this actually is no
14302 // InstantSpell, so we return nil
14303 if (spell->spellType != SPELL_INSTANT) {
14304 lua_pushnil(L);
14305 return 1;
14306 }
14307
14308 if (lua_gettop(L) == 1) {
14309 pushBoolean(L, spell->getNeedDirection());
14310 } else {
14311 spell->setNeedDirection(getBoolean(L, 2));
14312 pushBoolean(L, true);
14313 }
14314 } else {
14315 lua_pushnil(L);
14316 }
14317 return 1;
14318}
14319
14320// only for InstantSpells
14321int LuaScriptInterface::luaSpellHasParams(lua_State *L) {
14322 // spell:hasParams(bool)
14323 InstantSpell *spell = dynamic_cast<InstantSpell *>(getUserdata<Spell>(L, 1));
14324 if (spell) {
14325 // if spell != SPELL_INSTANT, it means that this actually is no
14326 // InstantSpell, so we return nil
14327 if (spell->spellType != SPELL_INSTANT) {
14328 lua_pushnil(L);
14329 return 1;
14330 }
14331
14332 if (lua_gettop(L) == 1) {
14333 pushBoolean(L, spell->getHasParam());
14334 } else {
14335 spell->setHasParam(getBoolean(L, 2));
14336 pushBoolean(L, true);
14337 }
14338 } else {
14339 lua_pushnil(L);
14340 }
14341 return 1;
14342}
14343
14344// only for InstantSpells
14345int LuaScriptInterface::luaSpellHasPlayerNameParam(lua_State *L) {
14346 // spell:hasPlayerNameParam(bool)
14347 InstantSpell *spell = dynamic_cast<InstantSpell *>(getUserdata<Spell>(L, 1));
14348 if (spell) {
14349 // if spell != SPELL_INSTANT, it means that this actually is no
14350 // InstantSpell, so we return nil
14351 if (spell->spellType != SPELL_INSTANT) {
14352 lua_pushnil(L);
14353 return 1;
14354 }
14355
14356 if (lua_gettop(L) == 1) {
14357 pushBoolean(L, spell->getHasPlayerNameParam());
14358 } else {
14359 spell->setHasPlayerNameParam(getBoolean(L, 2));
14360 pushBoolean(L, true);
14361 }
14362 } else {
14363 lua_pushnil(L);
14364 }
14365 return 1;
14366}
14367
14368// only for InstantSpells
14369int LuaScriptInterface::luaSpellNeedCasterTargetOrDirection(lua_State *L) {
14370 // spell:needCasterTargetOrDirection(bool)
14371 InstantSpell *spell = dynamic_cast<InstantSpell *>(getUserdata<Spell>(L, 1));
14372 if (spell) {
14373 // if spell != SPELL_INSTANT, it means that this actually is no
14374 // InstantSpell, so we return nil
14375 if (spell->spellType != SPELL_INSTANT) {
14376 lua_pushnil(L);
14377 return 1;
14378 }
14379
14380 if (lua_gettop(L) == 1) {
14381 pushBoolean(L, spell->getNeedCasterTargetOrDirection());
14382 } else {
14383 spell->setNeedCasterTargetOrDirection(getBoolean(L, 2));
14384 pushBoolean(L, true);
14385 }
14386 } else {
14387 lua_pushnil(L);
14388 }
14389 return 1;
14390}
14391
14392// only for InstantSpells
14393int LuaScriptInterface::luaSpellIsBlockingWalls(lua_State *L) {
14394 // spell:blockWalls(bool)
14395 InstantSpell *spell = dynamic_cast<InstantSpell *>(getUserdata<Spell>(L, 1));
14396 if (spell) {
14397 // if spell != SPELL_INSTANT, it means that this actually is no
14398 // InstantSpell, so we return nil
14399 if (spell->spellType != SPELL_INSTANT) {
14400 lua_pushnil(L);
14401 return 1;
14402 }
14403
14404 if (lua_gettop(L) == 1) {
14405 pushBoolean(L, spell->getBlockWalls());
14406 } else {
14407 spell->setBlockWalls(getBoolean(L, 2));
14408 pushBoolean(L, true);
14409 }
14410 } else {
14411 lua_pushnil(L);
14412 }
14413 return 1;
14414}
14415
14416// only for RuneSpells
14417int LuaScriptInterface::luaSpellRuneId(lua_State *L) {
14418 // spell:runeId(id)
14419 RuneSpell *spell = dynamic_cast<RuneSpell *>(getUserdata<Spell>(L, 1));
14420 if (spell) {
14421 // if spell != SPELL_RUNE, it means that this actually is no RuneSpell, so
14422 // we return nil
14423 if (spell->spellType != SPELL_RUNE) {
14424 lua_pushnil(L);
14425 return 1;
14426 }
14427
14428 if (lua_gettop(L) == 1) {
14429 lua_pushnumber(L, spell->getRuneItemId());
14430 } else {
14431 spell->setRuneItemId(getNumber<uint16_t>(L, 2));
14432 pushBoolean(L, true);
14433 }
14434 } else {
14435 lua_pushnil(L);
14436 }
14437 return 1;
14438}
14439
14440// only for RuneSpells
14441int LuaScriptInterface::luaSpellCharges(lua_State *L) {
14442 // spell:charges(charges)
14443 RuneSpell *spell = dynamic_cast<RuneSpell *>(getUserdata<Spell>(L, 1));
14444 if (spell) {
14445 // if spell != SPELL_RUNE, it means that this actually is no RuneSpell, so
14446 // we return nil
14447 if (spell->spellType != SPELL_RUNE) {
14448 lua_pushnil(L);
14449 return 1;
14450 }
14451
14452 if (lua_gettop(L) == 1) {
14453 lua_pushnumber(L, spell->getCharges());
14454 } else {
14455 spell->setCharges(getNumber<uint32_t>(L, 2));
14456 pushBoolean(L, true);
14457 }
14458 } else {
14459 lua_pushnil(L);
14460 }
14461 return 1;
14462}
14463
14464// only for RuneSpells
14465int LuaScriptInterface::luaSpellAllowFarUse(lua_State *L) {
14466 // spell:allowFarUse(bool)
14467 RuneSpell *spell = dynamic_cast<RuneSpell *>(getUserdata<Spell>(L, 1));
14468 if (spell) {
14469 // if spell != SPELL_RUNE, it means that this actually is no RuneSpell, so
14470 // we return nil
14471 if (spell->spellType != SPELL_RUNE) {
14472 lua_pushnil(L);
14473 return 1;
14474 }
14475
14476 if (lua_gettop(L) == 1) {
14477 pushBoolean(L, spell->getAllowFarUse());
14478 } else {
14479 spell->setAllowFarUse(getBoolean(L, 2));
14480 pushBoolean(L, true);
14481 }
14482 } else {
14483 lua_pushnil(L);
14484 }
14485 return 1;
14486}
14487
14488// only for RuneSpells
14489int LuaScriptInterface::luaSpellBlockWalls(lua_State *L) {
14490 // spell:blockWalls(bool)
14491 RuneSpell *spell = dynamic_cast<RuneSpell *>(getUserdata<Spell>(L, 1));
14492 if (spell) {
14493 // if spell != SPELL_RUNE, it means that this actually is no RuneSpell, so
14494 // we return nil
14495 if (spell->spellType != SPELL_RUNE) {
14496 lua_pushnil(L);
14497 return 1;
14498 }
14499
14500 if (lua_gettop(L) == 1) {
14501 pushBoolean(L, spell->getCheckLineOfSight());
14502 } else {
14503 spell->setCheckLineOfSight(getBoolean(L, 2));
14504 pushBoolean(L, true);
14505 }
14506 } else {
14507 lua_pushnil(L);
14508 }
14509 return 1;
14510}
14511
14512// only for RuneSpells
14513int LuaScriptInterface::luaSpellCheckFloor(lua_State *L) {
14514 // spell:checkFloor(bool)
14515 RuneSpell *spell = dynamic_cast<RuneSpell *>(getUserdata<Spell>(L, 1));
14516 if (spell) {
14517 // if spell != SPELL_RUNE, it means that this actually is no RuneSpell, so
14518 // we return nil
14519 if (spell->spellType != SPELL_RUNE) {
14520 lua_pushnil(L);
14521 return 1;
14522 }
14523
14524 if (lua_gettop(L) == 1) {
14525 pushBoolean(L, spell->getCheckFloor());
14526 } else {
14527 spell->setCheckFloor(getBoolean(L, 2));
14528 pushBoolean(L, true);
14529 }
14530 } else {
14531 lua_pushnil(L);
14532 }
14533 return 1;
14534}
14535
14536int LuaScriptInterface::luaCreateAction(lua_State *L) {
14537 // Action()
14538 if (getScriptEnv()->getScriptInterface() !=
14539 &g_scripts->getScriptInterface()) {
14540 reportErrorFunc("Actions can only be registered in the Scripts interface.");
14541 lua_pushnil(L);
14542 return 1;
14543 }
14544
14545 Action *action = new Action(getScriptEnv()->getScriptInterface());
14546 if (action) {
14547 action->fromLua = true;
14548 pushUserdata<Action>(L, action);
14549 setMetatable(L, -1, "Action");
14550 } else {
14551 lua_pushnil(L);
14552 }
14553 return 1;
14554}
14555
14556int LuaScriptInterface::luaActionOnUse(lua_State *L) {
14557 // action:onUse(callback)
14558 Action *action = getUserdata<Action>(L, 1);
14559 if (action) {
14560 if (!action->loadCallback()) {
14561 pushBoolean(L, false);
14562 return 1;
14563 }
14564 action->scripted = true;
14565 pushBoolean(L, true);
14566 } else {
14567 lua_pushnil(L);
14568 }
14569 return 1;
14570}
14571
14572int LuaScriptInterface::luaActionRegister(lua_State *L) {
14573 // action:register()
14574 Action *action = getUserdata<Action>(L, 1);
14575 if (action) {
14576 if (!action->isScripted()) {
14577 pushBoolean(L, false);
14578 return 1;
14579 }
14580 pushBoolean(L, g_actions->registerLuaEvent(action));
14581 action->getActionIdRange().clear();
14582 action->getItemIdRange().clear();
14583 action->getUniqueIdRange().clear();
14584 } else {
14585 lua_pushnil(L);
14586 }
14587 return 1;
14588}
14589
14590int LuaScriptInterface::luaActionItemId(lua_State *L) {
14591 // action:id(ids)
14592 Action *action = getUserdata<Action>(L, 1);
14593 if (action) {
14594 int parameters =
14595 lua_gettop(L) -
14596 1; // - 1 because self is a parameter aswell, which we want to skip ofc
14597 if (parameters > 1) {
14598 for (int i = 0; i < parameters; ++i) {
14599 action->addItemId(getNumber<uint32_t>(L, 2 + i));
14600 }
14601 } else {
14602 action->addItemId(getNumber<uint32_t>(L, 2));
14603 }
14604 pushBoolean(L, true);
14605 } else {
14606 lua_pushnil(L);
14607 }
14608 return 1;
14609}
14610
14611int LuaScriptInterface::luaActionActionId(lua_State *L) {
14612 // action:aid(aids)
14613 Action *action = getUserdata<Action>(L, 1);
14614 if (action) {
14615 int parameters =
14616 lua_gettop(L) -
14617 1; // - 1 because self is a parameter aswell, which we want to skip ofc
14618 if (parameters > 1) {
14619 for (int i = 0; i < parameters; ++i) {
14620 action->addActionId(getNumber<uint32_t>(L, 2 + i));
14621 }
14622 } else {
14623 action->addActionId(getNumber<uint32_t>(L, 2));
14624 }
14625 pushBoolean(L, true);
14626 } else {
14627 lua_pushnil(L);
14628 }
14629 return 1;
14630}
14631
14632int LuaScriptInterface::luaActionUniqueId(lua_State *L) {
14633 // action:uid(uids)
14634 Action *action = getUserdata<Action>(L, 1);
14635 if (action) {
14636 int parameters =
14637 lua_gettop(L) -
14638 1; // - 1 because self is a parameter aswell, which we want to skip ofc
14639 if (parameters > 1) {
14640 for (int i = 0; i < parameters; ++i) {
14641 action->addUniqueId(getNumber<uint32_t>(L, 2 + i));
14642 }
14643 } else {
14644 action->addUniqueId(getNumber<uint32_t>(L, 2));
14645 }
14646 pushBoolean(L, true);
14647 } else {
14648 lua_pushnil(L);
14649 }
14650 return 1;
14651}
14652
14653int LuaScriptInterface::luaActionAllowFarUse(lua_State *L) {
14654 // action:allowFarUse(bool)
14655 Action *action = getUserdata<Action>(L, 1);
14656 if (action) {
14657 action->setAllowFarUse(getBoolean(L, 2));
14658 pushBoolean(L, true);
14659 } else {
14660 lua_pushnil(L);
14661 }
14662 return 1;
14663}
14664
14665int LuaScriptInterface::luaActionBlockWalls(lua_State *L) {
14666 // action:blockWalls(bool)
14667 Action *action = getUserdata<Action>(L, 1);
14668 if (action) {
14669 action->setCheckLineOfSight(getBoolean(L, 2));
14670 pushBoolean(L, true);
14671 } else {
14672 lua_pushnil(L);
14673 }
14674 return 1;
14675}
14676
14677int LuaScriptInterface::luaActionCheckFloor(lua_State *L) {
14678 // action:checkFloor(bool)
14679 Action *action = getUserdata<Action>(L, 1);
14680 if (action) {
14681 action->setCheckFloor(getBoolean(L, 2));
14682 pushBoolean(L, true);
14683 } else {
14684 lua_pushnil(L);
14685 }
14686 return 1;
14687}
14688
14689int LuaScriptInterface::luaCreateTalkaction(lua_State *L) {
14690 // TalkAction(words)
14691 if (getScriptEnv()->getScriptInterface() !=
14692 &g_scripts->getScriptInterface()) {
14693 reportErrorFunc(
14694 "TalkActions can only be registered in the Scripts interface.");
14695 lua_pushnil(L);
14696 return 1;
14697 }
14698
14699 TalkAction *talk = new TalkAction(getScriptEnv()->getScriptInterface());
14700 if (talk) {
14701 talk->setWords(getString(L, 2));
14702 talk->fromLua = true;
14703 pushUserdata<TalkAction>(L, talk);
14704 setMetatable(L, -1, "TalkAction");
14705 } else {
14706 lua_pushnil(L);
14707 }
14708 return 1;
14709}
14710
14711int LuaScriptInterface::luaTalkactionOnSay(lua_State *L) {
14712 // talkAction:onSay(callback)
14713 TalkAction *talk = getUserdata<TalkAction>(L, 1);
14714 if (talk) {
14715 if (!talk->loadCallback()) {
14716 pushBoolean(L, false);
14717 return 1;
14718 }
14719 pushBoolean(L, true);
14720 } else {
14721 lua_pushnil(L);
14722 }
14723 return 1;
14724}
14725
14726int LuaScriptInterface::luaTalkactionRegister(lua_State *L) {
14727 // talkAction:register()
14728 TalkAction *talk = getUserdata<TalkAction>(L, 1);
14729 if (talk) {
14730 if (!talk->isScripted()) {
14731 pushBoolean(L, false);
14732 return 1;
14733 }
14734 pushBoolean(L, g_talkActions->registerLuaEvent(talk));
14735 } else {
14736 lua_pushnil(L);
14737 }
14738 return 1;
14739}
14740
14741int LuaScriptInterface::luaTalkactionSeparator(lua_State *L) {
14742 // talkAction:separator(sep)
14743 TalkAction *talk = getUserdata<TalkAction>(L, 1);
14744 if (talk) {
14745 talk->setSeparator(getString(L, 2).c_str());
14746 pushBoolean(L, true);
14747 } else {
14748 lua_pushnil(L);
14749 }
14750 return 1;
14751}
14752
14753int LuaScriptInterface::luaCreateCreatureEvent(lua_State *L) {
14754 // CreatureEvent(eventName)
14755 if (getScriptEnv()->getScriptInterface() !=
14756 &g_scripts->getScriptInterface()) {
14757 reportErrorFunc(
14758 "CreatureEvents can only be registered in the Scripts interface.");
14759 lua_pushnil(L);
14760 return 1;
14761 }
14762
14763 CreatureEvent *creature =
14764 new CreatureEvent(getScriptEnv()->getScriptInterface());
14765 if (creature) {
14766 creature->setName(getString(L, 2));
14767 creature->fromLua = true;
14768 pushUserdata<CreatureEvent>(L, creature);
14769 setMetatable(L, -1, "CreatureEvent");
14770 } else {
14771 lua_pushnil(L);
14772 }
14773 return 1;
14774}
14775
14776int LuaScriptInterface::luaCreatureEventType(lua_State *L) {
14777 // creatureevent:type(callback)
14778 CreatureEvent *creature = getUserdata<CreatureEvent>(L, 1);
14779 if (creature) {
14780 std::string typeName = getString(L, 2);
14781 std::string tmpStr = asLowerCaseString(typeName);
14782 if (tmpStr == "login") {
14783 creature->setEventType(CREATURE_EVENT_LOGIN);
14784 } else if (tmpStr == "logout") {
14785 creature->setEventType(CREATURE_EVENT_LOGOUT);
14786 } else if (tmpStr == "think") {
14787 creature->setEventType(CREATURE_EVENT_THINK);
14788 } else if (tmpStr == "preparedeath") {
14789 creature->setEventType(CREATURE_EVENT_PREPAREDEATH);
14790 } else if (tmpStr == "death") {
14791 creature->setEventType(CREATURE_EVENT_DEATH);
14792 } else if (tmpStr == "kill") {
14793 creature->setEventType(CREATURE_EVENT_KILL);
14794 } else if (tmpStr == "advance") {
14795 creature->setEventType(CREATURE_EVENT_ADVANCE);
14796 } else if (tmpStr == "modalwindow") {
14797 creature->setEventType(CREATURE_EVENT_MODALWINDOW);
14798 } else if (tmpStr == "textedit") {
14799 creature->setEventType(CREATURE_EVENT_TEXTEDIT);
14800 } else if (tmpStr == "healthchange") {
14801 creature->setEventType(CREATURE_EVENT_HEALTHCHANGE);
14802 } else if (tmpStr == "manachange") {
14803 creature->setEventType(CREATURE_EVENT_MANACHANGE);
14804 } else if (tmpStr == "extendedopcode") {
14805 creature->setEventType(CREATURE_EVENT_EXTENDED_OPCODE);
14806 } else {
14807 std::cout << "[Error - CreatureEvent::configureLuaEvent] Invalid type "
14808 "for creature event: "
14809 << typeName << std::endl;
14810 pushBoolean(L, false);
14811 }
14812 creature->setLoaded(true);
14813 pushBoolean(L, true);
14814 } else {
14815 lua_pushnil(L);
14816 }
14817 return 1;
14818}
14819
14820int LuaScriptInterface::luaCreatureEventRegister(lua_State *L) {
14821 // creatureevent:register()
14822 CreatureEvent *creature = getUserdata<CreatureEvent>(L, 1);
14823 if (creature) {
14824 if (!creature->isScripted()) {
14825 pushBoolean(L, false);
14826 return 1;
14827 }
14828 pushBoolean(L, g_creatureEvents->registerLuaEvent(creature));
14829 } else {
14830 lua_pushnil(L);
14831 }
14832 return 1;
14833}
14834
14835int LuaScriptInterface::luaCreatureEventOnCallback(lua_State *L) {
14836 // creatureevent:onLogin / logout / etc. (callback)
14837 CreatureEvent *creature = getUserdata<CreatureEvent>(L, 1);
14838 if (creature) {
14839 if (!creature->loadCallback()) {
14840 pushBoolean(L, false);
14841 return 1;
14842 }
14843 pushBoolean(L, true);
14844 } else {
14845 lua_pushnil(L);
14846 }
14847 return 1;
14848}
14849
14850int LuaScriptInterface::luaCreateMoveEvent(lua_State *L) {
14851 // MoveEvent()
14852 if (getScriptEnv()->getScriptInterface() !=
14853 &g_scripts->getScriptInterface()) {
14854 reportErrorFunc(
14855 "MoveEvents can only be registered in the Scripts interface.");
14856 lua_pushnil(L);
14857 return 1;
14858 }
14859
14860 MoveEvent *moveevent = new MoveEvent(getScriptEnv()->getScriptInterface());
14861 if (moveevent) {
14862 moveevent->fromLua = true;
14863 pushUserdata<MoveEvent>(L, moveevent);
14864 setMetatable(L, -1, "MoveEvent");
14865 } else {
14866 lua_pushnil(L);
14867 }
14868 return 1;
14869}
14870
14871int LuaScriptInterface::luaMoveEventType(lua_State *L) {
14872 // moveevent:type(callback)
14873 MoveEvent *moveevent = getUserdata<MoveEvent>(L, 1);
14874 if (moveevent) {
14875 std::string typeName = getString(L, 2);
14876 std::string tmpStr = asLowerCaseString(typeName);
14877 if (tmpStr == "stepin") {
14878 moveevent->setEventType(MOVE_EVENT_STEP_IN);
14879 moveevent->stepFunction = moveevent->StepInField;
14880 } else if (tmpStr == "stepout") {
14881 moveevent->setEventType(MOVE_EVENT_STEP_OUT);
14882 moveevent->stepFunction = moveevent->StepOutField;
14883 } else if (tmpStr == "equip") {
14884 moveevent->setEventType(MOVE_EVENT_EQUIP);
14885 moveevent->equipFunction = moveevent->EquipItem;
14886 } else if (tmpStr == "deequip") {
14887 moveevent->setEventType(MOVE_EVENT_DEEQUIP);
14888 moveevent->equipFunction = moveevent->DeEquipItem;
14889 } else if (tmpStr == "additem") {
14890 moveevent->setEventType(MOVE_EVENT_ADD_ITEM_ITEMTILE);
14891 moveevent->moveFunction = moveevent->AddItemField;
14892 } else if (tmpStr == "removeitem") {
14893 moveevent->setEventType(MOVE_EVENT_REMOVE_ITEM_ITEMTILE);
14894 moveevent->moveFunction = moveevent->RemoveItemField;
14895 } else {
14896 std::cout << "Error: [MoveEvent::configureMoveEvent] No valid event name "
14897 << typeName << std::endl;
14898 pushBoolean(L, false);
14899 }
14900 pushBoolean(L, true);
14901 } else {
14902 lua_pushnil(L);
14903 }
14904 return 1;
14905}
14906
14907int LuaScriptInterface::luaMoveEventRegister(lua_State *L) {
14908 // moveevent:register()
14909 MoveEvent *moveevent = getUserdata<MoveEvent>(L, 1);
14910 if (moveevent) {
14911 if ((moveevent->getEventType() == MOVE_EVENT_EQUIP ||
14912 moveevent->getEventType() == MOVE_EVENT_DEEQUIP) &&
14913 moveevent->getSlot() == SLOTP_WHEREEVER) {
14914 uint32_t id = moveevent->getItemIdRange().at(0);
14915 ItemType &it = Item::items.getItemType(id);
14916 moveevent->setSlot(it.slotPosition);
14917 }
14918 if (!moveevent->isScripted()) {
14919 pushBoolean(L, g_moveEvents->registerLuaFunction(moveevent));
14920 return 1;
14921 }
14922 pushBoolean(L, g_moveEvents->registerLuaEvent(moveevent));
14923 moveevent->getItemIdRange().clear();
14924 moveevent->getActionIdRange().clear();
14925 moveevent->getUniqueIdRange().clear();
14926 moveevent->getPosList().clear();
14927 } else {
14928 lua_pushnil(L);
14929 }
14930 return 1;
14931}
14932
14933int LuaScriptInterface::luaMoveEventOnCallback(lua_State *L) {
14934 // moveevent:onEquip / deEquip / etc. (callback)
14935 MoveEvent *moveevent = getUserdata<MoveEvent>(L, 1);
14936 if (moveevent) {
14937 if (!moveevent->loadCallback()) {
14938 pushBoolean(L, false);
14939 return 1;
14940 }
14941 pushBoolean(L, true);
14942 } else {
14943 lua_pushnil(L);
14944 }
14945 return 1;
14946}
14947
14948int LuaScriptInterface::luaMoveEventSlot(lua_State *L) {
14949 // moveevent:slot(slot)
14950 MoveEvent *moveevent = getUserdata<MoveEvent>(L, 1);
14951 if (moveevent) {
14952 if (moveevent->getEventType() == MOVE_EVENT_EQUIP ||
14953 moveevent->getEventType() == MOVE_EVENT_DEEQUIP) {
14954 if (!moveevent->getSlotName().empty()) {
14955 std::string slotName = getString(L, 2);
14956 std::string tmpStr = asLowerCaseString(slotName);
14957 tmpStr = asLowerCaseString(moveevent->getSlotName());
14958 if (tmpStr == "head") {
14959 moveevent->setSlot(SLOTP_HEAD);
14960 } else if (tmpStr == "necklace") {
14961 moveevent->setSlot(SLOTP_NECKLACE);
14962 } else if (tmpStr == "backpack") {
14963 moveevent->setSlot(SLOTP_BACKPACK);
14964 } else if (tmpStr == "armor" || tmpStr == "body") {
14965 moveevent->setSlot(SLOTP_ARMOR);
14966 } else if (tmpStr == "right-hand") {
14967 moveevent->setSlot(SLOTP_RIGHT);
14968 } else if (tmpStr == "left-hand") {
14969 moveevent->setSlot(SLOTP_LEFT);
14970 } else if (tmpStr == "hand" || tmpStr == "shield") {
14971 moveevent->setSlot(SLOTP_RIGHT | SLOTP_LEFT);
14972 } else if (tmpStr == "legs") {
14973 moveevent->setSlot(SLOTP_LEGS);
14974 } else if (tmpStr == "feet") {
14975 moveevent->setSlot(SLOTP_FEET);
14976 } else if (tmpStr == "ring") {
14977 moveevent->setSlot(SLOTP_RING);
14978 } else if (tmpStr == "ammo") {
14979 moveevent->setSlot(SLOTP_AMMO);
14980 } else {
14981 std::cout
14982 << "[Warning - MoveEvent::configureMoveEvent] Unknown slot type: "
14983 << moveevent->getSlotName() << std::endl;
14984 }
14985 }
14986 }
14987 pushBoolean(L, true);
14988 } else {
14989 lua_pushnil(L);
14990 }
14991 return 1;
14992}
14993
14994int LuaScriptInterface::luaMoveEventLevel(lua_State *L) {
14995 // moveevent:level(lvl)
14996 MoveEvent *moveevent = getUserdata<MoveEvent>(L, 1);
14997 if (moveevent) {
14998 moveevent->setRequiredLevel(getNumber<uint32_t>(L, 2));
14999 moveevent->setWieldInfo(WIELDINFO_LEVEL);
15000 pushBoolean(L, true);
15001 } else {
15002 lua_pushnil(L);
15003 }
15004 return 1;
15005}
15006
15007int LuaScriptInterface::luaMoveEventMagLevel(lua_State *L) {
15008 // moveevent:magicLevel(lvl)
15009 MoveEvent *moveevent = getUserdata<MoveEvent>(L, 1);
15010 if (moveevent) {
15011 moveevent->setRequiredMagLevel(getNumber<uint32_t>(L, 2));
15012 moveevent->setWieldInfo(WIELDINFO_MAGLV);
15013 pushBoolean(L, true);
15014 } else {
15015 lua_pushnil(L);
15016 }
15017 return 1;
15018}
15019
15020int LuaScriptInterface::luaMoveEventPremium(lua_State *L) {
15021 // moveevent:premium(bool)
15022 MoveEvent *moveevent = getUserdata<MoveEvent>(L, 1);
15023 if (moveevent) {
15024 moveevent->setNeedPremium(getBoolean(L, 2));
15025 moveevent->setWieldInfo(WIELDINFO_PREMIUM);
15026 pushBoolean(L, true);
15027 } else {
15028 lua_pushnil(L);
15029 }
15030 return 1;
15031}
15032
15033int LuaScriptInterface::luaMoveEventVocation(lua_State *L) {
15034 // moveevent:vocation(vocName[, showInDescription = false, lastVoc = false])
15035 MoveEvent *moveevent = getUserdata<MoveEvent>(L, 1);
15036 if (moveevent) {
15037 moveevent->addVocEquipMap(getString(L, 2));
15038 moveevent->setWieldInfo(WIELDINFO_VOCREQ);
15039 std::string tmp;
15040 bool showInDescription = false;
15041 bool lastVoc = false;
15042 if (getBoolean(L, 3)) {
15043 showInDescription = getBoolean(L, 3);
15044 }
15045 if (getBoolean(L, 4)) {
15046 lastVoc = getBoolean(L, 4);
15047 }
15048 if (showInDescription) {
15049 if (moveevent->getVocationString().empty()) {
15050 tmp = asLowerCaseString(getString(L, 2));
15051 tmp += "s";
15052 moveevent->setVocationString(tmp);
15053 } else {
15054 tmp = moveevent->getVocationString();
15055 if (lastVoc) {
15056 tmp += " and ";
15057 } else {
15058 tmp += ", ";
15059 }
15060 tmp += asLowerCaseString(getString(L, 2));
15061 tmp += "s";
15062 moveevent->setVocationString(tmp);
15063 }
15064 }
15065 pushBoolean(L, true);
15066 } else {
15067 lua_pushnil(L);
15068 }
15069 return 1;
15070}
15071
15072int LuaScriptInterface::luaMoveEventItemId(lua_State *L) {
15073 // moveevent:id(ids)
15074 MoveEvent *moveevent = getUserdata<MoveEvent>(L, 1);
15075 if (moveevent) {
15076 int parameters =
15077 lua_gettop(L) -
15078 1; // - 1 because self is a parameter aswell, which we want to skip ofc
15079 if (parameters > 1) {
15080 for (int i = 0; i < parameters; ++i) {
15081 moveevent->addItemId(getNumber<uint32_t>(L, 2 + i));
15082 }
15083 } else {
15084 moveevent->addItemId(getNumber<uint32_t>(L, 2));
15085 }
15086 pushBoolean(L, true);
15087 } else {
15088 lua_pushnil(L);
15089 }
15090 return 1;
15091}
15092
15093int LuaScriptInterface::luaMoveEventActionId(lua_State *L) {
15094 // moveevent:aid(ids)
15095 MoveEvent *moveevent = getUserdata<MoveEvent>(L, 1);
15096 if (moveevent) {
15097 int parameters =
15098 lua_gettop(L) -
15099 1; // - 1 because self is a parameter aswell, which we want to skip ofc
15100 if (parameters > 1) {
15101 for (int i = 0; i < parameters; ++i) {
15102 moveevent->addActionId(getNumber<uint32_t>(L, 2 + i));
15103 }
15104 } else {
15105 moveevent->addActionId(getNumber<uint32_t>(L, 2));
15106 }
15107 pushBoolean(L, true);
15108 } else {
15109 lua_pushnil(L);
15110 }
15111 return 1;
15112}
15113
15114int LuaScriptInterface::luaMoveEventUniqueId(lua_State *L) {
15115 // moveevent:uid(ids)
15116 MoveEvent *moveevent = getUserdata<MoveEvent>(L, 1);
15117 if (moveevent) {
15118 int parameters =
15119 lua_gettop(L) -
15120 1; // - 1 because self is a parameter aswell, which we want to skip ofc
15121 if (parameters > 1) {
15122 for (int i = 0; i < parameters; ++i) {
15123 moveevent->addUniqueId(getNumber<uint32_t>(L, 2 + i));
15124 }
15125 } else {
15126 moveevent->addUniqueId(getNumber<uint32_t>(L, 2));
15127 }
15128 pushBoolean(L, true);
15129 } else {
15130 lua_pushnil(L);
15131 }
15132 return 1;
15133}
15134
15135int LuaScriptInterface::luaMoveEventPosition(lua_State *L) {
15136 // moveevent:position(positions)
15137 MoveEvent *moveevent = getUserdata<MoveEvent>(L, 1);
15138 if (moveevent) {
15139 int parameters =
15140 lua_gettop(L) -
15141 1; // - 1 because self is a parameter aswell, which we want to skip ofc
15142 if (parameters > 1) {
15143 for (int i = 0; i < parameters; ++i) {
15144 moveevent->addPosList(getPosition(L, 2 + i));
15145 }
15146 } else {
15147 moveevent->addPosList(getPosition(L, 2));
15148 }
15149 pushBoolean(L, true);
15150 } else {
15151 lua_pushnil(L);
15152 }
15153 return 1;
15154}
15155
15156int LuaScriptInterface::luaCreateGlobalEvent(lua_State *L) {
15157 // GlobalEvent(eventName)
15158 if (getScriptEnv()->getScriptInterface() !=
15159 &g_scripts->getScriptInterface()) {
15160 reportErrorFunc(
15161 "GlobalEvents can only be registered in the Scripts interface.");
15162 lua_pushnil(L);
15163 return 1;
15164 }
15165
15166 GlobalEvent *global = new GlobalEvent(getScriptEnv()->getScriptInterface());
15167 if (global) {
15168 global->setName(getString(L, 2));
15169 global->setEventType(GLOBALEVENT_NONE);
15170 global->fromLua = true;
15171 pushUserdata<GlobalEvent>(L, global);
15172 setMetatable(L, -1, "GlobalEvent");
15173 } else {
15174 lua_pushnil(L);
15175 }
15176 return 1;
15177}
15178
15179int LuaScriptInterface::luaGlobalEventType(lua_State *L) {
15180 // globalevent:type(callback)
15181 GlobalEvent *global = getUserdata<GlobalEvent>(L, 1);
15182 if (global) {
15183 std::string typeName = getString(L, 2);
15184 std::string tmpStr = asLowerCaseString(typeName);
15185 if (tmpStr == "startup") {
15186 global->setEventType(GLOBALEVENT_STARTUP);
15187 } else if (tmpStr == "shutdown") {
15188 global->setEventType(GLOBALEVENT_SHUTDOWN);
15189 } else if (tmpStr == "record") {
15190 global->setEventType(GLOBALEVENT_RECORD);
15191 } else {
15192 std::cout << "[Error - CreatureEvent::configureLuaEvent] Invalid type "
15193 "for global event: "
15194 << typeName << std::endl;
15195 pushBoolean(L, false);
15196 }
15197 pushBoolean(L, true);
15198 } else {
15199 lua_pushnil(L);
15200 }
15201 return 1;
15202}
15203
15204int LuaScriptInterface::luaGlobalEventRegister(lua_State *L) {
15205 // globalevent:register()
15206 GlobalEvent *globalevent = getUserdata<GlobalEvent>(L, 1);
15207 if (globalevent) {
15208 if (!globalevent->isScripted()) {
15209 pushBoolean(L, false);
15210 return 1;
15211 }
15212 pushBoolean(L, g_globalEvents->registerLuaEvent(globalevent));
15213 } else {
15214 lua_pushnil(L);
15215 }
15216 return 1;
15217}
15218
15219int LuaScriptInterface::luaGlobalEventOnCallback(lua_State *L) {
15220 // globalevent:onThink / record / etc. (callback)
15221 GlobalEvent *globalevent = getUserdata<GlobalEvent>(L, 1);
15222 if (globalevent) {
15223 if (!globalevent->loadCallback()) {
15224 pushBoolean(L, false);
15225 return 1;
15226 }
15227 pushBoolean(L, true);
15228 } else {
15229 lua_pushnil(L);
15230 }
15231 return 1;
15232}
15233
15234int LuaScriptInterface::luaGlobalEventTime(lua_State *L) {
15235 // globalevent:time(time)
15236 GlobalEvent *globalevent = getUserdata<GlobalEvent>(L, 1);
15237 if (globalevent) {
15238 std::string timer = getString(L, 2);
15239 std::vector<int32_t> params = vectorAtoi(explodeString(timer, ":"));
15240
15241 int32_t hour = params.front();
15242 if (hour < 0 || hour > 23) {
15243 std::cout << "[Error - GlobalEvent::configureEvent] Invalid hour \""
15244 << timer
15245 << "\" for globalevent with name: " << globalevent->getName()
15246 << std::endl;
15247 pushBoolean(L, false);
15248 return 1;
15249 }
15250
15251 globalevent->setInterval(hour << 16);
15252
15253 int32_t min = 0;
15254 int32_t sec = 0;
15255 if (params.size() > 1) {
15256 min = params[1];
15257 if (min < 0 || min > 59) {
15258 std::cout << "[Error - GlobalEvent::configureEvent] Invalid minute \""
15259 << timer
15260 << "\" for globalevent with name: " << globalevent->getName()
15261 << std::endl;
15262 pushBoolean(L, false);
15263 return 1;
15264 }
15265
15266 if (params.size() > 2) {
15267 sec = params[2];
15268 if (sec < 0 || sec > 59) {
15269 std::cout << "[Error - GlobalEvent::configureEvent] Invalid second \""
15270 << timer << "\" for globalevent with name: "
15271 << globalevent->getName() << std::endl;
15272 pushBoolean(L, false);
15273 return 1;
15274 }
15275 }
15276 }
15277
15278 time_t current_time = time(nullptr);
15279 tm *timeinfo = localtime(&current_time);
15280 timeinfo->tm_hour = hour;
15281 timeinfo->tm_min = min;
15282 timeinfo->tm_sec = sec;
15283
15284 time_t difference =
15285 static_cast<time_t>(difftime(mktime(timeinfo), current_time));
15286 if (difference < 0) {
15287 difference += 86400;
15288 }
15289
15290 globalevent->setNextExecution(current_time + difference);
15291 globalevent->setEventType(GLOBALEVENT_TIMER);
15292 pushBoolean(L, true);
15293 } else {
15294 lua_pushnil(L);
15295 }
15296 return 1;
15297}
15298
15299int LuaScriptInterface::luaGlobalEventInterval(lua_State *L) {
15300 // globalevent:interval(interval)
15301 GlobalEvent *globalevent = getUserdata<GlobalEvent>(L, 1);
15302 if (globalevent) {
15303 globalevent->setInterval(getNumber<uint32_t>(L, 2));
15304 globalevent->setNextExecution(OTSYS_TIME() + getNumber<uint32_t>(L, 2));
15305 pushBoolean(L, true);
15306 } else {
15307 lua_pushnil(L);
15308 }
15309 return 1;
15310}
15311
15312// Weapon
15313int LuaScriptInterface::luaCreateWeapon(lua_State *L) {
15314 // Weapon(type)
15315 if (getScriptEnv()->getScriptInterface() !=
15316 &g_scripts->getScriptInterface()) {
15317 reportErrorFunc("Weapons can only be registered in the Scripts interface.");
15318 lua_pushnil(L);
15319 return 1;
15320 }
15321
15322 WeaponType_t type = getNumber<WeaponType_t>(L, 2);
15323 switch (type) {
15324 case WEAPON_SWORD:
15325 case WEAPON_AXE:
15326 case WEAPON_CLUB: {
15327 WeaponMelee *weapon = new WeaponMelee(getScriptEnv()->getScriptInterface());
15328 if (weapon) {
15329 pushUserdata<WeaponMelee>(L, weapon);
15330 setMetatable(L, -1, "Weapon");
15331 weapon->weaponType = type;
15332 } else {
15333 lua_pushnil(L);
15334 }
15335 break;
15336 }
15337 case WEAPON_DISTANCE:
15338 case WEAPON_AMMO: {
15339 WeaponDistance *weapon =
15340 new WeaponDistance(getScriptEnv()->getScriptInterface());
15341 if (weapon) {
15342 pushUserdata<WeaponDistance>(L, weapon);
15343 setMetatable(L, -1, "Weapon");
15344 weapon->weaponType = type;
15345 } else {
15346 lua_pushnil(L);
15347 }
15348 break;
15349 }
15350 case WEAPON_WAND: {
15351 WeaponWand *weapon = new WeaponWand(getScriptEnv()->getScriptInterface());
15352 if (weapon) {
15353 pushUserdata<WeaponWand>(L, weapon);
15354 setMetatable(L, -1, "Weapon");
15355 weapon->weaponType = type;
15356 } else {
15357 lua_pushnil(L);
15358 }
15359 break;
15360 }
15361 default: {
15362 lua_pushnil(L);
15363 break;
15364 }
15365 }
15366 return 1;
15367}
15368
15369int LuaScriptInterface::luaWeaponAction(lua_State *L) {
15370 // weapon:action(callback)
15371 Weapon *weapon = getUserdata<Weapon>(L, 1);
15372 if (weapon) {
15373 std::string typeName = getString(L, 2);
15374 std::string tmpStr = asLowerCaseString(typeName);
15375 if (tmpStr == "removecount") {
15376 weapon->action = WEAPONACTION_REMOVECOUNT;
15377 } else if (tmpStr == "removecharge") {
15378 weapon->action = WEAPONACTION_REMOVECHARGE;
15379 } else if (tmpStr == "move") {
15380 weapon->action = WEAPONACTION_MOVE;
15381 } else {
15382 std::cout << "Error: [Weapon::action] No valid action " << typeName
15383 << std::endl;
15384 pushBoolean(L, false);
15385 }
15386 pushBoolean(L, true);
15387 } else {
15388 lua_pushnil(L);
15389 }
15390 return 1;
15391}
15392
15393int LuaScriptInterface::luaWeaponRegister(lua_State *L) {
15394 // weapon:register()
15395 Weapon *weapon = getUserdata<Weapon>(L, 1);
15396 if (weapon) {
15397 if (weapon->weaponType == WEAPON_DISTANCE ||
15398 weapon->weaponType == WEAPON_AMMO) {
15399 weapon = getUserdata<WeaponDistance>(L, 1);
15400 } else if (weapon->weaponType == WEAPON_WAND) {
15401 weapon = getUserdata<WeaponWand>(L, 1);
15402 } else {
15403 weapon = getUserdata<WeaponMelee>(L, 1);
15404 }
15405
15406 uint16_t id = weapon->getID();
15407 ItemType &it = Item::items.getItemType(id);
15408 it.weaponType = weapon->weaponType;
15409
15410 if (weapon->getWieldInfo() != 0) {
15411 it.wieldInfo = weapon->getWieldInfo();
15412 it.vocationString = weapon->getVocationString();
15413 it.minReqLevel = weapon->getReqLevel();
15414 it.minReqMagicLevel = weapon->getReqMagLv();
15415 }
15416
15417 weapon->configureWeapon(it);
15418 pushBoolean(L, g_weapons->registerLuaEvent(weapon));
15419 } else {
15420 lua_pushnil(L);
15421 }
15422 return 1;
15423}
15424
15425int LuaScriptInterface::luaWeaponOnUseWeapon(lua_State *L) {
15426 // weapon:onUseWeapon(callback)
15427 Weapon *weapon = getUserdata<Weapon>(L, 1);
15428 if (weapon) {
15429 if (!weapon->loadCallback()) {
15430 pushBoolean(L, false);
15431 return 1;
15432 }
15433 pushBoolean(L, true);
15434 } else {
15435 lua_pushnil(L);
15436 }
15437 return 1;
15438}
15439
15440int LuaScriptInterface::luaWeaponUnproperly(lua_State *L) {
15441 // weapon:wieldedUnproperly(bool)
15442 Weapon *weapon = getUserdata<Weapon>(L, 1);
15443 if (weapon) {
15444 weapon->setWieldUnproperly(getBoolean(L, 2));
15445 pushBoolean(L, true);
15446 } else {
15447 lua_pushnil(L);
15448 }
15449 return 1;
15450}
15451
15452int LuaScriptInterface::luaWeaponLevel(lua_State *L) {
15453 // weapon:level(lvl)
15454 Weapon *weapon = getUserdata<Weapon>(L, 1);
15455 if (weapon) {
15456 weapon->setRequiredLevel(getNumber<uint32_t>(L, 2));
15457 weapon->setWieldInfo(WIELDINFO_LEVEL);
15458 pushBoolean(L, true);
15459 } else {
15460 lua_pushnil(L);
15461 }
15462 return 1;
15463}
15464
15465int LuaScriptInterface::luaWeaponMagicLevel(lua_State *L) {
15466 // weapon:magicLevel(lvl)
15467 Weapon *weapon = getUserdata<Weapon>(L, 1);
15468 if (weapon) {
15469 weapon->setRequiredMagLevel(getNumber<uint32_t>(L, 2));
15470 weapon->setWieldInfo(WIELDINFO_MAGLV);
15471 pushBoolean(L, true);
15472 } else {
15473 lua_pushnil(L);
15474 }
15475 return 1;
15476}
15477
15478int LuaScriptInterface::luaWeaponMana(lua_State *L) {
15479 // weapon:mana(mana)
15480 Weapon *weapon = getUserdata<Weapon>(L, 1);
15481 if (weapon) {
15482 weapon->setMana(getNumber<uint32_t>(L, 2));
15483 pushBoolean(L, true);
15484 } else {
15485 lua_pushnil(L);
15486 }
15487 return 1;
15488}
15489
15490int LuaScriptInterface::luaWeaponManaPercent(lua_State *L) {
15491 // weapon:manaPercent(percent)
15492 Weapon *weapon = getUserdata<Weapon>(L, 1);
15493 if (weapon) {
15494 weapon->setManaPercent(getNumber<uint32_t>(L, 2));
15495 pushBoolean(L, true);
15496 } else {
15497 lua_pushnil(L);
15498 }
15499 return 1;
15500}
15501
15502int LuaScriptInterface::luaWeaponHealth(lua_State *L) {
15503 // weapon:health(health)
15504 Weapon *weapon = getUserdata<Weapon>(L, 1);
15505 if (weapon) {
15506 weapon->setHealth(getNumber<int32_t>(L, 2));
15507 pushBoolean(L, true);
15508 } else {
15509 lua_pushnil(L);
15510 }
15511 return 1;
15512}
15513
15514int LuaScriptInterface::luaWeaponHealthPercent(lua_State *L) {
15515 // weapon:healthPercent(percent)
15516 Weapon *weapon = getUserdata<Weapon>(L, 1);
15517 if (weapon) {
15518 weapon->setHealthPercent(getNumber<uint32_t>(L, 2));
15519 pushBoolean(L, true);
15520 } else {
15521 lua_pushnil(L);
15522 }
15523 return 1;
15524}
15525
15526int LuaScriptInterface::luaWeaponSoul(lua_State *L) {
15527 // weapon:soul(soul)
15528 Weapon *weapon = getUserdata<Weapon>(L, 1);
15529 if (weapon) {
15530 weapon->setSoul(getNumber<uint32_t>(L, 2));
15531 pushBoolean(L, true);
15532 } else {
15533 lua_pushnil(L);
15534 }
15535 return 1;
15536}
15537
15538int LuaScriptInterface::luaWeaponBreakChance(lua_State *L) {
15539 // weapon:breakChance(percent)
15540 Weapon *weapon = getUserdata<Weapon>(L, 1);
15541 if (weapon) {
15542 weapon->setBreakChance(getNumber<uint32_t>(L, 2));
15543 pushBoolean(L, true);
15544 } else {
15545 lua_pushnil(L);
15546 }
15547 return 1;
15548}
15549
15550int LuaScriptInterface::luaWeaponWandDamage(lua_State *L) {
15551 // weapon:damage(damage[min, max]) only use this if the weapon is a wand!
15552 WeaponWand *weapon = getUserdata<WeaponWand>(L, 1);
15553 if (weapon) {
15554 weapon->setMinChange(getNumber<uint32_t>(L, 2));
15555 if (lua_gettop(L) > 2) {
15556 weapon->setMaxChange(getNumber<uint32_t>(L, 3));
15557 } else {
15558 weapon->setMaxChange(getNumber<uint32_t>(L, 2));
15559 }
15560 pushBoolean(L, true);
15561 } else {
15562 lua_pushnil(L);
15563 }
15564 return 1;
15565}
15566
15567int LuaScriptInterface::luaWeaponElement(lua_State *L) {
15568 // weapon:element(combatType)
15569 Weapon *weapon = getUserdata<Weapon>(L, 1);
15570 if (weapon) {
15571 if (!getNumber<CombatType_t>(L, 2)) {
15572 std::string element = getString(L, 2);
15573 std::string tmpStrValue = asLowerCaseString(element);
15574 if (tmpStrValue == "earth") {
15575 weapon->params.combatType = COMBAT_EARTHDAMAGE;
15576 } else if (tmpStrValue == "ice") {
15577 weapon->params.combatType = COMBAT_ICEDAMAGE;
15578 } else if (tmpStrValue == "energy") {
15579 weapon->params.combatType = COMBAT_ENERGYDAMAGE;
15580 } else if (tmpStrValue == "fire") {
15581 weapon->params.combatType = COMBAT_FIREDAMAGE;
15582 } else if (tmpStrValue == "death") {
15583 weapon->params.combatType = COMBAT_DEATHDAMAGE;
15584 } else if (tmpStrValue == "holy") {
15585 weapon->params.combatType = COMBAT_HOLYDAMAGE;
15586 } else {
15587 std::cout << "[Warning - weapon:element] Type \"" << element
15588 << "\" does not exist." << std::endl;
15589 }
15590 } else {
15591 weapon->params.combatType = getNumber<CombatType_t>(L, 2);
15592 }
15593 pushBoolean(L, true);
15594 } else {
15595 lua_pushnil(L);
15596 }
15597 return 1;
15598}
15599
15600int LuaScriptInterface::luaWeaponPremium(lua_State *L) {
15601 // weapon:premium(bool)
15602 Weapon *weapon = getUserdata<Weapon>(L, 1);
15603 if (weapon) {
15604 weapon->setNeedPremium(getBoolean(L, 2));
15605 weapon->setWieldInfo(WIELDINFO_PREMIUM);
15606 pushBoolean(L, true);
15607 } else {
15608 lua_pushnil(L);
15609 }
15610 return 1;
15611}
15612
15613int LuaScriptInterface::luaWeaponVocation(lua_State *L) {
15614 // weapon:vocation(vocName[, showInDescription = false, lastVoc = false])
15615 Weapon *weapon = getUserdata<Weapon>(L, 1);
15616 if (weapon) {
15617 weapon->addVocWeaponMap(getString(L, 2));
15618 weapon->setWieldInfo(WIELDINFO_VOCREQ);
15619 std::string tmp;
15620 bool showInDescription = getBoolean(L, 3, false);
15621 bool lastVoc = getBoolean(L, 4, false);
15622
15623 if (showInDescription) {
15624 if (weapon->getVocationString().empty()) {
15625 tmp = asLowerCaseString(getString(L, 2));
15626 tmp += "s";
15627 weapon->setVocationString(tmp);
15628 } else {
15629 tmp = weapon->getVocationString();
15630 if (lastVoc) {
15631 tmp += " and ";
15632 } else {
15633 tmp += ", ";
15634 }
15635 tmp += asLowerCaseString(getString(L, 2));
15636 tmp += "s";
15637 weapon->setVocationString(tmp);
15638 }
15639 }
15640 pushBoolean(L, true);
15641 } else {
15642 lua_pushnil(L);
15643 }
15644 return 1;
15645}
15646
15647int LuaScriptInterface::luaWeaponId(lua_State *L) {
15648 // weapon:id(id)
15649 Weapon *weapon = getUserdata<Weapon>(L, 1);
15650 if (weapon) {
15651 weapon->setID(getNumber<uint32_t>(L, 2));
15652 pushBoolean(L, true);
15653 } else {
15654 lua_pushnil(L);
15655 }
15656 return 1;
15657}
15658
15659int LuaScriptInterface::luaWeaponAttack(lua_State *L) {
15660 // weapon:attack(atk)
15661 Weapon *weapon = getUserdata<Weapon>(L, 1);
15662 if (weapon) {
15663 uint16_t id = weapon->getID();
15664 ItemType &it = Item::items.getItemType(id);
15665 it.attack = getNumber<int32_t>(L, 2);
15666 pushBoolean(L, true);
15667 } else {
15668 lua_pushnil(L);
15669 }
15670 return 1;
15671}
15672
15673int LuaScriptInterface::luaWeaponDefense(lua_State *L) {
15674 // weapon:defense(defense[, extraDefense])
15675 Weapon *weapon = getUserdata<Weapon>(L, 1);
15676 if (weapon) {
15677 uint16_t id = weapon->getID();
15678 ItemType &it = Item::items.getItemType(id);
15679 it.defense = getNumber<int32_t>(L, 2);
15680 if (lua_gettop(L) > 2) {
15681 it.extraDefense = getNumber<int32_t>(L, 3);
15682 }
15683 pushBoolean(L, true);
15684 } else {
15685 lua_pushnil(L);
15686 }
15687 return 1;
15688}
15689
15690int LuaScriptInterface::luaWeaponRange(lua_State *L) {
15691 // weapon:range(range)
15692 Weapon *weapon = getUserdata<Weapon>(L, 1);
15693 if (weapon) {
15694 uint16_t id = weapon->getID();
15695 ItemType &it = Item::items.getItemType(id);
15696 it.shootRange = getNumber<uint8_t>(L, 2);
15697 pushBoolean(L, true);
15698 } else {
15699 lua_pushnil(L);
15700 }
15701 return 1;
15702}
15703
15704int LuaScriptInterface::luaWeaponCharges(lua_State *L) {
15705 // weapon:charges(charges[, showCharges = true])
15706 Weapon *weapon = getUserdata<Weapon>(L, 1);
15707 if (weapon) {
15708 bool showCharges = getBoolean(L, 3, true);
15709 uint16_t id = weapon->getID();
15710 ItemType &it = Item::items.getItemType(id);
15711
15712 it.charges = getNumber<uint8_t>(L, 2);
15713 it.showCharges = showCharges;
15714 pushBoolean(L, true);
15715 } else {
15716 lua_pushnil(L);
15717 }
15718 return 1;
15719}
15720
15721int LuaScriptInterface::luaWeaponDuration(lua_State *L) {
15722 // weapon:duration(duration[, showDuration = true])
15723 Weapon *weapon = getUserdata<Weapon>(L, 1);
15724 if (weapon) {
15725 bool showDuration = getBoolean(L, 3, true);
15726 uint16_t id = weapon->getID();
15727 ItemType &it = Item::items.getItemType(id);
15728
15729 it.decayTime = getNumber<uint32_t>(L, 2);
15730 it.showDuration = showDuration;
15731 pushBoolean(L, true);
15732 } else {
15733 lua_pushnil(L);
15734 }
15735 return 1;
15736}
15737
15738int LuaScriptInterface::luaWeaponDecayTo(lua_State *L) {
15739 // weapon:decayTo([itemid = 0]
15740 Weapon *weapon = getUserdata<Weapon>(L, 1);
15741 if (weapon) {
15742 uint16_t itemid = getNumber<uint16_t>(L, 2, 0);
15743 uint16_t id = weapon->getID();
15744 ItemType &it = Item::items.getItemType(id);
15745
15746 it.decayTo = itemid;
15747 pushBoolean(L, true);
15748 } else {
15749 lua_pushnil(L);
15750 }
15751 return 1;
15752}
15753
15754int LuaScriptInterface::luaWeaponTransformEquipTo(lua_State *L) {
15755 // weapon:transformEquipTo(itemid)
15756 Weapon *weapon = getUserdata<Weapon>(L, 1);
15757 if (weapon) {
15758 uint16_t id = weapon->getID();
15759 ItemType &it = Item::items.getItemType(id);
15760 it.transformEquipTo = getNumber<uint16_t>(L, 2);
15761 pushBoolean(L, true);
15762 } else {
15763 lua_pushnil(L);
15764 }
15765 return 1;
15766}
15767
15768int LuaScriptInterface::luaWeaponTransformDeEquipTo(lua_State *L) {
15769 // weapon:transformDeEquipTo(itemid)
15770 Weapon *weapon = getUserdata<Weapon>(L, 1);
15771 if (weapon) {
15772 uint16_t id = weapon->getID();
15773 ItemType &it = Item::items.getItemType(id);
15774 it.transformDeEquipTo = getNumber<uint16_t>(L, 2);
15775 pushBoolean(L, true);
15776 } else {
15777 lua_pushnil(L);
15778 }
15779 return 1;
15780}
15781
15782int LuaScriptInterface::luaWeaponShootType(lua_State *L) {
15783 // weapon:shootType(type)
15784 Weapon *weapon = getUserdata<Weapon>(L, 1);
15785 if (weapon) {
15786 uint16_t id = weapon->getID();
15787 ItemType &it = Item::items.getItemType(id);
15788 it.shootType = getNumber<ShootType_t>(L, 2);
15789 pushBoolean(L, true);
15790 } else {
15791 lua_pushnil(L);
15792 }
15793 return 1;
15794}
15795
15796int LuaScriptInterface::luaWeaponSlotType(lua_State *L) {
15797 // weapon:slotType(slot)
15798 Weapon *weapon = getUserdata<Weapon>(L, 1);
15799 if (weapon) {
15800 uint16_t id = weapon->getID();
15801 ItemType &it = Item::items.getItemType(id);
15802 std::string slot = getString(L, 2);
15803
15804 if (slot == "two-handed") {
15805 it.slotPosition |= SLOTP_TWO_HAND;
15806 } else {
15807 it.slotPosition |= SLOTP_HAND;
15808 }
15809 pushBoolean(L, true);
15810 } else {
15811 lua_pushnil(L);
15812 }
15813 return 1;
15814}
15815
15816int LuaScriptInterface::luaWeaponAmmoType(lua_State *L) {
15817 // weapon:ammoType(type)
15818 WeaponDistance *weapon = getUserdata<WeaponDistance>(L, 1);
15819 if (weapon) {
15820 uint16_t id = weapon->getID();
15821 ItemType &it = Item::items.getItemType(id);
15822 std::string type = getString(L, 2);
15823
15824 if (type == "arrow") {
15825 it.ammoType = AMMO_ARROW;
15826 } else if (type == "bolt") {
15827 it.ammoType = AMMO_BOLT;
15828 } else {
15829 std::cout << "[Warning - weapon:ammoType] Type \"" << type
15830 << "\" does not exist." << std::endl;
15831 lua_pushnil(L);
15832 return 1;
15833 }
15834 pushBoolean(L, true);
15835 } else {
15836 lua_pushnil(L);
15837 }
15838 return 1;
15839}
15840
15841int LuaScriptInterface::luaWeaponHitChance(lua_State *L) {
15842 // weapon:hitChance(chance)
15843 Weapon *weapon = getUserdata<Weapon>(L, 1);
15844 if (weapon) {
15845 uint16_t id = weapon->getID();
15846 ItemType &it = Item::items.getItemType(id);
15847 it.hitChance = getNumber<int8_t>(L, 2);
15848 pushBoolean(L, true);
15849 } else {
15850 lua_pushnil(L);
15851 }
15852 return 1;
15853}
15854
15855int LuaScriptInterface::luaWeaponMaxHitChance(lua_State *L) {
15856 // weapon:maxHitChance(max)
15857 Weapon *weapon = getUserdata<Weapon>(L, 1);
15858 if (weapon) {
15859 uint16_t id = weapon->getID();
15860 ItemType &it = Item::items.getItemType(id);
15861 it.maxHitChance = getNumber<int32_t>(L, 2);
15862 pushBoolean(L, true);
15863 } else {
15864 lua_pushnil(L);
15865 }
15866 return 1;
15867}
15868
15869int LuaScriptInterface::luaWeaponExtraElement(lua_State *L) {
15870 // weapon:extraElement(atk, combatType)
15871 Weapon *weapon = getUserdata<Weapon>(L, 1);
15872 if (weapon) {
15873 uint16_t id = weapon->getID();
15874 ItemType &it = Item::items.getItemType(id);
15875 it.abilities.get()->elementDamage = getNumber<uint16_t>(L, 2);
15876
15877 if (!getNumber<CombatType_t>(L, 3)) {
15878 std::string element = getString(L, 3);
15879 std::string tmpStrValue = asLowerCaseString(element);
15880 if (tmpStrValue == "earth") {
15881 it.abilities.get()->elementType = COMBAT_EARTHDAMAGE;
15882 } else if (tmpStrValue == "ice") {
15883 it.abilities.get()->elementType = COMBAT_ICEDAMAGE;
15884 } else if (tmpStrValue == "energy") {
15885 it.abilities.get()->elementType = COMBAT_ENERGYDAMAGE;
15886 } else if (tmpStrValue == "fire") {
15887 it.abilities.get()->elementType = COMBAT_FIREDAMAGE;
15888 } else if (tmpStrValue == "death") {
15889 it.abilities.get()->elementType = COMBAT_DEATHDAMAGE;
15890 } else if (tmpStrValue == "holy") {
15891 it.abilities.get()->elementType = COMBAT_HOLYDAMAGE;
15892 } else {
15893 std::cout << "[Warning - weapon:extraElement] Type \"" << element
15894 << "\" does not exist." << std::endl;
15895 }
15896 } else {
15897 it.abilities.get()->elementType = getNumber<CombatType_t>(L, 3);
15898 }
15899 pushBoolean(L, true);
15900 } else {
15901 lua_pushnil(L);
15902 }
15903 return 1;
15904}
15905
15906//
15907LuaEnvironment::LuaEnvironment() : LuaScriptInterface("Main Interface") {}
15908
15909LuaEnvironment::~LuaEnvironment() {
15910 delete testInterface;
15911 closeState();
15912}
15913
15914bool LuaEnvironment::initState() {
15915 luaState = luaL_newstate();
15916 if (!luaState) {
15917 return false;
15918 }
15919
15920 luaL_openlibs(luaState);
15921 registerFunctions();
15922
15923 runningEventId = EVENT_ID_USER;
15924 return true;
15925}
15926
15927bool LuaEnvironment::reInitState() {
15928 // TODO: get children, reload children
15929 closeState();
15930 return initState();
15931}
15932
15933bool LuaEnvironment::closeState() {
15934 if (!luaState) {
15935 return false;
15936 }
15937
15938 for (const auto &combatEntry : combatIdMap) {
15939 clearCombatObjects(combatEntry.first);
15940 }
15941
15942 for (const auto &areaEntry : areaIdMap) {
15943 clearAreaObjects(areaEntry.first);
15944 }
15945
15946 for (auto &timerEntry : timerEvents) {
15947 LuaTimerEventDesc timerEventDesc = std::move(timerEntry.second);
15948 for (int32_t parameter : timerEventDesc.parameters) {
15949 luaL_unref(luaState, LUA_REGISTRYINDEX, parameter);
15950 }
15951 luaL_unref(luaState, LUA_REGISTRYINDEX, timerEventDesc.function);
15952 }
15953
15954 combatIdMap.clear();
15955 areaIdMap.clear();
15956 timerEvents.clear();
15957 cacheFiles.clear();
15958
15959 lua_close(luaState);
15960 luaState = nullptr;
15961 return true;
15962}
15963
15964LuaScriptInterface *LuaEnvironment::getTestInterface() {
15965 if (!testInterface) {
15966 testInterface = new LuaScriptInterface("Test Interface");
15967 testInterface->initState();
15968 }
15969 return testInterface;
15970}
15971
15972Combat *LuaEnvironment::getCombatObject(uint32_t id) const {
15973 auto it = combatMap.find(id);
15974 if (it == combatMap.end()) {
15975 return nullptr;
15976 }
15977 return it->second;
15978}
15979
15980Combat *LuaEnvironment::createCombatObject(LuaScriptInterface *interface) {
15981 Combat *combat = new Combat;
15982 combatMap[++lastCombatId] = combat;
15983 combatIdMap[interface].push_back(lastCombatId);
15984 return combat;
15985}
15986
15987void LuaEnvironment::clearCombatObjects(LuaScriptInterface *interface) {
15988 auto it = combatIdMap.find(interface);
15989 if (it == combatIdMap.end()) {
15990 return;
15991 }
15992
15993 for (uint32_t id : it->second) {
15994 auto itt = combatMap.find(id);
15995 if (itt != combatMap.end()) {
15996 delete itt->second;
15997 combatMap.erase(itt);
15998 }
15999 }
16000 it->second.clear();
16001}
16002
16003AreaCombat *LuaEnvironment::getAreaObject(uint32_t id) const {
16004 auto it = areaMap.find(id);
16005 if (it == areaMap.end()) {
16006 return nullptr;
16007 }
16008 return it->second;
16009}
16010
16011uint32_t LuaEnvironment::createAreaObject(LuaScriptInterface *interface) {
16012 areaMap[++lastAreaId] = new AreaCombat;
16013 areaIdMap[interface].push_back(lastAreaId);
16014 return lastAreaId;
16015}
16016
16017void LuaEnvironment::clearAreaObjects(LuaScriptInterface *interface) {
16018 auto it = areaIdMap.find(interface);
16019 if (it == areaIdMap.end()) {
16020 return;
16021 }
16022
16023 for (uint32_t id : it->second) {
16024 auto itt = areaMap.find(id);
16025 if (itt != areaMap.end()) {
16026 delete itt->second;
16027 areaMap.erase(itt);
16028 }
16029 }
16030 it->second.clear();
16031}
16032
16033void LuaEnvironment::executeTimerEvent(uint32_t eventIndex) {
16034 auto it = timerEvents.find(eventIndex);
16035 if (it == timerEvents.end()) {
16036 return;
16037 }
16038
16039 LuaTimerEventDesc timerEventDesc = std::move(it->second);
16040 timerEvents.erase(it);
16041
16042 // push function
16043 lua_rawgeti(luaState, LUA_REGISTRYINDEX, timerEventDesc.function);
16044
16045 // push parameters
16046 for (auto parameter : boost::adaptors::reverse(timerEventDesc.parameters)) {
16047 lua_rawgeti(luaState, LUA_REGISTRYINDEX, parameter);
16048 }
16049
16050 // call the function
16051 if (reserveScriptEnv()) {
16052 ScriptEnvironment *env = getScriptEnv();
16053 env->setTimerEvent();
16054 env->setScriptId(timerEventDesc.scriptId, this);
16055 callFunction(timerEventDesc.parameters.size());
16056 } else {
16057 std::cout
16058 << "[Error - LuaScriptInterface::executeTimerEvent] Call stack overflow"
16059 << std::endl;
16060 }
16061
16062 // free resources
16063 luaL_unref(luaState, LUA_REGISTRYINDEX, timerEventDesc.function);
16064 for (auto parameter : timerEventDesc.parameters) {
16065 luaL_unref(luaState, LUA_REGISTRYINDEX, parameter);
16066 }
16067}
16068
16069
Top