From 1960d6e1d863a1ce45fc250708950d9eae2b4ba7 Mon Sep 17 00:00:00 2001 From: Antz Date: Thu, 16 Nov 2023 22:08:48 +0000 Subject: [PATCH] [Eluna] Updated Eluna to latest revision. Thanks to @PargeLenis for helping fix --- src/game/CMakeLists.txt | 12 +- src/modules/Eluna/BindingMap.h | 2 +- src/modules/Eluna/CMakeLists.txt | 80 - src/modules/Eluna/CMangos/AuraMethods.h | 206 + .../Eluna/CMangos/BattleGroundMethods.h | 255 + src/modules/Eluna/CMangos/CorpseMethods.h | 91 + src/modules/Eluna/CMangos/CreatureMethods.h | 1223 +++++ src/modules/Eluna/CMangos/ElunaQueryMethods.h | 343 ++ src/modules/Eluna/CMangos/GameObjectMethods.h | 340 ++ src/modules/Eluna/CMangos/GlobalMethods.h | 3076 +++++++++++ src/modules/Eluna/CMangos/GroupMethods.h | 423 ++ src/modules/Eluna/CMangos/GuildMethods.h | 273 + src/modules/Eluna/CMangos/ItemMethods.h | 803 +++ src/modules/Eluna/CMangos/MapMethods.h | 341 ++ src/modules/Eluna/CMangos/ObjectMethods.h | 498 ++ src/modules/Eluna/CMangos/PlayerMethods.h | 4036 +++++++++++++++ src/modules/Eluna/CMangos/QuestMethods.h | 199 + src/modules/Eluna/CMangos/SpellMethods.h | 194 + src/modules/Eluna/CMangos/UnitMethods.h | 2689 ++++++++++ src/modules/Eluna/CMangos/VehicleMethods.h | 115 + .../Eluna/CMangos/WorldObjectMethods.h | 1163 +++++ .../Eluna/CMangos/WorldPacketMethods.h | 350 ++ src/modules/Eluna/ElunaCompat.cpp | 64 + src/modules/Eluna/ElunaCompat.h | 30 + src/modules/Eluna/ElunaCreatureAI.h | 21 +- src/modules/Eluna/ElunaEventMgr.h | 2 + src/modules/Eluna/ElunaIncludes.h | 55 +- src/modules/Eluna/ElunaInstanceAI.h | 10 + src/modules/Eluna/ElunaTemplate.h | 2 + src/modules/Eluna/ElunaUtility.cpp | 19 +- src/modules/Eluna/ElunaUtility.h | 26 +- src/modules/Eluna/GossipHooks.cpp | 22 +- src/modules/Eluna/GroupHooks.cpp | 27 + src/modules/Eluna/GuildHooks.cpp | 57 + src/modules/Eluna/Hooks.h | 23 +- src/modules/Eluna/ItemHooks.cpp | 16 + src/modules/Eluna/LuaEngine.cpp | 7 +- src/modules/Eluna/LuaEngine.h | 24 + src/modules/Eluna/LuaFunctions.cpp | 1331 +---- src/modules/Eluna/{ => Mangos}/AuraMethods.h | 23 + .../Eluna/Mangos/BattleGroundMethods.h | 281 ++ .../Eluna/{ => Mangos}/CorpseMethods.h | 14 + .../Eluna/{ => Mangos}/CreatureMethods.h | 104 +- .../Eluna/{ => Mangos}/ElunaQueryMethods.h | 26 + .../Eluna/{ => Mangos}/GameObjectMethods.h | 34 + .../Eluna/{ => Mangos}/GlobalMethods.h | 150 +- src/modules/Eluna/{ => Mangos}/GroupMethods.h | 47 +- src/modules/Eluna/{ => Mangos}/GuildMethods.h | 31 + src/modules/Eluna/{ => Mangos}/ItemMethods.h | 78 + src/modules/Eluna/{ => Mangos}/MapMethods.h | 32 + .../Eluna/{ => Mangos}/ObjectMethods.h | 54 +- .../Eluna/{ => Mangos}/PlayerMethods.h | 345 +- src/modules/Eluna/{ => Mangos}/QuestMethods.h | 25 + src/modules/Eluna/{ => Mangos}/SpellMethods.h | 25 + src/modules/Eluna/{ => Mangos}/UnitMethods.h | 204 +- .../Eluna/{ => Mangos}/VehicleMethods.h | 17 + .../Eluna/{ => Mangos}/WorldObjectMethods.h | 60 + .../Eluna/{ => Mangos}/WorldPacketMethods.h | 36 + src/modules/Eluna/PacketHooks.cpp | 12 + src/modules/Eluna/PlayerHooks.cpp | 119 + src/modules/Eluna/README.md | 23 +- src/modules/Eluna/ServerHooks.cpp | 2 +- src/modules/Eluna/TrinityCore/AuraMethods.h | 195 + .../Eluna/TrinityCore/BattleGroundMethods.h | 253 + src/modules/Eluna/TrinityCore/CorpseMethods.h | 91 + .../Eluna/TrinityCore/CreatureMethods.h | 1361 +++++ .../Eluna/TrinityCore/ElunaQueryMethods.h | 342 ++ .../Eluna/TrinityCore/GameObjectMethods.h | 347 ++ src/modules/Eluna/TrinityCore/GlobalMethods.h | 3017 +++++++++++ src/modules/Eluna/TrinityCore/GroupMethods.h | 477 ++ src/modules/Eluna/TrinityCore/GuildMethods.h | 276 + src/modules/Eluna/TrinityCore/ItemMethods.h | 885 ++++ src/modules/Eluna/TrinityCore/MapMethods.h | 370 ++ src/modules/Eluna/TrinityCore/ObjectMethods.h | 498 ++ src/modules/Eluna/TrinityCore/PlayerMethods.h | 4133 +++++++++++++++ src/modules/Eluna/TrinityCore/QuestMethods.h | 203 + src/modules/Eluna/TrinityCore/SpellMethods.h | 198 + src/modules/Eluna/TrinityCore/UnitMethods.h | 2711 ++++++++++ .../Eluna/TrinityCore/VehicleMethods.h | 114 + .../Eluna/TrinityCore/WorldObjectMethods.h | 1183 +++++ .../Eluna/TrinityCore/WorldPacketMethods.h | 347 ++ src/modules/Eluna/VMangos/AuraMethods.h | 230 + .../Eluna/{ => VMangos}/BattleGroundMethods.h | 35 +- src/modules/Eluna/VMangos/CorpseMethods.h | 95 + src/modules/Eluna/VMangos/CreatureMethods.h | 1517 ++++++ src/modules/Eluna/VMangos/ElunaQueryMethods.h | 399 ++ src/modules/Eluna/VMangos/GameObjectMethods.h | 355 ++ src/modules/Eluna/VMangos/GlobalMethods.h | 2973 +++++++++++ src/modules/Eluna/VMangos/GroupMethods.h | 473 ++ src/modules/Eluna/VMangos/GuildMethods.h | 329 ++ src/modules/Eluna/VMangos/ItemMethods.h | 843 ++++ src/modules/Eluna/VMangos/MapMethods.h | 405 ++ src/modules/Eluna/VMangos/ObjectMethods.h | 506 ++ src/modules/Eluna/VMangos/PlayerMethods.h | 4477 +++++++++++++++++ src/modules/Eluna/VMangos/QuestMethods.h | 212 + src/modules/Eluna/VMangos/SpellMethods.h | 218 + src/modules/Eluna/VMangos/UnitMethods.h | 3165 ++++++++++++ src/modules/Eluna/VMangos/VehicleMethods.h | 128 + .../Eluna/VMangos/WorldObjectMethods.h | 1231 +++++ .../Eluna/VMangos/WorldPacketMethods.h | 346 ++ src/modules/Eluna/docs/DOC_GEN.md | 2 +- src/modules/Eluna/docs/ElunaDoc/__main__.py | 3 +- .../Eluna/docs/ElunaDoc/static/main.js | 10 +- .../Eluna/docs/ElunaDoc/templates/_base.html | 2 +- .../Eluna/docs/ElunaDoc/templates/index.html | 4 +- src/modules/Eluna/docs/INSTALL.md | 14 +- src/modules/Eluna/docs/MERGING.md | 6 +- .../Eluna/extensions/StackTracePlus/README.md | 40 +- .../StackTracePlus/StackTracePlus.ext | 578 +-- src/modules/Eluna/lmarshal.cpp | 7 +- 110 files changed, 53971 insertions(+), 1823 deletions(-) delete mode 100644 src/modules/Eluna/CMakeLists.txt create mode 100644 src/modules/Eluna/CMangos/AuraMethods.h create mode 100644 src/modules/Eluna/CMangos/BattleGroundMethods.h create mode 100644 src/modules/Eluna/CMangos/CorpseMethods.h create mode 100644 src/modules/Eluna/CMangos/CreatureMethods.h create mode 100644 src/modules/Eluna/CMangos/ElunaQueryMethods.h create mode 100644 src/modules/Eluna/CMangos/GameObjectMethods.h create mode 100644 src/modules/Eluna/CMangos/GlobalMethods.h create mode 100644 src/modules/Eluna/CMangos/GroupMethods.h create mode 100644 src/modules/Eluna/CMangos/GuildMethods.h create mode 100644 src/modules/Eluna/CMangos/ItemMethods.h create mode 100644 src/modules/Eluna/CMangos/MapMethods.h create mode 100644 src/modules/Eluna/CMangos/ObjectMethods.h create mode 100644 src/modules/Eluna/CMangos/PlayerMethods.h create mode 100644 src/modules/Eluna/CMangos/QuestMethods.h create mode 100644 src/modules/Eluna/CMangos/SpellMethods.h create mode 100644 src/modules/Eluna/CMangos/UnitMethods.h create mode 100644 src/modules/Eluna/CMangos/VehicleMethods.h create mode 100644 src/modules/Eluna/CMangos/WorldObjectMethods.h create mode 100644 src/modules/Eluna/CMangos/WorldPacketMethods.h create mode 100644 src/modules/Eluna/ElunaCompat.cpp create mode 100644 src/modules/Eluna/ElunaCompat.h rename src/modules/Eluna/{ => Mangos}/AuraMethods.h (88%) create mode 100644 src/modules/Eluna/Mangos/BattleGroundMethods.h rename src/modules/Eluna/{ => Mangos}/CorpseMethods.h (82%) rename src/modules/Eluna/{ => Mangos}/CreatureMethods.h (89%) rename src/modules/Eluna/{ => Mangos}/ElunaQueryMethods.h (92%) rename src/modules/Eluna/{ => Mangos}/GameObjectMethods.h (87%) rename src/modules/Eluna/{ => Mangos}/GlobalMethods.h (94%) rename src/modules/Eluna/{ => Mangos}/GroupMethods.h (86%) rename src/modules/Eluna/{ => Mangos}/GuildMethods.h (89%) rename src/modules/Eluna/{ => Mangos}/ItemMethods.h (86%) rename src/modules/Eluna/{ => Mangos}/MapMethods.h (90%) rename src/modules/Eluna/{ => Mangos}/ObjectMethods.h (88%) rename src/modules/Eluna/{ => Mangos}/PlayerMethods.h (88%) rename src/modules/Eluna/{ => Mangos}/QuestMethods.h (88%) rename src/modules/Eluna/{ => Mangos}/SpellMethods.h (87%) rename src/modules/Eluna/{ => Mangos}/UnitMethods.h (90%) rename src/modules/Eluna/{ => Mangos}/VehicleMethods.h (85%) rename src/modules/Eluna/{ => Mangos}/WorldObjectMethods.h (93%) rename src/modules/Eluna/{ => Mangos}/WorldPacketMethods.h (86%) create mode 100644 src/modules/Eluna/TrinityCore/AuraMethods.h create mode 100644 src/modules/Eluna/TrinityCore/BattleGroundMethods.h create mode 100644 src/modules/Eluna/TrinityCore/CorpseMethods.h create mode 100644 src/modules/Eluna/TrinityCore/CreatureMethods.h create mode 100644 src/modules/Eluna/TrinityCore/ElunaQueryMethods.h create mode 100644 src/modules/Eluna/TrinityCore/GameObjectMethods.h create mode 100644 src/modules/Eluna/TrinityCore/GlobalMethods.h create mode 100644 src/modules/Eluna/TrinityCore/GroupMethods.h create mode 100644 src/modules/Eluna/TrinityCore/GuildMethods.h create mode 100644 src/modules/Eluna/TrinityCore/ItemMethods.h create mode 100644 src/modules/Eluna/TrinityCore/MapMethods.h create mode 100644 src/modules/Eluna/TrinityCore/ObjectMethods.h create mode 100644 src/modules/Eluna/TrinityCore/PlayerMethods.h create mode 100644 src/modules/Eluna/TrinityCore/QuestMethods.h create mode 100644 src/modules/Eluna/TrinityCore/SpellMethods.h create mode 100644 src/modules/Eluna/TrinityCore/UnitMethods.h create mode 100644 src/modules/Eluna/TrinityCore/VehicleMethods.h create mode 100644 src/modules/Eluna/TrinityCore/WorldObjectMethods.h create mode 100644 src/modules/Eluna/TrinityCore/WorldPacketMethods.h create mode 100644 src/modules/Eluna/VMangos/AuraMethods.h rename src/modules/Eluna/{ => VMangos}/BattleGroundMethods.h (82%) create mode 100644 src/modules/Eluna/VMangos/CorpseMethods.h create mode 100644 src/modules/Eluna/VMangos/CreatureMethods.h create mode 100644 src/modules/Eluna/VMangos/ElunaQueryMethods.h create mode 100644 src/modules/Eluna/VMangos/GameObjectMethods.h create mode 100644 src/modules/Eluna/VMangos/GlobalMethods.h create mode 100644 src/modules/Eluna/VMangos/GroupMethods.h create mode 100644 src/modules/Eluna/VMangos/GuildMethods.h create mode 100644 src/modules/Eluna/VMangos/ItemMethods.h create mode 100644 src/modules/Eluna/VMangos/MapMethods.h create mode 100644 src/modules/Eluna/VMangos/ObjectMethods.h create mode 100644 src/modules/Eluna/VMangos/PlayerMethods.h create mode 100644 src/modules/Eluna/VMangos/QuestMethods.h create mode 100644 src/modules/Eluna/VMangos/SpellMethods.h create mode 100644 src/modules/Eluna/VMangos/UnitMethods.h create mode 100644 src/modules/Eluna/VMangos/VehicleMethods.h create mode 100644 src/modules/Eluna/VMangos/WorldObjectMethods.h create mode 100644 src/modules/Eluna/VMangos/WorldPacketMethods.h diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt index bad1d0459d..e69093c305 100644 --- a/src/game/CMakeLists.txt +++ b/src/game/CMakeLists.txt @@ -83,7 +83,12 @@ source_group("World\\Handlers" FILES ${SRC_GRP_WORLD_HANDLERS}) # Build the Eluna library if enabled if(SCRIPT_LIB_ELUNA) - file(GLOB SRC_GRP_ELUNA ${CMAKE_SOURCE_DIR}/src/modules/Eluna/*.cpp ${CMAKE_SOURCE_DIR}/src/modules/Eluna/*.h) + file(GLOB SRC_GRP_ELUNA + ${CMAKE_SOURCE_DIR}/src/modules/Eluna/*.cpp + ${CMAKE_SOURCE_DIR}/src/modules/Eluna/*.h + ${CMAKE_SOURCE_DIR}/src/modules/Eluna/Mangos/*.cpp + ${CMAKE_SOURCE_DIR}/src/modules/Eluna/Mangos/*.h + ) source_group("Eluna" FILES ${SRC_GRP_ELUNA}) endif() @@ -255,7 +260,10 @@ target_include_directories(game Warden Warden/Modules WorldHandlers - $<$:${CMAKE_SOURCE_DIR}/src/modules/Eluna> + $<$: + ${CMAKE_SOURCE_DIR}/src/modules/Eluna + ${CMAKE_SOURCE_DIR}/src/modules/Eluna/Mangos + > $<$: ${CMAKE_SOURCE_DIR}/src/modules/Bots ${CMAKE_SOURCE_DIR}/src/modules/Bots/playerbot diff --git a/src/modules/Eluna/BindingMap.h b/src/modules/Eluna/BindingMap.h index 8fc9d1df5b..287d48929b 100644 --- a/src/modules/Eluna/BindingMap.h +++ b/src/modules/Eluna/BindingMap.h @@ -279,7 +279,7 @@ class hash_helper { return std::hash::type>()(t); } - + template ::value>::type* = nullptr> static inline result_type hash(T const & t) { diff --git a/src/modules/Eluna/CMakeLists.txt b/src/modules/Eluna/CMakeLists.txt deleted file mode 100644 index eed38dc193..0000000000 --- a/src/modules/Eluna/CMakeLists.txt +++ /dev/null @@ -1,80 +0,0 @@ -# -# Copyright (C) 2010 - 2016 Eluna Lua Engine -# This program is free software licensed under GPL version 3 -# Please see the included DOCS/LICENSE.md for more information -# - -if( ${CMAKE_PROJECT_NAME} STREQUAL "MaNGOS" ) - - if ( USE_COREPCH ) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) - include_directories(${CMAKE_SOURCE_DIR}) - endif () - - # Iterates through all the source files and adds them to the solution - file(GLOB sources_localdir *.cpp *.h) - - # Adds all the method headers to its own source group - file(GLOB method_headers *Methods.h) - source_group("Methods" FILES ${method_headers}) - - set(LuaEngine_STAT_SRCS - ${LuaEngine_STAT_SRCS} - ${sources_localdir} - ) - - include_directories( - ${CMAKE_SOURCE_DIR}/dep/zlib - ${CMAKE_SOURCE_DIR}/dep/lualib - ${CMAKE_BINARY_DIR} - ${ACE_INCLUDE_DIR} - ${MYSQL_INCLUDE_DIR} - ${OPENSSL_INCLUDE_DIR} - ) - - add_library(LuaEngine STATIC - ${LuaEngine_STAT_SRCS} - ${game_STAT_SRCS} - ${game_STAT_PCH_SRC} - ) - - include_directories( - ${CMAKE_SOURCE_DIR}/dep/g3dlite - ${CMAKE_SOURCE_DIR}/src/shared - ${CMAKE_SOURCE_DIR}/src/shared/Common - ${CMAKE_SOURCE_DIR}/src/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/shared/Log - ${CMAKE_SOURCE_DIR}/src/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/shared/Threading - ${CMAKE_SOURCE_DIR}/src/framework - ${CMAKE_SOURCE_DIR}/src/framework/Platform - ${CMAKE_SOURCE_DIR}/src/game/BattleGround - ${CMAKE_SOURCE_DIR}/src/game/Server - ${CMAKE_SOURCE_DIR}/src/game/vmap - ${CMAKE_SOURCE_DIR}/src/game/Maps - ${CMAKE_SOURCE_DIR}/src/game/MotionGenerators - ${CMAKE_SOURCE_DIR}/src/game/Tools - ${CMAKE_SOURCE_DIR}/src/game/References - ${CMAKE_SOURCE_DIR}/src/game/WorldHandlers - ${CMAKE_SOURCE_DIR}/src/game/Object - ) - - if( WIN32 ) - if ( MSVC ) - add_custom_command(TARGET LuaEngine - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bin/$(ConfigurationName)/lua_scripts/extensions/" - COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/extensions" "${CMAKE_BINARY_DIR}/bin/$(ConfigurationName)/lua_scripts/extensions/" - ) - elseif ( MINGW ) - add_custom_command(TARGET LuaEngine - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bin/lua_scripts/extensions/" - COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/extensions" "${CMAKE_BINARY_DIR}/bin/lua_scripts/extensions/" - ) - endif() - endif() - - install(DIRECTORY extensions DESTINATION "${BIN_DIR}/lua_scripts/") - -endif() diff --git a/src/modules/Eluna/CMangos/AuraMethods.h b/src/modules/Eluna/CMangos/AuraMethods.h new file mode 100644 index 0000000000..2e621f8d29 --- /dev/null +++ b/src/modules/Eluna/CMangos/AuraMethods.h @@ -0,0 +1,206 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef AURAMETHODS_H +#define AURAMETHODS_H + +/*** + * The persistent effect of a [Spell] that remains on a [Unit] after the [Spell] + * has been cast. + * + * As an example, if you cast a damage-over-time spell on a target, an [Aura] is + * put on the target that deals damage continuously. + * + * [Aura]s on your player are displayed in-game as a series of icons to the left + * of the mini-map. + * + * Inherits all methods from: none + */ +namespace LuaAura +{ + /** + * Returns the [Unit] that casted the [Spell] that caused this [Aura] to be applied. + * + * @return [Unit] caster + */ + int GetCaster(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetCaster()); + return 1; + } + + /** + * Returns the GUID of the [Unit] that casted the [Spell] that caused this [Aura] to be applied. + * + * @return string caster_guid : the GUID of the Unit as a decimal string + */ + int GetCasterGUID(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetCasterGuid()); + return 1; + } + + /** + * Returns the level of the [Unit] that casted the [Spell] that caused this [Aura] to be applied. + * + * @return uint32 caster_level + */ + int GetCasterLevel(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetCaster()->GetLevel()); + return 1; + } + + /** + * Returns the amount of time left until the [Aura] expires. + * + * @return int32 duration : amount of time left in milliseconds + */ + int GetDuration(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetAuraDuration()); + return 1; + } + + /** + * Returns the ID of the [Spell] that caused this [Aura] to be applied. + * + * @return uint32 aura_id + */ + int GetAuraId(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetId()); + return 1; + } + + /** + * Returns the amount of time this [Aura] lasts when applied. + * + * To determine how much time has passed since this Aura was applied, + * subtract the result of [Aura]:GetDuration from the result of this method. + * + * @return int32 max_duration : the maximum duration of the Aura, in milliseconds + */ + int GetMaxDuration(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetAuraMaxDuration()); + return 1; + } + + /** + * Returns the number of times the [Aura] has "stacked". + * + * This is the same as the number displayed on the [Aura]'s icon in-game. + * + * @return uint32 stack_amount + */ + int GetStackAmount(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetStackAmount()); + return 1; + } + + /** + * Returns the [Unit] that the [Aura] has been applied to. + * + * @return [Unit] owner + */ + int GetOwner(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetTarget()); + return 1; + } + + /** + * Change the amount of time before the [Aura] expires. + * + * @param int32 duration : the new duration of the Aura, in milliseconds + */ + int SetDuration(lua_State* L, Aura* aura) + { + int32 duration = Eluna::CHECKVAL(L, 2); + aura->GetHolder()->SetAuraDuration(duration); +#if (defined(TBC) || defined(CLASSIC)) + aura->GetHolder()->UpdateAuraDuration(); +#else + aura->GetHolder()->SendAuraUpdate(false); +#endif + return 0; + } + + /** + * Change the maximum amount of time before the [Aura] expires. + * + * This does not affect the current duration of the [Aura], but if the [Aura] + * is reset to the maximum duration, it will instead change to `duration`. + * + * @param int32 duration : the new maximum duration of the Aura, in milliseconds + */ + int SetMaxDuration(lua_State* L, Aura* aura) + { + int32 duration = Eluna::CHECKVAL(L, 2); + aura->GetHolder()->SetAuraMaxDuration(duration); +#if (defined(TBC) || defined(CLASSIC)) + aura->GetHolder()->UpdateAuraDuration(); +#else + aura->GetHolder()->SendAuraUpdate(false); +#endif + return 0; + } + + /** + * Change the amount of times the [Aura] has "stacked" on the [Unit]. + * + * If `amount` is greater than or equal to the current number of stacks, + * then the [Aura] has its duration reset to the maximum duration. + * + * @param uint32 amount + */ + int SetStackAmount(lua_State* L, Aura* aura) + { + uint8 amount = Eluna::CHECKVAL(L, 2); +#ifndef CATA + aura->GetHolder()->SetStackAmount(amount, aura->GetTarget()); +#else + aura->GetHolder()->SetStackAmount(amount); +#endif + return 0; + } + + /** + * Remove this [Aura] from the [Unit] it is applied to. + */ + int Remove(lua_State* L, Aura* aura) + { + aura->GetTarget()->RemoveSpellAuraHolder(aura->GetHolder(), AURA_REMOVE_BY_CANCEL); + Eluna::CHECKOBJ(L, 1)->Invalidate(); + return 0; + } + + ElunaRegister AuraMethods[] = + { + // Getters + { "GetCaster", &LuaAura::GetCaster }, + { "GetCasterGUID", &LuaAura::GetCasterGUID }, + { "GetCasterLevel", &LuaAura::GetCasterLevel }, + { "GetDuration", &LuaAura::GetDuration }, + { "GetMaxDuration", &LuaAura::GetMaxDuration }, + { "GetAuraId", &LuaAura::GetAuraId }, + { "GetStackAmount", &LuaAura::GetStackAmount }, + { "GetOwner", &LuaAura::GetOwner }, + + // Setters + { "SetDuration", &LuaAura::SetDuration }, + { "SetMaxDuration", &LuaAura::SetMaxDuration }, + { "SetStackAmount", &LuaAura::SetStackAmount }, + + // Other + { "Remove", &LuaAura::Remove }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/BattleGroundMethods.h b/src/modules/Eluna/CMangos/BattleGroundMethods.h new file mode 100644 index 0000000000..bc0a9aad9c --- /dev/null +++ b/src/modules/Eluna/CMangos/BattleGroundMethods.h @@ -0,0 +1,255 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef BATTLEGROUNDMETHODS_H +#define BATTLEGROUNDMETHODS_H + +/*** + * Contains the state of a battleground, e.g. Warsong Gulch, Arathi Basin, etc. + * + * Inherits all methods from: none + */ +namespace LuaBattleGround +{ + /** + * Returns the name of the [BattleGround]. + * + * @return string name + */ + int GetName(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetName()); + return 1; + } + + /** + * Returns the amount of alive players in the [BattleGround] by the team ID. + * + * @param [Team] team : team ID + * @return uint32 count + */ + int GetAlivePlayersCountByTeam(lua_State* L, BattleGround* bg) + { + uint32 team = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, bg->GetAlivePlayersCountByTeam((Team)team)); + return 1; + } + + /** + * Returns the [Map] of the [BattleGround]. + * + * @return [Map] map + */ + int GetMap(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, static_cast(bg->GetBgMap())); + return 1; + } + + /** + * Returns the bonus honor given by amount of kills in the specific [BattleGround]. + * + * @param uint32 kills : amount of kills + * @return uint32 bonusHonor + */ + int GetBonusHonorFromKillCount(lua_State* L, BattleGround* bg) + { + uint32 kills = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, bg->GetBonusHonorFromKill(kills)); + return 1; + } + +#ifndef AZEROTHCORE + /** + * Returns the bracket ID of the specific [BattleGround]. + * + * @return [BattleGroundBracketId] bracketId + */ + int GetBracketId(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetBracketId()); + return 1; + } +#endif + + /** + * Returns the end time of the [BattleGround]. + * + * @return uint32 endTime + */ + int GetEndTime(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetEndTime()); + return 1; + } + + /** + * Returns the amount of free slots for the selected team in the specific [BattleGround]. + * + * @param [Team] team : team ID + * @return uint32 freeSlots + */ + int GetFreeSlotsForTeam(lua_State* L, BattleGround* bg) + { + uint32 team = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, bg->GetFreeSlotsForTeam((Team)team)); + return 1; + } + + /** + * Returns the instance ID of the [BattleGround]. + * + * @return uint32 instanceId + */ + int GetInstanceId(lua_State* L, BattleGround* bg) + { +#ifndef CATA + Eluna::Push(L, bg->GetInstanceId()); +#else + Eluna::Push(L, bg->GetInstanceID()); +#endif + return 1; + } + + /** + * Returns the map ID of the [BattleGround]. + * + * @return uint32 mapId + */ + int GetMapId(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMapId()); + return 1; + } + + /** + * Returns the type ID of the [BattleGround]. + * + * @return [BattleGroundTypeId] typeId + */ + int GetTypeId(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetTypeId()); + return 1; + } + + /** + * Returns the max allowed [Player] level of the specific [BattleGround]. + * + * @return uint32 maxLevel + */ + int GetMaxLevel(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMaxLevel()); + return 1; + } + + /** + * Returns the minimum allowed [Player] level of the specific [BattleGround]. + * + * @return uint32 minLevel + */ + int GetMinLevel(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMinLevel()); + return 1; + } + + /** + * Returns the maximum allowed [Player] count of the specific [BattleGround]. + * + * @return uint32 maxPlayerCount + */ + int GetMaxPlayers(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMaxPlayers()); + return 1; + } + + /** + * Returns the minimum allowed [Player] count of the specific [BattleGround]. + * + * @return uint32 minPlayerCount + */ + int GetMinPlayers(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMinPlayers()); + return 1; + } + + /** + * Returns the maximum allowed [Player] count per team of the specific [BattleGround]. + * + * @return uint32 maxTeamPlayerCount + */ + int GetMaxPlayersPerTeam(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMaxPlayersPerTeam()); + return 1; + } + + /** + * Returns the minimum allowed [Player] count per team of the specific [BattleGround]. + * + * @return uint32 minTeamPlayerCount + */ + int GetMinPlayersPerTeam(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMinPlayersPerTeam()); + return 1; + } + + /** + * Returns the winning team of the specific [BattleGround]. + * + * @return [Team] team + */ + int GetWinner(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetWinner()); + return 1; + } + + /** + * Returns the status of the specific [BattleGround]. + * + * @return [BattleGroundStatus] status + */ + int GetStatus(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetStatus()); + return 1; + } + + ElunaRegister BattleGroundMethods[] = + { + // Getters + { "GetName", &LuaBattleGround::GetName }, + { "GetAlivePlayersCountByTeam", &LuaBattleGround::GetAlivePlayersCountByTeam }, + { "GetMap", &LuaBattleGround::GetMap }, + { "GetBonusHonorFromKillCount", &LuaBattleGround::GetBonusHonorFromKillCount }, + { "GetBracketId", &LuaBattleGround::GetBracketId }, + { "GetEndTime", &LuaBattleGround::GetEndTime }, + { "GetFreeSlotsForTeam", &LuaBattleGround::GetFreeSlotsForTeam }, + { "GetInstanceId", &LuaBattleGround::GetInstanceId }, + { "GetMapId", &LuaBattleGround::GetMapId }, + { "GetTypeId", &LuaBattleGround::GetTypeId }, + { "GetMaxLevel", &LuaBattleGround::GetMaxLevel }, + { "GetMinLevel", &LuaBattleGround::GetMinLevel }, + { "GetMaxPlayers", &LuaBattleGround::GetMaxPlayers }, + { "GetMinPlayers", &LuaBattleGround::GetMinPlayers }, + { "GetMaxPlayersPerTeam", &LuaBattleGround::GetMaxPlayersPerTeam }, + { "GetMinPlayersPerTeam", &LuaBattleGround::GetMinPlayersPerTeam }, + { "GetWinner", &LuaBattleGround::GetWinner }, + { "GetStatus", &LuaBattleGround::GetStatus }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/CorpseMethods.h b/src/modules/Eluna/CMangos/CorpseMethods.h new file mode 100644 index 0000000000..05a0e0618f --- /dev/null +++ b/src/modules/Eluna/CMangos/CorpseMethods.h @@ -0,0 +1,91 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef CORPSEMETHODS_H +#define CORPSEMETHODS_H + +/*** + * The remains of a [Player] that has died. + * + * Inherits all methods from: [Object], [WorldObject] + */ +namespace LuaCorpse +{ + /** + * Returns the GUID of the [Player] that left the [Corpse] behind. + * + * @return ObjectGuid ownerGUID + */ + int GetOwnerGUID(lua_State* L, Corpse* corpse) + { + Eluna::Push(L, corpse->GetOwnerGuid()); + return 1; + } + + /** + * Returns the time when the [Player] became a ghost and spawned this [Corpse]. + * + * @return uint32 ghostTime + */ + int GetGhostTime(lua_State* L, Corpse* corpse) + { + Eluna::Push(L, corpse->GetGhostTime()); + return 1; + } + + /** + * Returns the [CorpseType] of a [Corpse]. + * + * enum CorpseType + * { + * CORPSE_BONES = 0, + * CORPSE_RESURRECTABLE_PVE = 1, + * CORPSE_RESURRECTABLE_PVP = 2 + * }; + * + * @return [CorpseType] corpseType + */ + int GetType(lua_State* L, Corpse* corpse) + { + Eluna::Push(L, corpse->GetType()); + return 1; + } + + /** + * Sets the "ghost time" to the current time. + * + * See [Corpse:GetGhostTime]. + */ + int ResetGhostTime(lua_State* /*L*/, Corpse* corpse) + { + corpse->ResetGhostTime(); + return 0; + } + + /** + * Saves the [Corpse] to the database. + */ + int SaveToDB(lua_State* /*L*/, Corpse* corpse) + { + corpse->SaveToDB(); + return 0; + } + + ElunaRegister CorpseMethods[] = + { + // Getters + { "GetOwnerGUID", &LuaCorpse::GetOwnerGUID }, + { "GetGhostTime", &LuaCorpse::GetGhostTime }, + { "GetType", &LuaCorpse::GetType }, + + // Other + { "ResetGhostTime", &LuaCorpse::ResetGhostTime }, + { "SaveToDB", &LuaCorpse::SaveToDB }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/CreatureMethods.h b/src/modules/Eluna/CMangos/CreatureMethods.h new file mode 100644 index 0000000000..2fbc344808 --- /dev/null +++ b/src/modules/Eluna/CMangos/CreatureMethods.h @@ -0,0 +1,1223 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef CREATUREMETHODS_H +#define CREATUREMETHODS_H + +/*** + * Non-[Player] controlled [Unit]s (i.e. NPCs). + * + * Inherits all methods from: [Object], [WorldObject], [Unit] + */ +namespace LuaCreature +{ + /** + * Returns `true` if the [Creature] can regenerate health, + * and returns `false` otherwise. + * + * @return bool isRegenerating + */ + int IsRegeneratingHealth(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsRegeneratingHealth()); + return 1; + } + +#ifndef CATA + /** + * Returns `true` if the [Creature] is set to not give reputation when killed, + * and returns `false` otherwise. + * + * @return bool reputationDisabled + */ + int IsReputationGainDisabled(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsNoReputation()); + return 1; + } +#endif + + /** + * Returns `true` if the [Creature] completes the [Quest] with the ID `questID`, + * and returns `false` otherwise. + * + * @param uint32 questID : the ID of a [Quest] + * @return bool completesQuest + */ + int CanCompleteQuest(lua_State* L, Creature* creature) + { + uint32 quest_id = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->HasInvolvedQuest(quest_id)); + return 1; + } + + /** + * Returns `true` if the [Creature] can be targeted for attack, + * and returns `false` otherwise. + * + * @param bool mustBeDead = false : if `true`, only returns `true` if the [Creature] is also dead. Otherwise, it must be alive. + * @return bool targetable + */ + int IsTargetableForAttack(lua_State* L, Creature* creature) + { + bool mustBeDead = Eluna::CHECKVAL(L, 2, false); + +#ifndef CATA + Eluna::Push(L, creature->IsTargetableForAttack(mustBeDead)); +#else + Eluna::Push(L, creature->isTargetableForAttack(mustBeDead)); +#endif + return 1; + } + + /** + * Returns `true` if the [Creature] can assist `friend` in combat against `enemy`, + * and returns `false` otherwise. + * + * @param [Unit] friend : the Unit we will be assisting + * @param [Unit] enemy : the Unit that we would attack if we assist `friend` + * @param bool checkFaction = true : if `true`, the [Creature] must be the same faction as `friend` to assist + * @return bool canAssist + */ + int CanAssistTo(lua_State* L, Creature* creature) + { + Unit* u = Eluna::CHECKOBJ(L, 2); + Unit* enemy = Eluna::CHECKOBJ(L, 3); + bool checkfaction = Eluna::CHECKVAL(L, 4, true); + + Eluna::Push(L, creature->CanAssistTo(u, enemy, checkfaction)); + return 1; + } + + /** + * Returns `true` if the [Creature] has searched for combat assistance already, + * and returns `false` otherwise. + * + * @return bool searchedForAssistance + */ + int HasSearchedAssistance(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->HasSearchedAssistance()); + return 1; + } + + /** + * Returns `true` if the [Creature] will give its loot to `player`, + * and returns `false` otherwise. + * + * @return bool tapped + */ + int IsTappedBy(lua_State* L, Creature* creature) + { + Player* player = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, creature->IsTappedBy(player)); + return 1; + } + + /** + * Returns `true` if the [Creature] will give its loot to a [Player] or [Group], + * and returns `false` otherwise. + * + * @return bool hasLootRecipient + */ + int HasLootRecipient(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->HasLootRecipient()); + return 1; + } + + /** + * Returns `true` if the [Creature] can start attacking nearby hostile [Unit]s, + * and returns `false` otherwise. + * + * @return bool canAggro + */ + int CanAggro(lua_State* L, Creature* creature) + { + Eluna::Push(L, !creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)); + return 1; + } + + /** + * Returns `true` if the [Creature] can move through deep water, + * and returns `false` otherwise. + * + * @return bool canSwim + */ + int CanSwim(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->CanSwim()); + return 1; + } + + /** + * Returns `true` if the [Creature] can move on land, + * and returns `false` otherwise. + * + * @return bool canWalk + */ + int CanWalk(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->CanWalk()); + return 1; + } + + /** + * Returns `true` if the [Creature] is returning to its spawn position from combat, + * and returns `false` otherwise. + * + * @return bool inEvadeMode + */ + int IsInEvadeMode(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsInEvadeMode()); + return 1; + } + + /** + * Returns `true` if the [Creature]'s rank is Elite or Rare Elite, + * and returns `false` otherwise. + * + * @return bool isElite + */ + int IsElite(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsElite()); + return 1; + } + + /** + * Returns `true` if the [Creature] is a city guard, + * and returns `false` otherwise. + * + * @return bool isGuard + */ + int IsGuard(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsGuard()); + return 1; + } + + /** + * Returns `true` if the [Creature] is a civilian, + * and returns `false` otherwise. + * + * @return bool isCivilian + */ + int IsCivilian(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsCivilian()); + return 1; + } + + /** + * Returns `true` if the [Creature] is the leader of a player faction, + * and returns `false` otherwise. + * + * @return bool isLeader + */ + int IsRacialLeader(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsRacialLeader()); + return 1; + } + + /** + * Returns `true` if the [Creature]'s rank is Boss, + * and returns `false` otherwise. + * + * @return bool isWorldBoss + */ + int IsWorldBoss(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsWorldBoss()); + return 1; + } + + /** + * Returns `true` if the [Creature] cannot cast `spellId` due to a category cooldown, + * and returns `false` otherwise. + * + * @param uint32 spellId : the ID of a [Spell] + * @return bool hasCooldown + */ + int HasCategoryCooldown(lua_State* L, Creature* creature) + { + uint32 spell = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->HasCategoryCooldown(spell)); + return 1; + } + + /** + * Returns `true` if the [Creature] can cast `spellId` when mind-controlled, + * and returns `false` otherwise. + * + * @param uint32 spellId : the ID of a [Spell] + * @return bool hasSpell + */ + int HasSpell(lua_State* L, Creature* creature) + { + uint32 id = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->HasSpell(id)); + return 1; + } + + /** + * Returns `true` if the [Creature] starts the [Quest] `questId`, + * and returns `false` otherwise. + * + * @param uint32 questId : the ID of a [Quest] + * @return bool hasQuest + */ + int HasQuest(lua_State* L, Creature* creature) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->HasQuest(questId)); + return 1; + } + + /** + * Returns `true` if the [Creature] has `spellId` on cooldown, + * and returns `false` otherwise. + * + * @param uint32 spellId : the ID of a [Spell] + * @return bool hasCooldown + */ + int HasSpellCooldown(lua_State* L, Creature* creature) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->HasSpellCooldown(spellId)); + return 1; + } + + /** + * Returns `true` if the [Creature] can fly, + * and returns `false` otherwise. + * + * @return bool canFly + */ + int CanFly(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->CanFly()); + return 1; + } + + /** + * Returns the time it takes for this [Creature] to respawn once killed. + * + * This value does not usually change over a [Creature]'s lifespan, + * but can be modified by [Creature:SetRespawnDelay]. + * + * @return uint32 respawnDelay : the respawn delay, in seconds + */ + int GetRespawnDelay(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetRespawnDelay()); + return 1; + } + + /** + * Returns the radius the [Creature] is permitted to wander from its + * respawn point. + * + * @return float wanderRadius + */ + int GetWanderRadius(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetRespawnRadius()); + return 1; + } + + /** + * Returns the current waypoint ID of the [Creature]. + * + * @return uint32 wpId + */ + int GetCurrentWaypointId(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetMotionMaster()->getLastReachedWaypoint()); + return 1; + } + + /** + * Returns the default movement type for this [Creature]. + * + * @return [MovementGeneratorType] defaultMovementType + */ + int GetDefaultMovementType(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetDefaultMovementType()); + return 1; + } + + /** + * Returns the aggro range of the [Creature] for `target`. + * + * @param [Unit] target + * @return float aggroRange + */ + int GetAggroRange(lua_State* L, Creature* creature) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + + float AttackDist = creature->GetAttackDistance(target); + float ThreatRadius = sWorld.getConfig(CONFIG_FLOAT_THREAT_RADIUS); + Eluna::Push(L, ThreatRadius > AttackDist ? ThreatRadius : AttackDist); + return 1; + } + + /** + * Returns the effective aggro range of the [Creature] for `target`. + * + * If this is smaller than the minimum aggro range set in the config file, + * that is used as the aggro range instead. + * + * @param [Unit] target + * @return float attackDistance + */ + int GetAttackDistance(lua_State* L, Creature* creature) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, creature->GetAttackDistance(target)); + return 1; + } + + /** + * Returns the [Group] that can loot this [Creature]. + * + * @return [Group] lootRecipientGroup : the group or `nil` + */ + int GetLootRecipientGroup(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetGroupLootRecipient()); + return 1; + } + + /** + * Returns the [Player] that can loot this [Creature]. + * + * @return [Player] lootRecipient : the player or `nil` + */ + int GetLootRecipient(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetLootRecipient()); + return 1; + } + + /** + * Returns the [Creature]'s script name. + * + * This is used by the core to apply C++ scripts to the Creature. + * + * It is not used by Eluna. Eluna will override AI scripts. + * + * @return string scriptName + */ + int GetScriptName(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetScriptName()); + return 1; + } + + /** + * Returns the [Creature]'s AI name. + * + * This is used by the core to assign the Creature's default AI. + * + * If the Creature is scripted by Eluna, the AI is overriden. + * + * @return string AIName + */ + int GetAIName(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetAIName()); + return 1; + } + + /** + * Returns the [Creature]'s script ID. + * + * Every C++ script name is assigned a unique ID by the core. + * This returns the ID for this [Creature]'s script name. + * + * @return uint32 scriptID + */ + int GetScriptId(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetScriptId()); + return 1; + } + + /** + * Returns the [Creature]'s cooldown for `spellID`. + * + * @param uint32 spellID + * @return uint32 cooldown : the cooldown, in milliseconds + */ + int GetCreatureSpellCooldownDelay(lua_State* L, Creature* creature) + { + uint32 spell = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->GetCreatureSpellCooldownDelay(spell)); + return 1; + } + + /** + * Returns the delay between when the [Creature] dies and when its body despawns. + * + * @return uint32 corpseDelay : the delay, in seconds + */ + int GetCorpseDelay(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetCorpseDelay()); + return 1; + } + + /** + * Returns position the [Creature] returns to when evading from combat + * or respawning. + * + * @return float x + * @return float y + * @return float z + * @return float o + */ + int GetHomePosition(lua_State* L, Creature* creature) + { + float x, y, z, o; + creature->GetRespawnCoord(x, y, z, &o); + + Eluna::Push(L, x); + Eluna::Push(L, y); + Eluna::Push(L, z); + Eluna::Push(L, o); + return 4; + } + + /** + * Sets the position the [Creature] returns to when evading from combat + * or respawning. + * + * @param float x + * @param float y + * @param float z + * @param float o + */ + int SetHomePosition(lua_State* L, Creature* creature) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float o = Eluna::CHECKVAL(L, 5); + + creature->SetRespawnCoord(x, y, z, o); + return 0; + } + + enum SelectAggroTarget + { + SELECT_TARGET_RANDOM = 0, // Just selects a random target + SELECT_TARGET_TOPAGGRO, // Selects targes from top aggro to bottom + SELECT_TARGET_BOTTOMAGGRO, // Selects targets from bottom aggro to top + SELECT_TARGET_NEAREST, + SELECT_TARGET_FARTHEST + }; + + /** + * Returns a target from the [Creature]'s threat list based on the + * supplied arguments. + * + * enum SelectAggroTarget + * { + * SELECT_TARGET_RANDOM = 0, //Just selects a random target + * SELECT_TARGET_TOPAGGRO, //Selects targets from top aggro to bottom + * SELECT_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top + * SELECT_TARGET_NEAREST, + * SELECT_TARGET_FARTHEST + * }; + * + * For example, if you wanted to select the third-farthest [Player] + * within 50 yards that has the [Aura] "Corrupted Blood" (ID 24328), + * you could use this function like so: + * + * target = creature:GetAITarget(4, true, 3, 50, 24328) + * + * @param [SelectAggroTarget] targetType : how the threat list should be sorted + * @param bool playerOnly = false : if `true`, skips targets that aren't [Player]s + * @param uint32 position = 0 : used as an offset into the threat list. If `targetType` is random, used as the number of players from top of aggro to choose from + * @param float distance = 0.0 : if positive, the maximum distance for the target. If negative, the minimum distance + * @param int32 aura = 0 : if positive, the target must have this [Aura]. If negative, the the target must not have this Aura + * @return [Unit] target : the target, or `nil` + */ + int GetAITarget(lua_State* L, Creature* creature) + { + uint32 targetType = Eluna::CHECKVAL(L, 2); + bool playerOnly = Eluna::CHECKVAL(L, 3, false); + uint32 position = Eluna::CHECKVAL(L, 4, 0); + float dist = Eluna::CHECKVAL(L, 5, 0.0f); + int32 aura = Eluna::CHECKVAL(L, 6, 0); + + ThreatList const& threatlist = creature->getThreatManager().getThreatList(); + + if (threatlist.empty()) + return 1; + if (position >= threatlist.size()) + return 1; + std::list targetList; + for (auto itr = threatlist.begin(); itr != threatlist.end(); ++itr) + { + Unit* target = (*itr)->getTarget(); + + if (!target) + continue; + if (playerOnly && target->GetTypeId() != TYPEID_PLAYER) + continue; + if (aura > 0 && !target->HasAura(aura)) + continue; + else if (aura < 0 && target->HasAura(-aura)) + continue; + if (dist > 0.0f && !creature->IsWithinDist(target, dist)) + continue; + else if (dist < 0.0f && creature->IsWithinDist(target, -dist)) + continue; + targetList.push_back(target); + } + + if (targetList.empty()) + return 1; + if (position >= targetList.size()) + return 1; + + if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) + targetList.sort(ElunaUtil::ObjectDistanceOrderPred(creature)); + + switch (targetType) + { + case SELECT_TARGET_NEAREST: + case SELECT_TARGET_TOPAGGRO: + { + std::list::const_iterator itr = targetList.begin(); + if (position) + std::advance(itr, position); + Eluna::Push(L, *itr); + } + break; + case SELECT_TARGET_FARTHEST: + case SELECT_TARGET_BOTTOMAGGRO: + { + std::list::reverse_iterator ritr = targetList.rbegin(); + if (position) + std::advance(ritr, position); + Eluna::Push(L, *ritr); + } + break; + case SELECT_TARGET_RANDOM: + { + std::list::const_iterator itr = targetList.begin(); + if (position) + std::advance(itr, urand(0, position)); + else + std::advance(itr, urand(0, targetList.size() - 1)); + Eluna::Push(L, *itr); + } + break; + default: + luaL_argerror(L, 2, "SelectAggroTarget expected"); + break; + } + + return 1; + } + + /** + * Returns all [Unit]s in the [Creature]'s threat list. + * + * @return table targets + */ + int GetAITargets(lua_State* L, Creature* creature) + { + auto const& threatlist = creature->getThreatManager().getThreatList(); + + lua_createtable(L, threatlist.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (auto itr = threatlist.begin(); itr != threatlist.end(); ++itr) + { + Unit* target = (*itr)->getTarget(); + if (!target) + continue; + Eluna::Push(L, target); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns the number of [Unit]s in this [Creature]'s threat list. + * + * @return double targetsCount + */ + int GetAITargetsCount(lua_State* L, Creature* creature) + { + Eluna::Push(L, (double)creature->getThreatManager().getThreatList().size()); + return 1; + } + + /** + * Returns the [Creature]'s NPC flags. + * + * These are used to control whether the NPC is a vendor, can repair items, + * can give quests, etc. + * + * @return [NPCFlags] npcFlags + */ + int GetNPCFlags(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetUInt32Value(UNIT_NPC_FLAGS)); + return 1; + } + + /** + * Returns the [Creature]'s Extra flags. + * + * These are used to control whether the NPC is a civilian, uses pathfinding, + * if it's a guard, etc. + * + * @return [ExtraFlags] extraFlags + */ + int GetExtraFlags(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetCreatureInfo()->ExtraFlags); + return 1; + } + +#if defined(CLASSIC) || defined(TBC) || defined(WOTLK) + /** + * Returns the [Creature]'s shield block value. + * + * @return uint32 shieldBlockValue + */ + int GetShieldBlockValue(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetShieldBlockValue()); + return 1; + } +#endif + + /** + * Returns the guid of the [Creature] that is used as the ID in the database + * + * @return uint32 dbguid + */ + int GetDBTableGUIDLow(lua_State* L, Creature* creature) + { + // on mangos based this is same as lowguid + Eluna::Push(L, creature->GetGUIDLow()); + return 1; + } + + /** + * Sets the [Creature]'s NPC flags to `flags`. + * + * @param [NPCFlags] flags + */ + int SetNPCFlags(lua_State* L, Creature* creature) + { + uint32 flags = Eluna::CHECKVAL(L, 2); + + creature->SetUInt32Value(UNIT_NPC_FLAGS, flags); + return 0; + } + + /** + * Makes the [Creature] able to fly if enabled. + * + * @param bool disable + */ + int SetDisableGravity(lua_State* L, Creature* creature) + { + bool disable = Eluna::CHECKVAL(L, 2); + + creature->SetLevitate(disable); + return 0; + } + + /** + * Sets the [Creature]'s death state to `deathState`. + * + * @param [DeathState] deathState + */ + int SetDeathState(lua_State* L, Creature* creature) + { + int32 state = Eluna::CHECKVAL(L, 2); + + creature->SetDeathState((DeathState)state); + return 0; + } + + /** + * Sets whether the [Creature] is currently walking or running. + * + * @param bool enable = true : `true` to enable walking, `false` for running + */ + int SetWalk(lua_State* L, Creature* creature) // TODO: Move same to Player ? + { + bool enable = Eluna::CHECKVAL(L, 2, true); + + creature->SetWalk(enable); + return 0; + } + + /** + * Equips given [Item]s to the [Unit]. Using 0 removes the equipped [Item] + * + * @param uint32 main_hand : main hand [Item]'s entry + * @param uint32 off_hand : off hand [Item]'s entry + * @param uint32 ranged : ranged [Item]'s entry + */ + int SetEquipmentSlots(lua_State* L, Creature* creature) + { + uint32 main_hand = Eluna::CHECKVAL(L, 2); + uint32 off_hand = Eluna::CHECKVAL(L, 3); + uint32 ranged = Eluna::CHECKVAL(L, 4); + + creature->SetVirtualItem(VIRTUAL_ITEM_SLOT_0, main_hand); + creature->SetVirtualItem(VIRTUAL_ITEM_SLOT_1, off_hand); + creature->SetVirtualItem(VIRTUAL_ITEM_SLOT_2, ranged); + return 0; + } + + /** + * Sets whether the [Creature] can be aggroed. + * + * @param bool allow = true : `true` to allow aggro, `false` to disable aggro + */ + int SetAggroEnabled(lua_State* L, Creature* creature) + { + bool allow = Eluna::CHECKVAL(L, 2, true); + + if (allow) + creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC); + else + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC); + return 0; + } +#ifndef CATA + /** + * Sets whether the [Creature] gives reputation or not. + * + * @param bool disable = true : `true` to disable reputation, `false` to enable + */ + int SetDisableReputationGain(lua_State* L, Creature* creature) + { + bool disable = Eluna::CHECKVAL(L, 2, true); + + creature->SetNoReputation(disable); + return 0; + } +#endif + + /** + * Sets the [Creature] as in combat with all [Player]s in the dungeon instance. + * + * This is used by raid bosses to prevent Players from using out-of-combat + * actions once the encounter has begun. + */ + int SetInCombatWithZone(lua_State* /*L*/, Creature* creature) + { + creature->SetInCombatWithZone(); + return 0; + } + + /** + * Sets the distance the [Creature] can wander from it's spawn point. + * + * @param float distance + */ + int SetWanderRadius(lua_State* L, Creature* creature) + { + float dist = Eluna::CHECKVAL(L, 2); + + creature->SetRespawnRadius(dist); + return 0; + } + + /** + * Sets the time it takes for the [Creature] to respawn when killed. + * + * @param uint32 delay : the delay, in seconds + */ + int SetRespawnDelay(lua_State* L, Creature* creature) + { + uint32 delay = Eluna::CHECKVAL(L, 2); + + creature->SetRespawnDelay(delay); + return 0; + } + + /** + * Sets the default movement type of the [Creature]. + * + * @param [MovementGeneratorType] type + */ + int SetDefaultMovementType(lua_State* L, Creature* creature) + { + int32 type = Eluna::CHECKVAL(L, 2); + + creature->SetDefaultMovementType((MovementGeneratorType)type); + return 0; + } + + /** + * Sets whether the [Creature] can search for assistance at low health or not. + * + * @param bool enable = true : `true` to disable searching, `false` to allow + */ + int SetNoSearchAssistance(lua_State* L, Creature* creature) + { + bool val = Eluna::CHECKVAL(L, 2, true); + + creature->SetNoSearchAssistance(val); + return 0; + } + + /** + * Sets whether the [Creature] can call nearby enemies for help in combat or not. + * + * @param bool enable = true : `true` to disable calling for help, `false` to enable + */ + int SetNoCallAssistance(lua_State* L, Creature* creature) + { + bool val = Eluna::CHECKVAL(L, 2, true); + + creature->SetNoCallAssistance(val); + return 0; + } + + /** + * Sets whether the creature is hovering / levitating or not. + * + * @param bool enable = true : `true` to enable hovering, `false` to disable + */ + int SetHover(lua_State* L, Creature* creature) + { + bool enable = Eluna::CHECKVAL(L, 2, true); + + // Copy paste from Aura::HandleAuraHover + // TODO: implement core side properly + WorldPacket data; + if (enable) + data.Initialize(SMSG_MOVE_SET_HOVER, 8 + 4); + else + data.Initialize(SMSG_MOVE_UNSET_HOVER, 8 + 4); + data << creature->GetPackGUID(); + data << uint32(0); + creature->SendMessageToSet(data, true); + return 0; + } + + /** + * Despawn this [Creature]. + * + * @param uint32 delay = 0 : dely to despawn in milliseconds + */ + int DespawnOrUnsummon(lua_State* L, Creature* creature) + { + uint32 msTimeToDespawn = Eluna::CHECKVAL(L, 2, 0); + + creature->ForcedDespawn(msTimeToDespawn); + return 0; + } + + /** + * Respawn this [Creature]. + */ + int Respawn(lua_State* /*L*/, Creature* creature) + { + creature->Respawn(); + return 0; + } + + /** + * Remove this [Creature]'s corpse. + */ + int RemoveCorpse(lua_State* /*L*/, Creature* creature) + { + creature->RemoveCorpse(); + return 0; + } + + /** + * Make the [Creature] start following its waypoint path. + */ + int MoveWaypoint(lua_State* /*L*/, Creature* creature) + { + creature->GetMotionMaster()->MoveWaypoint(); + return 0; + } + + /** + * Make the [Creature] call for assistance in combat from other nearby [Creature]s. + */ + int CallAssistance(lua_State* /*L*/, Creature* creature) + { + creature->CallAssistance(); + return 0; + } + + /** + * Make the [Creature] call for help in combat from friendly [Creature]s within `radius`. + * + * @param float radius + */ + int CallForHelp(lua_State* L, Creature* creature) + { + float radius = Eluna::CHECKVAL(L, 2); + + creature->CallForHelp(radius); + return 0; + } + + /** + * Make the [Creature] flee combat to get assistance from a nearby friendly [Creature]. + */ + int FleeToGetAssistance(lua_State* /*L*/, Creature* creature) + { + creature->DoFleeToGetAssistance(); + return 0; + } + + /** + * Make the [Creature] attack `target`. + * + * @param [Unit] target + */ + int AttackStart(lua_State* L, Creature* creature) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + + creature->AI()->AttackStart(target); + return 0; + } + + /** + * Save the [Creature] in the database. + */ + int SaveToDB(lua_State* /*L*/, Creature* creature) + { + creature->SaveToDB(); + return 0; + } + + /** + * Make the [Creature] try to find a new target. + * + * This should be called every update cycle for the Creature's AI. + */ + int SelectVictim(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->SelectHostileTarget()); + return 1; + } + + /** + * Transform the [Creature] into another Creature. + * + * @param uint32 entry : the Creature ID to transform into + * @param uint32 dataGUIDLow = 0 : use this Creature's model and equipment instead of the defaults + */ + int UpdateEntry(lua_State* L, Creature* creature) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + uint32 dataGuidLow = Eluna::CHECKVAL(L, 3, 0); + +#ifndef CATA + creature->UpdateEntry(entry, dataGuidLow ? eObjectMgr->GetCreatureData(dataGuidLow) : NULL); +#else + creature->UpdateEntry(entry, ALLIANCE, dataGuidLow ? eObjectMgr->GetCreatureData(dataGuidLow) : NULL); +#endif + return 0; + } + + /** + * Returns the [Creature]'s creature family ID (enumerated in CreatureFamily.dbc). + * + *
+     * enum CreatureFamily
+     * {
+     *     CREATURE_FAMILY_NONE                = 0,    // TrinityCore only
+     *     CREATURE_FAMILY_WOLF                = 1,
+     *     CREATURE_FAMILY_CAT                 = 2,
+     *     CREATURE_FAMILY_SPIDER              = 3,
+     *     CREATURE_FAMILY_BEAR                = 4,
+     *     CREATURE_FAMILY_BOAR                = 5,
+     *     CREATURE_FAMILY_CROCOLISK           = 6,
+     *     CREATURE_FAMILY_CARRION_BIRD        = 7,
+     *     CREATURE_FAMILY_CRAB                = 8,
+     *     CREATURE_FAMILY_GORILLA             = 9,
+     *     CREATURE_FAMILY_HORSE_CUSTOM        = 10,   // Does not exist in DBC but used for horse like beasts in DB
+     *     CREATURE_FAMILY_RAPTOR              = 11,
+     *     CREATURE_FAMILY_TALLSTRIDER         = 12,
+     *     CREATURE_FAMILY_FELHUNTER           = 15,
+     *     CREATURE_FAMILY_VOIDWALKER          = 16,
+     *     CREATURE_FAMILY_SUCCUBUS            = 17,
+     *     CREATURE_FAMILY_DOOMGUARD           = 19,
+     *     CREATURE_FAMILY_SCORPID             = 20,
+     *     CREATURE_FAMILY_TURTLE              = 21,
+     *     CREATURE_FAMILY_IMP                 = 23,
+     *     CREATURE_FAMILY_BAT                 = 24,
+     *     CREATURE_FAMILY_HYENA               = 25,
+     *     CREATURE_FAMILY_BIRD_OF_PREY        = 26,   // Named CREATURE_FAMILY_OWL in Mangos
+     *     CREATURE_FAMILY_WIND_SERPENT        = 27,
+     *     CREATURE_FAMILY_REMOTE_CONTROL      = 28,
+     *     CREATURE_FAMILY_FELGUARD            = 29,   // This and below is TBC+
+     *     CREATURE_FAMILY_DRAGONHAWK          = 30,
+     *     CREATURE_FAMILY_RAVAGER             = 31,
+     *     CREATURE_FAMILY_WARP_STALKER        = 32,
+     *     CREATURE_FAMILY_SPOREBAT            = 33,
+     *     CREATURE_FAMILY_NETHER_RAY          = 34,
+     *     CREATURE_FAMILY_SERPENT             = 35,
+     *     CREATURE_FAMILY_SEA_LION            = 36,   // TBC only
+     *     CREATURE_FAMILY_MOTH                = 37,   // This and below is WotLK+
+     *     CREATURE_FAMILY_CHIMAERA            = 38,
+     *     CREATURE_FAMILY_DEVILSAUR           = 39,
+     *     CREATURE_FAMILY_GHOUL               = 40,
+     *     CREATURE_FAMILY_SILITHID            = 41,
+     *     CREATURE_FAMILY_WORM                = 42,
+     *     CREATURE_FAMILY_RHINO               = 43,
+     *     CREATURE_FAMILY_WASP                = 44,
+     *     CREATURE_FAMILY_CORE_HOUND          = 45,
+     *     CREATURE_FAMILY_SPIRIT_BEAST        = 46
+     * };
+     * 
+ * + * @return [CreatureFamily] creatureFamily + */ + int GetCreatureFamily(lua_State* L, Creature* creature) + { + uint32 entry = creature->GetEntry(); + + CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(entry); + if (cInfo) + Eluna::Push(L, cInfo->Family); + return 1; + } + + ElunaRegister CreatureMethods[] = + { + // Getters + { "GetAITarget", &LuaCreature::GetAITarget }, + { "GetAITargets", &LuaCreature::GetAITargets }, + { "GetAITargetsCount", &LuaCreature::GetAITargetsCount }, + { "GetHomePosition", &LuaCreature::GetHomePosition }, + { "GetCorpseDelay", &LuaCreature::GetCorpseDelay }, + { "GetCreatureSpellCooldownDelay", &LuaCreature::GetCreatureSpellCooldownDelay }, + { "GetScriptId", &LuaCreature::GetScriptId }, + { "GetAIName", &LuaCreature::GetAIName }, + { "GetScriptName", &LuaCreature::GetScriptName }, + { "GetAttackDistance", &LuaCreature::GetAttackDistance }, + { "GetAggroRange", &LuaCreature::GetAggroRange }, + { "GetDefaultMovementType", &LuaCreature::GetDefaultMovementType }, + { "GetRespawnDelay", &LuaCreature::GetRespawnDelay }, + { "GetWanderRadius", &LuaCreature::GetWanderRadius }, + { "GetCurrentWaypointId", &LuaCreature::GetCurrentWaypointId }, + { "GetLootRecipient", &LuaCreature::GetLootRecipient }, + { "GetLootRecipientGroup", &LuaCreature::GetLootRecipientGroup }, + { "GetNPCFlags", &LuaCreature::GetNPCFlags }, + { "GetExtraFlags", &LuaCreature::GetExtraFlags }, + { "GetDBTableGUIDLow", &LuaCreature::GetDBTableGUIDLow }, + { "GetCreatureFamily", &LuaCreature::GetCreatureFamily }, +#ifndef CATA + { "GetShieldBlockValue", &LuaCreature::GetShieldBlockValue }, +#endif + + // Setters + { "SetHover", &LuaCreature::SetHover }, + { "SetDisableGravity", &LuaCreature::SetDisableGravity }, + { "SetAggroEnabled", &LuaCreature::SetAggroEnabled }, + { "SetNoCallAssistance", &LuaCreature::SetNoCallAssistance }, + { "SetNoSearchAssistance", &LuaCreature::SetNoSearchAssistance }, + { "SetDefaultMovementType", &LuaCreature::SetDefaultMovementType }, + { "SetRespawnDelay", &LuaCreature::SetRespawnDelay }, + { "SetWanderRadius", &LuaCreature::SetWanderRadius }, + { "SetInCombatWithZone", &LuaCreature::SetInCombatWithZone }, + { "SetNPCFlags", &LuaCreature::SetNPCFlags }, + { "SetDeathState", &LuaCreature::SetDeathState }, + { "SetWalk", &LuaCreature::SetWalk }, + { "SetHomePosition", &LuaCreature::SetHomePosition }, + { "SetEquipmentSlots", &LuaCreature::SetEquipmentSlots }, +#ifndef CATA + { "SetDisableReputationGain", &LuaCreature::SetDisableReputationGain }, +#endif + + // Boolean + { "IsRegeneratingHealth", &LuaCreature::IsRegeneratingHealth }, + { "IsWorldBoss", &LuaCreature::IsWorldBoss }, + { "IsRacialLeader", &LuaCreature::IsRacialLeader }, + { "IsCivilian", &LuaCreature::IsCivilian }, + { "IsGuard", &LuaCreature::IsGuard }, + { "IsElite", &LuaCreature::IsElite }, + { "IsInEvadeMode", &LuaCreature::IsInEvadeMode }, + { "HasCategoryCooldown", &LuaCreature::HasCategoryCooldown }, + { "CanWalk", &LuaCreature::CanWalk }, + { "CanSwim", &LuaCreature::CanSwim }, + { "CanAggro", &LuaCreature::CanAggro }, + { "HasSearchedAssistance", &LuaCreature::HasSearchedAssistance }, + { "IsTappedBy", &LuaCreature::IsTappedBy }, + { "HasLootRecipient", &LuaCreature::HasLootRecipient }, + { "CanAssistTo", &LuaCreature::CanAssistTo }, + { "IsTargetableForAttack", &LuaCreature::IsTargetableForAttack }, + { "CanCompleteQuest", &LuaCreature::CanCompleteQuest }, + { "HasSpell", &LuaCreature::HasSpell }, + { "HasQuest", &LuaCreature::HasQuest }, + { "HasSpellCooldown", &LuaCreature::HasSpellCooldown }, + { "CanFly", &LuaCreature::CanFly }, +#ifndef CATA + { "IsReputationGainDisabled", &LuaCreature::IsReputationGainDisabled }, +#endif + + // Other + { "FleeToGetAssistance", &LuaCreature::FleeToGetAssistance }, + { "CallForHelp", &LuaCreature::CallForHelp }, + { "CallAssistance", &LuaCreature::CallAssistance }, + { "RemoveCorpse", &LuaCreature::RemoveCorpse }, + { "DespawnOrUnsummon", &LuaCreature::DespawnOrUnsummon }, + { "Respawn", &LuaCreature::Respawn }, + { "AttackStart", &LuaCreature::AttackStart }, + { "SaveToDB", &LuaCreature::SaveToDB }, + { "SelectVictim", &LuaCreature::SelectVictim }, + { "MoveWaypoint", &LuaCreature::MoveWaypoint }, + { "UpdateEntry", &LuaCreature::UpdateEntry }, + + // Not implemented methods + { "GetWaypointPath", nullptr }, // TC/Acore + { "GetLootMode", nullptr }, // TC/Acore + { "SetRegeneratingHealth", nullptr }, // TC/Acore + { "SetLootMode", nullptr }, // TC/Acore + { "SetReactState", nullptr }, // TC/Acore + { "IsDungeonBoss", nullptr }, // TC/Acore + { "IsTrigger", nullptr }, // TC/Acore + { "CanStartAttack", nullptr }, // TC/Acore + { "IsDamageEnoughForLootingAndReward", nullptr }, // TC/Acore + { "HasLootMode", nullptr }, // TC/Acore + { "AddLootMode", nullptr }, // TC/Acore + { "ResetLootMode", nullptr }, // TC/Acore + { "RemoveLootMode", nullptr }, // TC/Acore + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/ElunaQueryMethods.h b/src/modules/Eluna/CMangos/ElunaQueryMethods.h new file mode 100644 index 0000000000..d344aea096 --- /dev/null +++ b/src/modules/Eluna/CMangos/ElunaQueryMethods.h @@ -0,0 +1,343 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef QUERYMETHODS_H +#define QUERYMETHODS_H + +#define RESULT result + +/*** + * The result of a database query. + * + * E.g. the return value of [Global:WorldDBQuery]. + * + * Inherits all methods from: none + */ +namespace LuaQuery +{ + static void CheckFields(lua_State* L, ElunaQuery* result) + { + uint32 field = Eluna::CHECKVAL(L, 2); + uint32 count = RESULT->GetFieldCount(); + if (field >= count) + { + char arr[256]; + sprintf(arr, "trying to access invalid field index %u. There are %u fields available and the indexes start from 0", field, count); + luaL_argerror(L, 2, arr); + } + } + + /** + * Returns `true` if the specified column of the current row is `NULL`, otherwise `false`. + * + * @param uint32 column + * @return bool isNull + */ + int IsNull(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + + Eluna::Push(L, RESULT->Fetch()[col].IsNULL()); + return 1; + } + + /** + * Returns the number of columns in the result set. + * + * @return uint32 columnCount + */ + int GetColumnCount(lua_State* L, ElunaQuery* result) + { + Eluna::Push(L, RESULT->GetFieldCount()); + return 1; + } + + /** + * Returns the number of rows in the result set. + * + * @return uint32 rowCount + */ + int GetRowCount(lua_State* L, ElunaQuery* result) + { + if (RESULT->GetRowCount() > (uint32)-1) + Eluna::Push(L, (uint32)-1); + else + Eluna::Push(L, (uint32)(RESULT->GetRowCount())); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a boolean. + * + * @param uint32 column + * @return bool data + */ + int GetBool(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetBool()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to an unsigned 8-bit integer. + * + * @param uint32 column + * @return uint8 data + */ + int GetUInt8(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetUInt8()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to an unsigned 16-bit integer. + * + * @param uint32 column + * @return uint16 data + */ + int GetUInt16(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetUInt16()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to an unsigned 32-bit integer. + * + * @param uint32 column + * @return uint32 data + */ + int GetUInt32(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetUInt32()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to an unsigned 64-bit integer. + * + * @param uint32 column + * @return uint64 data + */ + int GetUInt64(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetUInt64()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a signed 8-bit integer. + * + * @param uint32 column + * @return int8 data + */ + int GetInt8(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetInt8()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a signed 16-bit integer. + * + * @param uint32 column + * @return int16 data + */ + int GetInt16(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetInt16()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a signed 32-bit integer. + * + * @param uint32 column + * @return int32 data + */ + int GetInt32(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetInt32()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a signed 64-bit integer. + * + * @param uint32 column + * @return int64 data + */ + int GetInt64(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetInt64()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a 32-bit floating point value. + * + * @param uint32 column + * @return float data + */ + int GetFloat(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetFloat()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a 64-bit floating point value. + * + * @param uint32 column + * @return double data + */ + int GetDouble(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetDouble()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a string. + * + * @param uint32 column + * @return string data + */ + int GetString(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + + Eluna::Push(L, RESULT->Fetch()[col].GetString()); + return 1; + } + + /** + * Advances the [ElunaQuery] to the next row in the result set. + * + * *Do not* call this immediately after a query, or you'll skip the first row. + * + * Returns `false` if there was no new row, otherwise `true`. + * + * @return bool hadNextRow + */ + int NextRow(lua_State* L, ElunaQuery* result) + { + Eluna::Push(L, RESULT->NextRow()); + return 1; + } + + /** + * Returns a table from the current row where keys are field names and values are the row's values. + * + * All numerical values will be numbers and everything else is returned as a string. + * + * **For example,** the query: + * + * SELECT entry, name FROM creature_template + * + * would result in a table like: + * + * { entry = 123, name = "some creature name" } + * + * To move to next row use [ElunaQuery:NextRow]. + * + * @return table rowData : table filled with row columns and data where `T[column] = data` + */ + int GetRow(lua_State* L, ElunaQuery* result) + { + uint32 col = RESULT->GetFieldCount(); + Field* row = RESULT->Fetch(); + + lua_createtable(L, 0, col); + int tbl = lua_gettop(L); + + const QueryFieldNames& names = RESULT->GetFieldNames(); + + for (uint32 i = 0; i < col; ++i) + { + Eluna::Push(L, names[i]); + + const char* str = row[i].GetString(); + if (row[i].IsNULL() || !str) + Eluna::Push(L); + else + { + // MYSQL_TYPE_LONGLONG Interpreted as string for lua + switch (row[i].GetType()) + { + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + Eluna::Push(L, strtod(str, NULL)); + break; + default: + Eluna::Push(L, str); + break; + } + } + lua_rawset(L, tbl); + } + lua_settop(L, tbl); + return 1; + } + + ElunaRegister QueryMethods[] = + { + // Getters + { "GetColumnCount", &LuaQuery::GetColumnCount }, + { "GetRowCount", &LuaQuery::GetRowCount }, + { "GetRow", &LuaQuery::GetRow }, + { "GetBool", &LuaQuery::GetBool }, + { "GetUInt8", &LuaQuery::GetUInt8 }, + { "GetUInt16", &LuaQuery::GetUInt16 }, + { "GetUInt32", &LuaQuery::GetUInt32 }, + { "GetUInt64", &LuaQuery::GetUInt64 }, + { "GetInt8", &LuaQuery::GetInt8 }, + { "GetInt16", &LuaQuery::GetInt16 }, + { "GetInt32", &LuaQuery::GetInt32 }, + { "GetInt64", &LuaQuery::GetInt64 }, + { "GetFloat", &LuaQuery::GetFloat }, + { "GetDouble", &LuaQuery::GetDouble }, + { "GetString", &LuaQuery::GetString }, + + // Boolean + { "NextRow", &LuaQuery::NextRow }, + { "IsNull", &LuaQuery::IsNull }, + + { NULL, NULL } + }; +}; +#undef RESULT + +#endif diff --git a/src/modules/Eluna/CMangos/GameObjectMethods.h b/src/modules/Eluna/CMangos/GameObjectMethods.h new file mode 100644 index 0000000000..518b921dc7 --- /dev/null +++ b/src/modules/Eluna/CMangos/GameObjectMethods.h @@ -0,0 +1,340 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef GAMEOBJECTMETHODS_H +#define GAMEOBJECTMETHODS_H + +/*** + * Inherits all methods from: [Object], [WorldObject] + */ +namespace LuaGameObject +{ + /** + * Returns 'true' if the [GameObject] can give the specified [Quest] + * + * @param uint32 questId : quest entry Id to check + * @return bool hasQuest + */ + int HasQuest(lua_State* L, GameObject* go) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, go->HasQuest(questId)); + return 1; + } + + /** + * Returns 'true' if the [GameObject] is spawned + * + * @return bool isSpawned + */ + int IsSpawned(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->IsSpawned()); + return 1; + } + + /** + * Returns 'true' if the [GameObject] is a transport + * + * @return bool isTransport + */ + int IsTransport(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->IsTransport()); + return 1; + } + + /** + * Returns 'true' if the [GameObject] is active + * + * @return bool isActive + */ + int IsActive(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->isActiveObject()); + return 1; + } + + /** + * Returns display ID of the [GameObject] + * + * @return uint32 displayId + */ + int GetDisplayId(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetDisplayId()); + return 1; + } + + /** + * Returns the state of a [GameObject] + * Below are client side [GOState]s off of 3.3.5a + * + *
+     * enum GOState
+     * {
+     *     GO_STATE_ACTIVE             = 0,                        // show in world as used and not reset (closed door open)
+     *     GO_STATE_READY              = 1,                        // show in world as ready (closed door close)
+     *     GO_STATE_ACTIVE_ALTERNATIVE = 2                         // show in world as used in alt way and not reset (closed door open by cannon fire)
+     * };
+     * 
+ * + * @return [GOState] goState + */ + int GetGoState(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetGoState()); + return 1; + } + + /** + * Returns the [LootState] of a [GameObject] + * Below are [LootState]s off of 3.3.5a + * + *
+     * enum LootState
+     * {
+     *     GO_NOT_READY = 0,
+     *     GO_READY,                                               // can be ready but despawned, and then not possible activate until spawn
+     *     GO_ACTIVATED,
+     *     GO_JUST_DEACTIVATED
+     * };
+     * 
+ * + * @return [LootState] lootState + */ + int GetLootState(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetLootState()); + return 1; + } + + /** + * Returns the [Player] that can loot the [GameObject] + * + * Not the original looter and may be nil. + * + * @return [Player] player + */ + int GetLootRecipient(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetLootRecipient()); + return 1; + } + + /** + * Returns the [Group] that can loot the [GameObject] + * + * Not the original looter and may be nil. + * + * @return [Group] group + */ + int GetLootRecipientGroup(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetGroupLootRecipient()); + return 1; + } + + /** + * Returns the guid of the [GameObject] that is used as the ID in the database + * + * @return uint32 dbguid + */ + int GetDBTableGUIDLow(lua_State* L, GameObject* go) + { + // on mangos based this is same as lowguid + Eluna::Push(L, go->GetGUIDLow()); + return 1; + } + + /** + * Sets the state of a [GameObject] + * + *
+     * enum GOState
+     * {
+     *     GO_STATE_ACTIVE             = 0,                        // show in world as used and not reset (closed door open)
+     *     GO_STATE_READY              = 1,                        // show in world as ready (closed door close)
+     *     GO_STATE_ACTIVE_ALTERNATIVE = 2                         // show in world as used in alt way and not reset (closed door open by cannon fire)
+     * };
+     * 
+ * + * @param [GOState] state : all available go states can be seen above + */ + int SetGoState(lua_State* L, GameObject* go) + { + uint32 state = Eluna::CHECKVAL(L, 2, 0); + + if (state == 0) + go->SetGoState(GO_STATE_ACTIVE); + else if (state == 1) + go->SetGoState(GO_STATE_READY); + else if (state == 2) + go->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + + return 0; + } + + /** + * Sets the [LootState] of a [GameObject] + * Below are [LootState]s off of 3.3.5a + * + *
+     * enum LootState
+     * {
+     *     GO_NOT_READY = 0,
+     *     GO_READY,                                               // can be ready but despawned, and then not possible activate until spawn
+     *     GO_ACTIVATED,
+     *     GO_JUST_DEACTIVATED
+     * };
+     * 
+ * + * @param [LootState] state : all available loot states can be seen above + */ + int SetLootState(lua_State* L, GameObject* go) + { + uint32 state = Eluna::CHECKVAL(L, 2, 0); + + if (state == 0) + go->SetLootState(GO_NOT_READY); + else if (state == 1) + go->SetLootState(GO_READY); + else if (state == 2) + go->SetLootState(GO_ACTIVATED); + else if (state == 3) + go->SetLootState(GO_JUST_DEACTIVATED); + + return 0; + } + + /** + * Saves [GameObject] to the database + * + */ + int SaveToDB(lua_State* /*L*/, GameObject* go) + { + go->SaveToDB(); + return 0; + } + + /** + * Removes [GameObject] from the world + * + * The object is no longer reachable after this and it is not respawned. + * + * @param bool deleteFromDB : if true, it will delete the [GameObject] from the database + */ + int RemoveFromWorld(lua_State* L, GameObject* go) + { + bool deldb = Eluna::CHECKVAL(L, 2, false); + + // cs_gobject.cpp copy paste + ObjectGuid ownerGuid = go->GetOwnerGuid(); + if (ownerGuid) + { + Unit* owner = eObjectAccessor()GetUnit(*go, ownerGuid); + if (!owner || !ownerGuid.IsPlayer()) + return 0; + + owner->RemoveGameObject(go, false); + } + + if (deldb) + { + go->DeleteFromDB(); + } + + go->SetRespawnTime(0); + go->Delete(); + + Eluna::CHECKOBJ(L, 1)->Invalidate(); + return 0; + } + + /** + * Activates a door or a button/lever + * + * @param uint32 delay = 0 : cooldown time in seconds to restore the [GameObject] back to normal. 0 for infinite duration + */ + int UseDoorOrButton(lua_State* L, GameObject* go) + { + uint32 delay = Eluna::CHECKVAL(L, 2, 0); + + go->UseDoorOrButton(delay); + return 0; + } + + /** + * Despawns a [GameObject] + * + * The gameobject may be automatically respawned by the core + */ + int Despawn(lua_State* /*L*/, GameObject* go) + { + go->SetLootState(GO_JUST_DEACTIVATED); + return 0; + } + + /** + * Respawns a [GameObject] + */ + int Respawn(lua_State* /*L*/, GameObject* go) + { + go->Respawn(); + return 0; + } + + /** + * Sets the respawn or despawn time for the gameobject. + * + * Respawn time is also used as despawn time depending on gameobject settings + * + * @param int32 delay = 0 : cooldown time in seconds to respawn or despawn the object. 0 means never + */ + int SetRespawnTime(lua_State* L, GameObject* go) + { + int32 respawn = Eluna::CHECKVAL(L, 2); + + go->SetRespawnTime(respawn); + return 0; + } + + ElunaRegister GameObjectMethods[] = + { + // Getters + { "GetDisplayId", &LuaGameObject::GetDisplayId }, + { "GetGoState", &LuaGameObject::GetGoState }, + { "GetLootState", &LuaGameObject::GetLootState }, + { "GetLootRecipient", &LuaGameObject::GetLootRecipient }, + { "GetLootRecipientGroup", &LuaGameObject::GetLootRecipientGroup }, + { "GetDBTableGUIDLow", &LuaGameObject::GetDBTableGUIDLow }, + + // Setters + { "SetGoState", &LuaGameObject::SetGoState }, + { "SetLootState", &LuaGameObject::SetLootState }, + { "SetRespawnTime", &LuaGameObject::SetRespawnTime }, + + // Boolean + { "IsTransport", &LuaGameObject::IsTransport }, + { "IsActive", &LuaGameObject::IsActive }, + { "HasQuest", &LuaGameObject::HasQuest }, + { "IsSpawned", &LuaGameObject::IsSpawned }, + + // Other + { "RemoveFromWorld", &LuaGameObject::RemoveFromWorld }, + { "UseDoorOrButton", &LuaGameObject::UseDoorOrButton }, + { "Despawn", &LuaGameObject::Despawn }, + { "Respawn", &LuaGameObject::Respawn }, + { "SaveToDB", &LuaGameObject::SaveToDB }, + + // Not implemented methods + { "IsDestructible", nullptr }, // Not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/GlobalMethods.h b/src/modules/Eluna/CMangos/GlobalMethods.h new file mode 100644 index 0000000000..2ef1689e9f --- /dev/null +++ b/src/modules/Eluna/CMangos/GlobalMethods.h @@ -0,0 +1,3076 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef GLOBALMETHODS_H +#define GLOBALMETHODS_H + +#include "LuaEngine/BindingMap.h" + +/*** + * These functions can be used anywhere at any time, including at start-up. + */ +namespace LuaGlobalFunctions +{ + /** + * Returns Lua engine's name. + * + * Always returns "ElunaEngine" on Eluna. + * + * @return string engineName + */ + int GetLuaEngine(lua_State* L) + { + Eluna::Push(L, "ElunaEngine"); + return 1; + } + + /** + * Returns emulator's name. + * + * The result will be either `MaNGOS`, `cMaNGOS`, or `TrinityCore`. + * + * @return string coreName + */ + int GetCoreName(lua_State* L) + { + Eluna::Push(L, CORE_NAME); + return 1; + } + + /** + * Returns emulator .conf RealmID + * + * - for MaNGOS returns the realmID as it is stored in the core. + * - for TrinityCore returns the realmID as it is in the conf file. + * @return uint32 realm ID + */ + + int GetRealmID(lua_State* L) + { + Eluna::Push(L, realmID); + return 1; + } + + /** + * Returns emulator version + * + * - For TrinityCore returns the date of the last revision, e.g. `2015-08-26 22:53:12 +0300` + * - For cMaNGOS returns the date and time of the last revision, e.g. `2015-09-06 13:18:50` + * - for MaNGOS returns the version number as string, e.g. `21000` + * + * @return string version + */ + int GetCoreVersion(lua_State* L) + { + Eluna::Push(L, CORE_VERSION); + return 1; + } + + /** + * Returns emulator's supported expansion. + * + * Expansion is 0 for pre-TBC, 1 for TBC, 2 for WotLK, and 3 for Cataclysm. + * + * @return int32 expansion + */ + int GetCoreExpansion(lua_State* L) + { +#ifdef CLASSIC + Eluna::Push(L, 0); +#elif defined(TBC) + Eluna::Push(L, 1); +#elif defined(WOTLK) + Eluna::Push(L, 2); +#elif defined(CATA) + Eluna::Push(L, 3); +#endif + return 1; + } + + /** + * Returns [Quest] template + * + * @param uint32 questId : [Quest] entry ID + * @return [Quest] quest + */ + int GetQuest(lua_State* L) + { + uint32 questId = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, eObjectMgr->GetQuestTemplate(questId)); + return 1; + } + + /** + * Finds and Returns [Player] by guid if found + * + * @param ObjectGuid guid : guid of the [Player], you can get it with [Object:GetGUID] + * @return [Player] player + */ + int GetPlayerByGUID(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, eObjectAccessor()FindPlayer(guid)); + return 1; + } + + /** + * Finds and Returns [Player] by name if found + * + * @param string name : name of the [Player] + * @return [Player] player + */ + int GetPlayerByName(lua_State* L) + { + const char* name = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, eObjectAccessor()FindPlayerByName(name)); + return 1; + } + + /** + * Returns game time in seconds + * + * @return uint32 time + */ + int GetGameTime(lua_State* L) + { + Eluna::Push(L, eWorld->GetGameTime()); + return 1; + } + + /** + * Returns a table with all the current [Player]s in the world + * + * Does not return players that may be teleporting or otherwise not on any map. + * + * enum TeamId + * { + * TEAM_ALLIANCE = 0, + * TEAM_HORDE = 1, + * TEAM_NEUTRAL = 2 + * }; + * + * @param [TeamId] team = TEAM_NEUTRAL : optional check team of the [Player], Alliance, Horde or Neutral (All) + * @param bool onlyGM = false : optional check if GM only + * @return table worldPlayers + */ + int GetPlayersInWorld(lua_State* L) + { + uint32 team = Eluna::CHECKVAL(L, 1, TEAM_NEUTRAL); + bool onlyGM = Eluna::CHECKVAL(L, 2, false); + + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 i = 0; + + { + HashMapHolder::ReadGuard g(HashMapHolder::GetLock()); + const HashMapHolder::MapType& m = eObjectAccessor()GetPlayers(); + for (HashMapHolder::MapType::const_iterator it = m.begin(); it != m.end(); ++it) + { + if (Player* player = it->second) + { + if (!player->IsInWorld()) + continue; + if ((team == TEAM_NEUTRAL || player->GetTeamId() == team) && (!onlyGM || player->IsGameMaster())) + { + Eluna::Push(L, player); + lua_rawseti(L, tbl, ++i); + } + } + } + } + lua_settop(L, tbl); // push table to top of stack + return 1; + } + + /** + * Returns a [Guild] by name. + * + * @param string name + * @return [Guild] guild : the Guild, or `nil` if it doesn't exist + */ + int GetGuildByName(lua_State* L) + { + const char* name = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, eGuildMgr->GetGuildByName(name)); + return 1; + } + + /** + * Returns a [Map] by ID. + * + * @param uint32 mapId : see [Map.dbc](https://github.com/cmangos/issues/wiki/Map.dbc) + * @param uint32 instanceId = 0 : required if the map is an instance, otherwise don't pass anything + * @return [Map] map : the Map, or `nil` if it doesn't exist + */ + int GetMapById(lua_State* L) + { + uint32 mapid = Eluna::CHECKVAL(L, 1); + uint32 instance = Eluna::CHECKVAL(L, 2, 0); + + Eluna::Push(L, eMapMgr->FindMap(mapid, instance)); + return 1; + } + + /** + * Returns [Guild] by the leader's GUID + * + * @param ObjectGuid guid : the guid of a [Guild] leader + * @return [Guild] guild, or `nil` if it doesn't exist + */ + int GetGuildByLeaderGUID(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, eGuildMgr->GetGuildByLeader(guid)); + return 1; + } + + /** + * Returns the amount of [Player]s in the world. + * + * @return uint32 count + */ + int GetPlayerCount(lua_State* L) + { + Eluna::Push(L, eWorld->GetActiveSessionCount()); + return 1; + } + + /** + * Builds a [Player]'s GUID + * + * [Player] GUID consist of low GUID and type ID + * + * [Player] and [Creature] for example can have the same low GUID but not GUID. + * + * @param uint32 lowguid : low GUID of the [Player] + * @return ObjectGuid guid + */ + int GetPlayerGUID(lua_State* L) + { + uint32 lowguid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, MAKE_NEW_GUID(lowguid, 0, HIGHGUID_PLAYER)); + return 1; + } + + /** + * Builds an [Item]'s GUID. + * + * [Item] GUID consist of low GUID and type ID + * [Player] and [Item] for example can have the same low GUID but not GUID. + * + * @param uint32 lowguid : low GUID of the [Item] + * @return ObjectGuid guid + */ + int GetItemGUID(lua_State* L) + { + uint32 lowguid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, MAKE_NEW_GUID(lowguid, 0, HIGHGUID_ITEM)); + return 1; + } + + /** + * Builds a [GameObject]'s GUID. + * + * A GameObject's GUID consist of entry ID, low GUID and type ID + * + * A [Player] and GameObject for example can have the same low GUID but not GUID. + * + * @param uint32 lowguid : low GUID of the [GameObject] + * @param uint32 entry : entry ID of the [GameObject] + * @return ObjectGuid guid + */ + int GetObjectGUID(lua_State* L) + { + uint32 lowguid = Eluna::CHECKVAL(L, 1); + uint32 entry = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, MAKE_NEW_GUID(lowguid, entry, HIGHGUID_GAMEOBJECT)); + return 1; + } + + /** + * Builds a [Creature]'s GUID. + * + * [Creature] GUID consist of entry ID, low GUID and type ID + * + * [Player] and [Creature] for example can have the same low GUID but not GUID. + * + * @param uint32 lowguid : low GUID of the [Creature] + * @param uint32 entry : entry ID of the [Creature] + * @return ObjectGuid guid + */ + int GetUnitGUID(lua_State* L) + { + uint32 lowguid = Eluna::CHECKVAL(L, 1); + uint32 entry = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, MAKE_NEW_GUID(lowguid, entry, HIGHGUID_UNIT)); + return 1; + } + + /** + * Returns the low GUID from a GUID. + * + * A GUID consists of a low GUID, type ID, and possibly an entry ID depending on the type ID. + * + * Low GUID is an ID to distinct the objects of the same type. + * + * [Player] and [Creature] for example can have the same low GUID but not GUID. + * + * On TrinityCore all low GUIDs are different for all objects of the same type. + * For example creatures in instances are assigned new GUIDs when the Map is created. + * + * On MaNGOS and cMaNGOS low GUIDs are unique only on the same map. + * For example creatures in instances use the same low GUID assigned for that spawn in the database. + * This is why to identify a creature you have to know the instanceId and low GUID. See [Map:GetIntstanceId] + * + * @param ObjectGuid guid : GUID of an [Object] + * @return uint32 lowguid : low GUID of the [Object] + */ + int GetGUIDLow(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, guid.GetCounter()); + return 1; + } + + /** + * Returns an chat link for an [Item]. + * + * enum LocaleConstant + * { + * LOCALE_enUS = 0, + * LOCALE_koKR = 1, + * LOCALE_frFR = 2, + * LOCALE_deDE = 3, + * LOCALE_zhCN = 4, + * LOCALE_zhTW = 5, + * LOCALE_esES = 6, + * LOCALE_esMX = 7, + * LOCALE_ruRU = 8 + * }; + * + * @param uint32 entry : entry ID of an [Item] + * @param [LocaleConstant] locale = DEFAULT_LOCALE : locale to return the [Item] name in + * @return string itemLink + */ + int GetItemLink(lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const ItemTemplate* temp = eObjectMgr->GetItemTemplate(entry); + if (!temp) + return luaL_argerror(L, 1, "valid ItemEntry expected"); + + std::string name = temp->Name1; + if (ItemLocale const* il = eObjectMgr->GetItemLocale(entry)) + ObjectMgr::GetLocaleString(il->Name, static_cast(locale), name); + + std::ostringstream oss; + oss << "|c" << std::hex << ItemQualityColors[temp->Quality] << std::dec << + "|Hitem:" << entry << ":0:" << +#ifndef CLASSIC + "0:0:0:0:" << +#endif + "0:0:0:0|h[" << name << "]|h|r"; + + Eluna::Push(L, oss.str()); + return 1; + } + + /** + * Returns the type ID from a GUID. + * + * Type ID is different for each type ([Player], [Creature], [GameObject], etc.). + * + * GUID consist of entry ID, low GUID, and type ID. + * + * @param ObjectGuid guid : GUID of an [Object] + * @return int32 typeId : type ID of the [Object] + */ + int GetGUIDType(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, static_cast(guid.GetHigh())); + return 1; + } + + /** + * Returns the entry ID from a GUID. + * + * GUID consist of entry ID, low GUID, and type ID. + * + * @param ObjectGuid guid : GUID of an [Creature] or [GameObject] + * @return uint32 entry : entry ID, or `0` if `guid` is not a [Creature] or [GameObject] + */ + int GetGUIDEntry(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, guid.GetEntry()); + return 1; + } + + /** + * Returns the area or zone's name. + * + * enum LocaleConstant + * { + * LOCALE_enUS = 0, + * LOCALE_koKR = 1, + * LOCALE_frFR = 2, + * LOCALE_deDE = 3, + * LOCALE_zhCN = 4, + * LOCALE_zhTW = 5, + * LOCALE_esES = 6, + * LOCALE_esMX = 7, + * LOCALE_ruRU = 8 + * }; + * + * @param uint32 areaOrZoneId : area ID or zone ID + * @param [LocaleConstant] locale = DEFAULT_LOCALE : locale to return the name in + * @return string areaOrZoneName + */ + int GetAreaName(lua_State* L) + { + uint32 areaOrZoneId = Eluna::CHECKVAL(L, 1); + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaOrZoneId); + if (!areaEntry) + return luaL_argerror(L, 1, "valid Area or Zone ID expected"); + + Eluna::Push(L, areaEntry->area_name[locale]); + return 1; + } + + /** + * Returns the currently active game events. + * + * @return table activeEvents + */ + int GetActiveGameEvents(lua_State* L) + { + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 counter = 1; + GameEventMgr::ActiveEvents const& activeEvents = eGameEventMgr->GetActiveEventList(); + + for (GameEventMgr::ActiveEvents::const_iterator i = activeEvents.begin(); i != activeEvents.end(); ++i) + { + Eluna::Push(L, *i); + lua_rawseti(L, tbl, counter); + + counter++; + } + + lua_settop(L, tbl); + return 1; + } + + static int RegisterEntryHelper(lua_State* L, int regtype) + { + uint32 id = Eluna::CHECKVAL(L, 1); + uint32 ev = Eluna::CHECKVAL(L, 2); + luaL_checktype(L, 3, LUA_TFUNCTION); + uint32 shots = Eluna::CHECKVAL(L, 4, 0); + + lua_pushvalue(L, 3); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef >= 0) + return Eluna::GetEluna(L)->Register(L, regtype, id, ObjectGuid(), 0, ev, functionRef, shots); + else + luaL_argerror(L, 3, "unable to make a ref to function"); + return 0; + } + + static int RegisterEventHelper(lua_State* L, int regtype) + { + uint32 ev = Eluna::CHECKVAL(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + uint32 shots = Eluna::CHECKVAL(L, 3, 0); + + lua_pushvalue(L, 2); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef >= 0) + return Eluna::GetEluna(L)->Register(L, regtype, 0, ObjectGuid(), 0, ev, functionRef, shots); + else + luaL_argerror(L, 2, "unable to make a ref to function"); + return 0; + } + + static int RegisterUniqueHelper(lua_State* L, int regtype) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + uint32 instanceId = Eluna::CHECKVAL(L, 2); + uint32 ev = Eluna::CHECKVAL(L, 3); + luaL_checktype(L, 4, LUA_TFUNCTION); + uint32 shots = Eluna::CHECKVAL(L, 5, 0); + + lua_pushvalue(L, 4); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef >= 0) + return Eluna::GetEluna(L)->Register(L, regtype, 0, guid, instanceId, ev, functionRef, shots); + else + luaL_argerror(L, 4, "unable to make a ref to function"); + return 0; + } + + /** + * Registers a server event handler. + * + * enum ServerEvents + * { + * // Server + * SERVER_EVENT_ON_NETWORK_START = 1, // Not Implemented + * SERVER_EVENT_ON_NETWORK_STOP = 2, // Not Implemented + * SERVER_EVENT_ON_SOCKET_OPEN = 3, // Not Implemented + * SERVER_EVENT_ON_SOCKET_CLOSE = 4, // Not Implemented + * SERVER_EVENT_ON_PACKET_RECEIVE = 5, // (event, packet, player) - Player only if accessible. Can return false, newPacket + * SERVER_EVENT_ON_PACKET_RECEIVE_UNKNOWN = 6, // Not Implemented + * SERVER_EVENT_ON_PACKET_SEND = 7, // (event, packet, player) - Player only if accessible. Can return false + * + * // World + * WORLD_EVENT_ON_OPEN_STATE_CHANGE = 8, // (event, open) - Needs core support on Mangos + * WORLD_EVENT_ON_CONFIG_LOAD = 9, // (event, reload) + * // UNUSED = 10, + * WORLD_EVENT_ON_SHUTDOWN_INIT = 11, // (event, code, mask) + * WORLD_EVENT_ON_SHUTDOWN_CANCEL = 12, // (event) + * WORLD_EVENT_ON_UPDATE = 13, // (event, diff) + * WORLD_EVENT_ON_STARTUP = 14, // (event) + * WORLD_EVENT_ON_SHUTDOWN = 15, // (event) + * + * // Eluna + * ELUNA_EVENT_ON_LUA_STATE_CLOSE = 16, // (event) - triggers just before shutting down eluna (on shutdown and restart) + * + * // Map + * MAP_EVENT_ON_CREATE = 17, // (event, map) + * MAP_EVENT_ON_DESTROY = 18, // (event, map) + * MAP_EVENT_ON_GRID_LOAD = 19, // Not Implemented + * MAP_EVENT_ON_GRID_UNLOAD = 20, // Not Implemented + * MAP_EVENT_ON_PLAYER_ENTER = 21, // (event, map, player) + * MAP_EVENT_ON_PLAYER_LEAVE = 22, // (event, map, player) + * MAP_EVENT_ON_UPDATE = 23, // (event, map, diff) + * + * // Area trigger + * TRIGGER_EVENT_ON_TRIGGER = 24, // (event, player, triggerId) - Can return true + * + * // Weather + * WEATHER_EVENT_ON_CHANGE = 25, // (event, zoneId, state, grade) + * + * // Auction house + * AUCTION_EVENT_ON_ADD = 26, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) + * AUCTION_EVENT_ON_REMOVE = 27, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) + * AUCTION_EVENT_ON_SUCCESSFUL = 28, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) + * AUCTION_EVENT_ON_EXPIRE = 29, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) + * + * // AddOns + * ADDON_EVENT_ON_MESSAGE = 30, // (event, sender, type, prefix, msg, target) - target can be nil/whisper_target/guild/group/channel. Can return false + * + * WORLD_EVENT_ON_DELETE_CREATURE = 31, // (event, creature) + * WORLD_EVENT_ON_DELETE_GAMEOBJECT = 32, // (event, gameobject) + * + * // Eluna + * ELUNA_EVENT_ON_LUA_STATE_OPEN = 33, // (event) - triggers after all scripts are loaded + * + * GAME_EVENT_START = 34, // (event, gameeventid) + * GAME_EVENT_STOP = 35, // (event, gameeventid) + * }; + * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : server event ID, refer to ServerEvents above + * @param function function : function that will be called when the event occurs + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterServerEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_SERVER); + } + + /** + * Registers a [Player] event handler. + * + *
+     * enum PlayerEvents
+     * {
+     *     PLAYER_EVENT_ON_CHARACTER_CREATE        =     1,        // (event, player)
+     *     PLAYER_EVENT_ON_CHARACTER_DELETE        =     2,        // (event, guid)
+     *     PLAYER_EVENT_ON_LOGIN                   =     3,        // (event, player)
+     *     PLAYER_EVENT_ON_LOGOUT                  =     4,        // (event, player)
+     *     PLAYER_EVENT_ON_SPELL_CAST              =     5,        // (event, player, spell, skipCheck)
+     *     PLAYER_EVENT_ON_KILL_PLAYER             =     6,        // (event, killer, killed)
+     *     PLAYER_EVENT_ON_KILL_CREATURE           =     7,        // (event, killer, killed)
+     *     PLAYER_EVENT_ON_KILLED_BY_CREATURE      =     8,        // (event, killer, killed)
+     *     PLAYER_EVENT_ON_DUEL_REQUEST            =     9,        // (event, target, challenger)
+     *     PLAYER_EVENT_ON_DUEL_START              =     10,       // (event, player1, player2)
+     *     PLAYER_EVENT_ON_DUEL_END                =     11,       // (event, winner, loser, type)
+     *     PLAYER_EVENT_ON_GIVE_XP                 =     12,       // (event, player, amount, victim) - Can return new XP amount
+     *     PLAYER_EVENT_ON_LEVEL_CHANGE            =     13,       // (event, player, oldLevel)
+     *     PLAYER_EVENT_ON_MONEY_CHANGE            =     14,       // (event, player, amount) - Can return new money amount
+     *     PLAYER_EVENT_ON_REPUTATION_CHANGE       =     15,       // (event, player, factionId, standing, incremental) - Can return new standing
+     *     PLAYER_EVENT_ON_TALENTS_CHANGE          =     16,       // (event, player, points)
+     *     PLAYER_EVENT_ON_TALENTS_RESET           =     17,       // (event, player, noCost)
+     *     PLAYER_EVENT_ON_CHAT                    =     18,       // (event, player, msg, Type, lang) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_WHISPER                 =     19,       // (event, player, msg, Type, lang, receiver) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_GROUP_CHAT              =     20,       // (event, player, msg, Type, lang, group) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_GUILD_CHAT              =     21,       // (event, player, msg, Type, lang, guild) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_CHANNEL_CHAT            =     22,       // (event, player, msg, Type, lang, channel) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_EMOTE                   =     23,       // (event, player, emote) - Not triggered on any known emote
+     *     PLAYER_EVENT_ON_TEXT_EMOTE              =     24,       // (event, player, textEmote, emoteNum, guid)
+     *     PLAYER_EVENT_ON_SAVE                    =     25,       // (event, player)
+     *     PLAYER_EVENT_ON_BIND_TO_INSTANCE        =     26,       // (event, player, difficulty, mapid, permanent)
+     *     PLAYER_EVENT_ON_UPDATE_ZONE             =     27,       // (event, player, newZone, newArea)
+     *     PLAYER_EVENT_ON_MAP_CHANGE              =     28,       // (event, player)
+     *
+     *     // Custom
+     *     PLAYER_EVENT_ON_EQUIP                   =     29,       // (event, player, item, bag, slot)
+     *     PLAYER_EVENT_ON_FIRST_LOGIN             =     30,       // (event, player)
+     *     PLAYER_EVENT_ON_CAN_USE_ITEM            =     31,       // (event, player, itemEntry) - Can return InventoryResult enum value
+     *     PLAYER_EVENT_ON_LOOT_ITEM               =     32,       // (event, player, item, count)
+     *     PLAYER_EVENT_ON_ENTER_COMBAT            =     33,       // (event, player, enemy)
+     *     PLAYER_EVENT_ON_LEAVE_COMBAT            =     34,       // (event, player)
+     *     PLAYER_EVENT_ON_REPOP                   =     35,       // (event, player)
+     *     PLAYER_EVENT_ON_RESURRECT               =     36,       // (event, player)
+     *     PLAYER_EVENT_ON_LOOT_MONEY              =     37,       // (event, player, amount)
+     *     PLAYER_EVENT_ON_QUEST_ABANDON           =     38,       // (event, player, questId)
+     *     PLAYER_EVENT_ON_LEARN_TALENTS           =     39,       // (event, player, talentId, talentRank, spellid)
+     *     PLAYER_EVENT_ON_ENVIRONMENTAL_DEATH     =     40,       // (event, player, environmentalDamageType)
+     *     PLAYER_EVENT_ON_TRADE_ACCEPT            =     41,       // (event, player, target) - Can return false to interrupt trade
+     *     PLAYER_EVENT_ON_COMMAND                 =     42,       // (event, player, command) - player is nil if command used from console. Can return false
+     *     PLAYER_EVENT_ON_SKILL_CHANGE            =     43,       // (event, player, skillId, skillValue) - Returns new skill level value
+     *     PLAYER_EVENT_ON_LEARN_SPELL             =     44,       // (event, player, spellId)
+     *     PLAYER_EVENT_ON_ACHIEVEMENT_COMPLETE    =     45,       // (event, player, achievementId)
+     *     // UNUSED                               =     46,       // (event, player)
+     *     PLAYER_EVENT_ON_UPDATE_AREA             =     47,       // (event, player, oldArea, newArea)
+     *     PLAYER_EVENT_ON_TRADE_INIT              =     48,       // (event, player, target) - Can return false to interrupt trade
+     *     PLAYER_EVENT_ON_SEND_MAIL               =     49,       // (event, player, recipientGuid) - Can return false to interrupt sending
+     *     // UNUSED                               =     50,       // (event, player)
+     *     // UNUSED                               =     51,       // (event, player)
+     *     // UNUSED                               =     52,       // (event, player)
+     *     // UNUSED                               =     53,       // (event, player)
+     *     PLAYER_EVENT_ON_QUEST_STATUS_CHANGED    =     54,       // (event, player, questId, status)
+     * };
+     * 
+ * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : [Player] event Id, refer to PlayerEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterPlayerEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_PLAYER); + } + + /** + * Registers a [Guild] event handler. + * + *
+     * enum GuildEvents
+     * {
+     *     // Guild
+     *     GUILD_EVENT_ON_ADD_MEMBER               =     1,       // (event, guild, player, rank)
+     *     GUILD_EVENT_ON_REMOVE_MEMBER            =     2,       // (event, guild, player, isDisbanding)
+     *     GUILD_EVENT_ON_MOTD_CHANGE              =     3,       // (event, guild, newMotd)
+     *     GUILD_EVENT_ON_INFO_CHANGE              =     4,       // (event, guild, newInfo)
+     *     GUILD_EVENT_ON_CREATE                   =     5,       // (event, guild, leader, name)  // Not on TC
+     *     GUILD_EVENT_ON_DISBAND                  =     6,       // (event, guild)
+     *     GUILD_EVENT_ON_MONEY_WITHDRAW           =     7,       // (event, guild, player, amount, isRepair) - Can return new money amount
+     *     GUILD_EVENT_ON_MONEY_DEPOSIT            =     8,       // (event, guild, player, amount) - Can return new money amount
+     *     GUILD_EVENT_ON_ITEM_MOVE                =     9,       // (event, guild, player, item, isSrcBank, srcContainer, srcSlotId, isDestBank, destContainer, destSlotId)   // TODO
+     *     GUILD_EVENT_ON_EVENT                    =     10,      // (event, guild, eventType, plrGUIDLow1, plrGUIDLow2, newRank)  // TODO
+     *     GUILD_EVENT_ON_BANK_EVENT               =     11,      // (event, guild, eventType, tabId, playerGUIDLow, itemOrMoney, itemStackCount, destTabId)
+     *
+     *     GUILD_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : [Guild] event Id, refer to GuildEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterGuildEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_GUILD); + } + + /** + * Registers a [Group] event handler. + * + *
+     * enum GroupEvents
+     * {
+     *     // Group
+     *     GROUP_EVENT_ON_MEMBER_ADD               =     1,       // (event, group, guid)
+     *     GROUP_EVENT_ON_MEMBER_INVITE            =     2,       // (event, group, guid)
+     *     GROUP_EVENT_ON_MEMBER_REMOVE            =     3,       // (event, group, guid, method, kicker, reason)
+     *     GROUP_EVENT_ON_LEADER_CHANGE            =     4,       // (event, group, newLeaderGuid, oldLeaderGuid)
+     *     GROUP_EVENT_ON_DISBAND                  =     5,       // (event, group)
+     *     GROUP_EVENT_ON_CREATE                   =     6,       // (event, group, leaderGuid, groupType)
+     *     GROUP_EVENT_ON_MEMBER_ACCEPT            =     7,       // (event, group, player) - Can return false to disable accepting
+     *
+     *     GROUP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : [Group] event Id, refer to GroupEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterGroupEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_GROUP); + } + + /** + * Registers a [BattleGround] event handler. + * + *
+     * enum BGEvents
+     * {
+     *     BG_EVENT_ON_START                               = 1,    // (event, bg, bgId, instanceId) - Needs to be added to TC
+     *     BG_EVENT_ON_END                                 = 2,    // (event, bg, bgId, instanceId, winner) - Needs to be added to TC
+     *     BG_EVENT_ON_CREATE                              = 3,    // (event, bg, bgId, instanceId) - Needs to be added to TC
+     *     BG_EVENT_ON_PRE_DESTROY                         = 4,    // (event, bg, bgId, instanceId) - Needs to be added to TC
+     *     BG_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : [BattleGround] event Id, refer to BGEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterBGEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_BG); + } + + /** + * Registers a [WorldPacket] event handler. + * + *
+     * enum PacketEvents
+     * {
+     *     PACKET_EVENT_ON_PACKET_RECEIVE          =     5,       // (event, packet, player) - Player only if accessible. Can return false, newPacket
+     *     PACKET_EVENT_ON_PACKET_RECEIVE_UNKNOWN  =     6,       // Not Implemented
+     *     PACKET_EVENT_ON_PACKET_SEND             =     7,       // (event, packet, player) - Player only if accessible. Can return false
+     *
+     *     PACKET_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : opcode + * @param uint32 event : packet event Id, refer to PacketEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterPacketEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_PACKET); + } + + /** + * Registers a [Creature] gossip event handler. + * + *
+     * enum GossipEvents
+     * {
+     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
+     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
+     *     GOSSIP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [Creature] entry Id + * @param uint32 event : [Creature] gossip event Id, refer to GossipEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterCreatureGossipEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_CREATURE_GOSSIP); + } + + /** + * Registers a [GameObject] gossip event handler. + * + *
+     * enum GossipEvents
+     * {
+     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
+     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
+     *     GOSSIP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [GameObject] entry Id + * @param uint32 event : [GameObject] gossip event Id, refer to GossipEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterGameObjectGossipEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_GAMEOBJECT_GOSSIP); + } + + /** + * Registers an [Item] event handler. + * + *
+     * enum ItemEvents
+     * {
+     *     ITEM_EVENT_ON_DUMMY_EFFECT                      = 1,    // (event, caster, spellid, effindex, item)
+     *     ITEM_EVENT_ON_USE                               = 2,    // (event, player, item, target) - Can return false to stop the spell casting
+     *     ITEM_EVENT_ON_QUEST_ACCEPT                      = 3,    // (event, player, item, quest) - Can return true
+     *     ITEM_EVENT_ON_EXPIRE                            = 4,    // (event, player, itemid) - Can return true
+     *     ITEM_EVENT_ON_REMOVE                            = 5,    // (event, player, item) - Can return true
+     *     ITEM_EVENT_ON_ADD                               = 6,    // (event, player, item)
+     *     ITEM_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [Item] entry Id + * @param uint32 event : [Item] event Id, refer to ItemEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterItemEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_ITEM); + } + + /** + * Registers an [Item] gossip event handler. + * + *
+     * enum GossipEvents
+     * {
+     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
+     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
+     *     GOSSIP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [Item] entry Id + * @param uint32 event : [Item] gossip event Id, refer to GossipEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterItemGossipEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_ITEM_GOSSIP); + } + + /** + * Registers a [Map] event handler for all instance of a [Map]. + * + *
+     * enum InstanceEvents
+     * {
+     *     INSTANCE_EVENT_ON_INITIALIZE                    = 1,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_ON_LOAD                          = 2,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_ON_UPDATE                        = 3,    // (event, instance_data, map, diff)
+     *     INSTANCE_EVENT_ON_PLAYER_ENTER                  = 4,    // (event, instance_data, map, player)
+     *     INSTANCE_EVENT_ON_CREATURE_CREATE               = 5,    // (event, instance_data, map, creature)
+     *     INSTANCE_EVENT_ON_GAMEOBJECT_CREATE             = 6,    // (event, instance_data, map, go)
+     *     INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS   = 7,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_COUNT
+     * };
+     * 
+ * + * @param uint32 map_id : ID of a [Map] + * @param uint32 event : [Map] event ID, refer to MapEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + */ + int RegisterMapEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_MAP); + } + + /** + * Registers a [Map] event handler for one instance of a [Map]. + * + *
+     * enum InstanceEvents
+     * {
+     *     INSTANCE_EVENT_ON_INITIALIZE                    = 1,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_ON_LOAD                          = 2,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_ON_UPDATE                        = 3,    // (event, instance_data, map, diff)
+     *     INSTANCE_EVENT_ON_PLAYER_ENTER                  = 4,    // (event, instance_data, map, player)
+     *     INSTANCE_EVENT_ON_CREATURE_CREATE               = 5,    // (event, instance_data, map, creature)
+     *     INSTANCE_EVENT_ON_GAMEOBJECT_CREATE             = 6,    // (event, instance_data, map, go)
+     *     INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS   = 7,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_COUNT
+     * };
+     * 
+ * + * @param uint32 instance_id : ID of an instance of a [Map] + * @param uint32 event : [Map] event ID, refer to MapEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + */ + int RegisterInstanceEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_INSTANCE); + } + + /** + * Registers a [Player] gossip event handler. + * + * Note that you can not use `GOSSIP_EVENT_ON_HELLO` with this hook. It does nothing since players dont have an "on hello". + * + *
+     * enum GossipEvents
+     * {
+     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
+     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
+     *     GOSSIP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (menu_id, event, function) + * @proto cancel = (menu_id, event, function, shots) + * + * @param uint32 menu_id : [Player] gossip menu Id + * @param uint32 event : [Player] gossip event Id, refer to GossipEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterPlayerGossipEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_PLAYER_GOSSIP); + } + + /** + * Registers a [Creature] event handler. + * + *
+     * enum CreatureEvents
+     * {
+     *     CREATURE_EVENT_ON_ENTER_COMBAT                    = 1,  // (event, creature, target) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_LEAVE_COMBAT                    = 2,  // (event, creature) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_TARGET_DIED                     = 3,  // (event, creature, victim) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_DIED                            = 4,  // (event, creature, killer) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SPAWN                           = 5,  // (event, creature) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_REACH_WP                        = 6,  // (event, creature, type, id) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_AIUPDATE                        = 7,  // (event, creature, diff) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_RECEIVE_EMOTE                   = 8,  // (event, creature, player, emoteid) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_DAMAGE_TAKEN                    = 9,  // (event, creature, attacker, damage) - Can return true to stop normal action, can return new damage as second return value.
+     *     CREATURE_EVENT_ON_PRE_COMBAT                      = 10, // (event, creature, target) - Can return true to stop normal action
+     *     // UNUSED
+     *     CREATURE_EVENT_ON_OWNER_ATTACKED                  = 12, // (event, creature, target) - Can return true to stop normal action            // Not on mangos
+     *     CREATURE_EVENT_ON_OWNER_ATTACKED_AT               = 13, // (event, creature, attacker) - Can return true to stop normal action          // Not on mangos
+     *     CREATURE_EVENT_ON_HIT_BY_SPELL                    = 14, // (event, creature, caster, spellid) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SPELL_HIT_TARGET                = 15, // (event, creature, target, spellid) - Can return true to stop normal action
+     *     // UNUSED                                         = 16, // (event, creature)
+     *     // UNUSED                                         = 17, // (event, creature)
+     *     // UNUSED                                         = 18, // (event, creature)
+     *     CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE          = 19, // (event, creature, summon) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN       = 20, // (event, creature, summon) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED          = 21, // (event, creature, summon, killer) - Can return true to stop normal action    // Not on mangos
+     *     CREATURE_EVENT_ON_SUMMONED                        = 22, // (event, creature, summoner) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_RESET                           = 23, // (event, creature)
+     *     CREATURE_EVENT_ON_REACH_HOME                      = 24, // (event, creature) - Can return true to stop normal action
+     *     // UNUSED                                         = 25, // (event, creature)
+     *     CREATURE_EVENT_ON_CORPSE_REMOVED                  = 26, // (event, creature, respawndelay) - Can return true to stop normal action, can return new respawndelay as second return value
+     *     CREATURE_EVENT_ON_MOVE_IN_LOS                     = 27, // (event, creature, unit) - Can return true to stop normal action. Does not actually check LOS, just uses the sight range
+     *     // UNUSED                                         = 28, // (event, creature)
+     *     // UNUSED                                         = 29, // (event, creature)
+     *     CREATURE_EVENT_ON_DUMMY_EFFECT                    = 30, // (event, caster, spellid, effindex, creature)
+     *     CREATURE_EVENT_ON_QUEST_ACCEPT                    = 31, // (event, player, creature, quest) - Can return true
+     *     // UNUSED                                         = 32, // (event, creature)
+     *     // UNUSED                                         = 33, // (event, creature)
+     *     CREATURE_EVENT_ON_QUEST_REWARD                    = 34, // (event, player, creature, quest, opt) - Can return true
+     *     CREATURE_EVENT_ON_DIALOG_STATUS                   = 35, // (event, player, creature)
+     *     CREATURE_EVENT_ON_ADD                             = 36, // (event, creature)
+     *     CREATURE_EVENT_ON_REMOVE                          = 37, // (event, creature)
+     *     CREATURE_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : the ID of one or more [Creature]s + * @param uint32 event : refer to CreatureEvents above + * @param function function : function that will be called when the event occurs + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterCreatureEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_CREATURE); + } + + /** + * Registers a [Creature] event handler for a *single* [Creature]. + * + *
+     * enum CreatureEvents
+     * {
+     *     CREATURE_EVENT_ON_ENTER_COMBAT                    = 1,  // (event, creature, target) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_LEAVE_COMBAT                    = 2,  // (event, creature) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_TARGET_DIED                     = 3,  // (event, creature, victim) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_DIED                            = 4,  // (event, creature, killer) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SPAWN                           = 5,  // (event, creature) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_REACH_WP                        = 6,  // (event, creature, type, id) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_AIUPDATE                        = 7,  // (event, creature, diff) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_RECEIVE_EMOTE                   = 8,  // (event, creature, player, emoteid) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_DAMAGE_TAKEN                    = 9,  // (event, creature, attacker, damage) - Can return true to stop normal action, can return new damage as second return value.
+     *     CREATURE_EVENT_ON_PRE_COMBAT                      = 10, // (event, creature, target) - Can return true to stop normal action
+     *     // UNUSED
+     *     CREATURE_EVENT_ON_OWNER_ATTACKED                  = 12, // (event, creature, target) - Can return true to stop normal action            // Not on mangos
+     *     CREATURE_EVENT_ON_OWNER_ATTACKED_AT               = 13, // (event, creature, attacker) - Can return true to stop normal action          // Not on mangos
+     *     CREATURE_EVENT_ON_HIT_BY_SPELL                    = 14, // (event, creature, caster, spellid) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SPELL_HIT_TARGET                = 15, // (event, creature, target, spellid) - Can return true to stop normal action
+     *     // UNUSED                                         = 16, // (event, creature)
+     *     // UNUSED                                         = 17, // (event, creature)
+     *     // UNUSED                                         = 18, // (event, creature)
+     *     CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE          = 19, // (event, creature, summon) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN       = 20, // (event, creature, summon) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED          = 21, // (event, creature, summon, killer) - Can return true to stop normal action    // Not on mangos
+     *     CREATURE_EVENT_ON_SUMMONED                        = 22, // (event, creature, summoner) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_RESET                           = 23, // (event, creature)
+     *     CREATURE_EVENT_ON_REACH_HOME                      = 24, // (event, creature) - Can return true to stop normal action
+     *     // UNUSED                                         = 25, // (event, creature)
+     *     CREATURE_EVENT_ON_CORPSE_REMOVED                  = 26, // (event, creature, respawndelay) - Can return true to stop normal action, can return new respawndelay as second return value
+     *     CREATURE_EVENT_ON_MOVE_IN_LOS                     = 27, // (event, creature, unit) - Can return true to stop normal action. Does not actually check LOS, just uses the sight range
+     *     // UNUSED                                         = 28, // (event, creature)
+     *     // UNUSED                                         = 29, // (event, creature)
+     *     CREATURE_EVENT_ON_DUMMY_EFFECT                    = 30, // (event, caster, spellid, effindex, creature)
+     *     CREATURE_EVENT_ON_QUEST_ACCEPT                    = 31, // (event, player, creature, quest) - Can return true
+     *     // UNUSED                                         = 32, // (event, creature)
+     *     // UNUSED                                         = 33, // (event, creature)
+     *     CREATURE_EVENT_ON_QUEST_REWARD                    = 34, // (event, player, creature, quest, opt) - Can return true
+     *     CREATURE_EVENT_ON_DIALOG_STATUS                   = 35, // (event, player, creature)
+     *     CREATURE_EVENT_ON_ADD                             = 36, // (event, creature)
+     *     CREATURE_EVENT_ON_REMOVE                          = 37, // (event, creature)
+     *     CREATURE_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (guid, instance_id, event, function) + * @proto cancel = (guid, instance_id, event, function, shots) + * + * @param ObjectGuid guid : the GUID of a single [Creature] + * @param uint32 instance_id : the instance ID of a single [Creature] + * @param uint32 event : refer to CreatureEvents above + * @param function function : function that will be called when the event occurs + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterUniqueCreatureEvent(lua_State* L) + { + return RegisterUniqueHelper(L, Hooks::REGTYPE_CREATURE); + } + + /** + * Registers a [GameObject] event handler. + * + *
+     * enum GameObjectEvents
+     * {
+     *     GAMEOBJECT_EVENT_ON_AIUPDATE                    = 1,    // (event, go, diff)
+     *     GAMEOBJECT_EVENT_ON_SPAWN                       = 2,    // (event, go)
+     *     GAMEOBJECT_EVENT_ON_DUMMY_EFFECT                = 3,    // (event, caster, spellid, effindex, go) - Can return true to stop normal action
+     *     GAMEOBJECT_EVENT_ON_QUEST_ACCEPT                = 4,    // (event, player, go, quest) - Can return true to stop normal action
+     *     GAMEOBJECT_EVENT_ON_QUEST_REWARD                = 5,    // (event, player, go, quest, opt) - Can return true to stop normal action
+     *     GAMEOBJECT_EVENT_ON_DIALOG_STATUS               = 6,    // (event, player, go)
+     *     GAMEOBJECT_EVENT_ON_DESTROYED                   = 7,    // (event, go, attacker)
+     *     GAMEOBJECT_EVENT_ON_DAMAGED                     = 8,    // (event, go, attacker)
+     *     GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE           = 9,    // (event, go, state)
+     *     GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED            = 10,   // (event, go, state)
+     *     // UNUSED                                       = 11,   // (event, gameobject)
+     *     GAMEOBJECT_EVENT_ON_ADD                         = 12,   // (event, gameobject)
+     *     GAMEOBJECT_EVENT_ON_REMOVE                      = 13,   // (event, gameobject)
+     *     GAMEOBJECT_EVENT_ON_USE                         = 14,   // (event, go, player) - Can return true to stop normal action
+     *     GAMEOBJECT_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [GameObject] entry Id + * @param uint32 event : [GameObject] event Id, refer to GameObjectEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterGameObjectEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_GAMEOBJECT); + } + + /** + * Reloads the Lua engine. + */ + int ReloadEluna(lua_State* /*L*/) + { + Eluna::ReloadEluna(); + return 0; + } + + /** + * Runs a command. + * + * @param string command : the command to run + */ + int RunCommand(lua_State* L) + { + const char* command = Eluna::CHECKVAL(L, 1); + + eWorld->QueueCliCommand(new CliCommandHolder(0, SEC_CONSOLE, command, nullptr, nullptr)); + return 0; + } + + /** + * Sends a message to all [Player]s online. + * + * @param string message : message to send + */ + int SendWorldMessage(lua_State* L) + { + const char* message = Eluna::CHECKVAL(L, 1); + eWorld->SendServerMessage(SERVER_MSG_STRING, message); + return 0; + } + + /** + * Executes a SQL query on the world database and returns an [ElunaQuery]. + * + * The query is always executed synchronously + * (i.e. execution halts until the query has finished and then results are returned). + * + * local Q = WorldDBQuery("SELECT entry, name FROM creature_template LIMIT 10") + * if Q then + * repeat + * local entry, name = Q:GetUInt32(0), Q:GetString(1) + * print(entry, name) + * until not Q:NextRow() + * end + * + * @param string sql : query to execute + * @return [ElunaQuery] results or nil if no rows found or nil if no rows found + */ + int WorldDBQuery(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + + ElunaQuery* result = WorldDatabase.QueryNamed(query); + if (result) + Eluna::Push(L, result); + else + Eluna::Push(L); + return 1; + } + + /** + * Executes a SQL query on the world database. + * + * The query may be executed *asynchronously* (at a later, unpredictable time). + * If you need to execute the query synchronously, use [Global:WorldDBQuery] instead. + * + * Any results produced are ignored. + * If you need results from the query, use [Global:WorldDBQuery] instead. + * + * WorldDBExecute("DELETE FROM my_table") + * + * @param string sql : query to execute + */ + int WorldDBExecute(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + WorldDatabase.Execute(query); + return 0; + } + + /** + * Executes a SQL query on the character database and returns an [ElunaQuery]. + * + * The query is always executed synchronously + * (i.e. execution halts until the query has finished and then results are returned). + * + * For an example see [Global:WorldDBQuery]. + * + * @param string sql : query to execute + * @return [ElunaQuery] results or nil if no rows found + */ + int CharDBQuery(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + + QueryNamedResult* result = CharacterDatabase.QueryNamed(query); + if (result) + Eluna::Push(L, result); + else + Eluna::Push(L); + return 1; + } + + /** + * Executes a SQL query on the character database. + * + * The query may be executed *asynchronously* (at a later, unpredictable time). + * If you need to execute the query synchronously, use [Global:CharDBQuery] instead. + * + * Any results produced are ignored. + * If you need results from the query, use [Global:CharDBQuery] instead. + * + * CharDBExecute("DELETE FROM my_table") + * + * @param string sql : query to execute + */ + int CharDBExecute(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + CharacterDatabase.Execute(query); + return 0; + } + + /** + * Executes a SQL query on the login database and returns an [ElunaQuery]. + * + * The query is always executed synchronously + * (i.e. execution halts until the query has finished and then results are returned). + * + * For an example see [Global:WorldDBQuery]. + * + * @param string sql : query to execute + * @return [ElunaQuery] results or nil if no rows found + */ + int AuthDBQuery(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + + QueryNamedResult* result = LoginDatabase.QueryNamed(query); + if (result) + Eluna::Push(L, result); + else + Eluna::Push(L); + return 1; + } + + /** + * Executes a SQL query on the login database. + * + * The query may be executed *asynchronously* (at a later, unpredictable time). + * If you need to execute the query synchronously, use [Global:AuthDBQuery] instead. + * + * Any results produced are ignored. + * If you need results from the query, use [Global:AuthDBQuery] instead. + * + * AuthDBExecute("DELETE FROM my_table") + * + * @param string sql : query to execute + */ + int AuthDBExecute(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + LoginDatabase.Execute(query); + return 0; + } + + /** + * Registers a global timed event. + * + * When the passed function is called, the parameters `(eventId, delay, repeats)` are passed to it. + * + * Repeats will decrease on each call if the event does not repeat indefinitely + * + * @proto eventId = (function, delay) + * @proto eventId = (function, delaytable) + * @proto eventId = (function, delay, repeats) + * @proto eventId = (function, delaytable, repeats) + * + * @param function function : function to trigger when the time has passed + * @param uint32 delay : set time in milliseconds for the event to trigger + * @param table delaytable : a table `{min, max}` containing the minimum and maximum delay time + * @param uint32 repeats = 1 : how many times for the event to repeat, 0 is infinite + * @return int eventId : unique ID for the timed event used to cancel it or nil + */ + int CreateLuaEvent(lua_State* L) + { + luaL_checktype(L, 1, LUA_TFUNCTION); + uint32 min, max; + if (lua_istable(L, 2)) + { + Eluna::Push(L, 1); + lua_gettable(L, 2); + min = Eluna::CHECKVAL(L, -1); + Eluna::Push(L, 2); + lua_gettable(L, 2); + max = Eluna::CHECKVAL(L, -1); + lua_pop(L, 2); + } + else + min = max = Eluna::CHECKVAL(L, 2); + uint32 repeats = Eluna::CHECKVAL(L, 3, 1); + + if (min > max) + return luaL_argerror(L, 2, "min is bigger than max delay"); + + lua_pushvalue(L, 1); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF) + { + Eluna::GetEluna(L)->eventMgr->globalProcessor->AddEvent(functionRef, min, max, repeats); + Eluna::Push(L, functionRef); + } + return 1; + } + + /** + * Removes a global timed event specified by ID. + * + * @param int eventId : event Id to remove + * @param bool all_Events = false : remove from all events, not just global + */ + int RemoveEventById(lua_State* L) + { + int eventId = Eluna::CHECKVAL(L, 1); + bool all_Events = Eluna::CHECKVAL(L, 1, false); + + // not thread safe + if (all_Events) + Eluna::GetEluna(L)->eventMgr->SetState(eventId, LUAEVENT_STATE_ABORT); + else + Eluna::GetEluna(L)->eventMgr->globalProcessor->SetState(eventId, LUAEVENT_STATE_ABORT); + return 0; + } + + /** + * Removes all global timed events. + * + * @param bool all_Events = false : remove all events, not just global + */ + int RemoveEvents(lua_State* L) + { + bool all_Events = Eluna::CHECKVAL(L, 1, false); + + // not thread safe + if (all_Events) + Eluna::GetEluna(L)->eventMgr->SetStates(LUAEVENT_STATE_ABORT); + else + Eluna::GetEluna(L)->eventMgr->globalProcessor->SetStates(LUAEVENT_STATE_ABORT); + return 0; + } + + /** + * Performs an in-game spawn and returns the [Creature] or [GameObject] spawned. + * + * @param int32 spawnType : type of object to spawn, 1 = [Creature], 2 = [GameObject] + * @param uint32 entry : entry ID of the [Creature] or [GameObject] + * @param uint32 mapId : map ID to spawn the [Creature] or [GameObject] in + * @param uint32 instanceId : instance ID to put the [Creature] or [GameObject] in. Non instance is 0 + * @param float x : x coordinate of the [Creature] or [GameObject] + * @param float y : y coordinate of the [Creature] or [GameObject] + * @param float z : z coordinate of the [Creature] or [GameObject] + * @param float o : o facing/orientation of the [Creature] or [GameObject] + * @param bool save = false : optional to save the [Creature] or [GameObject] to the database + * @param uint32 durorresptime = 0 : despawn time of the [Creature] if it's not saved or respawn time of [GameObject] + * @param uint32 phase = 1 : phase to put the [Creature] or [GameObject] in + * @return [WorldObject] worldObject : returns [Creature] or [GameObject] + */ + int PerformIngameSpawn(lua_State* L) + { + int spawntype = Eluna::CHECKVAL(L, 1); + uint32 entry = Eluna::CHECKVAL(L, 2); + uint32 mapID = Eluna::CHECKVAL(L, 3); + uint32 instanceID = Eluna::CHECKVAL(L, 4); + float x = Eluna::CHECKVAL(L, 5); + float y = Eluna::CHECKVAL(L, 6); + float z = Eluna::CHECKVAL(L, 7); + float o = Eluna::CHECKVAL(L, 8); + bool save = Eluna::CHECKVAL(L, 9, false); + uint32 durorresptime = Eluna::CHECKVAL(L, 10, 0); +#if (!defined(TBC) && !defined(CLASSIC)) + uint32 phase = Eluna::CHECKVAL(L, 11, PHASEMASK_NORMAL); + if (!phase) + { + Eluna::Push(L); + return 1; + } +#endif + + Map* map = eMapMgr->FindMap(mapID, instanceID); + if (!map) + { + Eluna::Push(L); + return 1; + } + + if (spawntype == 1) // spawn creature + { + if (save) + { + CreatureInfo const* cinfo = ObjectMgr::GetCreatureTemplate(entry); + if (!cinfo) + { + Eluna::Push(L); + return 1; + } + +#if (defined(TBC) || defined(CLASSIC)) + CreatureCreatePos pos(map, x, y, z, o); +#else + CreatureCreatePos pos(map, x, y, z, o, phase); +#endif + Creature* pCreature = new Creature; + // used guids from specially reserved range (can be 0 if no free values) + uint32 lowguid = eObjectMgr->GenerateStaticCreatureLowGuid(); + if (!lowguid) + { + Eluna::Push(L); + return 1; + } +#ifndef CATA + if (!pCreature->Create(lowguid, lowguid, pos, cinfo)) +#else + if (!pCreature->Create(lowguid, pos, cinfo)) +#endif + { + delete pCreature; + Eluna::Push(L); + return 1; + } + +#ifdef TBC + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); +#elif defined(CLASSIC) + pCreature->SaveToDB(map->GetId()); +#else + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), phase); +#endif + + uint32 db_guid = pCreature->GetGUIDLow(); + + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); +#ifndef CATA + pCreature->LoadFromDB(db_guid, map, db_guid, 0); +#else + pCreature->LoadFromDB(db_guid, map); +#endif + + map->Add(pCreature); + eObjectMgr->AddCreatureToGrid(db_guid, eObjectMgr->GetCreatureData(db_guid)); + if (durorresptime) + pCreature->ForcedDespawn(durorresptime); + + Eluna::Push(L, pCreature); + } + else + { + CreatureInfo const* cinfo = ObjectMgr::GetCreatureTemplate(entry); + if (!cinfo) + { + Eluna::Push(L); + return 1; + } + + TemporarySpawn* pCreature = new TemporarySpawn(ObjectGuid(uint64(0))); + +#if (defined(TBC) || defined(CLASSIC)) + CreatureCreatePos pos(map, x, y, z, o); +#else + CreatureCreatePos pos(map, x, y, z, o, phase); +#endif +#ifdef CATA + if (!pCreature->Create(map->GenerateLocalLowGuid(cinfo->GetHighGuid()), pos, cinfo)) +#else + if (!pCreature->Create(map->GenerateLocalLowGuid(cinfo->GetHighGuid()), map->GenerateLocalLowGuid(cinfo->GetHighGuid()), pos, cinfo)) +#endif + { + delete pCreature; + { + Eluna::Push(L); + return 1; + } + } + + pCreature->SetRespawnCoord(pos); + + // Active state set before added to map + pCreature->SetActiveObjectState(false); + + // Also initializes the AI and MMGen + pCreature->Summon(durorresptime ? TEMPSPAWN_TIMED_OR_DEAD_DESPAWN : TEMPSPAWN_MANUAL_DESPAWN, durorresptime); + + // Creature Linking, Initial load is handled like respawn + if (pCreature->IsLinkingEventTrigger()) + map->GetCreatureLinkingHolder()->DoCreatureLinkingEvent(LINKING_EVENT_RESPAWN, pCreature); + + Eluna::Push(L, pCreature); + } + + return 1; + } + + if (spawntype == 2) // Spawn object + { + if (save) + { + const GameObjectInfo* gInfo = ObjectMgr::GetGameObjectInfo(entry); + if (!gInfo) + { + Eluna::Push(L); + return 1; + } + + // used guids from specially reserved range (can be 0 if no free values) + uint32 db_lowGUID = eObjectMgr->GenerateStaticGameObjectLowGuid(); + if (!db_lowGUID) + { + Eluna::Push(L); + return 1; + } + + GameObject* pGameObj = new GameObject; +#if (defined(TBC) || defined(CLASSIC)) + if (!pGameObj->Create(db_lowGUID, db_lowGUID, gInfo->id, map, x, y, z, o)) +#elif defined CATA + if (!pGameObj->Create(db_lowGUID, gInfo->id, map, phase, x, y, z, o)) +#else + if (!pGameObj->Create(db_lowGUID, db_lowGUID, gInfo->id, map, phase, x, y, z, o)) +#endif + { + delete pGameObj; + Eluna::Push(L); + return 1; + } + + if (durorresptime) + pGameObj->SetRespawnTime(durorresptime); + + // fill the gameobject data and save to the db +#ifdef TBC + pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); +#elif defined(CLASSIC) + pGameObj->SaveToDB(map->GetId()); +#else + pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), phase); +#endif + + // this will generate a new guid if the object is in an instance +#ifndef CATA + if (!pGameObj->LoadFromDB(db_lowGUID, map, db_lowGUID, 0)) +#else + if (!pGameObj->LoadFromDB(db_lowGUID, map)) +#endif + { + delete pGameObj; + Eluna::Push(L); + return 1; + } + + // DEBUG_LOG(GetMangosString(LANG_GAMEOBJECT_CURRENT), gInfo->name, db_lowGUID, x, y, z, o); + + map->Add(pGameObj); + pGameObj->AIM_Initialize(); + + eObjectMgr->AddGameobjectToGrid(db_lowGUID, eObjectMgr->GetGOData(db_lowGUID)); + + Eluna::Push(L, pGameObj); + } + else + { + GameObject* pGameObj = new GameObject; +#if (defined(TBC) || defined(CLASSIC)) + if (!pGameObj->Create(map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), entry, map, x, y, z, o)) +#elif !defined CATA + if (!pGameObj->Create(map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), entry, map, phase, x, y, z, o)) +#else + if (!pGameObj->Create(map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), entry, map, phase, x, y, z, o)) +#endif + { + delete pGameObj; + Eluna::Push(L); + return 1; + } + + pGameObj->SetRespawnTime(durorresptime / IN_MILLISECONDS); + + map->Add(pGameObj); + pGameObj->AIM_Initialize(); + + Eluna::Push(L, pGameObj); + } + return 1; + } + + Eluna::Push(L); + return 1; + } + + /** + * Creates a [WorldPacket]. + * + * @param [Opcodes] opcode : the opcode of the packet + * @param uint32 size : the size of the packet + * @return [WorldPacket] packet + */ + int CreatePacket(lua_State* L) + { + uint32 opcode = Eluna::CHECKVAL(L, 1); + size_t size = Eluna::CHECKVAL(L, 2); + if (opcode >= NUM_MSG_TYPES) + return luaL_argerror(L, 1, "valid opcode expected"); + +#ifdef CLASSIC + Eluna::Push(L, new WorldPacket((Opcodes)opcode, size)); +#else + Eluna::Push(L, new WorldPacket((OpcodesList)opcode, size)); +#endif + return 1; + } + + /** + * Adds an [Item] to a vendor and updates the world database. + * + * @param uint32 entry : [Creature] entry Id + * @param uint32 item : [Item] entry Id + * @param int32 maxcount : max [Item] stack count + * @param uint32 incrtime : combined with maxcount, incrtime tells how often (in seconds) the vendor list is refreshed and the limited [Item] copies are restocked + * @param uint32 extendedcost : unique cost of an [Item], such as conquest points for example + */ + int AddVendorItem(lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 item = Eluna::CHECKVAL(L, 2); + int maxcount = Eluna::CHECKVAL(L, 3); + uint32 incrtime = Eluna::CHECKVAL(L, 4); + uint32 extendedcost = Eluna::CHECKVAL(L, 5); + +#if defined TRINITY || AZEROTHCORE +#ifdef CATA + if (!eObjectMgr->IsVendorItemValid(entry, item, maxcount, incrtime, extendedcost, 1)) + return 0; + eObjectMgr->AddVendorItem(entry, item, maxcount, incrtime, extendedcost, 1); +#else + if (!eObjectMgr->IsVendorItemValid(entry, item, maxcount, incrtime, extendedcost)) + return 0; + eObjectMgr->AddVendorItem(entry, item, maxcount, incrtime, extendedcost); +#endif +#else +#ifndef CATA + if (!eObjectMgr->IsVendorItemValid(false, "npc_vendor", entry, item, maxcount, incrtime, extendedcost, 0)) +#else + if (!eObjectMgr->IsVendorItemValid(false, "npc_vendor", entry, item, VENDOR_ITEM_TYPE_ITEM, maxcount, incrtime, extendedcost, 0)) +#endif + return 0; +#ifdef CATA + eObjectMgr->AddVendorItem(entry, item, VENDOR_ITEM_TYPE_ITEM, maxcount, incrtime, extendedcost); +#elif !defined CLASSIC + eObjectMgr->AddVendorItem(entry, item, maxcount, incrtime, extendedcost); +#else + eObjectMgr->AddVendorItem(entry, item, maxcount, incrtime); +#endif +#endif//TRINITY + return 0; + } + + /** + * Removes an [Item] from a vendor and updates the database. + * + * @param uint32 entry : [Creature] entry Id + * @param uint32 item : [Item] entry Id + */ + int VendorRemoveItem(lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 item = Eluna::CHECKVAL(L, 2); + if (!eObjectMgr->GetCreatureTemplate(entry)) + return luaL_argerror(L, 1, "valid CreatureEntry expected"); + +#if defined(CATA) + eObjectMgr->RemoveVendorItem(entry, item, 1); +#else + eObjectMgr->RemoveVendorItem(entry, item); +#endif + return 0; + } + + /** + * Removes all [Item]s from a vendor and updates the database. + * + * @param uint32 entry : [Creature] entry Id + */ + int VendorRemoveAllItems(lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + VendorItemData const* items = eObjectMgr->GetNpcVendorItemList(entry); + if (!items || items->Empty()) + return 0; + + auto const itemlist = items->m_items; + for (auto itr = itemlist.begin(); itr != itemlist.end(); ++itr) +#if defined(CATA) + eObjectMgr->RemoveVendorItem(entry, (*itr)->item, 1); +#else + eObjectMgr->RemoveVendorItem(entry, (*itr)->item); +#endif + return 0; + } + + /** + * Kicks a [Player] from the server. + * + * @param [Player] player : [Player] to kick + */ + int Kick(lua_State* L) + { + Player* player = Eluna::CHECKOBJ(L, 1); + + player->GetSession()->KickPlayer(); + return 0; + } + + /** + * Ban's a [Player]'s account, character or IP + * + * enum BanMode + * { + * BAN_ACCOUNT = 0, + * BAN_CHARACTER = 1, + * BAN_IP = 2 + * }; + * + * @param [BanMode] banMode : method of ban, refer to BanMode above + * @param string nameOrIP : If BanMode is 0 then accountname, if 1 then charactername if 2 then ip + * @param uint32 duration : duration (in seconds) of the ban + * @param string reason = "" : ban reason, this is optional + * @param string whoBanned = "" : the [Player]'s name that banned the account, character or IP, this is optional + * @return int result : status of the ban. 0 if success, 1 if syntax error, 2 if target not found, 3 if a longer ban already exists, nil if unknown result + */ + int Ban(lua_State* L) + { + int banMode = Eluna::CHECKVAL(L, 1); + std::string nameOrIP = Eluna::CHECKVAL(L, 2); + uint32 duration = Eluna::CHECKVAL(L, 3); + const char* reason = Eluna::CHECKVAL(L, 4, ""); + const char* whoBanned = Eluna::CHECKVAL(L, 5, ""); + + const int BAN_ACCOUNT = 0; + const int BAN_CHARACTER = 1; + const int BAN_IP = 2; + + BanMode mode = BanMode::BAN_ACCOUNT; + + switch (banMode) + { + case BAN_ACCOUNT: + if (!AccountMgr::normalizeString(nameOrIP)) + return luaL_argerror(L, 2, "invalid account name"); + mode = BanMode::BAN_ACCOUNT; + break; + case BAN_CHARACTER: + if (!normalizePlayerName(nameOrIP)) + return luaL_argerror(L, 2, "invalid character name"); + mode = BanMode::BAN_CHARACTER; + break; + case BAN_IP: + if (!IsIPAddress(nameOrIP.c_str())) + return luaL_argerror(L, 2, "invalid ip"); + mode = BanMode::BAN_IP; + break; + default: + return luaL_argerror(L, 1, "unknown banmode"); + } + + BanReturn result; + result = eWorld->BanAccount(mode, nameOrIP, duration, reason, whoBanned); + + switch (result) + { + case BanReturn::BAN_SUCCESS: + Eluna::Push(L, 0); + break; + case BanReturn::BAN_SYNTAX_ERROR: + Eluna::Push(L, 1); + break; + case BanReturn::BAN_NOTFOUND: + Eluna::Push(L, 2); + break; + } + return 1; + } + + /** + * Saves all [Player]s. + */ + int SaveAllPlayers(lua_State* /*L*/) + { + eObjectAccessor()SaveAllPlayers(); + return 0; + } + + /** + * Sends mail to a [Player]. + * + * There can be several item entry-amount pairs at the end of the function. + * There can be maximum of 12 different items. + * + * enum MailStationery + * { + * MAIL_STATIONERY_TEST = 1, + * MAIL_STATIONERY_DEFAULT = 41, + * MAIL_STATIONERY_GM = 61, + * MAIL_STATIONERY_AUCTION = 62, + * MAIL_STATIONERY_VAL = 64, // Valentine + * MAIL_STATIONERY_CHR = 65, // Christmas + * MAIL_STATIONERY_ORP = 67 // Orphan + * }; + * + * @param string subject : title (subject) of the mail + * @param string text : contents of the mail + * @param uint32 receiverGUIDLow : low GUID of the receiver + * @param uint32 senderGUIDLow = 0 : low GUID of the sender + * @param [MailStationery] stationary = MAIL_STATIONERY_DEFAULT : type of mail that is being sent as, refer to MailStationery above + * @param uint32 delay = 0 : mail send delay in milliseconds + * @param uint32 money = 0 : money to send + * @param uint32 cod = 0 : cod money amount + * @param uint32 entry = 0 : entry of an [Item] to send with mail + * @param uint32 amount = 0 : amount of the [Item] to send with mail + * @return uint32 itemGUIDlow : low GUID of the item. Up to 12 values returned, returns nil if no further items are sent + */ + int SendMail(lua_State* L) + { + int i = 0; + std::string subject = Eluna::CHECKVAL(L, ++i); + std::string text = Eluna::CHECKVAL(L, ++i); + uint32 receiverGUIDLow = Eluna::CHECKVAL(L, ++i); + uint32 senderGUIDLow = Eluna::CHECKVAL(L, ++i, 0); + uint32 stationary = Eluna::CHECKVAL(L, ++i, MAIL_STATIONERY_DEFAULT); + uint32 delay = Eluna::CHECKVAL(L, ++i, 0); + uint32 money = Eluna::CHECKVAL(L, ++i, 0); + uint32 cod = Eluna::CHECKVAL(L, ++i, 0); + int argAmount = lua_gettop(L); + + MailSender sender(MAIL_NORMAL, senderGUIDLow, (MailStationery)stationary); + MailDraft draft(subject, text); + + if (cod) + draft.SetCOD(cod); + if (money) + draft.SetMoney(money); + + uint8 addedItems = 0; + while (addedItems <= MAX_MAIL_ITEMS && i + 2 <= argAmount) + { + uint32 entry = Eluna::CHECKVAL(L, ++i); + uint32 amount = Eluna::CHECKVAL(L, ++i); + + ItemTemplate const* item_proto = ObjectMgr::GetItemPrototype(entry); + if (!item_proto) + { + luaL_error(L, "Item entry %d does not exist", entry); + continue; + } + if (amount < 1 || (item_proto->MaxCount > 0 && amount > uint32(item_proto->MaxCount))) + { + luaL_error(L, "Item entry %d has invalid amount %d", entry, amount); + continue; + } + if (Item* item = Item::CreateItem(entry, amount)) + { + item->SaveToDB(); + draft.AddItem(item); + Eluna::Push(L, item->GetGUIDLow()); + ++addedItems; + } + } + + Player* receiverPlayer = eObjectAccessor()FindPlayer(MAKE_NEW_GUID(receiverGUIDLow, 0, HIGHGUID_PLAYER)); + draft.SendMailTo(MailReceiver(receiverPlayer, MAKE_NEW_GUID(receiverGUIDLow, 0, HIGHGUID_PLAYER)), sender); + return addedItems; + } + + /** + * Performs a bitwise AND (a & b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_and(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a & b); + return 1; + } + + /** + * Performs a bitwise OR (a | b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_or(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a | b); + return 1; + } + + /** + * Performs a bitwise left-shift (a << b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_lshift(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a << b); + return 1; + } + + /** + * Performs a bitwise right-shift (a >> b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_rshift(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a >> b); + return 1; + } + + /** + * Performs a bitwise XOR (a ^ b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_xor(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a ^ b); + return 1; + } + + /** + * Performs a bitwise NOT (~a). + * + * @param uint32 a + * @return uint32 result + */ + int bit_not(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, ~a); + return 1; + } + + /** + * Adds a taxi path to a specified map, returns the used pathId. + * + * Note that the first taxi point needs to be near the player when he starts the taxi path. + * The function should also be used only **once** per path added so use it on server startup for example. + * + * Related function: [Player:StartTaxi] + * + * -- Execute on startup + * local pathTable = {{mapid, x, y, z}, {mapid, x, y, z}} + * local path = AddTaxiPath(pathTable, 28135, 28135) + * + * -- Execute when the player should fly + * player:StartTaxi(path) + * + * @param table waypoints : table containing waypoints: {map, x, y, z[, actionFlag, delay]} + * @param uint32 mountA : alliance [Creature] entry + * @param uint32 mountH : horde [Creature] entry + * @param uint32 price = 0 : price of the taxi path + * @param uint32 pathId = 0 : path Id of the taxi path + * @return uint32 actualPathId + */ + int AddTaxiPath(lua_State* L) + { + luaL_checktype(L, 1, LUA_TTABLE); + uint32 mountA = Eluna::CHECKVAL(L, 2); + uint32 mountH = Eluna::CHECKVAL(L, 3); + uint32 price = Eluna::CHECKVAL(L, 4, 0); + uint32 pathId = Eluna::CHECKVAL(L, 5, 0); + lua_pushvalue(L, 1); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes} + + std::list nodes; + + int start = lua_gettop(L); + int end = start; + + Eluna::Push(L); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, nil + while (lua_next(L, -2) != 0) + { + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key, value + luaL_checktype(L, -1, LUA_TTABLE); + Eluna::Push(L); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key, value, nil + while (lua_next(L, -2) != 0) + { + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key, value, key2, value2 + lua_insert(L, end++); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, value2, key, value, key2 + } + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, value2, key, value + if (start == end) + continue; + if (end - start < 4) // no mandatory args, dont add + return luaL_argerror(L, 1, "all waypoints do not have mandatory arguments"); + + while (end - start < 8) // fill optional args with 0 + { + Eluna::Push(L, 0); + lua_insert(L, end++); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, node, key, value + } + TaxiPathNodeEntry entry; + // mandatory + entry.mapid = Eluna::CHECKVAL(L, start); + entry.x = Eluna::CHECKVAL(L, start + 1); + entry.y = Eluna::CHECKVAL(L, start + 2); + entry.z = Eluna::CHECKVAL(L, start + 3); + // optional + entry.actionFlag = Eluna::CHECKVAL(L, start + 4, 0); + entry.delay = Eluna::CHECKVAL(L, start + 5, 0); + + nodes.push_back(entry); + + while (end != start) // remove args + if (!lua_isnone(L, --end)) + lua_remove(L, end); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key, value + + lua_pop(L, 1); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key + } + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes} + lua_pop(L, 1); + // Stack: {nodes}, mountA, mountH, price, pathid + + if (nodes.size() < 2) + return 1; + if (!pathId) + pathId = sTaxiPathNodesByPath.size(); + if (sTaxiPathNodesByPath.size() <= pathId) + sTaxiPathNodesByPath.resize(pathId + 1); + sTaxiPathNodesByPath[pathId].clear(); + sTaxiPathNodesByPath[pathId].resize(nodes.size()); + static uint32 nodeId = 500; + uint32 startNode = nodeId; + uint32 index = 0; + for (std::list::iterator it = nodes.begin(); it != nodes.end(); ++it) + { + TaxiPathNodeEntry& entry = *it; + TaxiNodesEntry* nodeEntry = new TaxiNodesEntry(); + entry.path = pathId; + entry.index = nodeId; + nodeEntry->ID = index; + nodeEntry->map_id = entry.mapid; + nodeEntry->x = entry.x; + nodeEntry->y = entry.y; + nodeEntry->z = entry.z; + nodeEntry->MountCreatureID[0] = mountH; + nodeEntry->MountCreatureID[1] = mountA; + + sTaxiNodesStore.InsertEntry(nodeEntry, nodeId++); + +#ifdef CATA + sTaxiPathNodesByPath[pathId][index++] = new TaxiPathNodeEntry(entry); +#else + sTaxiPathNodesByPath[pathId].set(index++, new TaxiPathNodeEntry(entry)); +#endif + } + if (startNode >= nodeId) + return 1; + sTaxiPathSetBySource[startNode][nodeId - 1] = TaxiPathBySourceAndDestination(pathId, price); + TaxiPathEntry* pathEntry = new TaxiPathEntry(); + pathEntry->from = startNode; + pathEntry->to = nodeId - 1; + pathEntry->price = price; + pathEntry->ID = pathId; + sTaxiPathStore.InsertEntry(pathEntry, pathId); + Eluna::Push(L, pathId); + return 1; + } + + /** + * Returns `true` if the bag and slot is a valid inventory position, otherwise `false`. + * + * Some commonly used combinations: + * + * *Bag 255 (common character inventory)* + * + * - Slots 0-18: equipment + * - Slots 19-22: bag slots + * - Slots 23-38: backpack + * - Slots 39-66: bank main slots + * - Slots 67-74: bank bag slots + * - Slots 86-117: keyring + * + * *Bags 19-22 (equipped bags)* + * + * - Slots 0-35 + * + * *Bags 67-74 (bank bags)* + * + * - Slots 0-35 + * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return bool isInventoryPos + */ + int IsInventoryPos(lua_State* L) + { + uint8 bag = Eluna::CHECKVAL(L, 1); + uint8 slot = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, Player::IsInventoryPos(bag, slot)); + return 1; + } + + /** + * Returns `true` if the bag and slot is a valid equipment position, otherwise `false`. + * + * See [Global:IsInventoryPos] for bag/slot combination examples. + * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return bool isEquipmentPosition + */ + int IsEquipmentPos(lua_State* L) + { + uint8 bag = Eluna::CHECKVAL(L, 1); + uint8 slot = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, Player::IsEquipmentPos(bag, slot)); + return 1; + } + + /** + * Returns `true` if the bag and slot is a valid bank position, otherwise `false`. + * + * See [Global:IsInventoryPos] for bag/slot combination examples. + * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return bool isBankPosition + */ + int IsBankPos(lua_State* L) + { + uint8 bag = Eluna::CHECKVAL(L, 1); + uint8 slot = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, Player::IsBankPos(bag, slot)); + return 1; + } + + /** + * Returns `true` if the bag and slot is a valid bag position, otherwise `false`. + * + * See [Global:IsInventoryPos] for bag/slot combination examples. + * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return bool isBagPosition + */ + int IsBagPos(lua_State* L) + { + uint8 bag = Eluna::CHECKVAL(L, 1); + uint8 slot = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, Player::IsBagPos((bag << 8) + slot)); + return 1; + } + + /** + * Returns `true` if the event is currently active, otherwise `false`. + * + * @param uint16 eventId : the event id to check. + * @return bool isActive + */ + int IsGameEventActive(lua_State* L) + { + uint16 eventId = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, eGameEventMgr->IsActiveEvent(eventId)); + return 1; + } + + /** + * Returns the server's current time. + * + * @return uint32 currTime : the current time, in milliseconds + */ + int GetCurrTime(lua_State* L) + { + Eluna::Push(L, ElunaUtil::GetCurrTime()); + return 1; + } + + /** + * Returns the difference between an old timestamp and the current time. + * + * @param uint32 oldTime : an old timestamp, in milliseconds + * @return uint32 timeDiff : the difference, in milliseconds + */ + int GetTimeDiff(lua_State* L) + { + uint32 oldtimems = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, ElunaUtil::GetTimeDiff(oldtimems)); + return 1; + } + + static std::string GetStackAsString(lua_State* L) + { + std::ostringstream oss; + int top = lua_gettop(L); + for (int i = 1; i <= top; ++i) + { + oss << luaL_tolstring(L, i, NULL); + lua_pop(L, 1); + } + return oss.str(); + } + + /** + * Prints given parameters to the info log. + * + * @param ... + */ + int PrintInfo(lua_State* L) + { + ELUNA_LOG_INFO("%s", GetStackAsString(L).c_str()); + return 0; + } + + /** + * Prints given parameters to the error log. + * + * @param ... + */ + int PrintError(lua_State* L) + { + ELUNA_LOG_ERROR("%s", GetStackAsString(L).c_str()); + return 0; + } + + /** + * Prints given parameters to the debug log. + * + * @param ... + */ + int PrintDebug(lua_State* L) + { + ELUNA_LOG_DEBUG("%s", GetStackAsString(L).c_str()); + return 0; + } + + /** + * Starts the event by eventId, if force is set, the event will force start regardless of previous event state. + * + * @param uint16 eventId : the event id to start. + * @param bool force = false : set `true` to force start the event. + */ + int StartGameEvent(lua_State* L) + { + uint16 eventId = Eluna::CHECKVAL(L, 1); + bool force = Eluna::CHECKVAL(L, 2, false); + + eGameEventMgr->StartEvent(eventId, force); + return 0; + } + + /** + * Stops the event by eventId, if force is set, the event will force stop regardless of previous event state. + * + * @param uint16 eventId : the event id to stop. + * @param bool force = false : set `true` to force stop the event. + */ + int StopGameEvent(lua_State* L) + { + uint16 eventId = Eluna::CHECKVAL(L, 1); + bool force = Eluna::CHECKVAL(L, 2, false); + + eGameEventMgr->StopEvent(eventId, force); + return 0; + } + + /** + * Returns an object representing a `long long` (64-bit) value. + * + * The value by default is 0, but can be initialized to a value by passing a number or long long as a string. + * + * @proto value = () + * @proto value = (n) + * @proto value = (n_ll) + * @proto value = (n_str) + * @param int32 n + * @param int64 n_ll + * @param string n_str + * @return int64 value + */ + int CreateLongLong(lua_State* L) + { + long long init = 0; + if (lua_isstring(L, 1)) + { + std::string str = Eluna::CHECKVAL(L, 1); + std::istringstream iss(str); + iss >> init; + if (iss.bad()) + return luaL_argerror(L, 1, "long long (as string) could not be converted"); + } + else if (!lua_isnoneornil(L, 1)) + init = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, init); + return 1; + } + + /** + * Returns an object representing an `unsigned long long` (64-bit) value. + * + * The value by default is 0, but can be initialized to a value by passing a number or unsigned long long as a string. + * + * @proto value = () + * @proto value = (n) + * @proto value = (n_ull) + * @proto value = (n_str) + * @param uint32 n + * @param uint64 n_ull + * @param string n_str + * @return uint64 value + */ + int CreateULongLong(lua_State* L) + { + unsigned long long init = 0; + if (lua_isstring(L, 1)) + { + std::string str = Eluna::CHECKVAL(L, 1); + std::istringstream iss(str); + iss >> init; + if (iss.bad()) + return luaL_argerror(L, 1, "unsigned long long (as string) could not be converted"); + } + else if (!lua_isnoneornil(L, 1)) + init = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, init); + return 1; + } + + /** + * Unbinds event handlers for either all [BattleGround] events, or one type of event. + * + * If `event_type` is `nil`, all [BattleGround] event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterBGEvent] + */ + int ClearBattleGroundEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->BGEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->BGEventBindings->Clear(Key((Hooks::BGEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [Creature]'s events, or one type of event. + * + * If `event_type` is `nil`, all the [Creature]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [Creature], not just one. + * To bind and unbind events to a single [Creature], see [Global:RegisterUniqueCreatureEvent] and [Global:ClearUniqueCreatureEvents]. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of one or more [Creature]s whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterCreatureEvent] + */ + int ClearCreatureEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::CREATURE_EVENT_COUNT; ++i) + E->CreatureEventBindings->Clear(Key((Hooks::CreatureEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->CreatureEventBindings->Clear(Key((Hooks::CreatureEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [Creature]'s events, or one type of event. + * + * If `event_type` is `nil`, all the [Creature]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect only a single [Creature]. + * To bind and unbind events to all instances of a [Creature], see [Global:RegisterCreatureEvent] and [Global:ClearCreatureEvent]. + * + * @proto (entry) + * @proto (entry, event_type) + * @param ObjectGuid guid : the GUID of a single [Creature] whose handlers will be cleared + * @param uint32 instance_id : the instance ID of a single [Creature] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterCreatureEvent] + */ + int ClearUniqueCreatureEvents(lua_State* L) + { + typedef UniqueObjectKey Key; + + if (lua_isnoneornil(L, 3)) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + uint32 instanceId = Eluna::CHECKVAL(L, 2); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::CREATURE_EVENT_COUNT; ++i) + E->CreatureUniqueBindings->Clear(Key((Hooks::CreatureEvents)i, guid, instanceId)); + } + else + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + uint32 instanceId = Eluna::CHECKVAL(L, 2); + uint32 event_type = Eluna::CHECKVAL(L, 3); + Eluna::GetEluna(L)->CreatureUniqueBindings->Clear(Key((Hooks::CreatureEvents)event_type, guid, instanceId)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [Creature]'s gossip events, or one type of event. + * + * If `event_type` is `nil`, all the [Creature]'s gossip event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [Creature], not just one. + * To bind and unbind gossip events to a single [Creature], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of a [Creature] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterCreatureGossipEvent] + */ + int ClearCreatureGossipEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i) + E->CreatureGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->CreatureGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [GameObject]'s events, or one type of event. + * + * If `event_type` is `nil`, all the [GameObject]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [GameObject], not just one. + * To bind and unbind events to a single [GameObject], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of a [GameObject] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGameObjectEvent] + */ + int ClearGameObjectEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GAMEOBJECT_EVENT_COUNT; ++i) + E->GameObjectEventBindings->Clear(Key((Hooks::GameObjectEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->GameObjectEventBindings->Clear(Key((Hooks::GameObjectEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [GameObject]'s gossip events, or one type of event. + * + * If `event_type` is `nil`, all the [GameObject]'s gossip event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [GameObject], not just one. + * To bind and unbind gossip events to a single [GameObject], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of a [GameObject] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGameObjectGossipEvent] + */ + int ClearGameObjectGossipEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i) + E->GameObjectGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->GameObjectGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all [Group] events, or one type of [Group] event. + * + * If `event_type` is `nil`, all [Group] event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGroupEvent] + */ + int ClearGroupEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->GroupEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->GroupEventBindings->Clear(Key((Hooks::GroupEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all [Guild] events, or one type of [Guild] event. + * + * If `event_type` is `nil`, all [Guild] event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGuildEvent] + */ + int ClearGuildEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->GuildEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->GuildEventBindings->Clear(Key((Hooks::GuildEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of an [Item]'s events, or one type of event. + * + * If `event_type` is `nil`, all the [Item]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [Item], not just one. + * To bind and unbind events to a single [Item], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of an [Item] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterItemEvent] + */ + int ClearItemEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::ITEM_EVENT_COUNT; ++i) + E->ItemEventBindings->Clear(Key((Hooks::ItemEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->ItemEventBindings->Clear(Key((Hooks::ItemEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of an [Item]'s gossip events, or one type of event. + * + * If `event_type` is `nil`, all the [Item]'s gossip event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [Item], not just one. + * To bind and unbind gossip events to a single [Item], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of an [Item] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterItemGossipEvent] + */ + int ClearItemGossipEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i) + E->ItemGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->ItemGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [WorldPacket] opcode's events, or one type of event. + * + * If `event_type` is `nil`, all the [WorldPacket] opcode's event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto (opcode) + * @proto (opcode, event_type) + * @param uint32 opcode : the type of [WorldPacket] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPacketEvent] + */ + int ClearPacketEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::PACKET_EVENT_COUNT; ++i) + E->PacketEventBindings->Clear(Key((Hooks::PacketEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->PacketEventBindings->Clear(Key((Hooks::PacketEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all [Player] events, or one type of [Player] event. + * + * If `event_type` is `nil`, all [Player] event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPlayerEvent] + */ + int ClearPlayerEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->PlayerEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->PlayerEventBindings->Clear(Key((Hooks::PlayerEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [Player]'s gossip events, or one type of event. + * + * If `event_type` is `nil`, all the [Player]'s gossip event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the low GUID of a [Player] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPlayerGossipEvent] + */ + int ClearPlayerGossipEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i) + E->PlayerGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->PlayerGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all server events, or one type of event. + * + * If `event_type` is `nil`, all server event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterServerEvent] + */ + int ClearServerEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->ServerEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->ServerEventBindings->Clear(Key((Hooks::ServerEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a non-instanced [Map]'s events, or one type of event. + * + * If `event_type` is `nil`, all the non-instanced [Map]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto (map_id) + * @proto (map_id, event_type) + * @param uint32 map_id : the ID of a [Map] + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPlayerGossipEvent] + */ + int ClearMapEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::INSTANCE_EVENT_COUNT; ++i) + E->MapEventBindings->Clear(Key((Hooks::InstanceEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->MapEventBindings->Clear(Key((Hooks::InstanceEvents)event_type, entry)); + } + + return 0; + } + + /** + * Unbinds event handlers for either all of an instanced [Map]'s events, or one type of event. + * + * If `event_type` is `nil`, all the instanced [Map]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto (instance_id) + * @proto (instance_id, event_type) + * @param uint32 entry : the ID of an instance of a [Map] + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterInstanceEvent] + */ + int ClearInstanceEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::INSTANCE_EVENT_COUNT; ++i) + E->InstanceEventBindings->Clear(Key((Hooks::InstanceEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->InstanceEventBindings->Clear(Key((Hooks::InstanceEvents)event_type, entry)); + } + + return 0; + } + + luaL_Reg GlobalMethods[] = + { + // Hooks + { "RegisterPacketEvent", &LuaGlobalFunctions::RegisterPacketEvent }, + { "RegisterServerEvent", &LuaGlobalFunctions::RegisterServerEvent }, + { "RegisterPlayerEvent", &LuaGlobalFunctions::RegisterPlayerEvent }, + { "RegisterGuildEvent", &LuaGlobalFunctions::RegisterGuildEvent }, + { "RegisterGroupEvent", &LuaGlobalFunctions::RegisterGroupEvent }, + { "RegisterCreatureEvent", &LuaGlobalFunctions::RegisterCreatureEvent }, + { "RegisterUniqueCreatureEvent", &LuaGlobalFunctions::RegisterUniqueCreatureEvent }, + { "RegisterCreatureGossipEvent", &LuaGlobalFunctions::RegisterCreatureGossipEvent }, + { "RegisterGameObjectEvent", &LuaGlobalFunctions::RegisterGameObjectEvent }, + { "RegisterGameObjectGossipEvent", &LuaGlobalFunctions::RegisterGameObjectGossipEvent }, + { "RegisterItemEvent", &LuaGlobalFunctions::RegisterItemEvent }, + { "RegisterItemGossipEvent", &LuaGlobalFunctions::RegisterItemGossipEvent }, + { "RegisterPlayerGossipEvent", &LuaGlobalFunctions::RegisterPlayerGossipEvent }, + { "RegisterBGEvent", &LuaGlobalFunctions::RegisterBGEvent }, + { "RegisterMapEvent", &LuaGlobalFunctions::RegisterMapEvent }, + { "RegisterInstanceEvent", &LuaGlobalFunctions::RegisterInstanceEvent }, + + { "ClearBattleGroundEvents", &LuaGlobalFunctions::ClearBattleGroundEvents }, + { "ClearCreatureEvents", &LuaGlobalFunctions::ClearCreatureEvents }, + { "ClearUniqueCreatureEvents", &LuaGlobalFunctions::ClearUniqueCreatureEvents }, + { "ClearCreatureGossipEvents", &LuaGlobalFunctions::ClearCreatureGossipEvents }, + { "ClearGameObjectEvents", &LuaGlobalFunctions::ClearGameObjectEvents }, + { "ClearGameObjectGossipEvents", &LuaGlobalFunctions::ClearGameObjectGossipEvents }, + { "ClearGroupEvents", &LuaGlobalFunctions::ClearGroupEvents }, + { "ClearGuildEvents", &LuaGlobalFunctions::ClearGuildEvents }, + { "ClearItemEvents", &LuaGlobalFunctions::ClearItemEvents }, + { "ClearItemGossipEvents", &LuaGlobalFunctions::ClearItemGossipEvents }, + { "ClearPacketEvents", &LuaGlobalFunctions::ClearPacketEvents }, + { "ClearPlayerEvents", &LuaGlobalFunctions::ClearPlayerEvents }, + { "ClearPlayerGossipEvents", &LuaGlobalFunctions::ClearPlayerGossipEvents }, + { "ClearServerEvents", &LuaGlobalFunctions::ClearServerEvents }, + { "ClearMapEvents", &LuaGlobalFunctions::ClearMapEvents }, + { "ClearInstanceEvents", &LuaGlobalFunctions::ClearInstanceEvents }, + + // Getters + { "GetLuaEngine", &LuaGlobalFunctions::GetLuaEngine }, + { "GetCoreName", &LuaGlobalFunctions::GetCoreName }, + { "GetRealmID", &LuaGlobalFunctions::GetRealmID }, + { "GetCoreVersion", &LuaGlobalFunctions::GetCoreVersion }, + { "GetCoreExpansion", &LuaGlobalFunctions::GetCoreExpansion }, + { "GetQuest", &LuaGlobalFunctions::GetQuest }, + { "GetPlayerByGUID", &LuaGlobalFunctions::GetPlayerByGUID }, + { "GetPlayerByName", &LuaGlobalFunctions::GetPlayerByName }, + { "GetGameTime", &LuaGlobalFunctions::GetGameTime }, + { "GetPlayersInWorld", &LuaGlobalFunctions::GetPlayersInWorld }, + { "GetGuildByName", &LuaGlobalFunctions::GetGuildByName }, + { "GetGuildByLeaderGUID", &LuaGlobalFunctions::GetGuildByLeaderGUID }, + { "GetPlayerCount", &LuaGlobalFunctions::GetPlayerCount }, + { "GetPlayerGUID", &LuaGlobalFunctions::GetPlayerGUID }, + { "GetItemGUID", &LuaGlobalFunctions::GetItemGUID }, + { "GetObjectGUID", &LuaGlobalFunctions::GetObjectGUID }, + { "GetUnitGUID", &LuaGlobalFunctions::GetUnitGUID }, + { "GetGUIDLow", &LuaGlobalFunctions::GetGUIDLow }, + { "GetGUIDType", &LuaGlobalFunctions::GetGUIDType }, + { "GetGUIDEntry", &LuaGlobalFunctions::GetGUIDEntry }, + { "GetAreaName", &LuaGlobalFunctions::GetAreaName }, + { "bit_not", &LuaGlobalFunctions::bit_not }, + { "bit_xor", &LuaGlobalFunctions::bit_xor }, + { "bit_rshift", &LuaGlobalFunctions::bit_rshift }, + { "bit_lshift", &LuaGlobalFunctions::bit_lshift }, + { "bit_or", &LuaGlobalFunctions::bit_or }, + { "bit_and", &LuaGlobalFunctions::bit_and }, + { "GetItemLink", &LuaGlobalFunctions::GetItemLink }, + { "GetMapById", &LuaGlobalFunctions::GetMapById }, + { "GetCurrTime", &LuaGlobalFunctions::GetCurrTime }, + { "GetTimeDiff", &LuaGlobalFunctions::GetTimeDiff }, + { "PrintInfo", &LuaGlobalFunctions::PrintInfo }, + { "PrintError", &LuaGlobalFunctions::PrintError }, + { "PrintDebug", &LuaGlobalFunctions::PrintDebug }, + { "GetActiveGameEvents", &LuaGlobalFunctions::GetActiveGameEvents }, + + // Boolean + { "IsInventoryPos", &LuaGlobalFunctions::IsInventoryPos }, + { "IsEquipmentPos", &LuaGlobalFunctions::IsEquipmentPos }, + { "IsBankPos", &LuaGlobalFunctions::IsBankPos }, + { "IsBagPos", &LuaGlobalFunctions::IsBagPos }, + { "IsGameEventActive", &LuaGlobalFunctions::IsGameEventActive }, + + // Other + { "ReloadEluna", &LuaGlobalFunctions::ReloadEluna }, + { "RunCommand", &LuaGlobalFunctions::RunCommand }, + { "SendWorldMessage", &LuaGlobalFunctions::SendWorldMessage }, + { "WorldDBQuery", &LuaGlobalFunctions::WorldDBQuery }, + { "WorldDBExecute", &LuaGlobalFunctions::WorldDBExecute }, + { "CharDBQuery", &LuaGlobalFunctions::CharDBQuery }, + { "CharDBExecute", &LuaGlobalFunctions::CharDBExecute }, + { "AuthDBQuery", &LuaGlobalFunctions::AuthDBQuery }, + { "AuthDBExecute", &LuaGlobalFunctions::AuthDBExecute }, + { "CreateLuaEvent", &LuaGlobalFunctions::CreateLuaEvent }, + { "RemoveEventById", &LuaGlobalFunctions::RemoveEventById }, + { "RemoveEvents", &LuaGlobalFunctions::RemoveEvents }, + { "PerformIngameSpawn", &LuaGlobalFunctions::PerformIngameSpawn }, + { "CreatePacket", &LuaGlobalFunctions::CreatePacket }, + { "AddVendorItem", &LuaGlobalFunctions::AddVendorItem }, + { "VendorRemoveItem", &LuaGlobalFunctions::VendorRemoveItem }, + { "VendorRemoveAllItems", &LuaGlobalFunctions::VendorRemoveAllItems }, + { "Kick", &LuaGlobalFunctions::Kick }, + { "Ban", &LuaGlobalFunctions::Ban }, + { "SaveAllPlayers", &LuaGlobalFunctions::SaveAllPlayers }, + { "SendMail", &LuaGlobalFunctions::SendMail }, + { "AddTaxiPath", &LuaGlobalFunctions::AddTaxiPath }, + { "CreateInt64", &LuaGlobalFunctions::CreateLongLong }, + { "CreateUint64", &LuaGlobalFunctions::CreateULongLong }, + { "StartGameEvent", &LuaGlobalFunctions::StartGameEvent }, + { "StopGameEvent", &LuaGlobalFunctions::StopGameEvent }, + + { NULL, NULL } + }; +} +#endif diff --git a/src/modules/Eluna/CMangos/GroupMethods.h b/src/modules/Eluna/CMangos/GroupMethods.h new file mode 100644 index 0000000000..8d6db23660 --- /dev/null +++ b/src/modules/Eluna/CMangos/GroupMethods.h @@ -0,0 +1,423 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef GROUPMETHODS_H +#define GROUPMETHODS_H + +/*** + * Inherits all methods from: none + */ +namespace LuaGroup +{ + /** + * Returns 'true' if the [Player] is the [Group] leader + * + * @param ObjectGuid guid : guid of a possible leader + * @return bool isLeader + */ + int IsLeader(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->IsLeader(guid)); + return 1; + } + + /** + * Returns 'true' if the [Group] is full + * + * @return bool isFull + */ + int IsFull(lua_State* L, Group* group) + { + Eluna::Push(L, group->IsFull()); + return 1; + } + +#if !(defined(CLASSIC) || defined(TBC)) + /** + * Returns 'true' if the [Group] is a LFG group + * + * @return bool isLFGGroup + */ + int IsLFGGroup(lua_State* L, Group* group) + { + Eluna::Push(L, group->IsLFGGroup()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Group] is a raid [Group] + * + * @return bool isRaid + */ + int IsRaidGroup(lua_State* L, Group* group) + { + Eluna::Push(L, group->IsRaidGroup()); + return 1; + } + + /** + * Returns 'true' if the [Group] is a battleground [Group] + * + * @return bool isBG + */ + int IsBGGroup(lua_State* L, Group* group) + { + Eluna::Push(L, group->IsBattleGroup()); + return 1; + } + + /** + * Returns 'true' if the [Player] is a member of this [Group] + * + * @param ObjectGuid guid : guid of a player + * @return bool isMember + */ + int IsMember(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->IsMember(guid)); + return 1; + } + + /** + * Returns 'true' if the [Player] is an assistant of this [Group] + * + * @param ObjectGuid guid : guid of a player + * @return bool isAssistant + */ + int IsAssistant(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->IsAssistant(guid)); + return 1; + } + + /** + * Returns 'true' if the [Player]s are in the same subgroup in this [Group] + * + * @param [Player] player1 : first [Player] to check + * @param [Player] player2 : second [Player] to check + * @return bool sameSubGroup + */ + int SameSubGroup(lua_State* L, Group* group) + { + Player* player1 = Eluna::CHECKOBJ(L, 2); + Player* player2 = Eluna::CHECKOBJ(L, 3); + Eluna::Push(L, group->SameSubGroup(player1, player2)); + return 1; + } + + /** + * Returns 'true' if the subgroup has free slots in this [Group] + * + * @param uint8 subGroup : subGroup ID to check + * @return bool hasFreeSlot + */ + int HasFreeSlotSubGroup(lua_State* L, Group* group) + { + uint8 subGroup = Eluna::CHECKVAL(L, 2); + + if (subGroup >= MAX_RAID_SUBGROUPS) + { + luaL_argerror(L, 2, "valid subGroup ID expected"); + return 0; + } + + Eluna::Push(L, group->HasFreeSlotSubGroup(subGroup)); + return 1; + } + + /** + * Adds a new member to the [Group] + * + * @param [Player] player : [Player] to add to the group + * @return bool added : true if member was added + */ + int AddMember(lua_State* L, Group* group) + { + Player* player = Eluna::CHECKOBJ(L, 2); + + if (player->GetGroup() || !group->IsCreated() || group->IsFull()) + { + Eluna::Push(L, false); + return 1; + } + + if (player->GetGroupInvite()) + player->UninviteFromGroup(); + + bool success = group->AddMember(player->GetObjectGuid(), player->GetName()); + Eluna::Push(L, success); + return 1; + } + + /** + * Returns a table with the [Player]s in this [Group] + * + * @return table groupPlayers : table of [Player]s + */ + int GetMembers(lua_State* L, Group* group) + { + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (GroupReference* itr = group->GetFirstMember(); itr; itr = itr->next()) + { + Player* member = itr->getSource(); + + if (!member || !member->GetSession()) + continue; + + Eluna::Push(L, member); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); // push table to top of stack + return 1; + } + + /** + * Returns [Group] leader GUID + * + * @return ObjectGuid leaderGUID + */ + int GetLeaderGUID(lua_State* L, Group* group) + { + Eluna::Push(L, group->GetLeaderGuid()); + return 1; + } + + /** + * Returns the [Group]'s GUID + * + * @return ObjectGuid groupGUID + */ + int GetGUID(lua_State* L, Group* group) + { +#ifdef CLASSIC + Eluna::Push(L, group->GetId()); +#else + Eluna::Push(L, group->GET_GUID()); +#endif + return 1; + } + + /** + * Returns a [Group] member's GUID by their name + * + * @param string name : the [Player]'s name + * @return ObjectGuid memberGUID + */ + int GetMemberGUID(lua_State* L, Group* group) + { + const char* name = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->GetMemberGuid(name)); + return 1; + } + + /** + * Returns the member count of this [Group] + * + * @return uint32 memberCount + */ + int GetMembersCount(lua_State* L, Group* group) + { + Eluna::Push(L, group->GetMembersCount()); + return 1; + } + + /** + * Returns the [Player]'s subgroup ID of this [Group] + * + * @param ObjectGuid guid : guid of the player + * @return uint8 subGroupID : a valid subgroup ID or MAX_RAID_SUBGROUPS+1 + */ + int GetMemberGroup(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->GetMemberGroup(guid)); + return 1; + } + + /** + * Sets the leader of this [Group] + * + * @param ObjectGuid guid : guid of the new leader + */ + int SetLeader(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + group->ChangeLeader(guid); + group->SendUpdate(); + return 0; + } + + /** + * Sends a specified [WorldPacket] to this [Group] + * + * @param [WorldPacket] packet : the [WorldPacket] to send + * @param bool ignorePlayersInBg : ignores [Player]s in a battleground + * @param ObjectGuid ignore : ignore a [Player] by their GUID + */ + int SendPacket(lua_State* L, Group* group) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + bool ignorePlayersInBg = Eluna::CHECKVAL(L, 3); + ObjectGuid ignore = Eluna::CHECKVAL(L, 4); + + group->BroadcastPacket(*data, ignorePlayersInBg, -1, ignore); + return 0; + } + + /** + * Removes a [Player] from this [Group] and returns 'true' if successful + * + *
+     * enum RemoveMethod
+     * {
+     *     GROUP_REMOVEMETHOD_DEFAULT  = 0,
+     *     GROUP_REMOVEMETHOD_KICK     = 1,
+     *     GROUP_REMOVEMETHOD_LEAVE    = 2,
+     *     GROUP_REMOVEMETHOD_KICK_LFG = 3
+     * };
+     * 
+ * + * @param ObjectGuid guid : guid of the player to remove + * @param [RemoveMethod] method : method used to remove the player + * @return bool removed + */ + int RemoveMember(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + uint32 method = Eluna::CHECKVAL(L, 3, 0); + + Eluna::Push(L, group->RemoveMember(guid, method)); + return 1; + } + + /** + * Disbands this [Group] + * + */ + int Disband(lua_State* /*L*/, Group* group) + { + group->Disband(); + return 0; + } + + /** + * Converts this [Group] to a raid [Group] + * + */ + int ConvertToRaid(lua_State* /*L*/, Group* group) + { + group->ConvertToRaid(); + return 0; + } + + /** + * Sets the member's subGroup + * + * @param ObjectGuid guid : guid of the player to move + * @param uint8 groupID : the subGroup's ID + */ + int SetMembersGroup(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + uint8 subGroup = Eluna::CHECKVAL(L, 3); + + if (subGroup >= MAX_RAID_SUBGROUPS) + { + luaL_argerror(L, 3, "valid subGroup ID expected"); + return 0; + } + + if (!group->HasFreeSlotSubGroup(subGroup)) + return 0; + + group->ChangeMembersGroup(guid, subGroup); + return 0; + } + + /** + * Sets the target icon of an object for the [Group] + * + * @param uint8 icon : the icon (Skull, Square, etc) + * @param ObjectGuid target : GUID of the icon target, 0 is to clear the icon + * @param ObjectGuid setter : GUID of the icon setter + */ + int SetTargetIcon(lua_State* L, Group* group) + { + uint8 icon = Eluna::CHECKVAL(L, 2); + ObjectGuid target = Eluna::CHECKVAL(L, 3); + ObjectGuid setter = Eluna::CHECKVAL(L, 4, ObjectGuid()); + + if (icon >= TARGETICONCOUNT) + return luaL_argerror(L, 2, "valid target icon expected"); + +#if (defined(CLASSIC) || defined(TBC)) + group->SetTargetIcon(icon, target); +#else + group->SetTargetIcon(icon, setter, target); +#endif + return 0; + } + + /*int ConvertToLFG(lua_State* L, Group* group) // TODO: Implementation + { + group->ConvertToLFG(); + return 0; + }*/ + + ElunaRegister GroupMethods[] = + { + // Getters + { "GetMembers", &LuaGroup::GetMembers }, + { "GetLeaderGUID", &LuaGroup::GetLeaderGUID }, + { "GetGUID", &LuaGroup::GetGUID }, + { "GetMemberGroup", &LuaGroup::GetMemberGroup }, + { "GetMemberGUID", &LuaGroup::GetMemberGUID }, + { "GetMembersCount", &LuaGroup::GetMembersCount }, + + // Setters + { "SetLeader", &LuaGroup::SetLeader }, + { "SetMembersGroup", &LuaGroup::SetMembersGroup }, + { "SetTargetIcon", &LuaGroup::SetTargetIcon }, + + // Boolean + { "IsLeader", &LuaGroup::IsLeader }, + { "AddMember", &LuaGroup::AddMember }, + { "RemoveMember", &LuaGroup::RemoveMember }, + { "Disband", &LuaGroup::Disband }, + { "IsFull", &LuaGroup::IsFull }, + { "IsRaidGroup", &LuaGroup::IsRaidGroup }, + { "IsBGGroup", &LuaGroup::IsBGGroup }, + { "IsMember", &LuaGroup::IsMember }, + { "IsAssistant", &LuaGroup::IsAssistant }, + { "SameSubGroup", &LuaGroup::SameSubGroup }, + { "HasFreeSlotSubGroup", &LuaGroup::HasFreeSlotSubGroup }, +#if defined WOTLK + { "IsLFGGroup", &LuaGroup::IsLFGGroup }, +#endif + + // Other + { "SendPacket", &LuaGroup::SendPacket }, + { "ConvertToRaid", &LuaGroup::ConvertToRaid }, + + // Not implemented methods + { "IsBFGroup", nullptr }, // not implemented + { "ConvertToLFG", nullptr }, // not implemented + { "GetMemberFlags", nullptr }, // not implemented + { "SetMemberFlag", nullptr }, // not implemented + + { NULL, NULL } + }; +}; + +#endif diff --git a/src/modules/Eluna/CMangos/GuildMethods.h b/src/modules/Eluna/CMangos/GuildMethods.h new file mode 100644 index 0000000000..6fda4857fa --- /dev/null +++ b/src/modules/Eluna/CMangos/GuildMethods.h @@ -0,0 +1,273 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef GUILDMETHODS_H +#define GUILDMETHODS_H + +/*** + * Inherits all methods from: none + */ +namespace LuaGuild +{ + /** + * Returns a table with the [Player]s in this [Guild] + * + * Only the players that are online and on some map. + * + * @return table guildPlayers : table of [Player]s + */ + int GetMembers(lua_State* L, Guild* guild) + { + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 i = 0; + + { + HashMapHolder::ReadGuard g(HashMapHolder::GetLock()); + const HashMapHolder::MapType& m = eObjectAccessor()GetPlayers(); + for (HashMapHolder::MapType::const_iterator it = m.begin(); it != m.end(); ++it) + { + if (Player* player = it->second) + { + if (player->IsInWorld() && player->GetGuildId() == guild->GetId()) + { + Eluna::Push(L, player); + lua_rawseti(L, tbl, ++i); + } + } + } + } + lua_settop(L, tbl); // push table to top of stack + return 1; + } + + /** + * Returns the member count of this [Guild] + * + * @return uint32 memberCount + */ + int GetMemberCount(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetMemberSize()); + return 1; + } + + /** + * Finds and returns the [Guild] leader by their GUID if logged in + * + * @return [Player] leader + */ + int GetLeader(lua_State* L, Guild* guild) + { + Eluna::Push(L, eObjectAccessor()FindPlayer(guild->GetLeaderGuid())); + return 1; + } + + /** + * Returns [Guild] leader GUID + * + * @return ObjectGuid leaderGUID + */ + int GetLeaderGUID(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetLeaderGuid()); + return 1; + } + + /** + * Returns the [Guild]s entry ID + * + * @return uint32 entryId + */ + int GetId(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetId()); + return 1; + } + + /** + * Returns the [Guild]s name + * + * @return string guildName + */ + int GetName(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetName()); + return 1; + } + + /** + * Returns the [Guild]s current Message Of The Day + * + * @return string guildMOTD + */ + int GetMOTD(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetMOTD()); + return 1; + } + + /** + * Returns the [Guild]s current info + * + * @return string guildInfo + */ + int GetInfo(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetGINFO()); + return 1; + } + +#if defined(CLASSIC) || defined(TBC) || defined(WOTLK) + /** + * Sets the leader of this [Guild] + * + * @param [Player] leader : the [Player] leader to change + */ + int SetLeader(lua_State* L, Guild* guild) + { + Player* player = Eluna::CHECKOBJ(L, 2); + + guild->SetLeader(player->GET_GUID()); + return 0; + } +#endif + +#ifndef CLASSIC + /** + * Sets the information of the bank tab specified + * + * @param uint8 tabId : the ID of the tab specified + * @param string info : the information to be set to the bank tab + */ + int SetBankTabText(lua_State* L, Guild* guild) + { + uint8 tabId = Eluna::CHECKVAL(L, 2); + const char* text = Eluna::CHECKVAL(L, 3); + + guild->SetGuildBankTabText(tabId, text); + return 0; + } +#endif + + // SendPacketToGuild(packet) + /** + * Sends a [WorldPacket] to all the [Player]s in the [Guild] + * + * @param [WorldPacket] packet : the [WorldPacket] to be sent to the [Player]s + */ + int SendPacket(lua_State* L, Guild* guild) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + + guild->BroadcastPacket(*data); + return 0; + } + + // SendPacketToRankedInGuild(packet, rankId) + /** + * Sends a [WorldPacket] to all the [Player]s at the specified rank in the [Guild] + * + * @param [WorldPacket] packet : the [WorldPacket] to be sent to the [Player]s + * @param uint8 rankId : the rank ID + */ + int SendPacketToRanked(lua_State* L, Guild* guild) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + uint8 ranked = Eluna::CHECKVAL(L, 3); + + guild->BroadcastPacketToRank(*data, ranked); + return 0; + } + + /** + * Disbands the [Guild] + */ + int Disband(lua_State* /*L*/, Guild* guild) + { + guild->Disband(); + return 0; + } + + /** + * Adds the specified [Player] to the [Guild] at the specified rank. + * + * If no rank is specified, defaults to none. + * + * @param [Player] player : the [Player] to be added to the guild + * @param uint8 rankId : the rank ID + */ + int AddMember(lua_State* L, Guild* guild) + { + Player* player = Eluna::CHECKOBJ(L, 2); + uint8 rankId = Eluna::CHECKVAL(L, 3, GUILD_RANK_NONE); + + guild->AddMember(player->GET_GUID(), rankId); + return 0; + } + + /** + * Removes the specified [Player] from the [Guild]. + * + * @param [Player] player : the [Player] to be removed from the guild + * @param bool isDisbanding : default 'false', should only be set to 'true' if the guild is triggered to disband + */ + int DeleteMember(lua_State* L, Guild* guild) + { + Player* player = Eluna::CHECKOBJ(L, 2); + bool isDisbanding = Eluna::CHECKVAL(L, 3, false); + + guild->DelMember(player->GET_GUID(), isDisbanding); + return 0; + } + + /** + * Promotes/demotes the [Player] to the specified rank. + * + * @param [Player] player : the [Player] to be promoted/demoted + * @param uint8 rankId : the rank ID + */ + int SetMemberRank(lua_State* L, Guild* guild) + { + Player* player = Eluna::CHECKOBJ(L, 2); + uint8 newRank = Eluna::CHECKVAL(L, 3); + + guild->ChangeMemberRank(player->GET_GUID(), newRank); + return 0; + } + + ElunaRegister GuildMethods[] = + { + // Getters + { "GetMembers", &LuaGuild::GetMembers }, + { "GetLeader", &LuaGuild::GetLeader }, + { "GetLeaderGUID", &LuaGuild::GetLeaderGUID }, + { "GetId", &LuaGuild::GetId }, + { "GetName", &LuaGuild::GetName }, + { "GetMOTD", &LuaGuild::GetMOTD }, + { "GetInfo", &LuaGuild::GetInfo }, + { "GetMemberCount", &LuaGuild::GetMemberCount }, + + // Setters +#if defined(TBC) || defined(WOTLK) + { "SetBankTabText", &LuaGuild::SetBankTabText }, +#endif + { "SetMemberRank", &LuaGuild::SetMemberRank }, +#ifndef CATA + { "SetLeader", &LuaGuild::SetLeader }, +#endif + + // Other + { "SendPacket", &LuaGuild::SendPacket }, + { "SendPacketToRanked", &LuaGuild::SendPacketToRanked }, + { "Disband", &LuaGuild::Disband }, + { "AddMember", &LuaGuild::AddMember }, + { "DeleteMember", &LuaGuild::DeleteMember }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/ItemMethods.h b/src/modules/Eluna/CMangos/ItemMethods.h new file mode 100644 index 0000000000..110edb0626 --- /dev/null +++ b/src/modules/Eluna/CMangos/ItemMethods.h @@ -0,0 +1,803 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef ITEMMETHODS_H +#define ITEMMETHODS_H + +/*** + * Inherits all methods from: [Object] + */ +namespace LuaItem +{ + /** + * Returns 'true' if the [Item] is soulbound, 'false' otherwise + * + * @return bool isSoulBound + */ + int IsSoulBound(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsSoulBound()); + return 1; + } + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Returns 'true' if the [Item] is account bound, 'false' otherwise + * + * @return bool isAccountBound + */ + int IsBoundAccountWide(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsBoundAccountWide()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Item] is bound to a [Player] by an enchant, 'false' otehrwise + * + * @return bool isBoundByEnchant + */ + int IsBoundByEnchant(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsBoundByEnchant()); + return 1; + } + + /** + * Returns 'true' if the [Item] is not bound to the [Player] specified, 'false' otherwise + * + * @param [Player] player : the [Player] object to check the item against + * @return bool isNotBound + */ + int IsNotBoundToPlayer(lua_State* L, Item* item) + { + Player* player = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, item->IsBindedNotWith(player)); + return 1; + } + + /** + * Returns 'true' if the [Item] is locked, 'false' otherwise + * + * @return bool isLocked + */ + int IsLocked(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsLocked()); + return 1; + } + + /** + * Returns 'true' if the [Item] is a bag, 'false' otherwise + * + * @return bool isBag + */ + int IsBag(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsBag()); + return 1; + } + +#ifndef CLASSIC + /** + * Returns 'true' if the [Item] is a currency token, 'false' otherwise + * + * @return bool isCurrencyToken + */ + int IsCurrencyToken(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsCurrencyToken()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Item] is a not an empty bag, 'false' otherwise + * + * @return bool isNotEmptyBag + */ + int IsNotEmptyBag(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsNotEmptyBag()); + return 1; + } + + /** + * Returns 'true' if the [Item] is broken, 'false' otherwise + * + * @return bool isBroken + */ + int IsBroken(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsBroken()); + return 1; + } + + /** + * Returns 'true' if the [Item] can be traded, 'false' otherwise + * + * @return bool isTradeable + */ + int CanBeTraded(lua_State* L, Item* item) + { +#if (defined(TBC) || defined(CLASSIC)) + Eluna::Push(L, item->CanBeTraded()); +#else + bool mail = Eluna::CHECKVAL(L, 2, false); + Eluna::Push(L, item->CanBeTraded(mail)); +#endif + return 1; + } + + /** + * Returns 'true' if the [Item] is currently in a trade window, 'false' otherwise + * + * @return bool isInTrade + */ + int IsInTrade(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsInTrade()); + return 1; + } + + /** + * Returns 'true' if the [Item] is currently in a bag, 'false' otherwise + * + * @return bool isInBag + */ + int IsInBag(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsInBag()); + return 1; + } + + /** + * Returns 'true' if the [Item] is currently equipped, 'false' otherwise + * + * @return bool isEquipped + */ + int IsEquipped(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsEquipped()); + return 1; + } + + /** + * Returns 'true' if the [Item] has the [Quest] specified tied to it, 'false' otherwise + * + * @param uint32 questId : the [Quest] id to be checked + * @return bool hasQuest + */ + int HasQuest(lua_State* L, Item* item) + { + uint32 quest = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, item->HasQuest(quest)); + return 1; + } + + /** + * Returns 'true' if the [Item] is a potion, 'false' otherwise + * + * @return bool isPotion + */ + int IsPotion(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsPotion()); + return 1; + } + +#if defined(WOTLK) + /** + * Returns 'true' if the [Item] is a weapon vellum, 'false' otherwise + * + * @return bool isWeaponVellum + */ + int IsWeaponVellum(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsWeaponVellum()); + return 1; + } + + /** + * Returns 'true' if the [Item] is an armor vellum, 'false' otherwise + * + * @return bool isArmorVellum + */ + int IsArmorVellum(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsArmorVellum()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Item] is a conjured consumable, 'false' otherwise + * + * @return bool isConjuredConsumable + */ + int IsConjuredConsumable(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsConjuredConsumable()); + return 1; + } + + /** + * Returns the chat link of the [Item] + * + *
+     * enum LocaleConstant
+     * {
+     *     LOCALE_enUS = 0,
+     *     LOCALE_koKR = 1,
+     *     LOCALE_frFR = 2,
+     *     LOCALE_deDE = 3,
+     *     LOCALE_zhCN = 4,
+     *     LOCALE_zhTW = 5,
+     *     LOCALE_esES = 6,
+     *     LOCALE_esMX = 7,
+     *     LOCALE_ruRU = 8
+     * };
+     * 
+ * + * @param [LocaleConstant] locale = DEFAULT_LOCALE : locale to return the [Item]'s name in + * @return string itemLink + */ + int GetItemLink(lua_State* L, Item* item) + { + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const ItemTemplate* temp = item->GetTemplate(); + std::string name = temp->Name1; + if (ItemLocale const* il = eObjectMgr->GetItemLocale(temp->ItemId)) + ObjectMgr::GetLocaleString(il->Name, static_cast(locale), name); + +#ifndef CLASSIC + if (int32 itemRandPropId = item->GetItemRandomPropertyId()) + { +#if defined(CATA) + char* suffix = NULL; +#else + char* const* suffix = NULL; +#endif + if (itemRandPropId < 0) + { + const ItemRandomSuffixEntry* itemRandEntry = sItemRandomSuffixStore.LookupEntry(-item->GetItemRandomPropertyId()); + if (itemRandEntry) + suffix = itemRandEntry->nameSuffix; + } + else + { + const ItemRandomPropertiesEntry* itemRandEntry = sItemRandomPropertiesStore.LookupEntry(item->GetItemRandomPropertyId()); + if (itemRandEntry) + suffix = itemRandEntry->nameSuffix; + } + if (suffix) + { + name += ' '; + name += suffix[(name != temp->Name1) ? locale : uint8(DEFAULT_LOCALE)]; + } + } +#endif + + std::ostringstream oss; + oss << "|c" << std::hex << ItemQualityColors[temp->Quality] << std::dec << + "|Hitem:" << temp->ItemId << ":" << + item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT) << ":" << +#ifndef CLASSIC + item->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT) << ":" << + item->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_2) << ":" << + item->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_3) << ":" << + item->GetEnchantmentId(BONUS_ENCHANTMENT_SLOT) << ":" << +#endif + item->GetItemRandomPropertyId() << ":" << item->GetItemSuffixFactor() << ":" << + (uint32)item->GetOwner()->GetLevel() << "|h[" << name << "]|h|r"; + + Eluna::Push(L, oss.str()); + return 1; + } + + int GetOwnerGUID(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetOwnerGuid()); + return 1; + } + + /** + * Returns the [Player] who currently owns the [Item] + * + * @return [Player] player : the [Player] who owns the [Item] + */ + int GetOwner(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetOwner()); + return 1; + } + + /** + * Returns the [Item]s stack count + * + * @return uint32 count + */ + int GetCount(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetCount()); + return 1; + } + + /** + * Returns the [Item]s max stack count + * + * @return uint32 maxCount + */ + int GetMaxStackCount(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetMaxStackCount()); + return 1; + } + + /** + * Returns the [Item]s current slot + * + * @return uint8 slot + */ + int GetSlot(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetSlot()); + return 1; + } + + /** + * Returns the [Item]s current bag slot + * + * @return uint8 bagSlot + */ + int GetBagSlot(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetBagSlot()); + return 1; + } + + /** + * Returns the [Item]s enchantment ID by enchant slot specified + * + * @param [EnchantmentSlot] enchantSlot : the enchant slot specified + * @return uint32 enchantId : the id of the enchant slot specified + */ + int GetEnchantmentId(lua_State* L, Item* item) + { + uint32 enchant_slot = Eluna::CHECKVAL(L, 2); + + if (enchant_slot >= MAX_INSPECTED_ENCHANTMENT_SLOT) + return luaL_argerror(L, 2, "valid EnchantmentSlot expected"); + + Eluna::Push(L, item->GetEnchantmentId(EnchantmentSlot(enchant_slot))); + return 1; + } + + /** + * Returns the spell ID tied to the [Item] by spell index + * + * @param uint32 spellIndex : the spell index specified + * @return uint32 spellId : the id of the spell + */ + int GetSpellId(lua_State* L, Item* item) + { + uint32 index = Eluna::CHECKVAL(L, 2); + if (index >= MAX_ITEM_PROTO_SPELLS) + return luaL_argerror(L, 2, "valid SpellIndex expected"); + + Eluna::Push(L, item->GetTemplate()->Spells[index].SpellId); + return 1; + } + + /** + * Returns the spell trigger tied to the [Item] by spell index + * + * @param uint32 spellIndex : the spell index specified + * @return uint32 spellTrigger : the spell trigger of the specified index + */ + int GetSpellTrigger(lua_State* L, Item* item) + { + uint32 index = Eluna::CHECKVAL(L, 2); + if (index >= MAX_ITEM_PROTO_SPELLS) + return luaL_argerror(L, 2, "valid SpellIndex expected"); + + Eluna::Push(L, item->GetTemplate()->Spells[index].SpellTrigger); + return 1; + } + + /** + * Returns class of the [Item] + * + * @return uint32 class + */ + int GetClass(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->Class); + return 1; + } + + /** + * Returns subclass of the [Item] + * + * @return uint32 subClass + */ + int GetSubClass(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->SubClass); + return 1; + } + + /** + * Returns the name of the [Item] + * + * @return string name + */ + int GetName(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->Name1); + return 1; + } + + /** + * Returns the display ID of the [Item] + * + * @return uint32 displayId + */ + int GetDisplayId(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->DisplayInfoID); + return 1; + } + + /** + * Returns the quality of the [Item] + * + * @return uint32 quality + */ + int GetQuality(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->Quality); + return 1; + } + + /** + * Returns the default purchase count of the [Item] + * + * @return uint32 count + */ + int GetBuyCount(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->BuyCount); + return 1; + } + + /** + * Returns the purchase price of the [Item] + * + * @return uint32 price + */ + int GetBuyPrice(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->BuyPrice); + return 1; + } + + /** + * Returns the sell price of the [Item] + * + * @return uint32 price + */ + int GetSellPrice(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->SellPrice); + return 1; + } + + /** + * Returns the inventory type of the [Item] + * + * @return uint32 inventoryType + */ + int GetInventoryType(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->InventoryType); + return 1; + } + + /** + * Returns the [Player] classes allowed to use this [Item] + * + * @return uint32 allowableClass + */ + int GetAllowableClass(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->AllowableClass); + return 1; + } + + /** + * Returns the [Player] races allowed to use this [Item] + * + * @return uint32 allowableRace + */ + int GetAllowableRace(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->AllowableRace); + return 1; + } + + /** + * Returns the [Item]s level + * + * @return uint32 itemLevel + */ + int GetItemLevel(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->ItemLevel); + return 1; + } + + /** + * Returns the minimum level required to use this [Item] + * + * @return uint32 requiredLevel + */ + int GetRequiredLevel(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->RequiredLevel); + return 1; + } + +#ifdef WOTLK + int GetStatsCount(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->StatsCount); + return 1; + } +#endif + + /** + * Returns the random property ID of this [Item] + * + * @return uint32 randomPropertyId + */ + int GetRandomProperty(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->RandomProperty); + return 1; + } + +#ifndef CLASSIC + int GetRandomSuffix(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->RandomSuffix); + return 1; + } +#endif + + /** + * Returns the item set ID of this [Item] + * + * @return uint32 itemSetId + */ + int GetItemSet(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->ItemSet); + return 1; + } + + /** + * Returns the bag size of this [Item], 0 if [Item] is not a bag + * + * @return uint32 bagSize + */ + int GetBagSize(lua_State* L, Item* item) + { + if (Bag* bag = item->ToBag()) + Eluna::Push(L, bag->GetBagSize()); + else + Eluna::Push(L, 0); + return 1; + } + + /** + * Sets the [Player] specified as the owner of the [Item] + * + * @param [Player] player : the [Player] specified + */ + int SetOwner(lua_State* L, Item* item) + { + Player* player = Eluna::CHECKOBJ(L, 2); + + item->SetOwnerGuid(player->GET_GUID()); + return 0; + } + + /** + * Sets the binding of the [Item] to 'true' or 'false' + * + * @param bool setBinding + */ + int SetBinding(lua_State* L, Item* item) + { + bool soulbound = Eluna::CHECKVAL(L, 2); + + item->SetBinding(soulbound); + item->SetState(ITEM_CHANGED, item->GetOwner()); + + return 0; + } + + /** + * Sets the stack count of the [Item] + * + * @param uint32 count + */ + int SetCount(lua_State* L, Item* item) + { + uint32 count = Eluna::CHECKVAL(L, 2); + item->SetCount(count); + return 0; + } + + /** + * Sets the specified enchantment of the [Item] to the specified slot + * + * @param uint32 enchantId : the ID of the enchant to be applied + * @param uint32 enchantSlot : the slot for the enchant to be applied to + * @return bool enchantmentSuccess : if enchantment is successfully set to specified slot, returns 'true', otherwise 'false' + */ + int SetEnchantment(lua_State* L, Item* item) + { + Player* owner = item->GetOwner(); + if (!owner) + { + Eluna::Push(L, false); + return 1; + } + + uint32 enchant = Eluna::CHECKVAL(L, 2); + if (!sSpellItemEnchantmentStore.LookupEntry(enchant)) + { + Eluna::Push(L, false); + return 1; + } + + EnchantmentSlot slot = (EnchantmentSlot)Eluna::CHECKVAL(L, 3); + if (slot >= MAX_INSPECTED_ENCHANTMENT_SLOT) + return luaL_argerror(L, 2, "valid EnchantmentSlot expected"); + + owner->ApplyEnchantment(item, slot, false); + item->SetEnchantment(slot, enchant, 0, 0); + owner->ApplyEnchantment(item, slot, true); + Eluna::Push(L, true); + return 1; + } + + /* OTHER */ + /** + * Removes an enchant from the [Item] by the specified slot + * + * @param uint32 enchantSlot : the slot for the enchant to be removed from + * @return bool enchantmentRemoved : if enchantment is successfully removed from specified slot, returns 'true', otherwise 'false' + */ + int ClearEnchantment(lua_State* L, Item* item) + { + Player* owner = item->GetOwner(); + if (!owner) + { + Eluna::Push(L, false); + return 1; + } + + EnchantmentSlot slot = (EnchantmentSlot)Eluna::CHECKVAL(L, 2); + if (slot >= MAX_INSPECTED_ENCHANTMENT_SLOT) + return luaL_argerror(L, 2, "valid EnchantmentSlot expected"); + + if (!item->GetEnchantmentId(slot)) + { + Eluna::Push(L, false); + return 1; + } + + owner->ApplyEnchantment(item, slot, false); + item->ClearEnchantment(slot); + Eluna::Push(L, true); + return 1; + } + + /** + * Saves the [Item] to the database + */ + int SaveToDB(lua_State* /*L*/, Item* item) + { + item->SaveToDB(); + return 0; + } + + ElunaRegister ItemMethods[] = + { + // Getters + { "GetOwnerGUID", &LuaItem::GetOwnerGUID }, + { "GetOwner", &LuaItem::GetOwner }, + { "GetCount", &LuaItem::GetCount }, + { "GetMaxStackCount", &LuaItem::GetMaxStackCount }, + { "GetSlot", &LuaItem::GetSlot }, + { "GetBagSlot", &LuaItem::GetBagSlot }, + { "GetEnchantmentId", &LuaItem::GetEnchantmentId }, + { "GetSpellId", &LuaItem::GetSpellId }, + { "GetSpellTrigger", &LuaItem::GetSpellTrigger }, + { "GetItemLink", &LuaItem::GetItemLink }, + { "GetClass", &LuaItem::GetClass }, + { "GetSubClass", &LuaItem::GetSubClass }, + { "GetName", &LuaItem::GetName }, + { "GetDisplayId", &LuaItem::GetDisplayId }, + { "GetQuality", &LuaItem::GetQuality }, + { "GetBuyCount", &LuaItem::GetBuyCount }, + { "GetBuyPrice", &LuaItem::GetBuyPrice }, + { "GetSellPrice", &LuaItem::GetSellPrice }, + { "GetInventoryType", &LuaItem::GetInventoryType }, + { "GetAllowableClass", &LuaItem::GetAllowableClass }, + { "GetAllowableRace", &LuaItem::GetAllowableRace }, + { "GetItemLevel", &LuaItem::GetItemLevel }, + { "GetRequiredLevel", &LuaItem::GetRequiredLevel }, + { "GetRandomProperty", &LuaItem::GetRandomProperty }, + { "GetItemSet", &LuaItem::GetItemSet }, + { "GetBagSize", &LuaItem::GetBagSize }, +#if defined(TBC) || defined(WOTLK) + { "GetRandomSuffix", &LuaItem::GetRandomSuffix }, +#endif +#if defined(WOTLK) + { "GetStatsCount", &LuaItem::GetStatsCount }, +#endif + + // Setters + { "SetOwner", &LuaItem::SetOwner }, + { "SetBinding", &LuaItem::SetBinding }, + { "SetCount", &LuaItem::SetCount }, + + // Boolean + { "IsSoulBound", &LuaItem::IsSoulBound }, + { "IsBoundByEnchant", &LuaItem::IsBoundByEnchant }, + { "IsNotBoundToPlayer", &LuaItem::IsNotBoundToPlayer }, + { "IsLocked", &LuaItem::IsLocked }, + { "IsBag", &LuaItem::IsBag }, + { "IsNotEmptyBag", &LuaItem::IsNotEmptyBag }, + { "IsBroken", &LuaItem::IsBroken }, + { "CanBeTraded", &LuaItem::CanBeTraded }, + { "IsInTrade", &LuaItem::IsInTrade }, + { "IsInBag", &LuaItem::IsInBag }, + { "IsEquipped", &LuaItem::IsEquipped }, + { "HasQuest", &LuaItem::HasQuest }, + { "IsPotion", &LuaItem::IsPotion }, + { "IsConjuredConsumable", &LuaItem::IsConjuredConsumable }, + { "SetEnchantment", &LuaItem::SetEnchantment }, + { "ClearEnchantment", &LuaItem::ClearEnchantment }, +#if defined(TBC) || defined(WOTLK) + { "IsCurrencyToken", &LuaItem::IsCurrencyToken }, +#endif +#if defined(WOTLK) + { "IsBoundAccountWide", &LuaItem::IsBoundAccountWide }, + { "IsWeaponVellum", &LuaItem::IsWeaponVellum }, + { "IsArmorVellum", &LuaItem::IsArmorVellum }, +#endif + + // Other + { "SaveToDB", &LuaItem::SaveToDB }, + + // Not implemented methods + { "IsRefundExpired", nullptr }, // not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/MapMethods.h b/src/modules/Eluna/CMangos/MapMethods.h new file mode 100644 index 0000000000..dbf2bd5981 --- /dev/null +++ b/src/modules/Eluna/CMangos/MapMethods.h @@ -0,0 +1,341 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef MAPMETHODS_H +#define MAPMETHODS_H + +#include "LuaEngine/ElunaInstanceAI.h" + +/*** + * A game map, e.g. Azeroth, Eastern Kingdoms, the Molten Core, etc. + * + * Inherits all methods from: none + */ +namespace LuaMap +{ + +#ifndef CLASSIC + /** + * Returns `true` if the [Map] is an arena [BattleGround], `false` otherwise. + * + * @return bool isArena + */ + int IsArena(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsBattleArena()); + return 1; + } +#endif + + /** + * Returns `true` if the [Map] is a non-arena [BattleGround], `false` otherwise. + * + * @return bool isBattleGround + */ + int IsBattleground(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsBattleGround()); + return 1; + } + + /** + * Returns `true` if the [Map] is a dungeon, `false` otherwise. + * + * @return bool isDungeon + */ + int IsDungeon(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsDungeon()); + return 1; + } + + /** + * Returns `true` if the [Map] has no [Player]s, `false` otherwise. + * + * @return bool isEmpty + */ + int IsEmpty(lua_State* L, Map* map) + { + Eluna::Push(L, map->isEmpty()); + return 1; + } + +#ifndef CLASSIC + /** + * Returns `true` if the [Map] is a heroic, `false` otherwise. + * + * @return bool isHeroic + */ + int IsHeroic(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsHeroic()); + return 1; + } +#endif + + /** + * Returns `true` if the [Map] is a raid, `false` otherwise. + * + * @return bool isRaid + */ + int IsRaid(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsRaid()); + return 1; + } + + /** + * Returns the name of the [Map]. + * + * @return string mapName + */ + int GetName(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetMapName()); + return 1; + } + + /** + * Returns the height of the [Map] at the given X and Y coordinates. + * + * In case of no height found nil is returned + * + * @param float x + * @param float y + * @return float z + */ + int GetHeight(lua_State* L, Map* map) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); +#if (defined(TBC) || defined(CLASSIC)) + float z = map->GetHeight(x, y, MAX_HEIGHT); +#else + uint32 phasemask = Eluna::CHECKVAL(L, 4, 1); + float z = map->GetHeight(phasemask, x, y, MAX_HEIGHT); +#endif + if (z != INVALID_HEIGHT) + Eluna::Push(L, z); + return 1; + } + + /** + * Returns the difficulty of the [Map]. + * + * Always returns 0 if the expansion is pre-TBC. + * + * @return int32 difficulty + */ + int GetDifficulty(lua_State* L, Map* map) + { +#ifndef CLASSIC + Eluna::Push(L, map->GetDifficulty()); +#else + Eluna::Push(L, (Difficulty)0); +#endif + return 1; + } + + /** + * Returns the instance ID of the [Map]. + * + * @return uint32 instanceId + */ + int GetInstanceId(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetInstanceId()); + return 1; + } + + /** + * Returns the player count currently on the [Map] (excluding GMs). + * + * @return uint32 playerCount + */ + int GetPlayerCount(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetPlayersCountExceptGMs()); + return 1; + } + + /** + * Returns the ID of the [Map]. + * + * @return uint32 mapId + */ + int GetMapId(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetId()); + return 1; + } + + /** + * Returns the area ID of the [Map] at the specified X, Y, and Z coordinates. + * + * @param float x + * @param float y + * @param float z + * @param uint32 phasemask = PHASEMASK_NORMAL + * @return uint32 areaId + */ + int GetAreaId(lua_State* L, Map* map) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + + Eluna::Push(L, map->GetTerrain()->GetAreaId(x, y, z)); + return 1; + } + + /** + * Returns a [WorldObject] by its GUID from the map if it is spawned. + * + * @param ObjectGuid guid + * @return [WorldObject] object + */ + int GetWorldObject(lua_State* L, Map* map) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, map->GetWorldObject(guid)); + return 1; + } + + /** + * Sets the [Weather] type based on [WeatherType] and grade supplied. + * + * enum WeatherType + * { + * WEATHER_TYPE_FINE = 0, + * WEATHER_TYPE_RAIN = 1, + * WEATHER_TYPE_SNOW = 2, + * WEATHER_TYPE_STORM = 3, + * WEATHER_TYPE_THUNDERS = 86, + * WEATHER_TYPE_BLACKRAIN = 90 + * }; + * + * @param uint32 zone : id of the zone to set the weather for + * @param [WeatherType] type : the [WeatherType], see above available weather types + * @param float grade : the intensity/grade of the [Weather], ranges from 0 to 1 + */ + int SetWeather(lua_State* L, Map* map) + { + (void)map; // ensure that the variable is referenced in order to pass compiler checks + uint32 zoneId = Eluna::CHECKVAL(L, 2); + uint32 weatherType = Eluna::CHECKVAL(L, 3); + float grade = Eluna::CHECKVAL(L, 4); + + if (Weather::IsValidWeatherType(weatherType)) + map->SetWeather(zoneId, (WeatherType)weatherType, grade, false); + return 0; + } + + /** + * Gets the instance data table for the [Map], if it exists. + * + * The instance must be scripted using Eluna for this to succeed. + * If the instance is scripted in C++ this will return `nil`. + * + * @return table instance_data : instance data table, or `nil` + */ + int GetInstanceData(lua_State* L, Map* map) + { + ElunaInstanceAI* iAI = dynamic_cast(map->GetInstanceData()); + + if (iAI) + Eluna::GetEluna(L)->PushInstanceData(L, iAI, false); + else + Eluna::Push(L); // nil + + return 1; + } + + /** + * Saves the [Map]'s instance data to the database. + */ + int SaveInstanceData(lua_State* /*L*/, Map* map) + { + ElunaInstanceAI* iAI = dynamic_cast(map->GetInstanceData()); + + if (iAI) + iAI->SaveToDB(); + + return 0; + } + + /** + * Returns a table with all the current [Player]s in the map + * + * enum TeamId + * { + * TEAM_ALLIANCE = 0, + * TEAM_HORDE = 1, + * TEAM_NEUTRAL = 2 + * }; + * + * @param [TeamId] team : optional check team of the [Player], Alliance, Horde or Neutral (All) + * @return table mapPlayers + */ + int GetPlayers(lua_State* L, Map* map) + { + uint32 team = Eluna::CHECKVAL(L, 2, TEAM_NEUTRAL); + + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 i = 0; + + Map::PlayerList const& players = map->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* player = itr->getSource(); + if (!player) + continue; + if (player->GetSession() && (team >= TEAM_NEUTRAL || player->GetTeamId() == team)) + { + Eluna::Push(L, player); + lua_rawseti(L, tbl, ++i); + } + } + + lua_settop(L, tbl); + return 1; + } + + ElunaRegister MapMethods[] = + { + // Getters + { "GetName", &LuaMap::GetName }, + { "GetDifficulty", &LuaMap::GetDifficulty }, + { "GetInstanceId", &LuaMap::GetInstanceId }, + { "GetInstanceData", &LuaMap::GetInstanceData }, + { "GetPlayerCount", &LuaMap::GetPlayerCount }, + { "GetPlayers", &LuaMap::GetPlayers }, + { "GetMapId", &LuaMap::GetMapId }, + { "GetAreaId", &LuaMap::GetAreaId }, + { "GetHeight", &LuaMap::GetHeight }, + { "GetWorldObject", &LuaMap::GetWorldObject }, + + // Setters + { "SetWeather", &LuaMap::SetWeather }, + + // Boolean + { "IsBattleground", &LuaMap::IsBattleground }, + { "IsDungeon", &LuaMap::IsDungeon }, + { "IsEmpty", &LuaMap::IsEmpty }, + { "IsRaid", &LuaMap::IsRaid }, +#if defined(TBC) || defined(WOTLK) + { "IsArena", &LuaMap::IsArena }, + { "IsHeroic", &LuaMap::IsHeroic }, +#endif + + // Other + { "SaveInstanceData", &LuaMap::SaveInstanceData }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/ObjectMethods.h b/src/modules/Eluna/CMangos/ObjectMethods.h new file mode 100644 index 0000000000..c59e171ca7 --- /dev/null +++ b/src/modules/Eluna/CMangos/ObjectMethods.h @@ -0,0 +1,498 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef OBJECTMETHODS_H +#define OBJECTMETHODS_H + +/*** + * A basic game object (either an [Item] or a [WorldObject]). + * + * Objects in MaNGOS/Trinity are stored an a giant block of "values". + * Subclasses of Object, like [WorldObject], extend the block with more data specific to that subclass. + * Further subclasses, like [Player], extend it even further. + * + * A detailed map of all the fields in this data block can be found in the UpdateFields.h file of your emulator + * (it varies depending on the expansion supported). + * + * The GetValue methods in this class (e.g. [Object:GetInt32Value]) provide low-level access to the data block. + * Other methods, like [Object:HasFlag] and [Object:GetScale], merely wrap the GetValue methods and provide a simpler interface. + * + * Inherits all methods from: none + */ +namespace LuaObject +{ + /** + * Returns `true` if the specified flag is set, otherwise `false`. + * + * @param uint16 index : the index of the flags data in the [Object] + * @param uint32 flag : the flag to check for in the flags data + * @return bool hasFlag + */ + int HasFlag(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 flag = Eluna::CHECKVAL(L, 3); + + Eluna::Push(L, obj->HasFlag(index, flag)); + return 1; + } + + /** + * Returns `true` if the [Object] has been added to its [Map], otherwise `false`. + * + * @return bool inWorld + */ + int IsInWorld(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->IsInWorld()); + return 1; + } + + /** + * Returns the data at the specified index, casted to a signed 32-bit integer. + * + * @param uint16 index + * @return int32 value + */ + int GetInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, obj->GetInt32Value(index)); + return 1; + } + + /** + * Returns the data at the specified index, casted to a unsigned 32-bit integer. + * + * @param uint16 index + * @return uint32 value + */ + int GetUInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, obj->GetUInt32Value(index)); + return 1; + } + + /** + * Returns the data at the specified index, casted to a single-precision floating point value. + * + * @param uint16 index + * @return float value + */ + int GetFloatValue(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, obj->GetFloatValue(index)); + return 1; + } + + /** + * Returns the data at the specified index and offset, casted to an unsigned 8-bit integer. + * + * E.g. if you want the second byte at index 10, you would pass in 1 as the offset. + * + * @param uint16 index + * @param uint8 offset : should be 0, 1, 2, or 3 + * @return uint8 value + */ + int GetByteValue(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetByteValue(index, offset)); + return 1; + } + + /** + * Returns the data at the specified index and offset, casted to a signed 16-bit integer. + * + * E.g. if you want the second half-word at index 10, you would pass in 1 as the offset. + * + * @param uint16 index + * @param uint8 offset : should be 0 or 1 + * @return uint16 value + */ + int GetUInt16Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetUInt16Value(index, offset)); + return 1; + } + + /** + * Returns the scale/size of the [Object]. + * + * This affects the size of a [WorldObject] in-game, but [Item]s don't have a "scale". + * + * @return float scale + */ + int GetScale(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GetObjectScale()); + return 1; + } + + /** + * Returns the entry of the [Object]. + * + * [Player]s do not have an "entry". + * + * @return uint32 entry + */ + int GetEntry(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GetEntry()); + return 1; + } + + /** + * Returns the GUID of the [Object]. + * + * GUID is an unique identifier for the object. + * + * However on MaNGOS and cMangos creatures and gameobjects inside different maps can share + * the same GUID but not on the same map. + * + * On TrinityCore this value is unique across all maps + * + * @return ObjectGuid guid + */ + int GetGUID(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GET_GUID()); + return 1; + } + + /** + * Returns the low-part of the [Object]'s GUID. + * + * On TrinityCore all low GUIDs are different for all objects of the same type. + * For example creatures in instances are assigned new GUIDs when the Map is created. + * + * On MaNGOS and cMaNGOS low GUIDs are unique only on the same map. + * For example creatures in instances use the same low GUID assigned for that spawn in the database. + * This is why to identify a creature you have to know the instanceId and low GUID. See [Map:GetIntstanceId] + * + * @return uint32 guidLow + */ + int GetGUIDLow(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GetGUIDLow()); + return 1; + } + + /** + * Returns the TypeId of the [Object]. + * + * enum TypeID + * { + * TYPEID_OBJECT = 0, + * TYPEID_ITEM = 1, + * TYPEID_CONTAINER = 2, + * TYPEID_UNIT = 3, + * TYPEID_PLAYER = 4, + * TYPEID_GAMEOBJECT = 5, + * TYPEID_DYNAMICOBJECT = 6, + * TYPEID_CORPSE = 7 + * }; + * + * @return uint8 typeID + */ + int GetTypeId(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GetTypeId()); + return 1; + } + + /** + * Returns the data at the specified index, casted to an unsigned 64-bit integer. + * + * @param uint16 index + * @return uint64 value + */ + int GetUInt64Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, obj->GetUInt64Value(index)); + return 1; + } + + /** + * Sets the specified flag in the data value at the specified index. + * + * If the flag was already set, it remains set. + * + * To remove a flag, use [Object:RemoveFlag]. + * + * @param uint16 index + * @param uint32 value + */ + int SetFlag(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 flag = Eluna::CHECKVAL(L, 3); + + obj->SetFlag(index, flag); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to a signed 32-bit integer. + * + * @param uint16 index + * @param int32 value + */ + int SetInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + int32 value = Eluna::CHECKVAL(L, 3); + obj->SetInt32Value(index, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to an unsigned 32-bit integer. + * + * @param uint16 index + * @param uint32 value + */ + int SetUInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 value = Eluna::CHECKVAL(L, 3); + obj->SetUInt32Value(index, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to an unsigned 32-bit integer. + * + * @param uint16 index + * @param uint32 value + */ + int UpdateUInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 value = Eluna::CHECKVAL(L, 3); + obj->UpdateUInt32Value(index, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to a single-precision floating point value. + * + * @param uint16 index + * @param float value + */ + int SetFloatValue(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + float value = Eluna::CHECKVAL(L, 3); + + obj->SetFloatValue(index, value); + return 0; + } + + /** + * Sets the data at the specified index and offset to the given value, converted to an unsigned 8-bit integer. + * + * @param uint16 index + * @param uint8 offset : should be 0, 1, 2, or 3 + * @param uint8 value + */ + int SetByteValue(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + uint8 value = Eluna::CHECKVAL(L, 4); + obj->SetByteValue(index, offset, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to an unsigned 16-bit integer. + * + * @param uint16 index + * @param uint8 offset : should be 0 or 1 + * @param uint16 value + */ + int SetUInt16Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + uint16 value = Eluna::CHECKVAL(L, 4); + obj->SetUInt16Value(index, offset, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to a signed 16-bit integer. + * + * @param uint16 index + * @param uint8 offset : should be 0 or 1 + * @param int16 value + */ + int SetInt16Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + int16 value = Eluna::CHECKVAL(L, 4); + obj->SetInt16Value(index, offset, value); + return 0; + } + + /** + * Sets the [Object]'s scale/size to the given value. + * + * @param float scale + */ + int SetScale(lua_State* L, Object* obj) + { + float size = Eluna::CHECKVAL(L, 2); + + obj->SetObjectScale(size); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to an unsigned 64-bit integer. + * + * @param uint16 index + * @param uint64 value + */ + int SetUInt64Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint64 value = Eluna::CHECKVAL(L, 3); + obj->SetUInt64Value(index, value); + return 0; + } + + /** + * Removes a flag from the value at the specified index. + * + * @param uint16 index + * @param uint32 flag + */ + int RemoveFlag(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 flag = Eluna::CHECKVAL(L, 3); + + obj->RemoveFlag(index, flag); + return 0; + } + + /** + * Attempts to convert the [Object] to a [Corpse]. + * + * If the [Object] is not a [Corpse], returns `nil`. + * + * @return [Corpse] corpse : the [Object] as a [Corpse], or `nil` + */ + int ToCorpse(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToCorpse()); + return 1; + } + + /** + * Attempts to convert the [Object] to a [GameObject]. + * + * If the [Object] is not a [GameObject], returns `nil`. + * + * @return [GameObject] gameObject : the [Object] as a [GameObject], or `nil` + */ + int ToGameObject(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToGameObject()); + return 1; + } + + /** + * Attempts to convert the [Object] to a [Unit]. + * + * If the [Object] is not a [Unit], returns `nil`. + * + * @return [Unit] unit : the [Object] as a [Unit], or `nil` + */ + int ToUnit(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToUnit()); + return 1; + } + + /** + * Attempts to convert the [Object] to a [Creature]. + * + * If the [Object] is not a [Creature], returns `nil`. + * + * @return [Creature] creature : the [Object] as a [Creature], or `nil` + */ + int ToCreature(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToCreature()); + return 1; + } + + /** + * Attempts to convert the [Object] to a [Player]. + * + * If the [Object] is not a [Player], returns `nil`. + * + * @return [Player] player : the [Object] as a [Player], or `nil` + */ + int ToPlayer(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToPlayer()); + return 1; + } + + ElunaRegister ObjectMethods[] = + { + // Getters + { "GetEntry", &LuaObject::GetEntry }, + { "GetGUID", &LuaObject::GetGUID }, + { "GetGUIDLow", &LuaObject::GetGUIDLow }, + { "GetInt32Value", &LuaObject::GetInt32Value }, + { "GetUInt32Value", &LuaObject::GetUInt32Value }, + { "GetFloatValue", &LuaObject::GetFloatValue }, + { "GetByteValue", &LuaObject::GetByteValue }, + { "GetUInt16Value", &LuaObject::GetUInt16Value }, + { "GetUInt64Value", &LuaObject::GetUInt64Value }, + { "GetScale", &LuaObject::GetScale }, + { "GetTypeId", &LuaObject::GetTypeId }, + + // Setters + { "SetInt32Value", &LuaObject::SetInt32Value }, + { "SetUInt32Value", &LuaObject::SetUInt32Value }, + { "UpdateUInt32Value", &LuaObject::UpdateUInt32Value }, + { "SetFloatValue", &LuaObject::SetFloatValue }, + { "SetByteValue", &LuaObject::SetByteValue }, + { "SetUInt16Value", &LuaObject::SetUInt16Value }, + { "SetInt16Value", &LuaObject::SetInt16Value }, + { "SetUInt64Value", &LuaObject::SetUInt64Value }, + { "SetScale", &LuaObject::SetScale }, + { "SetFlag", &LuaObject::SetFlag }, + + // Boolean + { "IsInWorld", &LuaObject::IsInWorld }, + { "HasFlag", &LuaObject::HasFlag }, + + // Other + { "ToGameObject", &LuaObject::ToGameObject }, + { "ToUnit", &LuaObject::ToUnit }, + { "ToCreature", &LuaObject::ToCreature }, + { "ToPlayer", &LuaObject::ToPlayer }, + { "ToCorpse", &LuaObject::ToCorpse }, + { "RemoveFlag", &LuaObject::RemoveFlag }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/PlayerMethods.h b/src/modules/Eluna/CMangos/PlayerMethods.h new file mode 100644 index 0000000000..dc005d3850 --- /dev/null +++ b/src/modules/Eluna/CMangos/PlayerMethods.h @@ -0,0 +1,4036 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef PLAYERMETHODS_H +#define PLAYERMETHODS_H + +/*** + * Inherits all methods from: [Object], [WorldObject], [Unit] + */ +namespace LuaPlayer +{ +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Returns 'true' if the [Player] can Titan Grip, 'false' otherwise. + * + * @return bool canTitanGrip + */ + int CanTitanGrip(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanTitanGrip()); + return 1; + } + + /** + * Returns 'true' if the [Player] has a talent by ID in specified spec, 'false' otherwise. + * + * @param uint32 spellId : talent spellId to check + * @param uint8 spec : specified spec. 0 for primary, 1 for secondary. + * @return bool hasTalent + */ + int HasTalent(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + uint8 maxSpecs = MAX_TALENT_SPECS; + uint8 spec = Eluna::CHECKVAL(L, 3); + if (spec >= maxSpecs) + return 1; + Eluna::Push(L, player->HasTalent(spellId, spec)); + return 1; + } + + /** + * Returns 'true' if the [Player] has completed the specified achievement, 'false' otherwise. + * + * @param uint32 achievementId + * @return bool hasAchieved + */ + int HasAchieved(lua_State* L, Player* player) + { + uint32 achievementId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetAchievementMgr().HasAchievement(achievementId)); + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] has an active [Quest] by specific ID, 'false' otherwise. + * + * @param uint32 questId + * @return bool hasQuest + */ + int HasQuest(lua_State* L, Player* player) + { + uint32 quest = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->IsActiveQuest(quest)); + return 1; + } + + /** + * Returns 'true' if the [Player] has a skill by specific ID, 'false' otherwise. + * + * @param uint32 skill + * @return bool hasSkill + */ + int HasSkill(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasSkill(skill)); + return 1; + } + + /** + * Returns 'true' if the [Player] has a [Spell] by specific ID, 'false' otherwise. + * + * @param uint32 spellId + * @return bool hasSpell + */ + int HasSpell(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasSpell(id)); + return 1; + } + + /** + * Returns true if [Player] has specified login flag + * + * @param uint32 flag + * @return bool hasLoginFlag + */ + int HasAtLoginFlag(lua_State* L, Player* player) + { + uint32 flag = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasAtLoginFlag((AtLoginFlags)flag)); + return 1; + } + + /** + * Returns true if [Player] has [Quest] for [GameObject] + * + * @param int32 entry : entry of a [GameObject] + * @return bool hasQuest + */ + int HasQuestForGO(lua_State* L, Player* player) + { + int32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasQuestForGO(entry)); + return 1; + } + +#ifndef CLASSIC + /** + * Returns 'true' if the [Player] has a title by specific ID, 'false' otherwise. + * + * @param uint32 titleId + * @return bool hasTitle + */ + int HasTitle(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); + if (titleInfo) + Eluna::Push(L, player->HasTitle(titleInfo)); + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] has the given amount of item entry specified, 'false' otherwise. + * + * @param uint32 itemId : entry of the item + * @param uint32 count = 1 : amount of items the player needs should have + * @param bool check_bank = false : determines if the item can be in player bank + * @return bool hasItem + */ + int HasItem(lua_State* L, Player* player) + { + uint32 itemId = Eluna::CHECKVAL(L, 2); + uint32 count = Eluna::CHECKVAL(L, 3, 1); + bool check_bank = Eluna::CHECKVAL(L, 4, false); + Eluna::Push(L, player->HasItemCount(itemId, count, check_bank)); + return 1; + } + + /** + * Returns 'true' if the [Player] has a quest for the item entry specified, 'false' otherwise. + * + * @param uint32 entry : entry of the item + * @return bool hasQuest + */ + int HasQuestForItem(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasQuestForItem(entry)); + return 1; + } + + /** + * Returns 'true' if the [Player] can use the item or item entry specified, 'false' otherwise. + * + * @proto canUse = (item) + * @proto canUse = (entry) + * @param [Item] item : an instance of an item + * @param uint32 entry : entry of the item + * @return bool canUse + */ + int CanUseItem(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2, false); + if (item) + Eluna::Push(L, player->CanUseItem(item) == EQUIP_ERR_OK); + else + { + uint32 entry = Eluna::CHECKVAL(L, 2); + const ItemTemplate* temp = eObjectMgr->GetItemTemplate(entry); + if (temp) + Eluna::Push(L, player->CanUseItem(temp) == EQUIP_ERR_OK); + else + Eluna::Push(L, false); + } + return 1; + } + + /** + * Returns 'true' if the [Spell] specified by ID is currently on cooldown for the [Player], 'false' otherwise. + * + * @param uint32 spellId + * @return bool hasSpellCooldown + */ + int HasSpellCooldown(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasSpellCooldown(spellId)); + return 1; + } + + /** + * Returns 'true' if the [Player] can share [Quest] specified by ID, 'false' otherwise. + * + * @param uint32 entryId + * @return bool hasSpellCooldown + */ + int CanShareQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->CanShareQuest(entry)); + return 1; + } + + /** + * Returns 'true' if the [Player] can currently communicate through chat, 'false' otherwise. + * + * @return bool canSpeak + */ + int CanSpeak(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanSpeak()); + return 1; + } + + /** + * Returns 'true' if the [Player] has permission to uninvite others from the current group, 'false' otherwise. + * + * @return bool canUninviteFromGroup + */ + int CanUninviteFromGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanUninviteFromGroup() == ERR_PARTY_RESULT_OK); + return 1; + } + +#ifndef CLASSIC + /** + * Returns 'true' if the [Player] can fly, 'false' otherwise. + * + * @return bool canFly + */ + int CanFly(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanFly()); + return 1; + } +#endif + +#ifdef CLASSIC + /** + * Returns [Player] kills + * + * @param bool honorable = true : if victims are honorable + * @return uint32 kills + */ + int GetHonorStoredKills(lua_State* L, Player* player) + { + bool honorable = Eluna::CHECKVAL(L, 2, true); + + Eluna::Push(L, player->GetHonorStoredKills(honorable)); + return 1; + } + + /** + * Returns rank points + * + * @return float rankPoints + */ + int GetRankPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetRankPoints()); + return 1; + } + + /** + * Returns last week's standing position + * + * @return int32 standingPos + */ + int GetHonorLastWeekStandingPos(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetHonorLastWeekStandingPos()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] is currently in water, 'false' otherwise. + * + * @return bool isInWater + */ + int IsInWater(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsInWater()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently moving, 'false' otherwise. + * + * @return bool isMoving + */ + int IsMoving(lua_State* L, Player* player) // enable for unit when mangos support it + { + Eluna::Push(L, player->IsMoving()); + return 1; + } + +#ifdef CLASSIC + /** + * Updates the [Player]s weekly honor status + */ + int UpdateHonor(lua_State* L, Player* player) + { + player->UpdateHonor(); + return 0; + } + + /** + * Resets the [Player]s weekly honor status + */ + int ResetHonor(lua_State* L, Player* player) + { + player->ResetHonor(); + return 0; + } + + /** + * Clears all of [Player]s weekly honor status + */ + int ClearHonorInfo(lua_State* L, Player* player) + { + player->ClearHonorInfo(); + return 0; + } +#endif + +#ifndef CLASSIC + /** + * Returns 'true' if the [Player] is currently flying, 'false' otherwise. + * + * @return bool isFlying + */ + int IsFlying(lua_State* L, Player* player) // enable for unit when mangos support it + { + Eluna::Push(L, player->IsFlying()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] is in a [Group], 'false' otherwise. + * + * @return bool isInGroup + */ + int IsInGroup(lua_State* L, Player* player) + { + Eluna::Push(L, (player->GetGroup() != NULL)); + return 1; + } + + /** + * Returns 'true' if the [Player] is in a [Guild], 'false' otherwise. + * + * @return bool isInGuild + */ + int IsInGuild(lua_State* L, Player* player) + { + Eluna::Push(L, (player->GetGuildId() != 0)); + return 1; + } + + /** + * Returns 'true' if the [Player] is a Game Master, 'false' otherwise. + * + * Note: This is only true when GM tag is activated! For alternative see [Player:GetGMRank] + * + * @return bool isGM + */ + int IsGM(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsGameMaster()); + return 1; + } + +#ifndef CLASSIC + /** + * Returns 'true' if the [Player] is in an arena team specified by type, 'false' otherwise. + * + * @param uint32 type + * @return bool isInArenaTeam + */ + int IsInArenaTeam(lua_State* L, Player* player) + { + uint32 type = Eluna::CHECKVAL(L, 2); + if (type < MAX_ARENA_SLOT && player->GetArenaTeamId(type)) + Eluna::Push(L, true); + else + Eluna::Push(L, false); + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] is immune to everything. + * + * @return bool isImmune + */ + int IsImmuneToDamage(lua_State* L, Player* player) + { + Eluna::Push(L, player->isTotalImmune()); + return 1; + } + + /** + * Returns 'true' if the [Player] satisfies all requirements to complete the quest entry. + * + * @param uint32 entry + * @return bool canComplete + */ + int CanCompleteQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->CanCompleteQuest(entry)); + return 1; + } + + /** + * Returns 'true' if the [Player] satisfies all requirements to complete the repeatable quest entry. + * + * @param uint32 entry + * @return bool canComplete + */ + int CanCompleteRepeatableQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* qInfo = eObjectMgr->GetQuestTemplate(entry); + if (qInfo) + Eluna::Push(L, player->CanCompleteRepeatableQuest(qInfo)); + else + Eluna::Push(L, false); + + return 1; + } + + /** + * Returns 'true' if the [Player] satisfies all requirements to turn in the quest. + * + * @param uint32 entry + * @return bool canReward + */ + int CanRewardQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* qInfo = eObjectMgr->GetQuestTemplate(entry); + if (qInfo) + Eluna::Push(L, player->CanRewardQuest(qInfo, true)); + else + Eluna::Push(L, false); + + return 1; + } + + /** + * Returns 'true' if the [Player] is a part of the Horde faction, 'false' otherwise. + * + * @return bool isHorde + */ + int IsHorde(lua_State* L, Player* player) + { + Eluna::Push(L, (player->GetTeam() == HORDE)); + return 1; + } + + /** + * Returns 'true' if the [Player] is a part of the Alliance faction, 'false' otherwise. + * + * @return bool isAlliance + */ + int IsAlliance(lua_State* L, Player* player) + { + Eluna::Push(L, (player->GetTeam() == ALLIANCE)); + return 1; + } + + /** + * Returns 'true' if the [Player] is 'Do Not Disturb' flagged, 'false' otherwise. + * + * @return bool isDND + */ + int IsDND(lua_State* L, Player* player) + { + Eluna::Push(L, player->isDND()); + return 1; + } + + /** + * Returns 'true' if the [Player] is 'Away From Keyboard' flagged, 'false' otherwise. + * + * @return bool isAFK + */ + int IsAFK(lua_State* L, Player* player) + { + Eluna::Push(L, player->isAFK()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently falling, 'false' otherwise. + * + * @return bool isFalling + */ + int IsFalling(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsFalling()); + return 1; + } + + int IsGroupVisibleFor(lua_State* L, Player* player) + { + Player* target = Eluna::CHECKOBJ(L, 2); + Eluna::Push(L, player->IsGroupVisibleFor(target)); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently in the same raid as another [Player] by object, 'false' otherwise. + * + * @param [Player] player + * @return bool isInSameRaidWith + */ + int IsInSameRaidWith(lua_State* L, Player* player) + { + Player* target = Eluna::CHECKOBJ(L, 2); + Eluna::Push(L, player->IsInSameRaidWith(target)); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently in the same [Group] as another [Player] by object, 'false' otherwise. + * + * @param [Player] player + * @return bool isInSameGroupWith + */ + int IsInSameGroupWith(lua_State* L, Player* player) + { + Player* target = Eluna::CHECKOBJ(L, 2); + Eluna::Push(L, player->IsInSameGroupWith(target)); + return 1; + } + + /** + * Returns 'true' if the [Player] is eligible for Honor or XP gain by [Unit] specified, 'false' otherwise. + * + * @param [Unit] unit + * @return bool isHonorOrXPTarget + */ + int IsHonorOrXPTarget(lua_State* L, Player* player) + { + Unit* victim = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, player->isHonorOrXPTarget(victim)); + return 1; + } + + /** + * Returns 'true' if the [Player] can see anoter [Player] specified by object, 'false' otherwise. + * + * @param [Player] player + * @return bool isVisibleForPlayer + */ + int IsVisibleForPlayer(lua_State* L, Player* player) + { + Player* target = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, player->IsVisibleGloballyFor(target)); + return 1; + } + + int IsGMVisible(lua_State* L, Player* player) + { + Eluna::Push(L, player->isGMVisible()); + return 1; + } + + /** + * Returns 'true' if the [Player] has taxi cheat activated, 'false' otherwise. + * + * @return bool isTaxiCheater + */ + int IsTaxiCheater(lua_State* L, Player* player) + { + Eluna::Push(L, player->isTaxiCheater()); + return 1; + } + + int IsGMChat(lua_State* L, Player* player) + { + Eluna::Push(L, player->isGMChat()); + return 1; + } + + /** + * Returns 'true' if the [Player] is accepting whispers, 'false' otherwise. + * + * @return bool isAcceptingWhispers + */ + int IsAcceptingWhispers(lua_State* L, Player* player) + { + Eluna::Push(L, player->isAcceptWhispers()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently rested, 'false' otherwise. + * + * @return bool isRested + */ + int IsRested(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetRestBonus() > 0.0f); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently in a [BattleGround] queue, 'false' otherwise. + * + * @return bool inBattlegroundQueue + */ + int InBattlegroundQueue(lua_State* L, Player* player) + { + Eluna::Push(L, player->InBattleGroundQueue()); + return 1; + } + +#ifndef CLASSIC + /** + * Returns 'true' if the [Player] is currently in an arena, 'false' otherwise. + * + * @return bool inArena + */ + int InArena(lua_State* L, Player* player) + { + Eluna::Push(L, player->InArena()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] is currently in a [BattleGround], 'false' otherwise. + * + * @return bool inBattleGround + */ + int InBattleground(lua_State* L, Player* player) + { + Eluna::Push(L, player->InBattleGround()); + return 1; + } + + /** + * Returns 'true' if the [Player] can block incomming attacks, 'false' otherwise. + * + * @return bool canBlock + */ + int CanBlock(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanBlock()); + return 1; + } + + /** + * Returns 'true' if the [Player] can parry incomming attacks, 'false' otherwise. + * + * @return bool canParry + */ + int CanParry(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanParry()); + return 1; + } + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Returns the amount of available specs the [Player] currently has + * + * @return uint8 specCount + */ + int GetSpecsCount(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSpecsCount()); + return 1; + } + + /** + * Returns the [Player]s active spec ID + * + * @return uint32 specId + */ + int GetActiveSpec(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetActiveSpec()); + return 1; + } +#endif + +#ifdef WOTLK + /** + * Returns the normal phase of the player instead of the actual phase possibly containing GM phase + * + * @return uint32 phasemask + */ + int GetPhaseMaskForSpawn(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetPhaseMaskForSpawn()); + return 1; + } +#endif + +#if defined(TBC) || defined (WOTLK) + /** + * Returns the [Player]s current amount of Arena Points + * + * @return uint32 arenaPoints + */ + int GetArenaPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetArenaPoints()); + return 1; + } + + /** + * Returns the [Player]s current amount of Honor Points + * + * @return uint32 honorPoints + */ + int GetHonorPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetHonorPoints()); + return 1; + } +#endif +#if defined(CLASSIC) || defined(TBC) || defined (WOTLK) + /** + * Returns the [Player]s current shield block value + * + * @return uint32 blockValue + */ + int GetShieldBlockValue(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetShieldBlockValue()); + return 1; + } +#endif + + /** + * Returns the [Player]s cooldown delay by specified [Spell] ID + * + * @param uint32 spellId + * @return uint32 spellCooldownDelay + */ + int GetSpellCooldownDelay(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, uint32(player->GetSpellCooldownDelay(spellId))); + return 1; + } + + /** + * Returns the [Player]s current latency in MS + * + * @return uint32 latency + */ + int GetLatency(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetLatency()); + return 1; + } + + /** + * Returns [Player]s original sub group + * + * @return uint8 subGroup + */ + int GetOriginalSubGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetOriginalSubGroup()); + return 1; + } + + /** + * Returns [Player]s original [Group] object + * + * @return [Group] group + */ + int GetOriginalGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetOriginalGroup()); + return 1; + } + + /** + * Returns a random Raid Member [Player] object within radius specified of [Player] + * + * @param float radius + * @return [Player] player + */ + int GetNextRandomRaidMember(lua_State* L, Player* player) + { + float radius = Eluna::CHECKVAL(L, 2); + +#ifndef CATA + Eluna::Push(L, player->GetNextRandomRaidMember(radius, SPELL_AURA_NONE)); +#else + Eluna::Push(L, player->GetNextRandomRaidMember(radius)); +#endif + return 1; + } + + /** + * Returns [Player]s current sub group + * + * @return uint8 subGroup + */ + int GetSubGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSubGroup()); + return 1; + } + + /** + * Returns [Group] invitation + * + * @return [Group] group + */ + int GetGroupInvite(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetGroupInvite()); + return 1; + } + + /** + * Returns rested experience bonus + * + * @param uint32 xp + * @return uint32 xpBonus + */ + int GetXPRestBonus(lua_State* L, Player* player) + { + uint32 xp = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetXPRestBonus(xp)); + return 1; + } + + /** + * Returns the [Player]s current [BattleGround] type ID + * + * @return [BattleGroundTypeId] typeId + */ + int GetBattlegroundTypeId(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetBattleGroundTypeId()); + return 1; + } + + /** + * Returns the [Player]s current [BattleGround] ID + * + * @return uint32 battleGroundId + */ + int GetBattlegroundId(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetBattleGroundId()); + return 1; + } + + /** + * Returns the [Player]s reputation rank of faction specified + * + * @param uint32 faction + * @return [ReputationRank] rank + */ + int GetReputationRank(lua_State* L, Player* player) + { + uint32 faction = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetReputationRank(faction)); + return 1; + } + + /** + * Returns the [Player]s current level of intoxication + * + * @return uint16 drunkValue + */ + int GetDrunkValue(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetDrunkValue()); + return 1; + } + + /** + * Returns skill temporary bonus value + * + * @param uint32 skill + * @param int16 bonusVal + */ + int GetSkillTempBonusValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); +#ifndef CATA + Eluna::Push(L, player->GetSkillBonusTemporary(skill)); +#else + Eluna::Push(L, player->GetSkillTempBonusValue(skill)); +#endif + return 1; + } + + /** + * Returns skill permanent bonus value + * + * @param uint32 skill + * @param int16 bonusVal + */ + int GetSkillPermBonusValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); +#ifndef CATA + Eluna::Push(L, player->GetSkillBonusPermanent(skill)); +#else + Eluna::Push(L, player->GetSkillPermBonusValue(skill)); +#endif + return 1; + } + + /** + * Returns skill value without bonus' + * + * @param uint32 skill + * @return uint16 pureVal + */ + int GetPureSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); +#ifndef CATA + Eluna::Push(L, player->GetSkillValuePure(skill)); +#else + Eluna::Push(L, player->GetPureSkillValue(skill)); +#endif + return 1; + } + + /** + * Returns base skill value + * + * @param uint32 skill + * @return uint16 baseVal + */ + int GetBaseSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); +#ifndef CATA + Eluna::Push(L, player->GetSkillValueBase(skill)); +#else + Eluna::Push(L, player->GetBaseSkillValue(skill)); +#endif + return 1; + } + + /** + * Returns skill value + * + * @param uint32 skill + * @return uint16 val + */ + int GetSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetSkillValue(skill)); + return 1; + } + + /** + * Returns max value of specified skill without bonus' + * + * @param uint32 skill + * @return uint16 pureVal + */ + int GetPureMaxSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); +#ifndef CATA + Eluna::Push(L, player->GetSkillMaxPure(skill)); +#else + Eluna::Push(L, player->GetPureMaxSkillValue(skill)); +#endif + return 1; + } + + /** + * Returns max value of specified skill + * + * @param uint32 skill + * @return uint16 val + */ + int GetMaxSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); +#ifndef CATA + Eluna::Push(L, player->GetSkillMax(skill)); +#else + Eluna::Push(L, player->GetMaxSkillValue(skill)); +#endif + return 1; + } + + /** + * Returns mana bonus from amount of intellect + * + * @return float bonus + */ + int GetManaBonusFromIntellect(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetManaBonusFromIntellect()); + return 1; + } + + /** + * Returns health bonus from amount of stamina + * + * @return float bonus + */ + int GetHealthBonusFromStamina(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetHealthBonusFromStamina()); + return 1; + } + + /** + * Returns raid or dungeon difficulty + * + * @param bool isRaid = true : argument is TrinityCore only + * @return int32 difficulty + */ + int GetDifficulty(lua_State* L, Player* player) + { +#ifdef TBC + Eluna::Push(L, player->GetDifficulty()); +#elif defined(CLASSIC) + Eluna::Push(L, (Difficulty)0); +#else + bool isRaid = Eluna::CHECKVAL(L, 2, true); + Eluna::Push(L, player->GetDifficulty(isRaid)); +#endif + return 1; + } + + /** + * Returns the [Player]s current guild rank + * + * @return uint32 guildRank + */ + int GetGuildRank(lua_State* L, Player* player) // TODO: Move to Guild Methods + { + Eluna::Push(L, player->GetRank()); + return 1; + } + + /** + * Returns the [Player]s free talent point amount + * + * @return uint32 freeTalentPointAmt + */ + int GetFreeTalentPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetFreeTalentPoints()); + return 1; + } + + /** + * Returns the name of the [Player]s current [Guild] + * + * @return string guildName + */ + int GetGuildName(lua_State* L, Player* player) + { + if (!player->GetGuildId()) + return 1; + Eluna::Push(L, eGuildMgr->GetGuildNameById(player->GetGuildId())); + return 1; + } + + /** + * Returns the amount of reputation the [Player] has with the faction specified + * + * @param uint32 faction + * @return int32 reputationAmt + */ + int GetReputation(lua_State* L, Player* player) + { + uint32 faction = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetReputationMgr().GetReputation(faction)); + return 1; + } + + /** + * Returns [Unit] target combo points are on + * + * @return [Unit] target + */ + int GetComboTarget(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetMap()->GetUnit(player->GetComboTargetGuid())); + return 1; + } + + /** + * Returns [Player]'s combo points + * + * @return uint8 comboPoints + */ + int GetComboPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetComboPoints()); + return 1; + } + + /** + * Returns the amount of time the [Player] has spent ingame + * + * @return uint32 inGameTime + */ + int GetInGameTime(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetInGameTime()); + return 1; + } + + /** + * Returns the status of the [Player]s [Quest] specified by entry ID + * + * @param uint32 questId + * @return [QuestStatus] questStatus + */ + int GetQuestStatus(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetQuestStatus(entry)); + return 1; + } + + /** + * Returns 'true' if the [Player]s [Quest] specified by entry ID has been rewarded, 'false' otherwise. + * + * @param uint32 questId + * @return bool questRewardStatus + */ + int GetQuestRewardStatus(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetQuestRewardStatus(questId)); + return 1; + } + + /** + * Returns [Quest] required [Creature] or [GameObject] count + * + * @param uint32 quest : entry of a quest + * @param int32 entry : entry of required [Creature] + * @return uint16 count + */ + int GetReqKillOrCastCurrentCount(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + int32 entry = Eluna::CHECKVAL(L, 3); + + Eluna::Push(L, player->GetReqKillOrCastCurrentCount(questId, entry)); + return 1; + } + + /** + * Returns the quest level of the [Player]s [Quest] specified by object + * + * @param uint32 questId + * @return [QuestStatus] questRewardStatus + */ + int GetQuestLevel(lua_State* L, Player* player) + { + Quest* quest = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, player->GetQuestLevelForPlayer(quest)); + return 1; + } + + /** + * Returns a [Player]s [Item] object by gear slot specified + * + * @param uint8 slot + * @return [Item] item + */ + int GetEquippedItemBySlot(lua_State* L, Player* player) + { + uint8 slot = Eluna::CHECKVAL(L, 2); + if (slot >= EQUIPMENT_SLOT_END) + return 1; + + Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); + Eluna::Push(L, item); + return 1; + } + + /** + * Returns the [Player]s current resting bonus + * + * @return float restBonus + */ + int GetRestBonus(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetRestBonus()); + return 1; + } + + /** + * Returns active GM chat tag + * + * @return uint8 tag + */ + int GetChatTag(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetChatTag()); + return 1; + } + + /** + * Returns an item in given bag on given slot. + * + *
+     * Possible and most commonly used combinations:
+     *
+     * bag = 255
+     * slots 0-18 equipment
+     * slots 19-22 equipped bag slots
+     * slots 23-38 backpack
+     * slots 39-66 bank main slots
+     * slots 67-74 bank bag slots
+     * slots 86-117 keyring
+     *
+     * bag = 19-22
+     * slots 0-35 for equipped bags
+     *
+     * bag = 67-74
+     * slots 0-35 for bank bags
+     * 
+ * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return [Item] item : [Item] or nil + */ + int GetItemByPos(lua_State* L, Player* player) + { + uint8 bag = Eluna::CHECKVAL(L, 2); + uint8 slot = Eluna::CHECKVAL(L, 3); + + Eluna::Push(L, player->GetItemByPos(bag, slot)); + return 1; + } + + /** + * Returns an [Item] from the player by guid. + * + * The item can be equipped, in bags or in bank. + * + * @param ObjectGuid guid : an item guid + * @return [Item] item + */ + int GetItemByGUID(lua_State* L, Player* player) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetItemByGuid(guid)); + return 1; + } + + /** + * Returns a mailed [Item] by guid. + * + * @param ObjectGuid guid : an item guid + * @return [Item] item + */ + int GetMailItem(lua_State* L, Player* player) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetMItem(guid.GetCounter())); + return 1; + } + + /** + * Returns an [Item] from the player by entry. + * + * The item can be equipped, in bags or in bank. + * + * @param uint32 entryId + * @return [Item] item + */ + int GetItemByEntry(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetItemByEntry(entry)); + return 1; + } + + /** + * Returns the database textID of the [WorldObject]'s gossip header text for the [Player] + * + * @param [WorldObject] object + * @return uint32 textId : key to npc_text database table + */ + int GetGossipTextId(lua_State* L, Player* player) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + Eluna::Push(L, player->GetGossipTextId(obj)); + return 1; + } + + /** + * Returns the [Player]s currently selected [Unit] object + * + * @return [Unit] unit + */ + int GetSelection(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetMap()->GetUnit(player->GetSelectionGuid())); + return 1; + } + + /** + * Returns the [Player]s GM Rank + * + * @return [AccountTypes] gmRank + */ + int GetGMRank(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetSecurity()); + return 1; + } + + /** + * Returns the [Player]s amount of money in copper + * + * @return uint32 coinage + */ + int GetCoinage(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetMoney()); + return 1; + } + + /** + * Returns the [Player]s current [Guild] ID + * + * @return uint32 guildId + */ + int GetGuildId(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetGuildId()); + return 1; + } + + /** + * Returns the [Player]s [TeamId] + * + * @return [TeamId] teamId + */ + int GetTeam(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetTeamId()); + return 1; + } + + /** + * Returns amount of the specified [Item] the [Player] has. + * + * @param uint32 entry : entry of the item + * @param bool checkinBank = false : also counts the items in player's bank if true + * @return uint32 itemamount + */ + int GetItemCount(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + bool checkinBank = Eluna::CHECKVAL(L, 3, false); + Eluna::Push(L, player->GetItemCount(entry, checkinBank)); + return 1; + } + + /** + * Returns the [Player]s lifetime Honorable Kills + * + * @return uint32 lifeTimeKils + */ + int GetLifetimeKills(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS)); + return 1; + } + + /** + * Returns the [Player]s IP address + * + * @return string ip + */ + int GetPlayerIP(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetRemoteAddress()); + return 1; + } + + /** + * Returns the [Player]s time played at current level + * + * @return uint32 currLevelPlayTime + */ + int GetLevelPlayedTime(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetLevelPlayedTime()); + return 1; + } + + /** + * Returns the [Player]s total time played + * + * @return uint32 totalPlayTime + */ + int GetTotalPlayedTime(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetTotalPlayedTime()); + return 1; + } + + /** + * Returns the [Player]s [Guild] object + * + * @return [Guild] guild + */ + int GetGuild(lua_State* L, Player* player) + { + Eluna::Push(L, eGuildMgr->GetGuildById(player->GetGuildId())); + return 1; + } + + /** + * Returns the [Player]s [Group] object + * + * @return [Group] group + */ + int GetGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetGroup()); + return 1; + } + + /** + * Returns the [Player]s account ID + * + * @return uint32 accountId + */ + int GetAccountId(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetAccountId()); + return 1; + } + + /** + * Returns the [Player]s account name + * + * @return string accountName + */ + int GetAccountName(lua_State* L, Player* player) + { + std::string accName; + if (eAccountMgr->GetName(player->GetSession()->GetAccountId(), accName)) + Eluna::Push(L, accName); + return 1; + } + + /** + * Returns the [Player]s [Corpse] object + * + * @return [Corpse] corpse + */ + int GetCorpse(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetCorpse()); + return 1; + } + + /** + * Returns the [Player]s database locale index + * + * @return int localeIndex + */ + int GetDbLocaleIndex(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetSessionDbLocaleIndex()); + return 1; + } + + /** + * Returns the [Player]s game client locale + * + * @return [LocaleConstant] locale + */ + int GetDbcLocale(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetSessionDbcLocale()); + return 1; + } + + /** + * Returns the amount of mails in the [Player]s mailbox + * + * @return uint32 count + */ + int GetMailCount(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetMailSize()); + return 1; + } + + /** + * Locks the player controls and disallows all movement and casting. + * + * @param bool apply = true : lock if true and unlock if false + */ + int SetPlayerLock(lua_State* L, Player* player) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + if (apply) + { + player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED | UNIT_FLAG_SILENCED); +#ifndef CATA + player->UpdateClientControl(player, 0); +#else + player->SetClientControl(player, 0); +#endif + } + else + { + player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED | UNIT_FLAG_SILENCED); +#ifndef CATA + player->UpdateClientControl(player, 1); +#else + player->SetClientControl(player, 1); +#endif + } + return 0; + } + + /** + * Sets the [Player]s login flag to the flag specified + * + * @param uint32 flag + */ + int SetAtLoginFlag(lua_State* L, Player* player) + { + uint32 flag = Eluna::CHECKVAL(L, 2); + + player->SetAtLoginFlag((AtLoginFlags)flag); + return 0; + } + + /** + * Sets the [Player]s sheathe state to the state specified + * + * @param uint32 sheatheState + */ + int SetSheath(lua_State* L, Player* player) + { + uint32 sheathed = Eluna::CHECKVAL(L, 2); + if (sheathed >= MAX_SHEATH_STATE) + return 0; + + player->SetSheath((SheathState)sheathed); + return 0; + } + + /** + * Sets the [Player]s intoxication level to the level specified + * + * @param uint8 drunkValue + */ + int SetDrunkValue(lua_State* L, Player* player) + { + uint8 newDrunkValue = Eluna::CHECKVAL(L, 2); + + player->SetDrunkValue(newDrunkValue); + return 0; + } + + /** + * Sets the [Player]s faction standing to that of the race specified + * + * @param uint8 raceId + */ + int SetFactionForRace(lua_State* L, Player* player) + { + uint8 race = Eluna::CHECKVAL(L, 2); + + player->setFactionForRace(race); + return 0; + } + + /** + * Sets (increases) skill of the [Player] + * + * @param uint16 id + * @param uint16 step + * @param uint16 currVal + * @param uint16 maxVal + */ + int SetSkill(lua_State* L, Player* player) + { + uint16 id = Eluna::CHECKVAL(L, 2); + uint16 step = Eluna::CHECKVAL(L, 3); + uint16 currVal = Eluna::CHECKVAL(L, 4); + uint16 maxVal = Eluna::CHECKVAL(L, 5); + + player->SetSkill(id, currVal, maxVal, step); + return 0; + } + + /** + * Sets the [Player]s guild rank to the rank specified + * + * @param uint8 rank + */ + int SetGuildRank(lua_State* L, Player* player) // TODO: Move to Guild Methods + { + uint8 rank = Eluna::CHECKVAL(L, 2); + + if (!player->GetGuildId()) + return 0; + + player->SetRank(rank); + return 0; + } + + /** + * Sets the [Player]s free talent points to the amount specified for the current spec + * + * @param uint32 talentPointAmt + */ + int SetFreeTalentPoints(lua_State* L, Player* player) + { + uint32 points = Eluna::CHECKVAL(L, 2); + + player->SetFreeTalentPoints(points); +#if (!defined(TBC) && !defined(CLASSIC)) + player->SendTalentsInfoData(false); +#endif + return 0; + } + + /** + * Sets the [Player]s reputation amount for the faction specified + * + * @param uint32 factionId + * @param int32 reputationValue + */ + int SetReputation(lua_State* L, Player* player) + { + uint32 faction = Eluna::CHECKVAL(L, 2); + int32 value = Eluna::CHECKVAL(L, 3); +#ifdef TBC + FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction); +#else + FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction); +#endif + player->GetReputationMgr().SetReputation(factionEntry, value); + return 0; + } + + /** + * Sets [Quest] state + * + * @param uint32 entry : entry of a quest + * @param uint32 status + */ + int SetQuestStatus(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + uint32 status = Eluna::CHECKVAL(L, 3); + if (status >= MAX_QUEST_STATUS) + return 0; + + player->SetQuestStatus(entry, (QuestStatus)status); + return 0; + } + + /** + * Sets the [Player]s rest bonus to the amount specified + * + * @param float restBonus + */ + int SetRestBonus(lua_State* L, Player* player) + { + float bonus = Eluna::CHECKVAL(L, 2); + + player->SetRestBonus(bonus); + return 0; + } + + /** + * Toggles whether the [Player] accepts whispers or not + * + * @param bool acceptWhispers = true + */ + int SetAcceptWhispers(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetAcceptWhispers(on); + return 0; + } + + /** + * Toggles PvP Death + * + * @param bool on = true + */ + int SetPvPDeath(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetPvPDeath(on); + return 0; + } + + /** + * Toggles whether the [Player] has GM visibility on or off + * + * @param bool gmVisible = true + */ + int SetGMVisible(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetGMVisible(on); + return 0; + } + + /** + * Toggles whether the [Player] has taxi cheat enabled or not + * + * @param bool taxiCheat = true + */ + int SetTaxiCheat(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetTaxiCheater(on); + return 0; + } + + /** + * Toggle Blizz (GM) tag + * + * @param bool on = true + */ + int SetGMChat(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetGMChat(on); + return 0; + } + + /** + * Toggles the [Player]s GM mode on or off + * + * @param bool setGmMode = true + */ + int SetGameMaster(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetGameMaster(on); + return 0; + } + + /** + * Sets the [Player]s gender to gender specified + * + * - GENDER_MALE = 0 + * - GENDER_FEMALE = 1 + * + * @param [Gender] gender + */ + int SetGender(lua_State* L, Player* player) + { + uint32 _gender = Eluna::CHECKVAL(L, 2); + + Gender gender; + switch (_gender) + { + case 0: + gender = GENDER_MALE; + break; + case 1: + gender = GENDER_FEMALE; + break; + default: + return luaL_argerror(L, 2, "valid Gender expected"); + } + + player->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender); + player->SetByteValue(PLAYER_BYTES_3, 0, gender); + player->InitDisplayIds(); + return 0; + } + +#if defined(TBC) || defined(WOTLK) + /** + * Sets the [Player]s Arena Points to the amount specified + * + * @param uint32 arenaPoints + */ + int SetArenaPoints(lua_State* L, Player* player) + { + uint32 arenaP = Eluna::CHECKVAL(L, 2); + player->SetArenaPoints(arenaP); + return 0; + } + + /** + * Sets the [Player]s Honor Points to the amount specified + * + * @param uint32 honorPoints + */ + int SetHonorPoints(lua_State* L, Player* player) + { + uint32 honorP = Eluna::CHECKVAL(L, 2); + player->SetHonorPoints(honorP); + return 0; + } +#endif + +#ifdef CLASSIC + /** + * Sets kills + * + * @param uint32 kills + * @param bool honorable = true : if victims were honorable + */ + int SetHonorStoredKills(lua_State* L, Player* player) + { + uint32 kills = Eluna::CHECKVAL(L, 2); + bool honorable = Eluna::CHECKVAL(L, 3, true); + + player->SetHonorStoredKills(kills, honorable); + return 0; + } + + /** + * Sets rank points + * + * @param float rankPoints + */ + int SetRankPoints(lua_State* L, Player* player) + { + float rankPoints = Eluna::CHECKVAL(L, 2); + + player->SetRankPoints(rankPoints); + return 0; + } + + /** + * Sets last week's honor standing position + * + * @param int32 standingPos + */ + int SetHonorLastWeekStandingPos(lua_State* L, Player* player) + { + int32 standingPos = Eluna::CHECKVAL(L, 2); + + player->SetHonorLastWeekStandingPos(standingPos); + return 0; + } +#endif + + /** + * Sets the [Player]s amount of Lifetime Honorable Kills to the value specified + * + * @param uint32 honorableKills + */ + int SetLifetimeKills(lua_State* L, Player* player) + { + uint32 val = Eluna::CHECKVAL(L, 2); + player->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, val); + return 0; + } + + /** + * Sets the [Player]s amount of money to copper specified + * + * @param uint32 copperAmt + */ + int SetCoinage(lua_State* L, Player* player) + { + uint32 amt = Eluna::CHECKVAL(L, 2); + player->SetMoney(amt); + return 0; + } + + /** + * Sets the [Player]s home location to the location specified + * + * @param float x : X Coordinate + * @param float y : Y Coordinate + * @param float z : Z Coordinate + * @param uint32 mapId : Map ID + * @param uint32 areaId : Area ID + */ + int SetBindPoint(lua_State* L, Player* player) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + uint32 mapId = Eluna::CHECKVAL(L, 5); + uint32 areaId = Eluna::CHECKVAL(L, 6); + + WorldLocation loc(mapId, x, y, z); + player->SetHomebindToLocation(loc, areaId); + return 0; + } + +#ifndef CLASSIC + /** + * Adds the specified title to the [Player]s list of known titles + * + * @param uint32 titleId + */ + int SetKnownTitle(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + CharTitlesEntry const* t = sCharTitlesStore.LookupEntry(id); + if (t) + player->SetTitle(t, false); + return 0; + } + +#endif + + /** + * Toggle the [Player]s FFA flag + * + * @param bool applyFFA = true + */ + int SetFFA(lua_State* L, Player* player) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + player->SetPvPFreeForAll(apply); + return 0; + } + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Resets the [Player]s pets talent points + */ + int ResetPetTalents(lua_State* /*L*/, Player* player) + { + Pet* pet = player->GetPet(); + Pet::resetTalentsForAllPetsOf(player, pet); + if (pet) + player->SendTalentsInfoData(true); + return 0; + } + + /** + * Reset the [Player]s completed achievements + */ + int ResetAchievements(lua_State* /*L*/, Player* player) + { + player->GetAchievementMgr().Reset(); + return 0; + } +#endif + + /** + * Shows the mailbox window to the player from specified guid. + * + * @param ObjectGuid guid = playerguid : guid of the mailbox window sender + */ + int SendShowMailBox(lua_State* L, Player* player) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2, player->GET_GUID()); + +#if (defined(CLASSIC) || defined(TBC)) + WorldPacket data(CMSG_GET_MAIL_LIST, 8); + data << guid; + player->GetSession()->HandleGetMailList(data); +#else + player->GetSession()->SendShowMailBox(guid); +#endif + return 0; + } + +#if defined(TBC) || defined(WOTLK) + /** + * Adds or detracts from the [Player]s current Arena Points + * + * @param int32 amount + */ + int ModifyArenaPoints(lua_State* L, Player* player) + { + int32 amount = Eluna::CHECKVAL(L, 2); + + player->ModifyArenaPoints(amount); + return 0; + } + + /** + * Adds or detracts from the [Player]s current Honor Points + * + * @param int32 amount + */ + int ModifyHonorPoints(lua_State* L, Player* player) + { + int32 amount = Eluna::CHECKVAL(L, 2); + + player->ModifyHonorPoints(amount); + return 0; + } +#endif + + /** + * Saves the [Player] to the database + */ + int SaveToDB(lua_State* /*L*/, Player* player) + { + player->SaveToDB(); + return 0; + } + + /** + * Sends a summon request to the player from the given summoner + * + * @param [Unit] summoner + */ + int SummonPlayer(lua_State* L, Player* player) + { + Unit* summoner = Eluna::CHECKOBJ(L, 2); + + float x, y, z; + summoner->GetPosition(x,y,z); +#ifndef CATA + player->SetSummonPoint(summoner->GetMapId(), x, y, z, summoner->GetMasterGuid()); +#else + player->SetSummonPoint(summoner->GetMapId(), x, y, z); +#endif + + WorldPacket data(SMSG_SUMMON_REQUEST, 8 + 4 + 4); + data << summoner->GET_GUID(); + data << uint32(summoner->GetZoneId()); + data << uint32(MAX_PLAYER_SUMMON_DELAY * IN_MILLISECONDS); + + player->GetSession()->SendPacket(data); + return 0; + } + + /** + * Mutes the [Player] for the amount of seconds specified + * + * @param uint32 muteTime + */ + int Mute(lua_State* L, Player* player) + { + uint32 muteseconds = Eluna::CHECKVAL(L, 2); + /*const char* reason = luaL_checkstring(E, 2);*/ // Mangos does not have a reason field in database. + + time_t muteTime = time(NULL) + muteseconds; + player->GetSession()->m_muteTime = muteTime; + std::ostringstream oss; + oss << "UPDATE account SET mutetime = " << muteTime << " WHERE id = " << player->GetSession()->GetAccountId(); + LoginDatabase.PExecute("%s", oss.str().c_str()); + return 0; + } + + /** + * Rewards the given quest entry for the [Player] if he has completed it. + * + * @param uint32 entry : quest entry + */ + int RewardQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* quest = eObjectMgr->GetQuestTemplate(entry); + + // If player doesn't have the quest + if (!quest || player->GetQuestStatus(entry) != QUEST_STATUS_COMPLETE) + return 0; + + player->RewardQuest(quest, 0, player); + return 0; + } + + /** + * Sends an auction house window to the [Player] from the [Unit] specified + * + * @param [Unit] sender + */ + int SendAuctionMenu(lua_State* L, Player* player) + { + Unit* unit = Eluna::CHECKOBJ(L, 2); + + AuctionHouseEntry const* ahEntry = AuctionHouseMgr::GetAuctionHouseEntry(unit); + if (!ahEntry) + return 0; + + WorldPacket data(MSG_AUCTION_HELLO, 12); + data << unit->GET_GUID(); + data << uint32(ahEntry->houseId); + data << uint8(1); + + player->GetSession()->SendPacket(data); + return 0; + } + + /** + * Sends a flightmaster window to the [Player] from the [Creature] specified + * + * @param [Creature] sender + */ + int SendTaxiMenu(lua_State* L, Player* player) + { + Creature* creature = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendTaxiMenu(creature); + return 0; + } + + /** + * Sends a spirit resurrection request to the [Player] + */ + int SendSpiritResurrect(lua_State* /*L*/, Player* player) + { + player->GetSession()->SendSpiritResurrect(); + return 0; + } + + /** + * Sends a tabard vendor window to the [Player] from the [WorldObject] specified + * + * @param [WorldObject] sender + */ + int SendTabardVendorActivate(lua_State* L, Player* player) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendTabardVendorActivate(obj->GET_GUID()); + return 0; + } + + /** + * Sends a bank window to the [Player] from the [WorldObject] specified. + * + * @param [WorldObject] sender + */ + int SendShowBank(lua_State* L, Player* player) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendShowBank(obj->GET_GUID()); + return 0; + } + + /** + * Sends a vendor window to the [Player] from the [WorldObject] specified. + * + * @param [WorldObject] sender + */ + int SendListInventory(lua_State* L, Player* player) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendListInventory(obj->GET_GUID()); + return 0; + } + + /** + * Sends a trainer window to the [Player] from the [Creature] specified + * + * @param [Creature] sender + */ + int SendTrainerList(lua_State* L, Player* player) + { + Creature* obj = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendTrainerList(obj->GET_GUID()); + return 0; + } + + /** + * Sends a guild invitation from the [Player]s [Guild] to the [Player] object specified + * + * @param [Player] invitee + */ + int SendGuildInvite(lua_State* L, Player* player) + { + Player* plr = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendGuildInvite(plr); + return 0; + } + + /** + * Sends an update for the world state to the [Player] + * + * @param uint32 field + * @param uint32 value + */ + int SendUpdateWorldState(lua_State* L, Player* player) + { + uint32 field = Eluna::CHECKVAL(L, 2); + uint32 value = Eluna::CHECKVAL(L, 3); + + player->SendUpdateWorldState(field, value); + return 0; + } + + /** + * Forces the [Player] to log out + * + * @param bool saveToDb = true + */ + int LogoutPlayer(lua_State* L, Player* player) + { + bool save = Eluna::CHECKVAL(L, 2, true); +#ifndef CATA + player->GetSession()->LogoutPlayer(); +#else + player->GetSession()->LogoutPlayer(save); +#endif + return 0; + } + + /** + * Forcefully removes the [Player] from a [BattleGround] raid group + */ + int RemoveFromBattlegroundRaid(lua_State* /*L*/, Player* player) + { + player->RemoveFromBattleGroundRaid(); + return 0; + } + + /** + * Unbinds the [Player] from his instances except the one he currently is in. + * + * Difficulty is not used on classic. + * + * @param uint32 map = true + * @param uint32 difficulty = 0 + */ + int UnbindInstance(lua_State* L, Player* player) + { + uint32 map = Eluna::CHECKVAL(L, 2); +#ifndef CLASSIC + uint32 difficulty = Eluna::CHECKVAL(L, 3, 0); + + if (difficulty < MAX_DIFFICULTY) + player->UnbindInstance(map, (Difficulty)difficulty); +#else//CLASSIC + player->UnbindInstance(map); +#endif + return 0; + } + + /** + * Unbinds the [Player] from his instances except the one he currently is in. + */ + int UnbindAllInstances(lua_State* /*L*/, Player* player) + { +#ifdef CLASSIC + Player::BoundInstancesMap& binds = player->GetBoundInstances(); + for (Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) + { + if (itr->first != player->GetMapId()) + player->UnbindInstance(itr); + else + ++itr; + } +#else + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Player::BoundInstancesMap& binds = player->GetBoundInstances(Difficulty(i)); + for (Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) + { + if (itr->first != player->GetMapId()) + player->UnbindInstance(itr, Difficulty(i)); + else + ++itr; + } + } +#endif + return 0; + } + + /** + * Forces the [Player] to leave a [BattleGround] + * + * @param bool teleToEntry = true + */ + int LeaveBattleground(lua_State* L, Player* player) + { + (void)L; // ensure that the variable is referenced in order to pass compiler checks + bool teleToEntryPoint = Eluna::CHECKVAL(L, 2, true); + player->LeaveBattleground(teleToEntryPoint); + return 0; + } + + /** + * Repairs [Item] at specified position. + * + * @param uint16 position + * @param bool cost = true + * @param float discountMod = 1.0 + */ + int DurabilityRepair(lua_State* L, Player* player) + { + uint16 position = Eluna::CHECKVAL(L, 2); + bool takeCost = Eluna::CHECKVAL(L, 3, true); + float discountMod = Eluna::CHECKVAL(L, 4, 1.0f); + +#ifdef CLASSIC + player->DurabilityRepair(position, takeCost, discountMod); +#else + player->DurabilityRepair(position, takeCost, discountMod, false); +#endif + return 0; + } + + /** + * Repairs all [Item]s. + * + * @param bool takeCost = true + * @param float discountMod = 1.0 + * @param bool guidBank = false + */ + int DurabilityRepairAll(lua_State* L, Player* player) + { + bool takeCost = Eluna::CHECKVAL(L, 2, true); + float discountMod = Eluna::CHECKVAL(L, 3, 1.0f); + bool guildBank = Eluna::CHECKVAL(L, 4, false); + +#ifdef CLASSIC + player->DurabilityRepairAll(takeCost, discountMod); +#else + player->DurabilityRepairAll(takeCost, discountMod, guildBank); +#endif + return 0; + } + + /** + * Sets durability loss for an [Item] in the specified slot + * + * @param int32 slot + */ + int DurabilityPointLossForEquipSlot(lua_State* L, Player* player) + { + int32 slot = Eluna::CHECKVAL(L, 2); + + if (slot >= EQUIPMENT_SLOT_START && slot < EQUIPMENT_SLOT_END) + player->DurabilityPointLossForEquipSlot((EquipmentSlots)slot); + return 0; + } + + /** + * Sets durability loss on all [Item]s equipped + * + * If inventory is true, sets durability loss for [Item]s in bags + * + * @param int32 points + * @param bool inventory = true + */ + int DurabilityPointsLossAll(lua_State* L, Player* player) + { + int32 points = Eluna::CHECKVAL(L, 2); + bool inventory = Eluna::CHECKVAL(L, 3, true); + + player->DurabilityPointsLossAll(points, inventory); + return 0; + } + + /** + * Sets durability loss for the specified [Item] + * + * @param [Item] item + * @param int32 points + */ + int DurabilityPointsLoss(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2); + int32 points = Eluna::CHECKVAL(L, 3); + + player->DurabilityPointsLoss(item, points); + return 0; + } + + /** + * Damages specified [Item] + * + * @param [Item] item + * @param double percent + */ + int DurabilityLoss(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2); + double percent = Eluna::CHECKVAL(L, 3); + + player->DurabilityLoss(item, percent); + return 0; + } + + /** + * Damages all [Item]s equipped. If inventory is true, damages [Item]s in bags + * + * @param double percent + * @param bool inventory = true + */ + int DurabilityLossAll(lua_State* L, Player* player) + { + double percent = Eluna::CHECKVAL(L, 2); + bool inventory = Eluna::CHECKVAL(L, 3, true); + + player->DurabilityLossAll(percent, inventory); + return 0; + } + + /** + * Kills the [Player] + */ + int KillPlayer(lua_State* /*L*/, Player* player) + { + player->KillPlayer(); + return 0; + } + + /** + * Forces the [Player] to leave a [Group] + */ + int RemoveFromGroup(lua_State* /*L*/, Player* player) + { + if (!player->GetGroup()) + return 0; + + player->RemoveFromGroup(); + return 0; + } + + /** + * Returns the [Player]s accumulated talent reset cost + * + * @return uint32 resetCost + */ + int ResetTalentsCost(lua_State* L, Player* player) + { + Eluna::Push(L, player->resetTalentsCost()); + return 1; + } + + /** + * Resets the [Player]s talents + * + * @param bool noCost = true + */ + int ResetTalents(lua_State* L, Player* player) + { + bool no_cost = Eluna::CHECKVAL(L, 2, true); + + player->resetTalents(no_cost); +#if (!defined(TBC) && !defined(CLASSIC)) + player->SendTalentsInfoData(false); +#endif + return 0; + } + + /** + * Removes the [Spell] from the [Player] + * + * @param uint32 entry : entry of a [Spell] + */ + int RemoveSpell(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->removeSpell(entry); + return 0; + } + + /** + * Clears the [Player]s combo points + */ + int ClearComboPoints(lua_State* /*L*/, Player* player) + { + player->ClearComboPoints(); + return 0; + } + + /** + * Adds combo points to the [Player] + * + * @param [Unit] target + * @param int8 count + */ + int AddComboPoints(lua_State* L, Player* player) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + int8 count = Eluna::CHECKVAL(L, 3); + + player->AddComboPoints(target, count); + return 0; + } + + /** + * Gives [Quest] monster talked to credit + * + * @param uint32 entry : entry of a [Creature] + * @param [Creature] creature + */ + int TalkedToCreature(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + Creature* creature = Eluna::CHECKOBJ(L, 3); + + player->TalkedToCreature(entry, creature->GET_GUID()); + return 0; + } + + /** + * Gives [Quest] monster killed credit + * + * @param uint32 entry : entry of a [Creature] + */ + int KilledMonsterCredit(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->KilledMonsterCredit(entry, player->GET_GUID()); + return 0; + } + + /** + * Completes a [Quest] if in a [Group] + * + * @param uint32 quest : entry of a quest + * @param [WorldObject] obj + */ + int GroupEventHappens(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + WorldObject* obj = Eluna::CHECKOBJ(L, 3); + + player->GroupEventHappens(questId, obj); + return 0; + } + + /** + * Completes the [Quest] if a [Quest] area is explored, or completes the [Quest] + * + * @param uint32 quest : entry of a [Quest] + */ + int AreaExploredOrEventHappens(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + + player->AreaExploredOrEventHappens(questId); + return 0; + } + + /** + * Sets the given [Quest] entry failed for the [Player]. + * + * @param uint32 entry : entry of a [Quest] + */ + int FailQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->FailQuest(entry); + return 0; + } + + /** + * Sets the given quest entry incomplete for the [Player]. + * + * @param uint32 entry : quest entry + */ + int IncompleteQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->IncompleteQuest(entry); + return 0; + } + + /** + * Completes the given quest entry for the [Player] and tries to satisfy all quest requirements. + * + * The player should have the quest to complete it. + * + * @param uint32 entry : quest entry + */ + int CompleteQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* quest = eObjectMgr->GetQuestTemplate(entry); + + // If player doesn't have the quest + if (!quest || player->GetQuestStatus(entry) == QUEST_STATUS_NONE) + return 0; + + // Add quest items for quests that require items + for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x) + { + uint32 id = quest->ReqItemId[x]; + uint32 count = quest->ReqItemCount[x]; + + if (!id || !count) + continue; + + uint32 curItemCount = player->GetItemCount(id, true); + + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count - curItemCount); + if (msg == EQUIP_ERR_OK) + { + Item* item = player->StoreNewItem(dest, id, true); + player->SendNewItem(item, count - curItemCount, true, false); + } + } + + // All creature/GO slain/cast (not required, but otherwise it will display "Creature slain 0/10") + for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) + { + int32 creature = quest->ReqCreatureOrGOId[i]; + uint32 creaturecount = quest->ReqCreatureOrGOCount[i]; + + if (uint32 spell_id = quest->ReqSpell[i]) + { + for (uint16 z = 0; z < creaturecount; ++z) + player->CastedCreatureOrGO(creature, ObjectGuid(), spell_id); + } + else if (creature > 0) + { + if (CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(creature)) + for (uint16 z = 0; z < creaturecount; ++z) +#ifndef CATA + player->KilledMonster(cInfo, nullptr); +#else + player->KilledMonster(cInfo, ObjectGuid()); +#endif + } + else if (creature < 0) + { + for (uint16 z = 0; z < creaturecount; ++z) + player->CastedCreatureOrGO(-creature, ObjectGuid(), 0); + } + } + + + // If the quest requires reputation to complete + if (uint32 repFaction = quest->GetRepObjectiveFaction()) + { + uint32 repValue = quest->GetRepObjectiveValue(); + uint32 curRep = player->GetReputationMgr().GetReputation(repFaction); + if (curRep < repValue) +#ifdef TBC + if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(repFaction)) +#else + if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(repFaction)) +#endif + player->GetReputationMgr().SetReputation(factionEntry, repValue); + } + + // If the quest requires money + int32 ReqOrRewMoney = quest->GetRewOrReqMoney(); + if (ReqOrRewMoney < 0) + player->ModifyMoney(-ReqOrRewMoney); + + player->CompleteQuest(entry); + return 0; + } + + /** + * Tries to add the given quest entry for the [Player]. + * + * @param uint32 entry : quest entry + */ + int AddQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* quest = eObjectMgr->GetQuestTemplate(entry); + + if (!quest) + return 0; + + // check item starting quest (it can work incorrectly if added without item in inventory) + for (uint32 id = 0; id < sItemStorage.GetMaxEntry(); ++id) + { + ItemPrototype const* pProto = sItemStorage.LookupEntry(id); + if (!pProto) + continue; + + if (pProto->StartQuest == entry) + return 0; + } + + // ok, normal (creature/GO starting) quest + if (player->CanAddQuest(quest, true)) + { + player->AddQuest(quest, NULL); + + if (player->CanCompleteQuest(entry)) + player->CompleteQuest(entry); + } + return 0; + } + + /** + * Removes the given quest entry from the [Player]. + * + * @param uint32 entry : quest entry + */ + int RemoveQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* quest = eObjectMgr->GetQuestTemplate(entry); + + if (!quest) + return 0; + + // remove all quest entries for 'entry' from quest log + for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot) + { + uint32 logQuest = player->GetQuestSlotQuestId(slot); + if (logQuest == entry) + { + player->SetQuestSlot(slot, 0); + + // we ignore unequippable quest items in this case, its' still be equipped + player->TakeQuestSourceItem(logQuest, false); + } + } + + // set quest status to not started (will updated in DB at next save) + player->SetQuestStatus(entry, QUEST_STATUS_NONE); + + // reset rewarded for restart repeatable quest + player->getQuestStatusMap()[entry].m_rewarded = false; + return 0; + } + + /** + * Sends whisper text from the [Player] + * + * @param string text + * @param uint32 lang : language the [Player] will speak + * @param [Player] receiver : is the [Player] that will receive the whisper, if TrinityCore + * @param ObjectGuid guid : is the GUID of a [Player] that will receive the whisper, not TrinityCore + */ + int Whisper(lua_State* L, Player* player) + { + std::string text = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); + ObjectGuid guid = Eluna::CHECKVAL(L, 4); + + player->Whisper(text, lang, guid); + return 0; + } + + /** + * Sends a text emote from the [Player] + * + * @param string emoteText + */ + int TextEmote(lua_State* L, Player* player) + { + std::string text = Eluna::CHECKVAL(L, 2); + + player->TextEmote(text); + return 0; + } + + /** + * Sends yell text from the [Player] + * + * @param string text : text for the [Player] to yells + * @param uint32 lang : language the [Player] will speak + */ + int Yell(lua_State* L, Player* player) + { + std::string text = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); + + player->Yell(text, lang); + return 0; + } + + /** + * Sends say text from the [Player] + * + * @param string text : text for the [Player] to say + * @param uint32 lang : language the [Player] will speak + */ + int Say(lua_State* L, Player* player) + { + std::string text = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); + + player->Say(text, lang); + return 0; + } + + /** + * Gives the [Player] experience + * + * @param uint32 xp : experience to give + * @param [Unit] victim = nil + */ + int GiveXP(lua_State* L, Player* player) + { + uint32 xp = Eluna::CHECKVAL(L, 2); + Unit* victim = Eluna::CHECKOBJ(L, 3, false); + + player->GiveXP(xp, nullptr); + return 0; + } + + /** + * Toggle the [Player]s 'Do Not Disturb' flag + */ + int ToggleDND(lua_State* /*L*/, Player* player) + { + player->ToggleDND(); + return 0; + } + + /** + * Toggle the [Player]s 'Away From Keyboard' flag + */ + int ToggleAFK(lua_State* /*L*/, Player* player) + { + player->ToggleAFK(); + return 0; + } + + /** + * Equips the given item or item entry to the given slot. Returns the equipped item or nil. + * + * enum EquipmentSlots // 19 slots + * { + * EQUIPMENT_SLOT_START = 0, + * EQUIPMENT_SLOT_HEAD = 0, + * EQUIPMENT_SLOT_NECK = 1, + * EQUIPMENT_SLOT_SHOULDERS = 2, + * EQUIPMENT_SLOT_BODY = 3, + * EQUIPMENT_SLOT_CHEST = 4, + * EQUIPMENT_SLOT_WAIST = 5, + * EQUIPMENT_SLOT_LEGS = 6, + * EQUIPMENT_SLOT_FEET = 7, + * EQUIPMENT_SLOT_WRISTS = 8, + * EQUIPMENT_SLOT_HANDS = 9, + * EQUIPMENT_SLOT_FINGER1 = 10, + * EQUIPMENT_SLOT_FINGER2 = 11, + * EQUIPMENT_SLOT_TRINKET1 = 12, + * EQUIPMENT_SLOT_TRINKET2 = 13, + * EQUIPMENT_SLOT_BACK = 14, + * EQUIPMENT_SLOT_MAINHAND = 15, + * EQUIPMENT_SLOT_OFFHAND = 16, + * EQUIPMENT_SLOT_RANGED = 17, + * EQUIPMENT_SLOT_TABARD = 18, + * EQUIPMENT_SLOT_END = 19 + * }; + * + * enum InventorySlots // 4 slots + * { + * INVENTORY_SLOT_BAG_START = 19, + * INVENTORY_SLOT_BAG_END = 23 + * }; + * + * @proto equippedItem = (item, slot) + * @proto equippedItem = (entry, slot) + * @param [Item] item : item to equip + * @param uint32 entry : entry of the item to equip + * @param uint32 slot : equipment slot to equip the item to The slot can be [EquipmentSlots] or [InventorySlots] + * @return [Item] equippedItem : item or nil if equipping failed + */ + int EquipItem(lua_State* L, Player* player) + { + uint16 dest = 0; + Item* item = Eluna::CHECKOBJ(L, 2, false); + uint32 slot = Eluna::CHECKVAL(L, 3); + + if (slot >= INVENTORY_SLOT_BAG_END) + return 1; + + if (!item) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + item = Item::CreateItem(entry, 1, player); + if (!item) + return 1; + + InventoryResult result = player->CanEquipItem(slot, dest, item, false); + if (result != EQUIP_ERR_OK) + { + delete item; + return 1; + } + player->ItemAddedQuestCheck(entry, 1); +#if (!defined(TBC) && !defined(CLASSIC)) + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, entry, 1); +#endif + } + else + { + InventoryResult result = player->CanEquipItem(slot, dest, item, false); + if (result != EQUIP_ERR_OK) + return 1; + player->RemoveItem(item->GetBagSlot(), item->GetSlot(), true); + } + + Eluna::Push(L, player->EquipItem(dest, item, true)); + player->AutoUnequipOffhandIfNeed(); + return 1; + } + + /** + * Returns true if the player can equip the given [Item] or item entry to the given slot, false otherwise. + * + * @proto canEquip = (item, slot) + * @proto canEquip = (entry, slot) + * @param [Item] item : item to equip + * @param uint32 entry : entry of the item to equip + * @param uint32 slot : equipment slot to test + * @return bool canEquip + */ + int CanEquipItem(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2, false); + uint32 slot = Eluna::CHECKVAL(L, 3); + if (slot >= EQUIPMENT_SLOT_END) + { + Eluna::Push(L, false); + return 1; + } + + if (!item) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + uint16 dest; + InventoryResult msg = player->CanEquipNewItem(slot, dest, entry, false); + if (msg != EQUIP_ERR_OK) + { + Eluna::Push(L, false); + return 1; + } + } + else + { + uint16 dest; + InventoryResult msg = player->CanEquipItem(slot, dest, item, false); + if (msg != EQUIP_ERR_OK) + { + Eluna::Push(L, false); + return 1; + } + } + Eluna::Push(L, true); + return 1; + } + +#ifndef CLASSIC + /** + * Removes a title by ID from the [Player]s list of known titles + * + * @param uint32 titleId + */ + int UnsetKnownTitle(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + CharTitlesEntry const* t = sCharTitlesStore.LookupEntry(id); + if (t) + player->SetTitle(t, true); + return 0; + } +#endif + + /** + * Advances all of the [Player]s weapon skills to the maximum amount available + */ + int AdvanceSkillsToMax(lua_State* /*L*/, Player* player) + { + player->UpdateSkillsToMaxSkillsForLevel(); + return 0; + } + + /** + * Advances all of the [Player]s skills to the amount specified + * + * @param uint32 skillStep + */ + int AdvanceAllSkills(lua_State* L, Player* player) + { + uint32 step = Eluna::CHECKVAL(L, 2); + + if (!step) + return 0; + + for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i) + { + if (SkillLineEntry const* entry = sSkillLineStore.LookupEntry(i)) + { + if (entry->categoryId == SKILL_CATEGORY_LANGUAGES || entry->categoryId == SKILL_CATEGORY_GENERIC) + continue; + + if (player->HasSkill(entry->id)) + player->UpdateSkill(entry->id, step); + } + } + + return 0; + } + + /** + * Advances a [Player]s specific skill to the amount specified + * + * @param uint32 skillId + * @param uint32 skillStep + */ + int AdvanceSkill(lua_State* L, Player* player) + { + uint32 _skillId = Eluna::CHECKVAL(L, 2); + uint32 _step = Eluna::CHECKVAL(L, 3); + if (_skillId && _step) + { + if (player->HasSkill(_skillId)) + player->UpdateSkill(_skillId, _step); + } + return 0; + } + + /** + * Teleports a [Player] to the location specified + * + * @param uint32 mappId + * @param float xCoord + * @param float yCoord + * @param float zCoord + * @param float orientation + */ + int Teleport(lua_State* L, Player* player) + { + uint32 mapId = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + +#if !defined(CATA) + if (player->IsTaxiFlying()) + player->TaxiFlightInterrupt(); + else + player->SaveRecallPosition(); +#else + if (player->IsTaxiFlying()) + { + player->GetMotionMaster()->MovementExpired(); + player->m_taxi.ClearTaxiDestinations(); + } +#endif + Eluna::Push(L, player->TeleportTo(mapId, x, y, z, o)); + return 1; + } + + int AddLifetimeKills(lua_State* L, Player* player) + { + uint32 val = Eluna::CHECKVAL(L, 2); + uint32 currentKills = player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS); + player->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, currentKills + val); + return 0; + } + + /** + * Adds the given amount of the specified item entry to the player. + * + * @param uint32 entry : entry of the item to add + * @param uint32 itemCount = 1 : amount of the item to add + * @return [Item] item : the item that was added or nil + */ + int AddItem(lua_State* L, Player* player) + { + uint32 itemId = Eluna::CHECKVAL(L, 2); + uint32 itemCount = Eluna::CHECKVAL(L, 3, 1); + + Eluna::Push(L, player->StoreNewItemInInventorySlot(itemId, itemCount)); + return 1; + } + + /** + * Removes the given amount of the specified [Item] from the player. + * + * @proto (item, itemCount) + * @proto (entry, itemCount) + * @param [Item] item : item to remove + * @param uint32 entry : entry of the item to remove + * @param uint32 itemCount = 1 : amount of the item to remove + */ + int RemoveItem(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2, false); + uint32 itemCount = Eluna::CHECKVAL(L, 3); + if (!item) + { + uint32 itemId = Eluna::CHECKVAL(L, 2); + player->DestroyItemCount(itemId, itemCount, true); + } + else + { + bool all = itemCount >= item->GetCount(); + player->DestroyItemCount(item, itemCount, true); + if (all) + Eluna::CHECKOBJ(L, 2)->Invalidate(); + } + return 0; + } + + /** + * Removes specified amount of lifetime kills + * + * @param uint32 val : kills to remove + */ + int RemoveLifetimeKills(lua_State* L, Player* player) + { + uint32 val = Eluna::CHECKVAL(L, 2); + uint32 currentKills = player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS); + if (val > currentKills) + val = currentKills; + player->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, currentKills - val); + return 0; + } + + /** + * Resets cooldown of the specified spell + * + * @param uint32 spellId + * @param bool update = true + */ + int ResetSpellCooldown(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + bool update = Eluna::CHECKVAL(L, 3, true); + + player->RemoveSpellCooldown(spellId, update); + return 0; + } + + /** + * Resets cooldown of the specified category + * + * @param uint32 category + * @param bool update = true + */ + int ResetTypeCooldowns(lua_State* L, Player* player) + { + uint32 category = Eluna::CHECKVAL(L, 2); + bool update = Eluna::CHECKVAL(L, 3, true); + (void)update; // ensure that the variable is referenced in order to pass compiler checks + + player->RemoveSpellCategoryCooldown(category, update); + return 0; + } + + /** + * Resets all of the [Player]'s cooldowns + */ + int ResetAllCooldowns(lua_State* /*L*/, Player* player) + { + player->RemoveAllCooldowns(); + return 0; + } + + /** + * Sends a Broadcast Message to the [Player] + * + * @param string message + */ + int SendBroadcastMessage(lua_State* L, Player* player) + { + const char* message = Eluna::CHECKVAL(L, 2); + if (std::string(message).length() > 0) + ChatHandler(player->GetSession()).SendSysMessage(message); + return 0; + } + + /** + * Sends an Area Trigger Message to the [Player] + * + * @param string message + */ + int SendAreaTriggerMessage(lua_State* L, Player* player) + { + std::string msg = Eluna::CHECKVAL(L, 2); + if (msg.length() > 0) + player->GetSession()->SendAreaTriggerMessage("%s", msg.c_str()); + return 0; + } + + /** + * Sends a Notification to the [Player] + * + * @param string message + */ + int SendNotification(lua_State* L, Player* player) + { + std::string msg = Eluna::CHECKVAL(L, 2); + if (msg.length() > 0) + player->GetSession()->SendNotification("%s", msg.c_str()); + return 0; + } + + /** + * Sends a [WorldPacket] to the [Player] + * + * @param [WorldPacket] packet + * @param bool selfOnly = true + */ + int SendPacket(lua_State* L, Player* player) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + bool selfOnly = Eluna::CHECKVAL(L, 3, true); + + if (selfOnly) + player->GetSession()->SendPacket(*data); + else + player->SendMessageToSet(*data, true); + return 0; + } + + /** + * Sends addon message to the [Player] receiver + * + * @param string prefix + * @param string message + * @param [ChatMsg] channel + * @param [Player] receiver + * + */ + int SendAddonMessage(lua_State* L, Player* player) + { + std::string prefix = Eluna::CHECKVAL(L, 2); + std::string message = Eluna::CHECKVAL(L, 3); + uint8 channel = Eluna::CHECKVAL(L, 4); + Player* receiver = Eluna::CHECKOBJ(L, 5); + + std::string fullmsg = prefix + "\t" + message; + + WorldPacket data(SMSG_MESSAGECHAT, 100); + data << uint8(channel); + data << int32(LANG_ADDON); + data << player->GET_GUID(); +#ifndef CLASSIC + data << uint32(0); + data << receiver->GET_GUID(); +#endif + data << uint32(fullmsg.length() + 1); + data << fullmsg; + data << uint8(0); + + receiver->GetSession()->SendPacket(data); + return 0; + } + + /** + * Kicks the [Player] from the server + */ + int KickPlayer(lua_State* /*L*/, Player* player) + { + player->GetSession()->KickPlayer(); + return 0; + } + + /** + * Adds or subtracts from the [Player]s money in copper + * + * @param int32 copperAmt : negative to remove, positive to add + */ + int ModifyMoney(lua_State* L, Player* player) + { + int32 amt = Eluna::CHECKVAL(L, 2); + + player->ModifyMoney(amt); + return 1; + } + + /** + * Teaches the [Player] the [Spell] specified by entry ID + * + * @param uint32 spellId + */ + int LearnSpell(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + + player->learnSpell(id, false); + return 0; + } + + /** + * Learn the [Player] the talent specified by talent_id and talentRank + * + * @param uint32 talent_id + * @param uint32 talentRank + */ + int LearnTalent(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + uint32 rank = Eluna::CHECKVAL(L, 3); + + player->LearnTalent(id, rank); +#if (!defined(TBC) && !defined(CLASSIC)) + player->SendTalentsInfoData(false); +#endif + + // if player has a pet, update owner talent auras + if (player->GetPet()) + player->GetPet()->CastOwnerTalentAuras(); + return 0; + } + +#if !defined(CLASSIC) + /** + * Remove cooldowns on spells that have less than 10 minutes of cooldown from the [Player], similarly to when you enter an arena. + */ + int RemoveArenaSpellCooldowns(lua_State* /*L*/, Player* player) + { + player->RemoveArenaSpellCooldowns(); + return 0; + } +#endif + + /** + * Resurrects the [Player]. + * + * @param float healthPercent = 100.0f + * @param bool ressSickness = false + */ + int ResurrectPlayer(lua_State* L, Player* player) + { + float percent = Eluna::CHECKVAL(L, 2, 100.0f); + bool sickness = Eluna::CHECKVAL(L, 3, false); + player->ResurrectPlayer(percent, sickness); + player->SpawnCorpseBones(); + return 0; + } + + /** + * Adds a new item to the gossip menu shown to the [Player] on next call to [Player:GossipSendMenu]. + * + * sender and intid are numbers which are passed directly to the gossip selection handler. Internally they are partly used for the database gossip handling. + * code specifies whether to show a box to insert text to. The player inserted text is passed to the gossip selection handler. + * money specifies an amount of money the player needs to have to click the option. An error message is shown if the player doesn't have enough money. + * Note that the money amount is only checked client side and is not removed from the player either. You will need to check again in your code before taking action. + * + * See also: [Player:GossipSendMenu], [Player:GossipAddQuests], [Player:GossipComplete], [Player:GossipClearMenu] + * + * @param uint32 icon : number that specifies used icon + * @param string msg : label on the gossip item + * @param uint32 sender : number passed to gossip handlers + * @param uint32 intid : number passed to gossip handlers + * @param bool code = false : show text input on click if true + * @param string popup = nil : if non empty string, a popup with given text shown on click + * @param uint32 money = 0 : required money in copper + */ + int GossipMenuAddItem(lua_State* L, Player* player) + { + uint32 _icon = Eluna::CHECKVAL(L, 2); + const char* msg = Eluna::CHECKVAL(L, 3); + uint32 _sender = Eluna::CHECKVAL(L, 4); + uint32 _intid = Eluna::CHECKVAL(L, 5); + bool _code = Eluna::CHECKVAL(L, 6, false); + const char* _promptMsg = Eluna::CHECKVAL(L, 7, ""); + uint32 _money = Eluna::CHECKVAL(L, 8, 0); +#if !defined(CLASSIC) && !defined(CATA) + player->GetPlayerMenu()->GetGossipMenu().AddMenuItem(_icon, msg, _sender, _intid, _promptMsg, _money, _code); +#elif defined(CLASSIC) + player->GetPlayerMenu()->GetGossipMenu().AddMenuItem(_icon, msg, _sender, _intid, _promptMsg, _code); +#elif defined(CATA) + player->PlayerTalkClass->GetGossipMenu().AddMenuItem(_icon, msg, _sender, _intid, _promptMsg, _money, _code); +#endif + return 0; + } + + /** + * Closes the [Player]s currently open Gossip Menu. + * + * See also: [Player:GossipMenuAddItem], [Player:GossipAddQuests], [Player:GossipSendMenu], [Player:GossipClearMenu] + */ + int GossipComplete(lua_State* /*L*/, Player* player) + { +#if !defined(CATA) + player->GetPlayerMenu()->CloseGossip(); +#else + player->PlayerTalkClass->CloseGossip(); +#endif + return 0; + } + + /** + * Sends the current gossip items of the player to him as a gossip menu with header text from the given textId. + * + * If sender is a [Player] then menu_id is mandatory, otherwise it is not used for anything. + * menu_id is the ID used to trigger the OnGossipSelect registered for players. See [Global:RegisterPlayerGossipEvent] + * + * See also: [Player:GossipMenuAddItem], [Player:GossipAddQuests], [Player:GossipComplete], [Player:GossipClearMenu] + * + * @proto (npc_text, sender) + * @proto (npc_text, sender, menu_id) + * @param uint32 npc_text : entry ID of a header text in npc_text database table, common default is 100 + * @param [Object] sender : object acting as the source of the sent gossip menu + * @param uint32 menu_id : if sender is a [Player] then menu_id is mandatory + */ + int GossipSendMenu(lua_State* L, Player* player) + { + uint32 npc_text = Eluna::CHECKVAL(L, 2); + Object* sender = Eluna::CHECKOBJ(L, 3); + if (sender->GetTypeId() == TYPEID_PLAYER) + { + uint32 menu_id = Eluna::CHECKVAL(L, 4); +#ifndef CATA + player->GetPlayerMenu()->GetGossipMenu().SetMenuId(menu_id); +#else + player->PlayerTalkClass->GetGossipMenu().SetMenuId(menu_id); +#endif + } +#ifndef CATA + player->GetPlayerMenu()->SendGossipMenu(npc_text, sender->GET_GUID()); +#else + player->PlayerTalkClass->SendGossipMenu(npc_text, sender->GET_GUID()); +#endif + return 0; + } + + /** + * Clears the [Player]s current gossip item list. + * + * See also: [Player:GossipMenuAddItem], [Player:GossipSendMenu], [Player:GossipAddQuests], [Player:GossipComplete] + * + * Note: This is needed when you show a gossip menu without using gossip hello or select hooks which do this automatically. + * Usually this is needed when using [Player] is the sender of a Gossip Menu. + */ + int GossipClearMenu(lua_State* /*L*/, Player* player) + { +#ifndef CATA + player->GetPlayerMenu()->ClearMenus(); +#else + player->PlayerTalkClass->ClearMenus(); +#endif + return 0; + } + + /** + * Attempts to start the taxi/flying to the given pathID + * + * @param uint32 pathId : pathId from DBC or [Global:AddTaxiPath] + */ + int StartTaxi(lua_State* L, Player* player) + { + uint32 pathId = Eluna::CHECKVAL(L, 2); + + player->ActivateTaxiPathTo(pathId); + return 0; + } + + /** + * Sends POI to the location on your map + * + * @param float x + * @param float y + * @param uint32 icon : map icon to show + * @param uint32 flags + * @param uint32 data + * @param string iconText + */ + int GossipSendPOI(lua_State* L, Player* player) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + uint32 icon = Eluna::CHECKVAL(L, 4); + uint32 flags = Eluna::CHECKVAL(L, 5); + uint32 data = Eluna::CHECKVAL(L, 6); + std::string iconText = Eluna::CHECKVAL(L, 7); + + WorldPacket packet(SMSG_GOSSIP_POI, 4 + 4 + 4 + 4 + 4 + 10); + packet << flags; + packet << x; + packet << y; + packet << icon; + packet << data; + packet << iconText; + + player->GetSession()->SendPacket(packet); + return 0; + } + + /** + * Adds the gossip items to the [Player]'s gossip for the quests the given [WorldObject] can offer to the player. + * + * @param [WorldObject] source : a questgiver with quests + */ + int GossipAddQuests(lua_State* L, Player* player) + { + WorldObject* source = Eluna::CHECKOBJ(L, 2); + + if (source->GetTypeId() == TYPEID_UNIT) + { + if (source->GetUInt32Value(UNIT_NPC_FLAGS) & UNIT_NPC_FLAG_QUESTGIVER) + player->PrepareQuestMenu(source->GET_GUID()); + } + else if (source->GetTypeId() == TYPEID_GAMEOBJECT) + { + if (source->ToGameObject()->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + player->PrepareQuestMenu(source->GET_GUID()); + } + return 0; + } + + /** + * Shows a quest accepting window to the [Player] for the given quest. + * + * @param uint32 questId : entry of a quest + * @param bool activateAccept = true : auto finish the quest + */ + int SendQuestTemplate(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + bool activateAccept = Eluna::CHECKVAL(L, 3, true); + + Quest const* quest = eObjectMgr->GetQuestTemplate(questId); + if (!quest) + return 0; + +#ifndef CATA + player->GetPlayerMenu()->SendQuestGiverQuestDetails(quest, player->GET_GUID(), activateAccept); +#else + player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, player->GET_GUID(), activateAccept); +#endif + return 0; + } + + /** + * Converts [Player]'s corpse to bones + */ + int SpawnBones(lua_State* /*L*/, Player* player) + { + player->SpawnCorpseBones(); + return 0; + } + + /** + * Loots [Player]'s bones for insignia + * + * @param [Player] looter + */ + int RemovedInsignia(lua_State* L, Player* player) + { + Player* looter = Eluna::CHECKOBJ(L, 2); + player->RemovedInsignia(looter); + return 0; + } + + /** + * Makes the [Player] invite another player to a group. + * + * @param [Player] invited : player to invite to group + * @return bool success : true if the player was invited to a group + */ + int GroupInvite(lua_State* L, Player* player) + { + Player* invited = Eluna::CHECKOBJ(L, 2); + + if (invited->GetGroup() || invited->GetGroupInvite()) + { + Eluna::Push(L, false); + return 1; + } + + // Get correct existing group if any + Group* group = player->GetGroup(); + + if (group && group->IsBattleGroup()) + group = player->GetOriginalGroup(); + + bool success = false; + + // Try invite if group found + if (group) + success = !group->IsFull() && group->AddInvite(invited); + else + { + // Create new group if one not found + group = new Group; + success = group->AddLeaderInvite(player) && group->AddInvite(invited); + if (!success) + delete group; + } + + if (success) + { +#if defined(CLASSIC) || defined(TBC) + WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size + data << player->GetName(); + invited->GetSession()->SendPacket(data); +#else + WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size + data << uint8(1); // invited/already in group flag + data << player->GetName(); // max len 48 + data << uint32(0); // unk + data << uint8(0); // count + data << uint32(0); // unk + invited->GetSession()->SendPacket(data); +#endif + } + + Eluna::Push(L, success); + return 1; + } + + /** + * Creates a new [Group] with the creator [Player] as leader. + * + * @param [Player] invited : player to add to group + * @return [Group] createdGroup : the created group or nil + */ + int GroupCreate(lua_State* L, Player* player) + { + Player* invited = Eluna::CHECKOBJ(L, 2); + + if (player->GetGroup() || invited->GetGroup()) + return 0; + + if (player->GetGroupInvite()) + player->UninviteFromGroup(); + if (invited->GetGroupInvite()) + invited->UninviteFromGroup(); + + // Try create new group + Group* group = new Group; + if (!group->AddLeaderInvite(player)) + { + delete group; + return 0; + } + + // Forming a new group, create it + if (!group->IsCreated()) + { + group->RemoveInvite(player); + if (!group->Create(group->GetLeaderGuid(), group->GetLeaderName())) + return 0; + sObjectMgr.AddGroup(group); + } + + if (!group->AddMember(invited->GetObjectGuid(), invited->GetName())) + return 0; + + Eluna::Push(L, group); + return 1; + } + + /** + * Starts a cinematic for the [Player] + * + * @param uint32 CinematicSequenceId : entry of a cinematic + */ + int SendCinematicStart(lua_State* L, Player* player) + { + uint32 CinematicSequenceId = Eluna::CHECKVAL(L, 2); + + player->SendCinematicStart(CinematicSequenceId); + return 0; + } + +#if !defined(CLASSIC) && !defined(TBC) + /** + * Starts a movie for the [Player] + * + * @param uint32 MovieId : entry of a movie + */ + int SendMovieStart(lua_State* L, Player* player) + { + uint32 MovieId = Eluna::CHECKVAL(L, 2); + + player->SendMovieStart(MovieId); + return 0; + } +#endif + + ElunaRegister PlayerMethods[] = + { + // Getters + { "GetSelection", &LuaPlayer::GetSelection }, + { "GetGMRank", &LuaPlayer::GetGMRank }, + { "GetGuildId", &LuaPlayer::GetGuildId }, + { "GetCoinage", &LuaPlayer::GetCoinage }, + { "GetTeam", &LuaPlayer::GetTeam }, + { "GetItemCount", &LuaPlayer::GetItemCount }, + { "GetGroup", &LuaPlayer::GetGroup }, + { "GetGuild", &LuaPlayer::GetGuild }, + { "GetAccountId", &LuaPlayer::GetAccountId }, + { "GetAccountName", &LuaPlayer::GetAccountName }, + { "GetLifetimeKills", &LuaPlayer::GetLifetimeKills }, + { "GetPlayerIP", &LuaPlayer::GetPlayerIP }, + { "GetLevelPlayedTime", &LuaPlayer::GetLevelPlayedTime }, + { "GetTotalPlayedTime", &LuaPlayer::GetTotalPlayedTime }, + { "GetItemByPos", &LuaPlayer::GetItemByPos }, + { "GetItemByEntry", &LuaPlayer::GetItemByEntry }, + { "GetItemByGUID", &LuaPlayer::GetItemByGUID }, + { "GetMailItem", &LuaPlayer::GetMailItem }, + { "GetReputation", &LuaPlayer::GetReputation }, + { "GetEquippedItemBySlot", &LuaPlayer::GetEquippedItemBySlot }, + { "GetQuestLevel", &LuaPlayer::GetQuestLevel }, + { "GetChatTag", &LuaPlayer::GetChatTag }, + { "GetRestBonus", &LuaPlayer::GetRestBonus }, + { "GetReqKillOrCastCurrentCount", &LuaPlayer::GetReqKillOrCastCurrentCount }, + { "GetQuestStatus", &LuaPlayer::GetQuestStatus }, + { "GetInGameTime", &LuaPlayer::GetInGameTime }, + { "GetComboPoints", &LuaPlayer::GetComboPoints }, + { "GetComboTarget", &LuaPlayer::GetComboTarget }, + { "GetGuildName", &LuaPlayer::GetGuildName }, + { "GetFreeTalentPoints", &LuaPlayer::GetFreeTalentPoints }, + { "GetSpellCooldownDelay", &LuaPlayer::GetSpellCooldownDelay }, + { "GetGuildRank", &LuaPlayer::GetGuildRank }, + { "GetDifficulty", &LuaPlayer::GetDifficulty }, + { "GetHealthBonusFromStamina", &LuaPlayer::GetHealthBonusFromStamina }, + { "GetManaBonusFromIntellect", &LuaPlayer::GetManaBonusFromIntellect }, + { "GetMaxSkillValue", &LuaPlayer::GetMaxSkillValue }, + { "GetPureMaxSkillValue", &LuaPlayer::GetPureMaxSkillValue }, + { "GetSkillValue", &LuaPlayer::GetSkillValue }, + { "GetBaseSkillValue", &LuaPlayer::GetBaseSkillValue }, + { "GetPureSkillValue", &LuaPlayer::GetPureSkillValue }, + { "GetSkillPermBonusValue", &LuaPlayer::GetSkillPermBonusValue }, + { "GetSkillTempBonusValue", &LuaPlayer::GetSkillTempBonusValue }, + { "GetReputationRank", &LuaPlayer::GetReputationRank }, + { "GetDrunkValue", &LuaPlayer::GetDrunkValue }, + { "GetBattlegroundId", &LuaPlayer::GetBattlegroundId }, + { "GetBattlegroundTypeId", &LuaPlayer::GetBattlegroundTypeId }, + { "GetXPRestBonus", &LuaPlayer::GetXPRestBonus }, + { "GetGroupInvite", &LuaPlayer::GetGroupInvite }, + { "GetSubGroup", &LuaPlayer::GetSubGroup }, + { "GetNextRandomRaidMember", &LuaPlayer::GetNextRandomRaidMember }, + { "GetOriginalGroup", &LuaPlayer::GetOriginalGroup }, + { "GetOriginalSubGroup", &LuaPlayer::GetOriginalSubGroup }, + { "GetLatency", &LuaPlayer::GetLatency }, + { "GetDbLocaleIndex", &LuaPlayer::GetDbLocaleIndex }, + { "GetDbcLocale", &LuaPlayer::GetDbcLocale }, + { "GetCorpse", &LuaPlayer::GetCorpse }, + { "GetGossipTextId", &LuaPlayer::GetGossipTextId }, + { "GetQuestRewardStatus", &LuaPlayer::GetQuestRewardStatus }, +#if defined(TBC) || defined(WOTLK) + { "GetArenaPoints", &LuaPlayer::GetArenaPoints }, + { "GetHonorPoints", &LuaPlayer::GetHonorPoints }, +#endif +#if defined(WOTLK) + { "GetPhaseMaskForSpawn", &LuaPlayer::GetPhaseMaskForSpawn }, + { "GetActiveSpec", &LuaPlayer::GetActiveSpec }, + { "GetSpecsCount", &LuaPlayer::GetSpecsCount }, +#endif +#ifndef CATA + { "GetShieldBlockValue", &LuaPlayer::GetShieldBlockValue }, +#endif + { "GetMailCount", &LuaPlayer::GetMailCount }, + + // Setters + { "AdvanceSkillsToMax", &LuaPlayer::AdvanceSkillsToMax }, + { "AdvanceSkill", &LuaPlayer::AdvanceSkill }, + { "AdvanceAllSkills", &LuaPlayer::AdvanceAllSkills }, + { "AddLifetimeKills", &LuaPlayer::AddLifetimeKills }, + { "SetCoinage", &LuaPlayer::SetCoinage }, + { "SetBindPoint", &LuaPlayer::SetBindPoint }, + { "SetLifetimeKills", &LuaPlayer::SetLifetimeKills }, + { "SetGameMaster", &LuaPlayer::SetGameMaster }, + { "SetGMChat", &LuaPlayer::SetGMChat }, + { "SetTaxiCheat", &LuaPlayer::SetTaxiCheat }, + { "SetGMVisible", &LuaPlayer::SetGMVisible }, + { "SetPvPDeath", &LuaPlayer::SetPvPDeath }, + { "SetAcceptWhispers", &LuaPlayer::SetAcceptWhispers }, + { "SetRestBonus", &LuaPlayer::SetRestBonus }, + { "SetQuestStatus", &LuaPlayer::SetQuestStatus }, + { "SetReputation", &LuaPlayer::SetReputation }, + { "SetFreeTalentPoints", &LuaPlayer::SetFreeTalentPoints }, + { "SetGuildRank", &LuaPlayer::SetGuildRank }, + { "SetSkill", &LuaPlayer::SetSkill }, + { "SetFactionForRace", &LuaPlayer::SetFactionForRace }, + { "SetDrunkValue", &LuaPlayer::SetDrunkValue }, + { "SetAtLoginFlag", &LuaPlayer::SetAtLoginFlag }, + { "SetPlayerLock", &LuaPlayer::SetPlayerLock }, + { "SetGender", &LuaPlayer::SetGender }, + { "SetSheath", &LuaPlayer::SetSheath }, +#if defined(TBC) || defined(WOTLK) + { "SetKnownTitle", &LuaPlayer::SetKnownTitle }, + { "UnsetKnownTitle", &LuaPlayer::UnsetKnownTitle }, + { "SetArenaPoints", &LuaPlayer::SetArenaPoints }, + { "SetHonorPoints", &LuaPlayer::SetHonorPoints }, +#endif + + // Boolean + { "IsInGroup", &LuaPlayer::IsInGroup }, + { "IsInGuild", &LuaPlayer::IsInGuild }, + { "IsGM", &LuaPlayer::IsGM }, + { "IsImmuneToDamage", &LuaPlayer::IsImmuneToDamage }, + { "IsAlliance", &LuaPlayer::IsAlliance }, + { "IsHorde", &LuaPlayer::IsHorde }, + { "HasItem", &LuaPlayer::HasItem }, + { "Teleport", &LuaPlayer::Teleport }, + { "AddItem", &LuaPlayer::AddItem }, + { "CanCompleteQuest", &LuaPlayer::CanCompleteQuest }, + { "CanEquipItem", &LuaPlayer::CanEquipItem }, + { "IsFalling", &LuaPlayer::IsFalling }, + { "ToggleAFK", &LuaPlayer::ToggleAFK }, + { "ToggleDND", &LuaPlayer::ToggleDND }, + { "IsAFK", &LuaPlayer::IsAFK }, + { "IsDND", &LuaPlayer::IsDND }, + { "IsAcceptingWhispers", &LuaPlayer::IsAcceptingWhispers }, + { "IsGMChat", &LuaPlayer::IsGMChat }, + { "IsTaxiCheater", &LuaPlayer::IsTaxiCheater }, + { "IsGMVisible", &LuaPlayer::IsGMVisible }, + { "HasQuest", &LuaPlayer::HasQuest }, + { "InBattlegroundQueue", &LuaPlayer::InBattlegroundQueue }, + { "CanSpeak", &LuaPlayer::CanSpeak }, + { "HasAtLoginFlag", &LuaPlayer::HasAtLoginFlag }, + { "CanUninviteFromGroup", &LuaPlayer::CanUninviteFromGroup }, + { "IsRested", &LuaPlayer::IsRested }, + { "IsVisibleForPlayer", &LuaPlayer::IsVisibleForPlayer }, + { "HasQuestForItem", &LuaPlayer::HasQuestForItem }, + { "HasQuestForGO", &LuaPlayer::HasQuestForGO }, + { "CanShareQuest", &LuaPlayer::CanShareQuest }, + { "IsInSameGroupWith", &LuaPlayer::IsInSameGroupWith }, + { "IsInSameRaidWith", &LuaPlayer::IsInSameRaidWith }, + { "IsGroupVisibleFor", &LuaPlayer::IsGroupVisibleFor }, + { "HasSkill", &LuaPlayer::HasSkill }, + { "IsHonorOrXPTarget", &LuaPlayer::IsHonorOrXPTarget }, + { "CanParry", &LuaPlayer::CanParry }, + { "CanBlock", &LuaPlayer::CanBlock }, + { "InBattleground", &LuaPlayer::InBattleground }, + { "CanUseItem", &LuaPlayer::CanUseItem }, + { "HasSpell", &LuaPlayer::HasSpell }, + { "HasSpellCooldown", &LuaPlayer::HasSpellCooldown }, + { "IsInWater", &LuaPlayer::IsInWater }, + { "IsMoving", &LuaPlayer::IsMoving }, +#if defined(TBC) || defined(WOTLK) + { "HasTitle", &LuaPlayer::HasTitle }, + { "IsInArenaTeam", &LuaPlayer::IsInArenaTeam }, + { "InArena", &LuaPlayer::InArena }, + { "CanFly", &LuaPlayer::CanFly }, + { "IsFlying", &LuaPlayer::IsFlying }, +#endif +#if defined(WOTLK) + { "HasAchieved", &LuaPlayer::HasAchieved }, + { "HasTalent", &LuaPlayer::HasTalent }, + { "CanTitanGrip", &LuaPlayer::CanTitanGrip }, +#endif + { "CanCompleteRepeatableQuest", &LuaPlayer::CanCompleteRepeatableQuest }, + { "CanRewardQuest", &LuaPlayer::CanRewardQuest }, + + // Gossip + { "GossipMenuAddItem", &LuaPlayer::GossipMenuAddItem }, + { "GossipSendMenu", &LuaPlayer::GossipSendMenu }, + { "GossipComplete", &LuaPlayer::GossipComplete }, + { "GossipClearMenu", &LuaPlayer::GossipClearMenu }, + + // Other + { "SendBroadcastMessage", &LuaPlayer::SendBroadcastMessage }, + { "SendAreaTriggerMessage", &LuaPlayer::SendAreaTriggerMessage }, + { "SendNotification", &LuaPlayer::SendNotification }, + { "SendPacket", &LuaPlayer::SendPacket }, + { "SendAddonMessage", &LuaPlayer::SendAddonMessage }, + { "ModifyMoney", &LuaPlayer::ModifyMoney }, + { "LearnSpell", &LuaPlayer::LearnSpell }, + { "LearnTalent", &LuaPlayer::LearnTalent }, + { "RemoveItem", &LuaPlayer::RemoveItem }, + { "RemoveLifetimeKills", &LuaPlayer::RemoveLifetimeKills }, + { "ResurrectPlayer", &LuaPlayer::ResurrectPlayer }, + { "EquipItem", &LuaPlayer::EquipItem }, + { "ResetSpellCooldown", &LuaPlayer::ResetSpellCooldown }, + { "ResetTypeCooldowns", &LuaPlayer::ResetTypeCooldowns }, + { "ResetAllCooldowns", &LuaPlayer::ResetAllCooldowns }, + { "GiveXP", &LuaPlayer::GiveXP }, + { "Say", &LuaPlayer::Say }, + { "Yell", &LuaPlayer::Yell }, + { "TextEmote", &LuaPlayer::TextEmote }, + { "Whisper", &LuaPlayer::Whisper }, + { "CompleteQuest", &LuaPlayer::CompleteQuest }, + { "IncompleteQuest", &LuaPlayer::IncompleteQuest }, + { "FailQuest", &LuaPlayer::FailQuest }, + { "AddQuest", &LuaPlayer::AddQuest }, + { "RemoveQuest", &LuaPlayer::RemoveQuest }, + { "AreaExploredOrEventHappens", &LuaPlayer::AreaExploredOrEventHappens }, + { "GroupEventHappens", &LuaPlayer::GroupEventHappens }, + { "KilledMonsterCredit", &LuaPlayer::KilledMonsterCredit }, + { "TalkedToCreature", &LuaPlayer::TalkedToCreature }, + { "AddComboPoints", &LuaPlayer::AddComboPoints }, + { "ClearComboPoints", &LuaPlayer::ClearComboPoints }, + { "RemoveSpell", &LuaPlayer::RemoveSpell }, + { "ResetTalents", &LuaPlayer::ResetTalents }, + { "ResetTalentsCost", &LuaPlayer::ResetTalentsCost }, + { "RemoveFromGroup", &LuaPlayer::RemoveFromGroup }, + { "KillPlayer", &LuaPlayer::KillPlayer }, + { "DurabilityLossAll", &LuaPlayer::DurabilityLossAll }, + { "DurabilityLoss", &LuaPlayer::DurabilityLoss }, + { "DurabilityPointsLoss", &LuaPlayer::DurabilityPointsLoss }, + { "DurabilityPointsLossAll", &LuaPlayer::DurabilityPointsLossAll }, + { "DurabilityPointLossForEquipSlot", &LuaPlayer::DurabilityPointLossForEquipSlot }, + { "DurabilityRepairAll", &LuaPlayer::DurabilityRepairAll }, + { "DurabilityRepair", &LuaPlayer::DurabilityRepair }, + { "LeaveBattleground", &LuaPlayer::LeaveBattleground }, + { "UnbindInstance", &LuaPlayer::UnbindInstance }, + { "UnbindAllInstances", &LuaPlayer::UnbindAllInstances }, + { "RemoveFromBattlegroundRaid", &LuaPlayer::RemoveFromBattlegroundRaid }, + { "KickPlayer", &LuaPlayer::KickPlayer }, + { "LogoutPlayer", &LuaPlayer::LogoutPlayer }, + { "SendTrainerList", &LuaPlayer::SendTrainerList }, + { "SendListInventory", &LuaPlayer::SendListInventory }, + { "SendShowBank", &LuaPlayer::SendShowBank }, + { "SendTabardVendorActivate", &LuaPlayer::SendTabardVendorActivate }, + { "SendSpiritResurrect", &LuaPlayer::SendSpiritResurrect }, + { "SendTaxiMenu", &LuaPlayer::SendTaxiMenu }, + { "SendUpdateWorldState", &LuaPlayer::SendUpdateWorldState }, + { "RewardQuest", &LuaPlayer::RewardQuest }, + { "SendAuctionMenu", &LuaPlayer::SendAuctionMenu }, + { "SendShowMailBox", &LuaPlayer::SendShowMailBox }, + { "StartTaxi", &LuaPlayer::StartTaxi }, + { "GossipSendPOI", &LuaPlayer::GossipSendPOI }, + { "GossipAddQuests", &LuaPlayer::GossipAddQuests }, + { "SendQuestTemplate", &LuaPlayer::SendQuestTemplate }, + { "SpawnBones", &LuaPlayer::SpawnBones }, + { "RemovedInsignia", &LuaPlayer::RemovedInsignia }, + { "SendGuildInvite", &LuaPlayer::SendGuildInvite }, + { "Mute", &LuaPlayer::Mute }, + { "SummonPlayer", &LuaPlayer::SummonPlayer }, + { "SaveToDB", &LuaPlayer::SaveToDB }, + { "GroupInvite", &LuaPlayer::GroupInvite }, + { "GroupCreate", &LuaPlayer::GroupCreate }, + { "SendCinematicStart", &LuaPlayer::SendCinematicStart }, +#if defined(TBC) || defined(WOTLK) + { "RemoveArenaSpellCooldowns", &LuaPlayer::RemoveArenaSpellCooldowns }, + { "ModifyHonorPoints", &LuaPlayer::ModifyHonorPoints }, + { "ModifyArenaPoints", &LuaPlayer::ModifyArenaPoints }, +#endif +#if defined(WOTLK) + { "ResetPetTalents", &LuaPlayer::ResetPetTalents }, + { "ResetAchievements", &LuaPlayer::ResetAchievements }, + { "SendMovieStart", &LuaPlayer::SendMovieStart }, +#endif + // Not implemented methods + { "GetChampioningFaction", nullptr }, // ACore & TC only + { "GetRecruiterId", nullptr }, // not implemented + { "GetHonorStoredKills", nullptr }, // classic only + { "GetRankPoints", nullptr }, // classic only + { "GetHonorLastWeekStandingPos", nullptr }, // classic only + { "SetHonorStoredKills", nullptr }, // classic only + { "SetRankPoints", nullptr }, // classic only + { "SetHonorLastWeekStandingPos", nullptr }, // classic only + { "SetMovement", nullptr }, // not implemented + { "SetFFA", nullptr }, // not implemented + { "IsImmuneToEnvironmentalDamage", nullptr}, // not implemented + { "InRandomLfgDungeon", nullptr }, // not implemented + { "HasPendingBind", nullptr }, //not implmented + { "CanFlyInZone", nullptr }, // not implemented + { "IsNeverVisible", nullptr }, // not implemented + { "IsUsingLfg", nullptr }, // not implemented + { "HasReceivedQuestReward", nullptr }, // not implemented + { "IsOutdoorPvPActive", nullptr }, // not implemented + { "IsARecruiter", nullptr }, // not implemented + { "SetAchievement", nullptr }, // TC/Acore + { "RemovePet", nullptr }, // not implemented + { "SummonPet", nullptr }, // not implemented + { "RemoveActiveQuest", nullptr }, // not implemented + { "RemoveRewardedQuest", nullptr }, // not implemented + { "KilledPlayerCredit", nullptr }, // not implemented + { "KillGOCredit", nullptr }, // not implemented + { "GainSpellComboPoints", nullptr }, // not implemented + { "AddTalent", nullptr }, // not implemented + { "BindToInstance", nullptr }, // not implemented + { "UpdateHonor", nullptr }, // classic only + { "ResetHonor", nullptr }, // classic only + { "ClearHonorInfo", nullptr }, // classic only + { "GetXP", nullptr }, // not implemented + { "GetXPForNextLevel", nullptr }, // not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/QuestMethods.h b/src/modules/Eluna/CMangos/QuestMethods.h new file mode 100644 index 0000000000..546aaac57b --- /dev/null +++ b/src/modules/Eluna/CMangos/QuestMethods.h @@ -0,0 +1,199 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef QUESTMETHODS_H +#define QUESTMETHODS_H + +/*** + * Inherits all methods from: none + */ +namespace LuaQuest +{ + /** + * Returns 'true' if the [Quest] has the specified flag, false otherwise. + * Below flags are based off of 3.3.5a. Subject to change. + * + *
+     * enum QuestFlags
+     * {
+     *     // Flags used at server and sent to client
+     *     QUEST_FLAGS_NONE                    = 0x0,
+     *     QUEST_FLAGS_STAY_ALIVE              = 0x1,       // Not used currently
+     *     QUEST_FLAGS_PARTY_ACCEPT            = 0x2,       // Not used currently. If player in party, all players that can accept this quest will receive confirmation box to accept quest CMSG_QUEST_CONFIRM_ACCEPT/SMSG_QUEST_CONFIRM_ACCEPT
+     *     QUEST_FLAGS_EXPLORATION             = 0x4,       // Not used currently
+     *     QUEST_FLAGS_SHARABLE                = 0x8,       // Can be shared: Player::CanShareQuest()
+     *     QUEST_FLAGS_HAS_CONDITION           = 0x10,      // Not used currently
+     *     QUEST_FLAGS_HIDE_REWARD_POI         = 0x20,      // Not used currently: Unsure of content
+     *     QUEST_FLAGS_RAID                    = 0x40,      // Not used currently
+     *     QUEST_FLAGS_TBC                     = 0x80,      // Not used currently: Available if TBC expansion enabled only
+     *     QUEST_FLAGS_NO_MONEY_FROM_XP        = 0x100,     // Not used currently: Experience is not converted to gold at max level
+     *     QUEST_FLAGS_HIDDEN_REWARDS          = 0x200,     // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE))
+     *     QUEST_FLAGS_TRACKING                = 0x400,     // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
+     *     QUEST_FLAGS_DEPRECATE_REPUTATION    = 0x800,     // Not used currently
+     *     QUEST_FLAGS_DAILY                   = 0x1000,    // Used to know quest is Daily one
+     *     QUEST_FLAGS_FLAGS_PVP               = 0x2000,    // Having this quest in log forces PvP flag
+     *     QUEST_FLAGS_UNAVAILABLE             = 0x4000,    // Used on quests that are not generically available
+     *     QUEST_FLAGS_WEEKLY                  = 0x8000,
+     *     QUEST_FLAGS_AUTOCOMPLETE            = 0x10000,   // auto complete
+     *     QUEST_FLAGS_DISPLAY_ITEM_IN_TRACKER = 0x20000,   // Displays usable item in quest tracker
+     *     QUEST_FLAGS_OBJ_TEXT                = 0x40000,   // use Objective text as Complete text
+     *     QUEST_FLAGS_AUTO_ACCEPT             = 0x80000,   // The client recognizes this flag as auto-accept. However, NONE of the current quests (3.3.5a) have this flag. Maybe blizz used to use it, or will use it in the future.
+     *
+     *     // ... 4.x added flags up to 0x80000000 - all unknown for now
+     * };
+     * 
+ * + * @param [QuestFlags] flag : all available flags can be seen above + * @return bool hasFlag + */ + int HasFlag(lua_State* L, Quest* quest) + { + uint32 flag = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, quest->HasQuestFlag((QuestFlags)flag)); + return 1; + } + +#ifndef CLASSIC + /** + * Returns 'true' if the [Quest] is a daily quest, false otherwise. + * + * @return bool isDaily + */ + int IsDaily(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->IsDaily()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Quest] is repeatable, false otherwise. + * + * @return bool isRepeatable + */ + int IsRepeatable(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->IsRepeatable()); + return 1; + } + + /** + * Returns entry ID of the [Quest]. + * + * @return uint32 entryId + */ + int GetId(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetQuestId()); + return 1; + } + + /** + * Returns the [Quest]'s level. + * + * @return uint32 level + */ + int GetLevel(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetQuestLevel()); + return 1; + } + + /** + * Returns the minimum level required to pick up the [Quest]. + * + * @return uint32 minLevel + */ + int GetMinLevel(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetMinLevel()); + return 1; + } + + /** + * Returns the next [Quest] entry ID. + * + * @return int32 entryId + */ + int GetNextQuestId(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetNextQuestId()); + return 1; + } + + /** + * Returns the previous [Quest] entry ID. + * + * @return int32 entryId + */ + int GetPrevQuestId(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetPrevQuestId()); + return 1; + } + + /** + * Returns the next [Quest] entry ID in the specific [Quest] chain. + * + * @return int32 entryId + */ + int GetNextQuestInChain(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetNextQuestInChain()); + return 1; + } + + /** + * Returns the [Quest]'s flags. + * + * @return [QuestFlags] flags + */ + int GetFlags(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetQuestFlags()); + return 1; + } + + /** + * Returns the [Quest]'s type. + * + * TODO: Document types available. + * + * @return uint32 type + */ + int GetType(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetType()); + return 1; + } + + ElunaRegister QuestMethods[] = + { + // Getters + { "GetId", &LuaQuest::GetId }, + { "GetLevel", &LuaQuest::GetLevel }, + { "GetMinLevel", &LuaQuest::GetMinLevel }, + { "GetNextQuestId", &LuaQuest::GetNextQuestId }, + { "GetPrevQuestId", &LuaQuest::GetPrevQuestId }, + { "GetNextQuestInChain", &LuaQuest::GetNextQuestInChain }, + { "GetFlags", &LuaQuest::GetFlags }, + { "GetType", &LuaQuest::GetType }, + + // Boolean + { "HasFlag", &LuaQuest::HasFlag }, +#if defined(TBC) || defined(WOTLK) + { "IsDaily", &LuaQuest::IsDaily }, +#endif + { "IsRepeatable", &LuaQuest::IsRepeatable }, + + // Not implemented methods + { "GetMaxLevel", nullptr }, // not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/SpellMethods.h b/src/modules/Eluna/CMangos/SpellMethods.h new file mode 100644 index 0000000000..3e3de37ea0 --- /dev/null +++ b/src/modules/Eluna/CMangos/SpellMethods.h @@ -0,0 +1,194 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef SPELLMETHODS_H +#define SPELLMETHODS_H + +/*** + * An instance of a spell, created when the spell is cast by a [Unit]. + * + * Inherits all methods from: none + */ +namespace LuaSpell +{ + /** + * Returns `true` if the [Spell] is automatically repeating, `false` otherwise. + * + * @return bool isAutoRepeating + */ + int IsAutoRepeat(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->IsAutoRepeat()); + return 1; + } + + /** + * Returns the [Unit] that casted the [Spell]. + * + * @return [Unit] caster + */ + int GetCaster(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->GetCaster()); + return 1; + } + + /** + * Returns the cast time of the [Spell]. + * + * @return int32 castTime + */ + int GetCastTime(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->GetCastTime()); + return 1; + } + + /** + * Returns the entry ID of the [Spell]. + * + * @return uint32 entryId + */ + int GetEntry(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->m_spellInfo->Id); + return 1; + } + + /** + * Returns the power cost of the [Spell]. + * + * @return uint32 powerCost + */ + int GetPowerCost(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->GetPowerCost()); + return 1; + } + + /** + * Returns the spell duration of the [Spell]. + * + * @return int32 duration + */ + int GetDuration(lua_State* L, Spell* spell) + { + Eluna::Push(L, GetSpellDuration(spell->m_spellInfo)); + return 1; + } + + /** + * Returns the target destination coordinates of the [Spell]. + * + * @return float x : x coordinate of the [Spell] + * @return float y : y coordinate of the [Spell] + * @return float z : z coordinate of the [Spell] + */ + int GetTargetDest(lua_State* L, Spell* spell) + { + if (!(spell->m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) + return 3; + float x, y, z; + spell->m_targets.getDestination(x, y, z); + Eluna::Push(L, x); + Eluna::Push(L, y); + Eluna::Push(L, z); + return 3; + } + + /** + * Returns the target [Object] of the [Spell]. + * + * The target can be any of the following [Object] types: + * - [Player] + * - [Creature] + * - [GameObject] + * - [Item] + * - [Corpse] + * + * @return [Object] target + */ + int GetTarget(lua_State* L, Spell* spell) + { + if (GameObject* target = spell->m_targets.getGOTarget()) + Eluna::Push(L, target); + else if (Item* target = spell->m_targets.getItemTarget()) + Eluna::Push(L, target); + else if (Corpse* target = spell->GetCaster()->GetMap()->GetCorpse(spell->m_targets.getCorpseTargetGuid())) + Eluna::Push(L, target); + else if (Unit* target = spell->m_targets.getUnitTarget()) + Eluna::Push(L, target); + return 1; + } + + /** + * Sets the [Spell] to automatically repeat. + * + * @param bool repeat : set variable to 'true' for spell to automatically repeat + */ + int SetAutoRepeat(lua_State* L, Spell* spell) + { + bool repeat = Eluna::CHECKVAL(L, 2); + spell->SetAutoRepeat(repeat); + return 0; + } + + /** + * Casts the [Spell]. + * + * @param bool skipCheck = false : skips initial checks to see if the [Spell] can be casted or not, this is optional + */ + int Cast(lua_State* L, Spell* spell) + { + bool skipCheck = Eluna::CHECKVAL(L, 2, false); + spell->cast(skipCheck); + return 0; + } + + /** + * Cancels the [Spell]. + */ + int Cancel(lua_State* /*L*/, Spell* spell) + { + spell->cancel(); + return 0; + } + + /** + * Finishes the [Spell]. + */ + int Finish(lua_State* /*L*/, Spell* spell) + { + spell->finish(); + return 0; + } + + ElunaRegister SpellMethods[] = + { + // Getters + { "GetCaster", &LuaSpell::GetCaster }, + { "GetCastTime", &LuaSpell::GetCastTime }, + { "GetEntry", &LuaSpell::GetEntry }, + { "GetDuration", &LuaSpell::GetDuration }, + { "GetPowerCost", &LuaSpell::GetPowerCost }, + { "GetTargetDest", &LuaSpell::GetTargetDest }, + { "GetTarget", &LuaSpell::GetTarget }, + + // Setters + { "SetAutoRepeat", &LuaSpell::SetAutoRepeat }, + + // Boolean + { "IsAutoRepeat", &LuaSpell::IsAutoRepeat }, + + // Other + { "Cancel", &LuaSpell::Cancel }, + { "Cast", &LuaSpell::Cast }, + { "Finish", &LuaSpell::Finish }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/UnitMethods.h b/src/modules/Eluna/CMangos/UnitMethods.h new file mode 100644 index 0000000000..1103d02182 --- /dev/null +++ b/src/modules/Eluna/CMangos/UnitMethods.h @@ -0,0 +1,2689 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef UNITMETHODS_H +#define UNITMETHODS_H + +/*** + * Inherits all methods from: [Object], [WorldObject] + */ +namespace LuaUnit +{ + /** + * The [Unit] tries to attack a given target + * + * @param [Unit] who : [Unit] to attack + * @param bool meleeAttack = false: attack with melee or not + * @return didAttack : if the [Unit] did not attack + */ + int Attack(lua_State* L, Unit* unit) + { + Unit* who = Eluna::CHECKOBJ(L, 2); + bool meleeAttack = Eluna::CHECKVAL(L, 3, false); + + Eluna::Push(L, unit->Attack(who, meleeAttack)); + return 1; + } + + /** + * The [Unit] stops attacking its target + * + * @return bool isAttacking : if the [Unit] wasn't attacking already + */ + int AttackStop(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->AttackStop()); + return 1; + } + + /** + * Returns true if the [Unit] is standing. + * + * @return bool isStanding + */ + int IsStandState(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsStandState()); + return 1; + } + + /** + * Returns true if the [Unit] is mounted. + * + * @return bool isMounted + */ + int IsMounted(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsMounted()); + return 1; + } + + /** + * Returns true if the [Unit] is rooted. + * + * @return bool isRooted + */ + int IsRooted(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isInRoots() || unit->IsRooted()); + return 1; + } + + /** + * Returns true if the [Unit] has full health. + * + * @return bool hasFullHealth + */ + int IsFullHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsFullHealth()); + return 1; + } + + /** + * Returns true if the [Unit] is in an accessible place for the given [Creature]. + * + * @param [WorldObject] obj + * @param float radius + * @return bool isAccessible + */ + int IsInAccessiblePlaceFor(lua_State* L, Unit* unit) + { + Creature* creature = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, unit->isInAccessablePlaceFor(creature)); + return 1; + } + + /** + * Returns true if the [Unit] an auctioneer. + * + * @return bool isAuctioneer + */ + int IsAuctioneer(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isAuctioner()); + return 1; + } + + /** + * Returns true if the [Unit] a guild master. + * + * @return bool isGuildMaster + */ + int IsGuildMaster(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isGuildMaster()); + return 1; + } + + /** + * Returns true if the [Unit] an innkeeper. + * + * @return bool isInnkeeper + */ + int IsInnkeeper(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isInnkeeper()); + return 1; + } + + /** + * Returns true if the [Unit] a trainer. + * + * @return bool isTrainer + */ + int IsTrainer(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isTrainer()); + return 1; + } + + /** + * Returns true if the [Unit] is able to show a gossip window. + * + * @return bool hasGossip + */ + int IsGossip(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isGossip()); + return 1; + } + + /** + * Returns true if the [Unit] is a taxi master. + * + * @return bool isTaxi + */ + int IsTaxi(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isTaxi()); + return 1; + } + + /** + * Returns true if the [Unit] is a spirit healer. + * + * @return bool isSpiritHealer + */ + int IsSpiritHealer(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isSpiritHealer()); + return 1; + } + + /** + * Returns true if the [Unit] is a spirit guide. + * + * @return bool isSpiritGuide + */ + int IsSpiritGuide(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isSpiritGuide()); + return 1; + } + + /** + * Returns true if the [Unit] is a tabard designer. + * + * @return bool isTabardDesigner + */ + int IsTabardDesigner(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isTabardDesigner()); + return 1; + } + + /** + * Returns true if the [Unit] provides services like vendor, training and auction. + * + * @return bool isTabardDesigner + */ + int IsServiceProvider(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isServiceProvider()); + return 1; + } + + /** + * Returns true if the [Unit] is a spirit guide or spirit healer. + * + * @return bool isSpiritService + */ + int IsSpiritService(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isSpiritService()); + return 1; + } + + /** + * Returns true if the [Unit] is alive. + * + * @return bool isAlive + */ + int IsAlive(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsAlive()); + return 1; + } + + /** + * Returns true if the [Unit] is dead. + * + * @return bool isDead + */ + int IsDead(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsDead()); + return 1; + } + + /** + * Returns true if the [Unit] is dying. + * + * @return bool isDying + */ + int IsDying(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsDying()); + return 1; + } + + /** + * Returns true if the [Unit] is a banker. + * + * @return bool isBanker + */ + int IsBanker(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isBanker()); + return 1; + } + + /** + * Returns true if the [Unit] is a vendor. + * + * @return bool isVendor + */ + int IsVendor(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isVendor()); + return 1; + } + + /** + * Returns true if the [Unit] is a battle master. + * + * @return bool isBattleMaster + */ + int IsBattleMaster(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isBattleMaster()); + return 1; + } + + /** + * Returns true if the [Unit] is a charmed. + * + * @return bool isCharmed + */ + int IsCharmed(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsCharmed()); + return 1; + } + + /** + * Returns true if the [Unit] is an armorer and can repair equipment. + * + * @return bool isArmorer + */ + int IsArmorer(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isArmorer()); + return 1; + } + + /** + * Returns true if the [Unit] is attacking a player. + * + * @return bool isAttackingPlayer + */ + int IsAttackingPlayer(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isAttackingPlayer()); + return 1; + } + + /** + * Returns true if the [Unit] flagged for PvP. + * + * @return bool isPvP + */ + int IsPvPFlagged(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsPvP()); + return 1; + } + +#ifndef CLASSIC + /** + * Returns true if the [Unit] is on a [Vehicle]. + * + * @return bool isOnVehicle + */ + int IsOnVehicle(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsBoarded()); + return 1; + } +#endif + + /** + * Returns true if the [Unit] is in combat. + * + * @return bool inCombat + */ + int IsInCombat(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsInCombat()); + return 1; + } + + /** + * Returns true if the [Unit] is under water. + * + * @return bool underWater + */ + int IsUnderWater(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsUnderwater()); + return 1; + } + + /** + * Returns true if the [Unit] is in water. + * + * @return bool inWater + */ + int IsInWater(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsInWater()); + return 1; + } + + /** + * Returns true if the [Unit] is not moving. + * + * @return bool notMoving + */ + int IsStopped(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsStopped()); + return 1; + } + + /** + * Returns true if the [Unit] is a quest giver. + * + * @return bool questGiver + */ + int IsQuestGiver(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isQuestGiver()); + return 1; + } + + /** + * Returns true if the [Unit]'s health is below the given percentage. + * + * @param int32 healthpct : percentage in integer from + * @return bool isBelow + */ + int HealthBelowPct(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->HealthBelowPct(Eluna::CHECKVAL(L, 2))); + return 1; + } + + /** + * Returns true if the [Unit]'s health is above the given percentage. + * + * @param int32 healthpct : percentage in integer from + * @return bool isAbove + */ + int HealthAbovePct(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->HealthAbovePct(Eluna::CHECKVAL(L, 2))); + return 1; + } + + /** + * Returns true if the [Unit] has an aura from the given spell entry. + * + * @param uint32 spell : entry of the aura spell + * @return bool hasAura + */ + int HasAura(lua_State* L, Unit* unit) + { + uint32 spell = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, unit->HasAura(spell)); + return 1; + } + + /** + * Returns true if the [Unit] is casting a spell + * + * @return bool isCasting + */ + int IsCasting(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsNonMeleeSpellCasted(false)); + return 1; + } + + /** + * Returns true if the [Unit] has the given unit state. + * + * @param [UnitState] state : an unit state + * @return bool hasState + */ + int HasUnitState(lua_State* L, Unit* unit) + { + uint32 state = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, unit->hasUnitState(state)); + return 1; + } + + /** + * Returns the [Unit]'s owner. + * + * @return [Unit] owner + */ + int GetOwner(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetOwner()); + return 1; + } + + /** + * Returns the [Unit]'s owner's GUID. + * + * @return ObjectGuid ownerGUID + */ + int GetOwnerGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetOwnerGuid()); + return 1; + } + + /** + * Returns the [Unit]'s mount's modelID. + * + * @return uint32 mountId : displayId of the mount + */ + int GetMountId(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetMountID()); + return 1; + } + + /** + * Returns the [Unit]'s creator's GUID. + * + * @return ObjectGuid creatorGUID + */ + int GetCreatorGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCreatorGuid()); + return 1; + } + + /** + * Returns the [Unit]'s charmer's GUID. + * + * @return ObjectGuid charmerGUID + */ + int GetCharmerGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCharmerGuid()); + return 1; + } + + /** + * Returns the GUID of the [Unit]'s charmed entity. + * + * @return ObjectGuid charmedGUID + */ + int GetCharmGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCharmGuid()); + return 1; + } + + /** + * Returns the GUID of the [Unit]'s pet. + * + * @return ObjectGuid petGUID + */ + int GetPetGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetPetGuid()); + return 1; + } + + /** + * Returns the GUID of the [Unit]'s charmer or owner. + * + * @return ObjectGuid controllerGUID + */ + int GetControllerGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCharmerOrOwnerGuid()); + return 1; + } + + /** + * Returns the GUID of the [Unit]'s charmer or owner or its own GUID. + * + * @return ObjectGuid controllerGUID + */ + int GetControllerGUIDS(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCharmerOrOwnerOrOwnGuid()); + return 1; + } + + /** + * Returns [Unit]'s specified stat + * + * @param uint32 statType + * @return float stat + */ + int GetStat(lua_State* L, Unit* unit) + { + uint32 stat = Eluna::CHECKVAL(L, 2); + + if (stat >= MAX_STATS) + return 1; + + Eluna::Push(L, unit->GetStat((Stats)stat)); + return 1; + } + + /** + * Returns the [Unit]'s base spell power + * + * @param uint32 spellSchool + * @return uint32 spellPower + */ + int GetBaseSpellPower(lua_State* L, Unit* unit) + { + uint32 spellschool = Eluna::CHECKVAL(L, 2); + + if (spellschool >= MAX_SPELL_SCHOOL) + return 1; + + Eluna::Push(L, unit->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + spellschool)); + return 1; + } + + /** + * Returns the [Unit]'s current victim target or nil. + * + * @return [Unit] victim + */ + int GetVictim(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetVictim()); + return 1; + } + + /** + * Returns the currently casted [Spell] of given type or nil. + * + *
+     * enum CurrentSpellTypes
+     * {
+     *     CURRENT_MELEE_SPELL             = 0,
+     *     CURRENT_GENERIC_SPELL           = 1,
+     *     CURRENT_CHANNELED_SPELL         = 2,
+     *     CURRENT_AUTOREPEAT_SPELL        = 3
+     * };
+     * 
+ * + * @param [CurrentSpellTypes] spellType + * @return [Spell] castedSpell + */ + int GetCurrentSpell(lua_State* L, Unit* unit) + { + uint32 type = Eluna::CHECKVAL(L, 2); + if (type >= CURRENT_MAX_SPELL) + return luaL_argerror(L, 2, "valid CurrentSpellTypes expected"); + Eluna::Push(L, unit->GetCurrentSpell(CurrentSpellTypes(type))); + return 1; + } + + /** + * Returns the [Unit]'s current stand state. + * + * @return uint8 standState + */ + int GetStandState(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->getStandState()); + return 1; + } + + /** + * Returns the [Unit]'s current display ID. + * + * @return uint32 displayId + */ + int GetDisplayId(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetDisplayId()); + return 1; + } + + /** + * Returns the [Unit]'s native/original display ID. + * + * @return uint32 displayId + */ + int GetNativeDisplayId(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetNativeDisplayId()); + return 1; + } + + /** + * Returns the [Unit]'s level. + * + * @return uint8 level + */ + int GetLevel(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetLevel()); + return 1; + } + + /** + * Returns the [Unit]'s health amount. + * + * @return uint32 healthAmount + */ + int GetHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetHealth()); + return 1; + } + + Powers PowerSelectorHelper(lua_State* L, Unit* unit, int powerType = -1) + { + if (powerType == -1) + return unit->GetPowerType(); + + if (powerType < 0 || powerType >= int(MAX_POWERS)) + luaL_argerror(L, 2, "valid Powers expected"); + + return (Powers)powerType; + } + + /** + * Returns the [Unit]'s power amount for given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + * @return uint32 powerAmount + */ + int GetPower(lua_State* L, Unit* unit) + { + int type = Eluna::CHECKVAL(L, 2, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + Eluna::Push(L, unit->GetPower(power)); + return 1; + } + + /** + * Returns the [Unit]'s max power amount for given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + * @return uint32 maxPowerAmount + */ + int GetMaxPower(lua_State* L, Unit* unit) + { + int type = Eluna::CHECKVAL(L, 2, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + Eluna::Push(L, unit->GetMaxPower(power)); + return 1; + } + + /** + * Returns the [Unit]'s power percent for given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + * @return float powerPct + */ + int GetPowerPct(lua_State* L, Unit* unit) + { + int type = Eluna::CHECKVAL(L, 2, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + float percent = ((float)unit->GetPower(power) / (float)unit->GetMaxPower(power)) * 100.0f; + Eluna::Push(L, percent); + return 1; + } + + /** + * Returns the [Unit]'s current power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @return [Powers] powerType + */ + int GetPowerType(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetPowerType()); + return 1; + } + + /** + * Returns the [Unit]'s max health. + * + * @return uint32 maxHealth + */ + int GetMaxHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetMaxHealth()); + return 1; + } + + /** + * Returns the [Unit]'s health percent. + * + * @return float healthPct + */ + int GetHealthPct(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetHealthPercent()); + return 1; + } + + /** + * Returns the [Unit]'s gender. + * + * @return uint8 gender : 0 for male, 1 for female and 2 for none + */ + int GetGender(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->getGender()); + return 1; + } + + /** + * Returns the [Unit]'s race ID. + * + * @return [Races] race + */ + int GetRace(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->getRace()); + return 1; + } + + /** + * Returns the [Unit]'s class ID. + * + * @return [Classes] class + */ + int GetClass(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->getClass()); + return 1; + } + + /** + * Returns the race mask + * + * @return uint32 racemask + */ + int GetRaceMask(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->getRaceMask()); + return 1; + } + + /** + * Returns the class mask + * + * @return uint32 classmask + */ + int GetClassMask(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->getClassMask()); + return 1; + } + + /** + * Returns the [Unit]'s creature type ID (enumerated in CreatureType.dbc). + * + *
+     * enum CreatureType
+     * {
+     *     CREATURE_TYPE_BEAST            = 1,
+     *     CREATURE_TYPE_DRAGONKIN        = 2,
+     *     CREATURE_TYPE_DEMON            = 3,
+     *     CREATURE_TYPE_ELEMENTAL        = 4,
+     *     CREATURE_TYPE_GIANT            = 5,
+     *     CREATURE_TYPE_UNDEAD           = 6,
+     *     CREATURE_TYPE_HUMANOID         = 7,
+     *     CREATURE_TYPE_CRITTER          = 8,
+     *     CREATURE_TYPE_MECHANICAL       = 9,
+     *     CREATURE_TYPE_NOT_SPECIFIED    = 10,
+     *     CREATURE_TYPE_TOTEM            = 11,
+     *     CREATURE_TYPE_NON_COMBAT_PET   = 12,     // This and below is TBC+
+     *     CREATURE_TYPE_GAS_CLOUD        = 13
+     * };
+     * 
+ * + * @return [CreatureType] creatureType + */ + int GetCreatureType(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCreatureType()); + return 1; + } + + /** + * Returns the [Unit]'s class' name in given or default locale or nil. + * + *
+     * enum LocaleConstant
+     * {
+     *     LOCALE_enUS = 0,
+     *     LOCALE_koKR = 1,
+     *     LOCALE_frFR = 2,
+     *     LOCALE_deDE = 3,
+     *     LOCALE_zhCN = 4,
+     *     LOCALE_zhTW = 5,
+     *     LOCALE_esES = 6,
+     *     LOCALE_esMX = 7,
+     *     LOCALE_ruRU = 8
+     * };
+     * 
+ * + * @param [LocaleConstant] locale = DEFAULT_LOCALE + * @return string className : class name or nil + */ + int GetClassAsString(lua_State* L, Unit* unit) + { + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const ChrClassesEntry* entry = sChrClassesStore.LookupEntry(unit->getClass()); + if (!entry) + return 1; + + Eluna::Push(L, entry->name[locale]); + return 1; + } + + /** + * Returns the [Unit]'s race's name in given or default locale or nil. + * + *
+     * enum LocaleConstant
+     * {
+     *     LOCALE_enUS = 0,
+     *     LOCALE_koKR = 1,
+     *     LOCALE_frFR = 2,
+     *     LOCALE_deDE = 3,
+     *     LOCALE_zhCN = 4,
+     *     LOCALE_zhTW = 5,
+     *     LOCALE_esES = 6,
+     *     LOCALE_esMX = 7,
+     *     LOCALE_ruRU = 8
+     * };
+     * 
+ * + * @param [LocaleConstant] locale = DEFAULT_LOCALE : locale to return the race name in + * @return string raceName : race name or nil + */ + int GetRaceAsString(lua_State* L, Unit* unit) + { + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const ChrRacesEntry* entry = sChrRacesStore.LookupEntry(unit->getRace()); + if (!entry) + return 1; + + Eluna::Push(L, entry->name[locale]); + return 1; + } + + /** + * Returns the [Unit]'s faction ID. + * + * @return uint32 faction + */ + int GetFaction(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetFaction()); + return 1; + } + + /** + * Returns the [Aura] of the given spell entry on the [Unit] or nil. + * + * @param uint32 spellID : entry of the aura spell + * @return [Aura] aura : aura object or nil + */ + int GetAura(lua_State* L, Unit* unit) + { + uint32 spellID = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, unit->GetAura(spellID, EFFECT_INDEX_0)); + return 1; + } + + /** + * Returns a table containing friendly [Unit]'s within given range of the [Unit]. + * + * @param float range = 533.333 : search radius + * @return table friendyUnits : table filled with friendly units + */ + int GetFriendlyUnitsInRange(lua_State* L, Unit* unit) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + + std::list list; + MaNGOS::AnyFriendlyUnitInObjectRangeCheck checker(unit, range); + MaNGOS::UnitListSearcher searcher(list, checker); + Cell::VisitGridObjects(unit, searcher, range); + ElunaUtil::ObjectGUIDCheck guidCheck(unit->GET_GUID()); + list.remove_if(guidCheck); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns a table containing unfriendly [Unit]'s within given range of the [Unit]. + * + * @param float range = 533.333 : search radius + * @return table unfriendyUnits : table filled with unfriendly units + */ + int GetUnfriendlyUnitsInRange(lua_State* L, Unit* unit) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + + std::list list; + MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck checker(unit, range); + MaNGOS::UnitListSearcher searcher(list, checker); + Cell::VisitGridObjects(unit, searcher, range); + ElunaUtil::ObjectGUIDCheck guidCheck(unit->GET_GUID()); + list.remove_if(guidCheck); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Returns [Unit]'s [Vehicle] methods + * + * @return [Vehicle] vehicle + */ + int GetVehicleKit(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetVehicleInfo()); + return 1; + } + + /** + * Returns the Critter Guid + * + * @return ObjectGuid critterGuid + */ + int GetCritterGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCritterGuid()); + return 1; + } +#endif + + /** + * Returns the [Unit]'s speed of given [UnitMoveType]. + * + *
+     * enum UnitMoveType
+     * {
+     *     MOVE_WALK           = 0,
+     *     MOVE_RUN            = 1,
+     *     MOVE_RUN_BACK       = 2,
+     *     MOVE_SWIM           = 3,
+     *     MOVE_SWIM_BACK      = 4,
+     *     MOVE_TURN_RATE      = 5,
+     *     MOVE_FLIGHT         = 6,
+     *     MOVE_FLIGHT_BACK    = 7,
+     *     MOVE_PITCH_RATE     = 8
+     * };
+     * 
+ * + * @param [UnitMoveType] type + * @return float speed + */ + int GetSpeed(lua_State* L, Unit* unit) + { + uint32 type = Eluna::CHECKVAL(L, 2); + if (type >= MAX_MOVE_TYPE) + return luaL_argerror(L, 2, "valid UnitMoveType expected"); + + Eluna::Push(L, unit->GetSpeedRate((UnitMoveType)type)); + return 1; + } + + /** + * Returns the current movement type for this [Unit]. + * + *
+     * enum MovementGeneratorType
+     * {
+     *     IDLE_MOTION_TYPE                = 0,
+     *     RANDOM_MOTION_TYPE              = 1,
+     *     WAYPOINT_MOTION_TYPE            = 2,
+     *     MAX_DB_MOTION_TYPE              = 3,
+     *     ANIMAL_RANDOM_MOTION_TYPE       = 3, // TC
+     *
+     *     CONFUSED_MOTION_TYPE            = 4,
+     *     CHASE_MOTION_TYPE               = 5,
+     *     HOME_MOTION_TYPE                = 6,
+     *     FLIGHT_MOTION_TYPE              = 7,
+     *     POINT_MOTION_TYPE               = 8,
+     *     FLEEING_MOTION_TYPE             = 9,
+     *     DISTRACT_MOTION_TYPE            = 10,
+     *     ASSISTANCE_MOTION_TYPE          = 11,
+     *     ASSISTANCE_DISTRACT_MOTION_TYPE = 12,
+     *     TIMED_FLEEING_MOTION_TYPE       = 13,
+     *     FOLLOW_MOTION_TYPE              = 14,
+     *     EFFECT_MOTION_TYPE              = 15, // mangos
+     *     ROTATE_MOTION_TYPE              = 15, // TC
+     *     EFFECT_MOTION_TYPE              = 16, // TC
+     *     NULL_MOTION_TYPE                = 17, // TC
+     * };
+     * 
+ * + * @return [MovementGeneratorType] movementType + */ + int GetMovementType(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetMotionMaster()->GetCurrentMovementGeneratorType()); + return 1; + } + + /** + * Sets the [Unit]'s owner GUID to given GUID. + * + * @param ObjectGuid guid : new owner guid + */ + int SetOwnerGUID(lua_State* L, Unit* unit) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + + unit->SetOwnerGuid(guid); + return 0; + } + + /** + * Sets the [Unit]'s PvP on or off. + * + * @param bool apply = true : true if set on, false if off + */ + int SetPvP(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + unit->SetPvP(apply); + return 0; + } + + /** + * Sets the [Unit]'s sheath state. + * + * enum SheathState + * { + * SHEATH_STATE_UNARMED = 0, // non prepared weapon + * SHEATH_STATE_MELEE = 1, // prepared melee weapon + * SHEATH_STATE_RANGED = 2 // prepared ranged weapon + * }; + * + * @param [SheathState] sheathState : valid SheathState + */ + int SetSheath(lua_State* L, Unit* unit) + { + uint32 sheathed = Eluna::CHECKVAL(L, 2); + if (sheathed >= MAX_SHEATH_STATE) + return luaL_argerror(L, 2, "valid SheathState expected"); + + unit->SetSheath((SheathState)sheathed); + return 0; + } + + /** + * Sets the [Unit]'s name internally. + * + * @param string name : new name + */ + int SetName(lua_State* L, Unit* unit) + { + const char* name = Eluna::CHECKVAL(L, 2); + if (std::string(name).length() > 0) + unit->SetName(name); + return 0; + } + + /** + * Sets the [Unit]'s speed of given [UnitMoveType] to given rate. + * If forced, packets sent to clients forcing the visual change. + * + *
+     * enum UnitMoveType
+     * {
+     *     MOVE_WALK           = 0,
+     *     MOVE_RUN            = 1,
+     *     MOVE_RUN_BACK       = 2,
+     *     MOVE_SWIM           = 3,
+     *     MOVE_SWIM_BACK      = 4,
+     *     MOVE_TURN_RATE      = 5,
+     *     MOVE_FLIGHT         = 6,
+     *     MOVE_FLIGHT_BACK    = 7,
+     *     MOVE_PITCH_RATE     = 8
+     * };
+     * 
+ * + * @param [UnitMoveType] type + * @param float rate + * @param bool forced = false + */ + int SetSpeed(lua_State* L, Unit* unit) + { + uint32 type = Eluna::CHECKVAL(L, 2); + float rate = Eluna::CHECKVAL(L, 3); + bool forced = Eluna::CHECKVAL(L, 4, false); + (void)forced; // ensure that the variable is referenced in order to pass compiler checks + if (type >= MAX_MOVE_TYPE) + return luaL_argerror(L, 2, "valid UnitMoveType expected"); + + unit->SetSpeedRate((UnitMoveType)type, rate, forced); + return 0; + } + + /** + * Sets the [Unit]'s faction. + * + * @param uint32 faction : new faction ID + */ + int SetFaction(lua_State* L, Unit* unit) + { + uint32 factionId = Eluna::CHECKVAL(L, 2); + unit->setFaction(factionId); + return 0; + } + + /** + * Sets the [Unit]'s level. + * + * @param uint8 level : new level + */ + int SetLevel(lua_State* L, Unit* unit) + { + uint8 newlevel = Eluna::CHECKVAL(L, 2); + + if (newlevel < 1) + return luaL_argerror(L, 2, "level cannot be below 1"); + + if (Player* player = unit->ToPlayer()) + { + player->GiveLevel(newlevel); + player->InitTalentForLevel(); + player->SetUInt32Value(PLAYER_XP, 0); + } + else + unit->SetLevel(newlevel); + + return 0; + } + + /** + * Sets the [Unit]'s health. + * + * @param uint32 health : new health + */ + int SetHealth(lua_State* L, Unit* unit) + { + uint32 amt = Eluna::CHECKVAL(L, 2); + unit->SetHealth(amt); + return 0; + } + + /** + * Sets the [Unit]'s max health. + * + * @param uint32 maxHealth : new max health + */ + int SetMaxHealth(lua_State* L, Unit* unit) + { + uint32 amt = Eluna::CHECKVAL(L, 2); + unit->SetMaxHealth(amt); + return 0; + } + + /** + * Sets the [Unit]'s power amount for the given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param uint32 amount : new power amount + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + */ + int SetPower(lua_State* L, Unit* unit) + { + uint32 amt = Eluna::CHECKVAL(L, 2); + int type = Eluna::CHECKVAL(L, 3, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + unit->SetPower(power, amt); + return 0; + } + + /** + * modifies the [Unit]'s power amount for the given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int32 amount : amount to modify + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + */ + int ModifyPower(lua_State* L, Unit* unit) + { + int32 amt = Eluna::CHECKVAL(L, 2); + int type = Eluna::CHECKVAL(L, 3, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + unit->ModifyPower(power, amt); + return 0; + } + + /** + * Sets the [Unit]'s max power amount for the given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + * @param uint32 maxPower : new max power amount + */ + int SetMaxPower(lua_State* L, Unit* unit) + { + int type = Eluna::CHECKVAL(L, 2, -1); + uint32 amt = Eluna::CHECKVAL(L, 3); + Powers power = PowerSelectorHelper(L, unit, type); + + unit->SetMaxPower(power, amt); + return 0; + } + + /** + * Sets the [Unit]'s power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param [Powers] type : a valid power type + */ + int SetPowerType(lua_State* L, Unit* unit) + { + uint32 type = Eluna::CHECKVAL(L, 2); + if (type >= int(MAX_POWERS)) + return luaL_argerror(L, 2, "valid Powers expected"); + + unit->SetPowerType((Powers)type); + return 0; + } + + /** + * Sets the [Unit]'s modelID. + * + * @param uint32 displayId + */ + int SetDisplayId(lua_State* L, Unit* unit) + { + uint32 model = Eluna::CHECKVAL(L, 2); + unit->SetDisplayId(model); + return 0; + } + + /** + * Sets the [Unit]'s native/default modelID. + * + * @param uint32 displayId + */ + int SetNativeDisplayId(lua_State* L, Unit* unit) + { + uint32 model = Eluna::CHECKVAL(L, 2); + unit->SetNativeDisplayId(model); + return 0; + } + + /** + * Sets the [Unit]'s facing/orientation. + * + * @param uint32 orientation + */ + int SetFacing(lua_State* L, Unit* unit) + { + float o = Eluna::CHECKVAL(L, 2); + unit->SetFacingTo(o); + return 0; + } + + /** + * Sets the [Unit] to face the given [WorldObject]'s direction. + * + * @param [WorldObject] target + */ + int SetFacingToObject(lua_State* L, Unit* unit) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + unit->SetFacingToObject(obj); + return 0; + } + + /** + * Sets creator GUID + * + * @param ObjectGuid guid + */ + int SetCreatorGUID(lua_State* L, Unit* unit) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + unit->SetCreatorGuid(guid); + return 0; + } + + /** + * Sets pet GUID + * + * @param ObjectGuid guid + */ + int SetPetGUID(lua_State* L, Unit* unit) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + unit->SetPetGuid(guid); + return 0; + } + + /** + * Toggles (Sets) [Unit]'s water walking + * + * @param bool enable = true + */ + int SetWaterWalk(lua_State* L, Unit* unit) + { + bool enable = Eluna::CHECKVAL(L, 2, true); + + unit->SetWaterWalk(enable); + return 0; + } + + /** + * Sets the [Unit]'s stand state + * + * @param uint8 state : stand state + */ + int SetStandState(lua_State* L, Unit* unit) + { + uint8 state = Eluna::CHECKVAL(L, 2); + + unit->SetStandState(state); + return 0; + } + + /** + * Sets the [Unit] in combat with the `enemy` [Unit]. + * + * @param [Unit] enemy : the [Unit] to start combat with + */ + int SetInCombatWith(lua_State* L, Unit* unit) + { + Unit* enemy = Eluna::CHECKOBJ(L, 2); + unit->SetInCombatWith(enemy); + return 0; + } + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Sets the [Unit]'s FFA flag on or off. + * + * @param bool apply = true + */ + int SetFFA(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + unit->SetPvPFreeForAll(apply); + return 0; + } + + /** + * Sets the [Unit]'s sanctuary flag on or off. + * + * @param bool apply = true + */ + int SetSanctuary(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + if (apply) + { + unit->SetPvPSanctuary(true); + unit->CombatStop(); + unit->CombatStopWithPets(); + } + else + unit->SetPvPSanctuary(false); + return 0; + } + + int SetCritterGUID(lua_State* L, Unit* unit) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + unit->SetCritterGuid(guid); + return 0; + } +#endif + + /** + * Roots the [Unit] to the ground, if 'false' specified, unroots the [Unit]. + * + * @param bool apply = true + */ + int SetRooted(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + unit->SetImmobilizedState(apply); + return 0; + } + + /** + * Confuses the [Unit], if 'false' specified, the [Unit] is no longer confused. + * + * @param bool apply = true + */ + int SetConfused(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + unit->SetConfused(apply); + return 0; + } + + /** + * Fears the [Unit], if 'false' specified, the [Unit] is no longer feared. + * + * @param bool apply = true + */ + int SetFeared(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + unit->SetFleeing(apply); + return 0; + } + + /** + * Clears the [Unit]'s threat list. + */ + int ClearThreatList(lua_State* /*L*/, Unit* unit) + { + unit->getThreatManager().clearReferences(); + return 0; + } + + /** + * Mounts the [Unit] on the given displayID/modelID. + * + * @param uint32 displayId + */ + int Mount(lua_State* L, Unit* unit) + { + uint32 displayId = Eluna::CHECKVAL(L, 2); + + unit->Mount(displayId); + return 0; + } + + /** + * Dismounts the [Unit]. + */ + int Dismount(lua_State* /*L*/, Unit* unit) + { + if (unit->IsMounted()) + { + unit->Unmount(); + unit->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + } + + return 0; + } + + /** + * Makes the [Unit] perform the given emote. + * + * @param uint32 emoteId + */ + int PerformEmote(lua_State* L, Unit* unit) + { + unit->HandleEmoteCommand(Eluna::CHECKVAL(L, 2)); + return 0; + } + + /** + * Makes the [Unit] perform the given emote continuously. + * + * @param uint32 emoteId + */ + int EmoteState(lua_State* L, Unit* unit) + { + uint32 emoteId = Eluna::CHECKVAL(L, 2); + + unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, emoteId); + return 0; + } + + /** + * Returns calculated percentage from Health + * + * @return int32 percentage + */ + int CountPctFromCurHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->CountPctFromCurHealth(Eluna::CHECKVAL(L, 2))); + return 1; + } + + /** + * Returns calculated percentage from Max Health + * + * @return int32 percentage + */ + int CountPctFromMaxHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->CountPctFromMaxHealth(Eluna::CHECKVAL(L, 2))); + return 1; + } + + /** + * Sends chat message to [Player] + * + * @param uint8 type : chat, whisper, etc + * @param uint32 lang : language to speak + * @param string msg + * @param [Player] target + */ + int SendChatMessageToPlayer(lua_State* L, Unit* unit) + { + uint8 type = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); + std::string msg = Eluna::CHECKVAL(L, 4); + Player* target = Eluna::CHECKOBJ(L, 5); + + if (type >= MAX_CHAT_MSG_TYPE) + return luaL_argerror(L, 2, "valid ChatMsg expected"); + if (lang >= LANGUAGES_COUNT) + return luaL_argerror(L, 3, "valid Language expected"); + + WorldPacket data; + ChatHandler::BuildChatPacket(data, ChatMsg(type), msg.c_str(), Language(lang), 0, unit->GET_GUID(), unit->GetName(), target->GET_GUID(), target->GetName()); + + target->GetSession()->SendPacket(data); + return 0; + } + + /** + * Stops the [Unit]'s movement + */ + int MoveStop(lua_State* /*L*/, Unit* unit) + { + unit->StopMoving(); + return 0; + } + + /** + * The [Unit]'s movement expires and clears movement + * + * @param bool reset = true : cleans movement + */ + int MoveExpire(lua_State* L, Unit* unit) + { + bool reset = Eluna::CHECKVAL(L, 2, true); + unit->GetMotionMaster()->MovementExpired(reset); + return 0; + } + + /** + * Clears the [Unit]'s movement + * + * @param bool reset = true : clean movement + */ + int MoveClear(lua_State* L, Unit* unit) + { + bool reset = Eluna::CHECKVAL(L, 2, true); + unit->GetMotionMaster()->Clear(reset); + return 0; + } + + /** + * The [Unit] will be idle + */ + int MoveIdle(lua_State* /*L*/, Unit* unit) + { + unit->GetMotionMaster()->MoveIdle(); + return 0; + } + + /** + * The [Unit] will move at random + * + * @param float radius : limit on how far the [Unit] will move at random + */ + int MoveRandom(lua_State* L, Unit* unit) + { + float radius = Eluna::CHECKVAL(L, 2); + float x, y, z; + unit->GetPosition(x, y, z); + + unit->GetMotionMaster()->MoveRandomAroundPoint(x, y, z, radius); + return 0; + } + + /** + * The [Unit] will move to its set home location + */ + int MoveHome(lua_State* /*L*/, Unit* unit) + { + unit->GetMotionMaster()->MoveTargetedHome(); + return 0; + } + + /** + * The [Unit] will follow the target + * + * @param [Unit] target : target to follow + * @param float dist = 0 : distance to start following + * @param float angle = 0 + */ + int MoveFollow(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + float dist = Eluna::CHECKVAL(L, 3, 0.0f); + float angle = Eluna::CHECKVAL(L, 4, 0.0f); + unit->GetMotionMaster()->MoveFollow(target, dist, angle); + return 0; + } + + /** + * The [Unit] will chase the target + * + * @param [Unit] target : target to chase + * @param float dist = 0 : distance start chasing + * @param float angle = 0 + */ + int MoveChase(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + float dist = Eluna::CHECKVAL(L, 3, 0.0f); + float angle = Eluna::CHECKVAL(L, 4, 0.0f); + unit->GetMotionMaster()->MoveChase(target, dist, angle); + return 0; + } + + /** + * The [Unit] will move confused + */ + int MoveConfused(lua_State* /*L*/, Unit* unit) + { + unit->GetMotionMaster()->MoveConfused(); + return 0; + } + + /** + * The [Unit] will flee + * + * @param [Unit] target + * @param uint32 time = 0 : flee delay + */ + int MoveFleeing(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + uint32 time = Eluna::CHECKVAL(L, 3, 0); + unit->GetMotionMaster()->MoveFleeing(target, time); + return 0; + } + + /** + * The [Unit] will move to the coordinates + * + * @param uint32 id : unique waypoint Id + * @param float x + * @param float y + * @param float z + * @param bool genPath = true : if true, generates path + */ + int MoveTo(lua_State* L, Unit* unit) + { + uint32 id = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + bool genPath = Eluna::CHECKVAL(L, 6, true); +#ifndef CATA + unit->GetMotionMaster()->MovePoint(id, x, y, z, FORCED_MOVEMENT_NONE, genPath); +#else + unit->GetMotionMaster()->MovePoint(id, x, y, z, genPath); +#endif + return 0; + } + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Makes the [Unit] jump to the coordinates + * + * @param float x + * @param float y + * @param float z + * @param float zSpeed : start velocity + * @param float maxHeight : maximum height + * @param uint32 id = 0 : unique movement Id + */ + int MoveJump(lua_State* L, Unit* unit) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float zSpeed = Eluna::CHECKVAL(L, 5); + float maxHeight = Eluna::CHECKVAL(L, 6); + uint32 id = Eluna::CHECKVAL(L, 7, 0); + +#if (defined(WOTLK) || defined(CATA)) + unit->GetMotionMaster()->MoveJump(x, y, z, zSpeed, maxHeight, id); +#else + Position pos(x, y, z); + unit->GetMotionMaster()->MoveJump(pos, zSpeed, maxHeight, id); +#endif + return 0; + } +#endif + + /** + * The [Unit] will whisper the message to a [Player] + * + * @param string msg : message for the [Unit] to emote + * @param uint32 lang : language for the [Unit] to speak + * @param [Player] receiver : specific [Unit] to receive the message + * @param bool bossWhisper = false : is a boss whisper + */ + int SendUnitWhisper(lua_State* L, Unit* unit) + { + const char* msg = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); + (void)lang; // ensure that the variable is referenced in order to pass compiler checks + Player* receiver = Eluna::CHECKOBJ(L, 4); + bool bossWhisper = Eluna::CHECKVAL(L, 5, false); + if (std::string(msg).length() > 0) + unit->MonsterWhisper(msg, receiver, bossWhisper); + return 0; + } + + /** + * The [Unit] will emote the message + * + * @param string msg : message for the [Unit] to emote + * @param [Unit] receiver = nil : specific [Unit] to receive the message + * @param bool bossEmote = false : is a boss emote + */ + int SendUnitEmote(lua_State* L, Unit* unit) + { + const char* msg = Eluna::CHECKVAL(L, 2); + Unit* receiver = Eluna::CHECKOBJ(L, 3, false); + bool bossEmote = Eluna::CHECKVAL(L, 4, false); + if (std::string(msg).length() > 0) + unit->MonsterTextEmote(msg, receiver, bossEmote); + return 0; + } + + /** + * The [Unit] will say the message + * + * @param string msg : message for the [Unit] to say + * @param uint32 language : language for the [Unit] to speak + */ + int SendUnitSay(lua_State* L, Unit* unit) + { + const char* msg = Eluna::CHECKVAL(L, 2); + uint32 language = Eluna::CHECKVAL(L, 3); + if (std::string(msg).length() > 0) + unit->MonsterSay(msg, language, unit); + return 0; + } + + /** + * The [Unit] will yell the message + * + * @param string msg : message for the [Unit] to yell + * @param uint32 language : language for the [Unit] to speak + */ + int SendUnitYell(lua_State* L, Unit* unit) + { + const char* msg = Eluna::CHECKVAL(L, 2); + uint32 language = Eluna::CHECKVAL(L, 3); + if (std::string(msg).length() > 0) + unit->MonsterYell(msg, language, unit); + return 0; + } + + /** + * Unmorphs the [Unit] setting it's display ID back to the native display ID. + */ + int DeMorph(lua_State* /*L*/, Unit* unit) + { + unit->DeMorph(); + return 0; + } + + /** + * Makes the [Unit] cast the spell on the target. + * + * @param [Unit] target = nil : can be self or another unit + * @param uint32 spell : entry of a spell + * @param bool triggered = false : if true the spell is instant and has no cost + */ + int CastSpell(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2, false); + uint32 spell = Eluna::CHECKVAL(L, 3); + bool triggered = Eluna::CHECKVAL(L, 4, false); + SpellEntry const* spellEntry = GetSpellStore()->LookupEntry(spell); + if (!spellEntry) + return 0; + + unit->CastSpell(target, spell, triggered ? TRIGGERED_OLD_TRIGGERED : 0); + return 0; + } + + /** + * Casts the [Spell] at target [Unit] with custom basepoints or casters. + * See also [Unit:CastSpell]. + * + * @param [Unit] target = nil + * @param uint32 spell + * @param bool triggered = false + * @param int32 bp0 = nil : custom basepoints for [Spell] effect 1. If nil, no change is made + * @param int32 bp1 = nil : custom basepoints for [Spell] effect 2. If nil, no change is made + * @param int32 bp2 = nil : custom basepoints for [Spell] effect 3. If nil, no change is made + * @param [Item] castItem = nil + * @param ObjectGuid originalCaster = ObjectGuid() + */ + int CastCustomSpell(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2, false); + uint32 spell = Eluna::CHECKVAL(L, 3); + bool triggered = Eluna::CHECKVAL(L, 4, false); + bool has_bp0 = !lua_isnoneornil(L, 5); + int32 bp0 = Eluna::CHECKVAL(L, 5, 0); + bool has_bp1 = !lua_isnoneornil(L, 6); + int32 bp1 = Eluna::CHECKVAL(L, 6, 0); + bool has_bp2 = !lua_isnoneornil(L, 7); + int32 bp2 = Eluna::CHECKVAL(L, 7, 0); + Item* castItem = Eluna::CHECKOBJ(L, 8, false); + ObjectGuid originalCaster = Eluna::CHECKVAL(L, 9, ObjectGuid()); + + unit->CastCustomSpell(target, spell, has_bp0 ? &bp0 : NULL, has_bp1 ? &bp1 : NULL, has_bp2 ? &bp2 : NULL, triggered, castItem, NULL, ObjectGuid(originalCaster)); + return 0; + } + + /** + * Makes the [Unit] cast the spell to the given coordinates, used for area effect spells. + * + * @param float x + * @param float y + * @param float z + * @param uint32 spell : entry of a spell + * @param bool triggered = true : if true the spell is instant and has no cost + */ + int CastSpellAoF(lua_State* L, Unit* unit) + { + float _x = Eluna::CHECKVAL(L, 2); + float _y = Eluna::CHECKVAL(L, 3); + float _z = Eluna::CHECKVAL(L, 4); + uint32 spell = Eluna::CHECKVAL(L, 5); + bool triggered = Eluna::CHECKVAL(L, 6, true); + + unit->CastSpell(_x, _y, _z, spell, triggered ? TRIGGERED_OLD_TRIGGERED : 0); + return 0; + } + + /** + * Clears the [Unit]'s combat + */ + int ClearInCombat(lua_State* /*L*/, Unit* unit) + { + unit->ClearInCombat(); + return 0; + } + + /** + * Stops the [Unit]'s current spell cast + * + * @param uint32 spell = 0 : entry of a spell + */ + int StopSpellCast(lua_State* L, Unit* unit) + { + uint32 spellId = Eluna::CHECKVAL(L, 2, 0); + unit->CastStop(spellId); + return 0; + } + + /** + * Interrupts [Unit]'s spell state, casting, etc. + * + * if spell is not interruptible, it will return + * + * @param int32 spellType : type of spell to interrupt + * @param bool delayed = true : skips if the spell is delayed + */ + int InterruptSpell(lua_State* L, Unit* unit) + { + int spellType = Eluna::CHECKVAL(L, 2); + bool delayed = Eluna::CHECKVAL(L, 3, true); + switch (spellType) + { + case 0: + spellType = CURRENT_MELEE_SPELL; + break; + case 1: + spellType = CURRENT_GENERIC_SPELL; + break; + case 2: + spellType = CURRENT_CHANNELED_SPELL; + break; + case 3: + spellType = CURRENT_AUTOREPEAT_SPELL; + break; + default: + return luaL_argerror(L, 2, "valid CurrentSpellTypes expected"); + } + + unit->InterruptSpell((CurrentSpellTypes)spellType, delayed); + return 0; + } + + /** + * Adds the [Aura] of the given spell entry on the given target from the [Unit]. + * + * @param uint32 spell : entry of a spell + * @param [Unit] target : aura will be applied on the target + * @return [Aura] aura + */ + int AddAura(lua_State* L, Unit* unit) + { + uint32 spell = Eluna::CHECKVAL(L, 2); + Unit* target = Eluna::CHECKOBJ(L, 3); + + SpellEntry const* spellEntry = GetSpellStore()->LookupEntry(spell); + if (!spellEntry) + return 1; + + if (!IsSpellAppliesAura(spellEntry) && !IsSpellHaveEffect(spellEntry, SPELL_EFFECT_PERSISTENT_AREA_AURA)) + return 1; + + SpellAuraHolder* holder = CreateSpellAuraHolder(spellEntry, target, unit); + + for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) + { +#ifdef CATA + SpellEffectEntry const* spellEffect = spellEntry->GetSpellEffect(SpellEffectIndex(i)); + if (!spellEffect) + continue; + uint8 eff = spellEffect->Effect; +#else + uint8 eff = spellEntry->Effect[i]; +#endif +#ifndef CATA + if (eff >= MAX_SPELL_EFFECTS) +#else + if (eff >= TOTAL_SPELL_EFFECTS) +#endif + continue; + if (IsAreaAuraEffect(eff) || + eff == SPELL_EFFECT_APPLY_AURA || + eff == SPELL_EFFECT_PERSISTENT_AREA_AURA) + { +#ifndef CATA + Aura* aur = CreateAura(spellEntry, SpellEffIndex(i), NULL, NULL, holder, target); +#else + Aura* aur = CreateAura(spellEntry, SpellEffIndex(i), NULL, holder, target); +#endif + holder->AddAura(aur, SpellEffIndex(i)); + } + } + Eluna::Push(L, target->AddSpellAuraHolder(holder)); + return 1; + } + + /** + * Removes [Aura] of the given spell entry from the [Unit]. + * + * @param uint32 spell : entry of a spell + */ + int RemoveAura(lua_State* L, Unit* unit) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + unit->RemoveAurasDueToSpell(spellId); + return 0; + } + + /** + * Removes all [Aura]'s from the [Unit]. + * + * Note: talents and racials are also auras, use with caution + */ + int RemoveAllAuras(lua_State* /*L*/, Unit* unit) + { + unit->RemoveAllAuras(); + return 0; + } + +#if !defined(CLASSIC) + /** + * Removes all positive visible [Aura]'s from the [Unit]. + */ + int RemoveArenaAuras(lua_State* /*L*/, Unit* unit) + { + unit->RemoveArenaAuras(); + return 0; + } +#endif + + /** + * Adds the given unit state for the [Unit]. + * + * @param [UnitState] state + */ + int AddUnitState(lua_State* L, Unit* unit) + { + uint32 state = Eluna::CHECKVAL(L, 2); + + unit->addUnitState(state); + return 0; + } + + /** + * Removes the given unit state from the [Unit]. + * + * @param [UnitState] state + */ + int ClearUnitState(lua_State* L, Unit* unit) + { + uint32 state = Eluna::CHECKVAL(L, 2); + + unit->clearUnitState(state); + return 0; + } + + /** + * Makes the [Unit] teleport to given coordinates within same map. + * + * @param float x + * @param float y + * @param float z + * @param float o : orientation + */ + int NearTeleport(lua_State* L, Unit* unit) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float o = Eluna::CHECKVAL(L, 5); + + unit->NearTeleportTo(x, y, z, o); + return 0; + } + + /** + * Makes the [Unit] damage the target [Unit] + * + *
+     * enum SpellSchools
+     * {
+     *     SPELL_SCHOOL_NORMAL  = 0,
+     *     SPELL_SCHOOL_HOLY    = 1,
+     *     SPELL_SCHOOL_FIRE    = 2,
+     *     SPELL_SCHOOL_NATURE  = 3,
+     *     SPELL_SCHOOL_FROST   = 4,
+     *     SPELL_SCHOOL_SHADOW  = 5,
+     *     SPELL_SCHOOL_ARCANE  = 6,
+     *     MAX_SPELL_SCHOOL     = 7
+     * };
+     * 
+ * + * @param [Unit] target : [Unit] to damage + * @param uint32 damage : amount to damage + * @param bool durabilityloss = true : if false, the damage does not do durability damage + * @param [SpellSchools] school = MAX_SPELL_SCHOOL : school the damage is done in or MAX_SPELL_SCHOOL for direct damage + * @param uint32 spell = 0 : spell that inflicts the damage + */ + int DealDamage(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + uint32 damage = Eluna::CHECKVAL(L, 3); + bool durabilityloss = Eluna::CHECKVAL(L, 4, true); + uint32 school = Eluna::CHECKVAL(L, 5, MAX_SPELL_SCHOOL); + uint32 spell = Eluna::CHECKVAL(L, 6, 0); + if (school > MAX_SPELL_SCHOOL) + return luaL_argerror(L, 6, "valid SpellSchool expected"); + + // flat melee damage without resistence/etc reduction + if (school == MAX_SPELL_SCHOOL) + { +#if !defined(CATA) + Unit::DealDamage(unit, target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, durabilityloss); + unit->SendAttackStateUpdate(HITINFO_NORMALSWING2, target, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); +#else + unit->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, durabilityloss); + unit->SendAttackStateUpdate(HITINFO_NORMALSWING2, target, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); +#endif + return 0; + } + + SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); + + if (schoolmask & SPELL_SCHOOL_MASK_NORMAL) +#ifndef CATA + damage = unit->CalcArmorReducedDamage(unit, target, damage); +#else + damage = unit->CalcArmorReducedDamage(target, damage); +#endif + +#ifdef TRINITY + // melee damage by specific school + if (!spell) + { + DamageInfo dmgInfo(unit, target, damage, nullptr, schoolmask, SPELL_DIRECT_DAMAGE, BASE_ATTACK); + unit->CalcAbsorbResist(dmgInfo); + + if (!dmgInfo.GetDamage()) + damage = 0; + else + damage = dmgInfo.GetDamage(); + + uint32 absorb = dmgInfo.GetAbsorb(); + uint32 resist = dmgInfo.GetResist(); + unit->DealDamageMods(target, damage, &absorb); +#ifdef TRINITY + Unit::DealDamage(unit, target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); +#else + unit->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); +#endif + unit->SendAttackStateUpdate(HITINFO_AFFECTS_VICTIM, target, 0, schoolmask, damage, absorb, resist, VICTIMSTATE_HIT, 0); + return 0; + } + + if (!spell) + return 0; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell); + if (!spellInfo) + return 0; + + SpellNonMeleeDamage dmgInfo(unit, target, spell, spellInfo->GetSchoolMask()); +#ifdef TRINITY + Unit::DealDamageMods(dmgInfo.target, dmgInfo.damage, &dmgInfo.absorb); +#else + damage = unit->SpellDamageBonusDone(target, spellInfo, damage, SPELL_DIRECT_DAMAGE; + damage = target->SpellDamageBonusTaken(unit, spellInfo, damage, SPELL_DIRECT_DAMAGE); + unit->CalculateSpellDamageTaken(&dmgInfo, damage, spellInfo); + unit->DealDamageMods(dmgInfo.target, dmgInfo.damage, &dmgInfo.absorb); +#endif + + unit->SendSpellNonMeleeDamageLog(&dmgInfo); + unit->DealSpellDamage(&dmgInfo, true); + return 0; +#elif AZEROTHCORE + if (!spell) + { + DamageInfo dmgInfo(unit, target, damage, nullptr, schoolmask, SPELL_DIRECT_DAMAGE); + unit->CalcAbsorbResist(dmgInfo); + + if (!dmgInfo.GetDamage()) + damage = 0; + else + damage = dmgInfo.GetDamage(); + + uint32 absorb = dmgInfo.GetAbsorb(); + uint32 resist = dmgInfo.GetResist(); + unit->DealDamageMods(target, damage, &absorb); + Unit::DealDamage(unit, target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); + unit->SendAttackStateUpdate(HITINFO_AFFECTS_VICTIM, target, 0, schoolmask, damage, absorb, resist, VICTIMSTATE_HIT, 0); + return 0; + } + + if (!spell) + return 0; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell); + if (!spellInfo) + return 0; + + SpellNonMeleeDamage dmgInfo(unit, target, spellInfo, spellInfo->GetSchoolMask()); + Unit::DealDamageMods(dmgInfo.target, dmgInfo.damage, &dmgInfo.absorb); + unit->SendSpellNonMeleeDamageLog(&dmgInfo); + unit->DealSpellDamage(&dmgInfo, true); + return 0; +#else + // melee damage by specific school + if (!spell) + { + uint32 absorb = 0; +#ifndef CATA + int32 resist = 0; +#else + uint32 resist = 0; +#endif + target->CalculateDamageAbsorbAndResist(unit, schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + + if (damage <= absorb + resist) + damage = 0; + else + damage -= absorb + resist; + +#ifndef CATA + unit->DealDamageMods(unit, target, damage, &absorb, DIRECT_DAMAGE); + unit->DealDamage(unit, target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); +#elif defined(CATA) + unit->DealDamageMods(target, damage, &absorb, DIRECT_DAMAGE); + unit->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); +#else + unit->DealDamageMods(target, damage, &absorb); + unit->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); +#endif + unit->SendAttackStateUpdate(HITINFO_NORMALSWING2, target, schoolmask, damage, absorb, resist, VICTIMSTATE_NORMAL, 0); + return 0; + } + + // non-melee damage + unit->SpellNonMeleeDamageLog(target, spell, damage); + return 0; +#endif + } + + /** + * Makes the [Unit] heal the target [Unit] with given spell + * + * @param [Unit] target : [Unit] to heal + * @param uint32 spell : spell that causes the healing + * @param uint32 amount : amount to heal + * @param bool critical = false : if true, heal is logged as critical + */ + int DealHeal(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + uint32 spell = Eluna::CHECKVAL(L, 3); + uint32 amount = Eluna::CHECKVAL(L, 4); + bool critical = Eluna::CHECKVAL(L, 5, false); + + SpellEntry const* spellEntry = GetSpellStore()->LookupEntry(spell); + if (spellEntry) + unit->DealHeal(target, amount, spellEntry, critical); + return 0; + } + + /** + * Makes the [Unit] kill the target [Unit] + * + * @param [Unit] target : [Unit] to kill + * @param bool durLoss = true : when true, the target's items suffer durability loss + */ + int Kill(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + bool durLoss = Eluna::CHECKVAL(L, 3, true); + +#if !defined(CATA) + unit->DealDamage(unit, target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, durLoss); +#else + unit->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, durLoss); +#endif + return 0; + } + + /** + * Adds threat to the [Unit] from the victim. + * + *
+     * enum SpellSchoolMask
+     * {
+     *     SPELL_SCHOOL_MASK_NONE    = 0,
+     *     SPELL_SCHOOL_MASK_NORMAL  = 1,
+     *     SPELL_SCHOOL_MASK_HOLY    = 2,
+     *     SPELL_SCHOOL_MASK_FIRE    = 4,
+     *     SPELL_SCHOOL_MASK_NATURE  = 8,
+     *     SPELL_SCHOOL_MASK_FROST   = 16,
+     *     SPELL_SCHOOL_MASK_SHADOW  = 32,
+     *     SPELL_SCHOOL_MASK_ARCANE  = 64,
+     * }
+     * 
+ * + * @param [Unit] victim : [Unit] that caused the threat + * @param float threat : threat amount + * @param [SpellSchoolMask] schoolMask = 0 : [SpellSchoolMask] of the threat causer + * @param uint32 spell = 0 : spell entry used for threat + */ + int AddThreat(lua_State* L, Unit* unit) + { + Unit* victim = Eluna::CHECKOBJ(L, 2); + float threat = Eluna::CHECKVAL(L, 3, true); + uint32 spell = Eluna::CHECKVAL(L, 4, 0); + + uint32 schoolMask = Eluna::CHECKVAL(L, 5, 0); + SpellEntry const* spellEntry = GetSpellStore()->LookupEntry(spell); + unit->AddThreat(victim, threat, false, (SpellSchoolMask)schoolMask, spellEntry); + +#ifdef CLASSIC + unit->AddThreat(victim, threat, false, spellEntry ? GetSchoolMask(spellEntry->School) : SPELL_SCHOOL_MASK_NONE, spellEntry); +#else + unit->AddThreat(victim, threat, false, spellEntry ? static_cast(spellEntry->SchoolMask) : SPELL_SCHOOL_MASK_NONE, spellEntry); +#endif + return 0; + } + + ElunaRegister UnitMethods[] = + { + // Getters + { "GetLevel", &LuaUnit::GetLevel }, + { "GetHealth", &LuaUnit::GetHealth }, + { "GetDisplayId", &LuaUnit::GetDisplayId }, + { "GetNativeDisplayId", &LuaUnit::GetNativeDisplayId }, + { "GetPower", &LuaUnit::GetPower }, + { "GetMaxPower", &LuaUnit::GetMaxPower }, + { "GetPowerType", &LuaUnit::GetPowerType }, + { "GetMaxHealth", &LuaUnit::GetMaxHealth }, + { "GetHealthPct", &LuaUnit::GetHealthPct }, + { "GetPowerPct", &LuaUnit::GetPowerPct }, + { "GetGender", &LuaUnit::GetGender }, + { "GetRace", &LuaUnit::GetRace }, + { "GetClass", &LuaUnit::GetClass }, + { "GetRaceMask", &LuaUnit::GetRaceMask }, + { "GetClassMask", &LuaUnit::GetClassMask }, + { "GetRaceAsString", &LuaUnit::GetRaceAsString }, + { "GetClassAsString", &LuaUnit::GetClassAsString }, + { "GetAura", &LuaUnit::GetAura }, + { "GetFaction", &LuaUnit::GetFaction }, + { "GetCurrentSpell", &LuaUnit::GetCurrentSpell }, + { "GetCreatureType", &LuaUnit::GetCreatureType }, + { "GetMountId", &LuaUnit::GetMountId }, + { "GetOwner", &LuaUnit::GetOwner }, + { "GetFriendlyUnitsInRange", &LuaUnit::GetFriendlyUnitsInRange }, + { "GetUnfriendlyUnitsInRange", &LuaUnit::GetUnfriendlyUnitsInRange }, + { "GetOwnerGUID", &LuaUnit::GetOwnerGUID }, + { "GetCreatorGUID", &LuaUnit::GetCreatorGUID }, + { "GetMinionGUID", &LuaUnit::GetPetGUID }, + { "GetCharmerGUID", &LuaUnit::GetCharmerGUID }, + { "GetCharmGUID", &LuaUnit::GetCharmGUID }, + { "GetPetGUID", &LuaUnit::GetPetGUID }, + { "GetControllerGUID", &LuaUnit::GetControllerGUID }, + { "GetControllerGUIDS", &LuaUnit::GetControllerGUIDS }, + { "GetStandState", &LuaUnit::GetStandState }, + { "GetVictim", &LuaUnit::GetVictim }, + { "GetSpeed", &LuaUnit::GetSpeed }, + { "GetStat", &LuaUnit::GetStat }, + { "GetBaseSpellPower", &LuaUnit::GetBaseSpellPower }, + { "GetMovementType", &LuaUnit::GetMovementType }, +#if defined(WOTLK) + { "GetCritterGUID", &LuaUnit::GetCritterGUID }, + { "GetVehicleKit", &LuaUnit::GetVehicleKit }, +#endif + + // Setters + { "SetFaction", &LuaUnit::SetFaction }, + { "SetLevel", &LuaUnit::SetLevel }, + { "SetHealth", &LuaUnit::SetHealth }, + { "SetMaxHealth", &LuaUnit::SetMaxHealth }, + { "SetPower", &LuaUnit::SetPower }, + { "SetMaxPower", &LuaUnit::SetMaxPower }, + { "SetPowerType", &LuaUnit::SetPowerType }, + { "SetDisplayId", &LuaUnit::SetDisplayId }, + { "SetNativeDisplayId", &LuaUnit::SetNativeDisplayId }, + { "SetFacing", &LuaUnit::SetFacing }, + { "SetFacingToObject", &LuaUnit::SetFacingToObject }, + { "SetSpeed", &LuaUnit::SetSpeed }, + {"SetRooted", &LuaUnit::SetRooted}, + {"SetConfused", &LuaUnit::SetConfused}, + {"SetFeared", &LuaUnit::SetFeared}, + { "SetPvP", &LuaUnit::SetPvP }, + { "SetOwnerGUID", &LuaUnit::SetOwnerGUID }, + { "SetName", &LuaUnit::SetName }, + { "SetSheath", &LuaUnit::SetSheath }, + { "SetCreatorGUID", &LuaUnit::SetCreatorGUID }, + { "SetMinionGUID", &LuaUnit::SetPetGUID }, + { "SetPetGUID", &LuaUnit::SetPetGUID }, + { "SetWaterWalk", &LuaUnit::SetWaterWalk }, + { "SetStandState", &LuaUnit::SetStandState }, + { "SetInCombatWith", &LuaUnit::SetInCombatWith }, + { "ModifyPower", &LuaUnit::ModifyPower }, +#if defined(WOTLK) + { "SetFFA", &LuaUnit::SetFFA }, + { "SetSanctuary", &LuaUnit::SetSanctuary }, + { "SetCritterGUID", &LuaUnit::SetCritterGUID }, +#endif + + // Boolean + { "IsAlive", &LuaUnit::IsAlive }, + { "IsDead", &LuaUnit::IsDead }, + { "IsDying", &LuaUnit::IsDying }, + { "IsPvPFlagged", &LuaUnit::IsPvPFlagged }, + { "IsInCombat", &LuaUnit::IsInCombat }, + { "IsBanker", &LuaUnit::IsBanker }, + { "IsBattleMaster", &LuaUnit::IsBattleMaster }, + { "IsCharmed", &LuaUnit::IsCharmed }, + { "IsArmorer", &LuaUnit::IsArmorer }, + { "IsAttackingPlayer", &LuaUnit::IsAttackingPlayer }, + { "IsInWater", &LuaUnit::IsInWater }, + { "IsUnderWater", &LuaUnit::IsUnderWater }, + { "IsAuctioneer", &LuaUnit::IsAuctioneer }, + { "IsGuildMaster", &LuaUnit::IsGuildMaster }, + { "IsInnkeeper", &LuaUnit::IsInnkeeper }, + { "IsTrainer", &LuaUnit::IsTrainer }, + { "IsGossip", &LuaUnit::IsGossip }, + { "IsTaxi", &LuaUnit::IsTaxi }, + { "IsSpiritHealer", &LuaUnit::IsSpiritHealer }, + { "IsSpiritGuide", &LuaUnit::IsSpiritGuide }, + { "IsTabardDesigner", &LuaUnit::IsTabardDesigner }, + { "IsServiceProvider", &LuaUnit::IsServiceProvider }, + { "IsSpiritService", &LuaUnit::IsSpiritService }, + { "HealthBelowPct", &LuaUnit::HealthBelowPct }, + { "HealthAbovePct", &LuaUnit::HealthAbovePct }, + { "IsMounted", &LuaUnit::IsMounted }, + { "AttackStop", &LuaUnit::AttackStop }, + { "Attack", &LuaUnit::Attack }, + { "IsStopped", &LuaUnit::IsStopped }, + { "HasUnitState", &LuaUnit::HasUnitState }, + { "IsQuestGiver", &LuaUnit::IsQuestGiver }, + { "IsInAccessiblePlaceFor", &LuaUnit::IsInAccessiblePlaceFor }, + { "IsVendor", &LuaUnit::IsVendor }, + { "IsRooted", &LuaUnit::IsRooted }, + { "IsFullHealth", &LuaUnit::IsFullHealth }, + { "HasAura", &LuaUnit::HasAura }, + { "IsCasting", &LuaUnit::IsCasting }, + { "IsStandState", &LuaUnit::IsStandState }, +#if defined(TBC) || defined(WOTLK) + { "IsOnVehicle", &LuaUnit::IsOnVehicle }, +#endif + + // Other + { "AddAura", &LuaUnit::AddAura }, + { "RemoveAura", &LuaUnit::RemoveAura }, + { "RemoveAllAuras", &LuaUnit::RemoveAllAuras }, + { "ClearInCombat", &LuaUnit::ClearInCombat }, + { "DeMorph", &LuaUnit::DeMorph }, + { "SendUnitWhisper", &LuaUnit::SendUnitWhisper }, + { "SendUnitEmote", &LuaUnit::SendUnitEmote }, + { "SendUnitSay", &LuaUnit::SendUnitSay }, + { "SendUnitYell", &LuaUnit::SendUnitYell }, + { "CastSpell", &LuaUnit::CastSpell }, + { "CastCustomSpell", &LuaUnit::CastCustomSpell }, + { "CastSpellAoF", &LuaUnit::CastSpellAoF }, + { "Kill", &LuaUnit::Kill }, + { "StopSpellCast", &LuaUnit::StopSpellCast }, + { "InterruptSpell", &LuaUnit::InterruptSpell }, + { "SendChatMessageToPlayer", &LuaUnit::SendChatMessageToPlayer }, + { "PerformEmote", &LuaUnit::PerformEmote }, + { "EmoteState", &LuaUnit::EmoteState }, + { "CountPctFromCurHealth", &LuaUnit::CountPctFromCurHealth }, + { "CountPctFromMaxHealth", &LuaUnit::CountPctFromMaxHealth }, + { "Dismount", &LuaUnit::Dismount }, + { "Mount", &LuaUnit::Mount }, + { "ClearThreatList", &LuaUnit::ClearThreatList }, + { "ClearUnitState", &LuaUnit::ClearUnitState }, + { "AddUnitState", &LuaUnit::AddUnitState }, + { "NearTeleport", &LuaUnit::NearTeleport }, + { "MoveIdle", &LuaUnit::MoveIdle }, + { "MoveRandom", &LuaUnit::MoveRandom }, + { "MoveHome", &LuaUnit::MoveHome }, + { "MoveFollow", &LuaUnit::MoveFollow }, + { "MoveChase", &LuaUnit::MoveChase }, + { "MoveConfused", &LuaUnit::MoveConfused }, + { "MoveFleeing", &LuaUnit::MoveFleeing }, + { "MoveTo", &LuaUnit::MoveTo }, + { "MoveStop", &LuaUnit::MoveStop }, + { "MoveExpire", &LuaUnit::MoveExpire }, + { "MoveClear", &LuaUnit::MoveClear }, + { "DealDamage", &LuaUnit::DealDamage }, + { "DealHeal", &LuaUnit::DealHeal }, + { "AddThreat", &LuaUnit::AddThreat }, +#if defined(TBC) || defined(WOTLK) + { "RemoveArenaAuras", &LuaUnit::RemoveArenaAuras }, +#endif +#if defined(WOTLK) + { "MoveJump", &LuaUnit::MoveJump }, +#endif + + // Not implemented methods + { "GetVehicle", nullptr }, // not implemented + { "SetStunned", nullptr }, // not implemented + { "SetCanFly", nullptr }, // not implemented + { "SetVisible", nullptr }, // not implemented + { "IsVisible", nullptr }, // not implemented + { "IsMoving", nullptr }, // not implemented + { "IsFlying", nullptr }, // not implemented + { "RestoreDisplayId", nullptr }, // not implemented + { "RestoreFaction", nullptr }, //not implemented + { "RemoveBindSightAuras", nullptr }, // not implemented + { "RemoveCharmAuras", nullptr }, // not implemented + { "DisableMelee", nullptr }, // not implemented + { "SummonGuardian", nullptr }, // not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/VehicleMethods.h b/src/modules/Eluna/CMangos/VehicleMethods.h new file mode 100644 index 0000000000..0693a15ec7 --- /dev/null +++ b/src/modules/Eluna/CMangos/VehicleMethods.h @@ -0,0 +1,115 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef VEHICLEMETHODS_H +#define VEHICLEMETHODS_H +#ifndef CLASSIC +#ifndef TBC + +/*** + * Inherits all methods from: none + */ +namespace LuaVehicle +{ + /** + * Returns true if the [Unit] passenger is on board + * + * @param [Unit] passenger + * @return bool isOnBoard + */ + int IsOnBoard(lua_State* L, Vehicle* vehicle) + { + Unit* passenger = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, vehicle->HasOnBoard(passenger)); + return 1; + } + + /** + * Returns the [Vehicle]'s owner + * + * @return [Unit] owner + */ + int GetOwner(lua_State* L, Vehicle* vehicle) + { + Eluna::Push(L, vehicle->GetOwner()); + return 1; + } + + /** + * Returns the [Vehicle]'s entry + * + * @return uint32 entry + */ + int GetEntry(lua_State* L, Vehicle* vehicle) + { + Eluna::Push(L, vehicle->GetVehicleEntry()->m_ID); + return 1; + } + + /** + * Returns the [Vehicle]'s passenger in the specified seat + * + * @param int8 seat + * @return [Unit] passenger + */ + int GetPassenger(lua_State* L, Vehicle* vehicle) + { + int8 seatId = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, vehicle->GetPassenger(seatId)); + return 1; + } + + /** + * Adds [Unit] passenger to a specified seat in the [Vehicle] + * + * @param [Unit] passenger + * @param int8 seat + */ + int AddPassenger(lua_State* L, Vehicle* vehicle) + { + Unit* passenger = Eluna::CHECKOBJ(L, 2); + int8 seatId = Eluna::CHECKVAL(L, 3); + + if (vehicle->CanBoard(passenger)) + vehicle->Board(passenger, seatId); + return 0; + } + + /** + * Removes [Unit] passenger from the [Vehicle] + * + * @param [Unit] passenger + */ + int RemovePassenger(lua_State* L, Vehicle* vehicle) + { + Unit* passenger = Eluna::CHECKOBJ(L, 2); + + vehicle->UnBoard(passenger, false); + return 0; + } + + ElunaRegister VehicleMethods[] = + { + // Getters + { "GetOwner", &LuaVehicle::GetOwner }, + { "GetEntry", &LuaVehicle::GetEntry }, + { "GetPassenger", &LuaVehicle::GetPassenger }, + + // Boolean + { "IsOnBoard", &LuaVehicle::IsOnBoard }, + + // Other + { "AddPassenger", &LuaVehicle::AddPassenger }, + { "RemovePassenger", &LuaVehicle::RemovePassenger }, + + { NULL, NULL } + }; +} + +#endif // CLASSIC +#endif // TBC +#endif // VEHICLEMETHODS_H diff --git a/src/modules/Eluna/CMangos/WorldObjectMethods.h b/src/modules/Eluna/CMangos/WorldObjectMethods.h new file mode 100644 index 0000000000..23cb926da4 --- /dev/null +++ b/src/modules/Eluna/CMangos/WorldObjectMethods.h @@ -0,0 +1,1163 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef WORLDOBJECTMETHODS_H +#define WORLDOBJECTMETHODS_H + +/*** + * Inherits all methods from: [Object] + */ +namespace LuaWorldObject +{ + /** + * Returns the name of the [WorldObject] + * + * @return string name + */ + int GetName(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetName()); + return 1; + } + + /** + * Returns the current [Map] object of the [WorldObject] + * + * @return [Map] mapObject + */ + int GetMap(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetMap()); + return 1; + } + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Returns the current phase of the [WorldObject] + * + * @return uint32 phase + */ + int GetPhaseMask(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPhaseMask()); + return 1; + } + + /** + * Sets the [WorldObject]'s phase mask. + * + * @param uint32 phaseMask + * @param bool update = true : update visibility to nearby objects + */ + int SetPhaseMask(lua_State* L, WorldObject* obj) + { + uint32 phaseMask = Eluna::CHECKVAL(L, 2); + bool update = Eluna::CHECKVAL(L, 3, true); + obj->SetPhaseMask(phaseMask, update); + return 0; + } +#endif + + /** + * Returns the current instance ID of the [WorldObject] + * + * @return uint32 instanceId + */ + int GetInstanceId(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetInstanceId()); + return 1; + } + + /** + * Returns the current area ID of the [WorldObject] + * + * @return uint32 areaId + */ + int GetAreaId(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetAreaId()); + return 1; + } + + /** + * Returns the current zone ID of the [WorldObject] + * + * @return uint32 zoneId + */ + int GetZoneId(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetZoneId()); + return 1; + } + + /** + * Returns the current map ID of the [WorldObject] + * + * @return uint32 mapId + */ + int GetMapId(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetMapId()); + return 1; + } + + /** + * Returns the current X coordinate of the [WorldObject] + * + * @return float x + */ + int GetX(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPositionX()); + return 1; + } + + /** + * Returns the current Y coordinate of the [WorldObject] + * + * @return float y + */ + int GetY(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPositionY()); + return 1; + } + + /** + * Returns the current Z coordinate of the [WorldObject] + * + * @return float z + */ + int GetZ(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPositionZ()); + return 1; + } + + /** + * Returns the current orientation of the [WorldObject] + * + * @return float orientation / facing + */ + int GetO(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetOrientation()); + return 1; + } + + /** + * Returns the coordinates and orientation of the [WorldObject] + * + * @return float x : x coordinate of the [WorldObject] + * @return float y : y coordinate of the [WorldObject] + * @return float z : z coordinate (height) of the [WorldObject] + * @return float o : facing / orientation of the [WorldObject] + */ + int GetLocation(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPositionX()); + Eluna::Push(L, obj->GetPositionY()); + Eluna::Push(L, obj->GetPositionZ()); + Eluna::Push(L, obj->GetOrientation()); + return 4; + } + + /** + * Returns the nearest [Player] object in sight of the [WorldObject] or within the given range + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return [Player] nearestPlayer + */ + int GetNearestPlayer(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 hostile = Eluna::CHECKVAL(L, 3, 0); + uint32 dead = Eluna::CHECKVAL(L, 4, 1); + + Unit* target = NULL; + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_PLAYER, 0, hostile, dead); + MaNGOS::UnitLastSearcher searcher(target, checker); + Cell::VisitWorldObjects(obj, searcher, range); + + Eluna::Push(L, target); + return 1; + } + + /** + * Returns the nearest [GameObject] object in sight of the [WorldObject] or within the given range and/or with a specific entry ID + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 entryId = 0 : optionally set entry ID of game object to find + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * + * @return [GameObject] nearestGameObject + */ + int GetNearestGameObject(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 entry = Eluna::CHECKVAL(L, 3, 0); + uint32 hostile = Eluna::CHECKVAL(L, 4, 0); + + GameObject* target = NULL; + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_GAMEOBJECT, entry, hostile); + MaNGOS::GameObjectLastSearcher searcher(target, checker); + Cell::VisitGridObjects(obj, searcher, range); + + Eluna::Push(L, target); + return 1; + } + + /** + * Returns the nearest [Creature] object in sight of the [WorldObject] or within the given range and/or with a specific entry ID + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 entryId = 0 : optionally set entry ID of creature to find + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return [Creature] nearestCreature + */ + int GetNearestCreature(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 entry = Eluna::CHECKVAL(L, 3, 0); + uint32 hostile = Eluna::CHECKVAL(L, 4, 0); + uint32 dead = Eluna::CHECKVAL(L, 5, 1); + + Creature* target = NULL; + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_UNIT, entry, hostile, dead); + MaNGOS::CreatureLastSearcher searcher(target, checker); + Cell::VisitGridObjects(obj, searcher, range); + + Eluna::Push(L, target); + return 1; + } + + /** + * Returns a table of [Player] objects in sight of the [WorldObject] or within the given range + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return table playersInRange : table of [Player]s + */ + int GetPlayersInRange(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 hostile = Eluna::CHECKVAL(L, 3, 0); + uint32 dead = Eluna::CHECKVAL(L, 4, 1); + + std::list list; + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_PLAYER, 0, hostile, dead); + MaNGOS::PlayerListSearcher searcher(list, checker); + Cell::VisitWorldObjects(obj, searcher, range); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns a table of [Creature] objects in sight of the [WorldObject] or within the given range and/or with a specific entry ID + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 entryId = 0 : optionally set entry ID of creatures to find + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return table creaturesInRange : table of [Creature]s + */ + int GetCreaturesInRange(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 entry = Eluna::CHECKVAL(L, 3, 0); + uint32 hostile = Eluna::CHECKVAL(L, 4, 0); + uint32 dead = Eluna::CHECKVAL(L, 5, 1); + + std::list list; + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_UNIT, entry, hostile, dead); + MaNGOS::CreatureListSearcher searcher(list, checker); + Cell::VisitGridObjects(obj, searcher, range); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns a table of [GameObject] objects in sight of the [WorldObject] or within the given range and/or with a specific entry ID + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 entryId = 0 : optionally set entry ID of game objects to find + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * + * @return table gameObjectsInRange : table of [GameObject]s + */ + int GetGameObjectsInRange(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 entry = Eluna::CHECKVAL(L, 3, 0); + uint32 hostile = Eluna::CHECKVAL(L, 4, 0); + + std::list list; + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_GAMEOBJECT, entry, hostile); + MaNGOS::GameObjectListSearcher searcher(list, checker); + Cell::VisitGridObjects(obj, searcher, range); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns nearest [WorldObject] in sight of the [WorldObject]. + * The distance, type, entry and hostility requirements the [WorldObject] must match can be passed. + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param [TypeMask] type = 0 : the [TypeMask] that the [WorldObject] must be. This can contain multiple types. 0 will be ingored + * @param uint32 entry = 0 : the entry of the [WorldObject], 0 will be ingored + * @param uint32 hostile = 0 : specifies whether the [WorldObject] needs to be 1 hostile, 2 friendly or 0 either + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return [WorldObject] worldObject + */ + int GetNearObject(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint16 type = Eluna::CHECKVAL(L, 3, 0); // TypeMask + uint32 entry = Eluna::CHECKVAL(L, 4, 0); + uint32 hostile = Eluna::CHECKVAL(L, 5, 0); // 0 none, 1 hostile, 2 friendly + uint32 dead = Eluna::CHECKVAL(L, 6, 1); // 0 both, 1 alive, 2 dead + + float x, y, z; + obj->GetPosition(x, y, z); + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, type, entry, hostile, dead); + + WorldObject* target = NULL; + MaNGOS::WorldObjectLastSearcher searcher(target, checker); + Cell::VisitAllObjects(obj, searcher, range); + + Eluna::Push(L, target); + return 1; + } + + /** + * Returns a table of [WorldObject]s in sight of the [WorldObject]. + * The distance, type, entry and hostility requirements the [WorldObject] must match can be passed. + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param [TypeMask] type = 0 : the [TypeMask] that the [WorldObject] must be. This can contain multiple types. 0 will be ingored + * @param uint32 entry = 0 : the entry of the [WorldObject], 0 will be ingored + * @param uint32 hostile = 0 : specifies whether the [WorldObject] needs to be 1 hostile, 2 friendly or 0 either + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return table worldObjectList : table of [WorldObject]s + */ + int GetNearObjects(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint16 type = Eluna::CHECKVAL(L, 3, 0); // TypeMask + uint32 entry = Eluna::CHECKVAL(L, 4, 0); + uint32 hostile = Eluna::CHECKVAL(L, 5, 0); // 0 none, 1 hostile, 2 friendly + uint32 dead = Eluna::CHECKVAL(L, 6, 1); // 0 both, 1 alive, 2 dead + + float x, y, z; + obj->GetPosition(x, y, z); + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, type, entry, hostile, dead); + + std::list list; + MaNGOS::WorldObjectListSearcher searcher(list, checker); + Cell::VisitAllObjects(obj, searcher, range); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns the distance from this [WorldObject] to another [WorldObject], or from this [WorldObject] to a point in 3d space. + * + * The function takes into account the given object sizes. See also [WorldObject:GetExactDistance], [WorldObject:GetDistance2d] + * + * @proto dist = (obj) + * @proto dist = (x, y, z) + * + * @param [WorldObject] obj + * @param float x : the X-coordinate of the point + * @param float y : the Y-coordinate of the point + * @param float z : the Z-coordinate of the point + * + * @return float dist : the distance in yards + */ + int GetDistance(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + Eluna::Push(L, obj->GetDistance(target)); + else + { + float X = Eluna::CHECKVAL(L, 2); + float Y = Eluna::CHECKVAL(L, 3); + float Z = Eluna::CHECKVAL(L, 4); + Eluna::Push(L, obj->GetDistance(X, Y, Z)); + } + return 1; + } + + /** + * Returns the distance from this [WorldObject] to another [WorldObject], or from this [WorldObject] to a point in 3d space. + * + * The function does not take into account the given object sizes, which means only the object coordinates are compared. See also [WorldObject:GetDistance], [WorldObject:GetDistance2d] + * + * @proto dist = (obj) + * @proto dist = (x, y, z) + * + * @param [WorldObject] obj + * @param float x : the X-coordinate of the point + * @param float y : the Y-coordinate of the point + * @param float z : the Z-coordinate of the point + * + * @return float dist : the distance in yards + */ + int GetExactDistance(lua_State* L, WorldObject* obj) + { + float x, y, z; + obj->GetPosition(x, y, z); + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + { + float x2, y2, z2; + target->GetPosition(x2, y2, z2); + x -= x2; + y -= y2; + z -= z2; + } + else + { + x -= Eluna::CHECKVAL(L, 2); + y -= Eluna::CHECKVAL(L, 3); + z -= Eluna::CHECKVAL(L, 4); + } + + Eluna::Push(L, std::sqrt(x*x + y*y + z*z)); + return 1; + } + + /** + * Returns the distance from this [WorldObject] to another [WorldObject], or from this [WorldObject] to a point in 2d space. + * + * The function takes into account the given object sizes. See also [WorldObject:GetDistance], [WorldObject:GetExactDistance2d] + * + * @proto dist = (obj) + * @proto dist = (x, y) + * + * @param [WorldObject] obj + * @param float x : the X-coordinate of the point + * @param float y : the Y-coordinate of the point + * + * @return float dist : the distance in yards + */ + int GetDistance2d(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + Eluna::Push(L, obj->GetDistance2d(target)); + else + { + float X = Eluna::CHECKVAL(L, 2); + float Y = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetDistance2d(X, Y)); + } + return 1; + } + + /** + * Returns the distance from this [WorldObject] to another [WorldObject], or from this [WorldObject] to a point in 2d space. + * + * The function does not take into account the given object sizes, which means only the object coordinates are compared. See also [WorldObject:GetDistance], [WorldObject:GetDistance2d] + * + * @proto dist = (obj) + * @proto dist = (x, y) + * + * @param [WorldObject] obj + * @param float x : the X-coordinate of the point + * @param float y : the Y-coordinate of the point + * + * @return float dist : the distance in yards + */ + int GetExactDistance2d(lua_State* L, WorldObject* obj) + { + float x, y, z; + obj->GetPosition(x, y, z); + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + { + float x2, y2, z2; + target->GetPosition(x2, y2, z2); + x -= x2; + y -= y2; + } + else + { + x -= Eluna::CHECKVAL(L, 2); + y -= Eluna::CHECKVAL(L, 3); + } + + Eluna::Push(L, std::sqrt(x*x + y*y)); + return 1; + } + + /** + * Returns the x, y and z of a point dist away from the [WorldObject]. + * + * @param float distance : specifies the distance of the point from the [WorldObject] in yards + * @param float angle : specifies the angle of the point relative to the orientation / facing of the [WorldObject] in radians + * + * @return float x + * @return float y + * @return float z + */ + int GetRelativePoint(lua_State* L, WorldObject* obj) + { + float dist = Eluna::CHECKVAL(L, 2); + float rad = Eluna::CHECKVAL(L, 3); + + float x, y, z; + obj->GetClosePoint(x, y, z, 0.0f, dist, rad); + + Eluna::Push(L, x); + Eluna::Push(L, y); + Eluna::Push(L, z); + return 3; + } + + /** + * Returns the angle between this [WorldObject] and another [WorldObject] or a point. + * + * The angle is the angle between two points and orientation will be ignored. + * + * @proto dist = (obj) + * @proto dist = (x, y) + * + * @param [WorldObject] object + * @param float x + * @param float y + * + * @return float angle : angle in radians in range 0..2*pi + */ + int GetAngle(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + Eluna::Push(L, obj->GetAngle(target)); + else + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetAngle(x, y)); + } + return 1; + } + + /** + * Sends a [WorldPacket] to [Player]s in sight of the [WorldObject]. + * + * @param [WorldPacket] packet + */ + int SendPacket(lua_State* L, WorldObject* obj) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + + obj->SendMessageToSet(*data, true); + return 0; + } + + /** + * Spawns a [GameObject] at specified location. + * + * @param uint32 entry : [GameObject] entry ID + * @param float x + * @param float y + * @param float z + * @param float o + * @param uint32 respawnDelay = 30 : respawn time in seconds + * @return [GameObject] gameObject + */ + int SummonGameObject(lua_State* L, WorldObject* obj) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + uint32 respawnDelay = Eluna::CHECKVAL(L, 7, 30); + + Eluna::Push(L, obj->SummonGameObject(entry, x, y, z, o, respawnDelay)); + return 1; + } + + /** + * Spawns the creature at specified location. + * + * enum TempSummonType + * { + * TEMPSUMMON_TIMED_OR_DEAD_DESPAWN = 1, // despawns after a specified time OR when the creature disappears + * TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN = 2, // despawns after a specified time OR when the creature dies + * TEMPSUMMON_TIMED_DESPAWN = 3, // despawns after a specified time + * TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT = 4, // despawns after a specified time after the creature is out of combat + * TEMPSUMMON_CORPSE_DESPAWN = 5, // despawns instantly after death + * TEMPSUMMON_CORPSE_TIMED_DESPAWN = 6, // despawns after a specified time after death + * TEMPSUMMON_DEAD_DESPAWN = 7, // despawns when the creature disappears + * TEMPSUMMON_MANUAL_DESPAWN = 8, // despawns when UnSummon() is called + * TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN = 9, // despawns after a specified time (OOC) OR when the creature dies + * TEMPSUMMON_TIMED_OOC_OR_DEAD_DESPAWN = 10 // despawns after a specified time (OOC) OR when the creature disappears + * }; + * + * @param uint32 entry : [Creature]'s entry ID + * @param float x + * @param float y + * @param float z + * @param float o + * @param [TempSummonType] spawnType = MANUAL_DESPAWN : defines how and when the creature despawns + * @param uint32 despawnTimer = 0 : despawn time in milliseconds + * @return [Creature] spawnedCreature + */ + int SpawnCreature(lua_State* L, WorldObject* obj) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + uint32 spawnType = Eluna::CHECKVAL(L, 7, 8); + uint32 despawnTimer = Eluna::CHECKVAL(L, 8, 0); + + TempSpawnType type; + switch (spawnType) + { + case 1: + type = TEMPSPAWN_TIMED_OR_DEAD_DESPAWN; + break; + case 2: + type = TEMPSPAWN_TIMED_OR_CORPSE_DESPAWN; + break; + case 3: + type = TEMPSPAWN_TIMED_DESPAWN; + break; + case 4: + type = TEMPSPAWN_TIMED_OOC_DESPAWN; + break; + case 5: + type = TEMPSPAWN_CORPSE_DESPAWN; + break; + case 6: + type = TEMPSPAWN_CORPSE_TIMED_DESPAWN; + break; + case 7: + type = TEMPSPAWN_DEAD_DESPAWN; + break; + case 8: + type = TEMPSPAWN_MANUAL_DESPAWN; + break; + case 9: + type = TEMPSPAWN_TIMED_OOC_OR_CORPSE_DESPAWN; + break; + case 10: + type = TEMPSPAWN_TIMED_OOC_OR_DEAD_DESPAWN; + break; + default: + return luaL_argerror(L, 7, "valid SpawnType expected"); + } + Eluna::Push(L, obj->SummonCreature(entry, x, y, z, o, type, despawnTimer)); + return 1; + } + + /** + * Registers a timed event to the [WorldObject] + * When the passed function is called, the parameters `(eventId, delay, repeats, worldobject)` are passed to it. + * Repeats will decrease on each call if the event does not repeat indefinitely + * + * Note that for [Creature] and [GameObject] the timed event timer ticks only if the creature is in sight of someone + * For all [WorldObject]s the timed events are removed when the object is destoryed. This means that for example a [Player]'s events are removed on logout. + * + * local function Timed(eventid, delay, repeats, worldobject) + * print(worldobject:GetName()) + * end + * worldobject:RegisterEvent(Timed, 1000, 5) -- do it after 1 second 5 times + * worldobject:RegisterEvent(Timed, {1000, 10000}, 0) -- do it after 1 to 10 seconds forever + * + * @proto eventId = (function, delay) + * @proto eventId = (function, delaytable) + * @proto eventId = (function, delay, repeats) + * @proto eventId = (function, delaytable, repeats) + * + * @param function function : function to trigger when the time has passed + * @param uint32 delay : set time in milliseconds for the event to trigger + * @param table delaytable : a table `{min, max}` containing the minimum and maximum delay time + * @param uint32 repeats = 1 : how many times for the event to repeat, 0 is infinite + * @return int eventId : unique ID for the timed event used to cancel it or nil + */ + int RegisterEvent(lua_State* L, WorldObject* obj) + { + luaL_checktype(L, 2, LUA_TFUNCTION); + uint32 min, max; + if (lua_istable(L, 3)) + { + Eluna::Push(L, 1); + lua_gettable(L, 3); + min = Eluna::CHECKVAL(L, -1); + Eluna::Push(L, 2); + lua_gettable(L, 3); + max = Eluna::CHECKVAL(L, -1); + lua_pop(L, 2); + } + else + min = max = Eluna::CHECKVAL(L, 3); + uint32 repeats = Eluna::CHECKVAL(L, 4, 1); + + if (min > max) + return luaL_argerror(L, 3, "min is bigger than max delay"); + + lua_pushvalue(L, 2); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF) + { + obj->elunaEvents->AddEvent(functionRef, min, max, repeats); + Eluna::Push(L, functionRef); + } + return 1; + } + + /** + * Removes the timed event from a [WorldObject] by the specified event ID + * + * @param int eventId : event Id to remove + */ + int RemoveEventById(lua_State* L, WorldObject* obj) + { + int eventId = Eluna::CHECKVAL(L, 2); + obj->elunaEvents->SetState(eventId, LUAEVENT_STATE_ABORT); + return 0; + } + + /** + * Removes all timed events from a [WorldObject] + * + */ + int RemoveEvents(lua_State* /*L*/, WorldObject* obj) + { + obj->elunaEvents->SetStates(LUAEVENT_STATE_ABORT); + return 0; + } + + /** + * Returns true if the given [WorldObject] or coordinates are in the [WorldObject]'s line of sight + * + * @proto isInLoS = (worldobject) + * @proto isInLoS = (x, y, z) + * + * @param [WorldObject] worldobject + * @param float x + * @param float y + * @param float z + * @return bool isInLoS + */ + int IsWithinLoS(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + + if (target) + Eluna::Push(L, obj->IsWithinLOSInMap(target)); + else + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + Eluna::Push(L, obj->IsWithinLOS(x, y, z)); + } + + return 1; + } + + /** + * Returns true if the [WorldObject]s are on the same map + * + * @param [WorldObject] worldobject + * @return bool isInMap + */ + int IsInMap(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, true); + Eluna::Push(L, obj->IsInMap(target)); + return 1; + } + + /** + * Returns true if the point is in the given distance of the [WorldObject] + * + * Notice that the distance is measured from the edge of the [WorldObject]. + * + * @param float x + * @param float y + * @param float z + * @param float distance + * @return bool isInDistance + */ + int IsWithinDist3d(lua_State* L, WorldObject* obj) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float dist = Eluna::CHECKVAL(L, 5); + Eluna::Push(L, obj->IsWithinDist3d(x, y, z, dist)); + return 1; + } + + /** + * Returns true if the point is in the given distance of the [WorldObject] + * + * The distance is measured only in x,y coordinates. + * Notice that the distance is measured from the edge of the [WorldObject]. + * + * @param float x + * @param float y + * @param float distance + * @return bool isInDistance + */ + int IsWithinDist2d(lua_State* L, WorldObject* obj) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float dist = Eluna::CHECKVAL(L, 4); + Eluna::Push(L, obj->IsWithinDist2d(x, y, dist)); + return 1; + } + + /** + * Returns true if the target is in the given distance of the [WorldObject] + * + * Notice that the distance is measured from the edge of the [WorldObject]s. + * + * @param [WorldObject] target + * @param float distance + * @param bool is3D = true : if false, only x,y coordinates used for checking + * @return bool isInDistance + */ + int IsWithinDist(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, true); + float distance = Eluna::CHECKVAL(L, 3); + bool is3D = Eluna::CHECKVAL(L, 4, true); + Eluna::Push(L, obj->IsWithinDist(target, distance, is3D)); + return 1; + } + + /** + * Returns true if the [WorldObject] is on the same map and within given distance + * + * Notice that the distance is measured from the edge of the [WorldObject]s. + * + * @param [WorldObject] target + * @param float distance + * @param bool is3D = true : if false, only x,y coordinates used for checking + * @return bool isInDistance + */ + int IsWithinDistInMap(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2); + float distance = Eluna::CHECKVAL(L, 3); + bool is3D = Eluna::CHECKVAL(L, 4, true); + + Eluna::Push(L, obj->IsWithinDistInMap(target, distance, is3D)); + return 1; + } + + /** + * Returns true if the target is within given range + * + * Notice that the distance is measured from the edge of the [WorldObject]s. + * + * @param [WorldObject] target + * @param float minrange + * @param float maxrange + * @param bool is3D = true : if false, only x,y coordinates used for checking + * @return bool isInDistance + */ + int IsInRange(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2); + float minrange = Eluna::CHECKVAL(L, 3); + float maxrange = Eluna::CHECKVAL(L, 4); + bool is3D = Eluna::CHECKVAL(L, 5, true); + + Eluna::Push(L, obj->IsInRange(target, minrange, maxrange, is3D)); + return 1; + } + + /** + * Returns true if the point is within given range + * + * Notice that the distance is measured from the edge of the [WorldObject]. + * + * @param float x + * @param float y + * @param float minrange + * @param float maxrange + * @return bool isInDistance + */ + int IsInRange2d(lua_State* L, WorldObject* obj) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float minrange = Eluna::CHECKVAL(L, 4); + float maxrange = Eluna::CHECKVAL(L, 5); + + Eluna::Push(L, obj->IsInRange2d(x, y, minrange, maxrange)); + return 1; + } + + /** + * Returns true if the point is within given range + * + * Notice that the distance is measured from the edge of the [WorldObject]. + * + * @param float x + * @param float y + * @param float z + * @param float minrange + * @param float maxrange + * @return bool isInDistance + */ + int IsInRange3d(lua_State* L, WorldObject* obj) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float minrange = Eluna::CHECKVAL(L, 5); + float maxrange = Eluna::CHECKVAL(L, 6); + + Eluna::Push(L, obj->IsInRange3d(x, y, z, minrange, maxrange)); + return 1; + } + + /** + * Returns true if the target is in the given arc in front of the [WorldObject] + * + * @param [WorldObject] target + * @param float arc = pi + * @return bool isInFront + */ + int IsInFront(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2); + float arc = Eluna::CHECKVAL(L, 3, static_cast(M_PI)); + + Eluna::Push(L, obj->isInFront(target, arc)); + return 1; + } + + /** + * Returns true if the target is in the given arc behind the [WorldObject] + * + * @param [WorldObject] target + * @param float arc = pi + * @return bool isInBack + */ + int IsInBack(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2); + float arc = Eluna::CHECKVAL(L, 3, static_cast(M_PI)); + + Eluna::Push(L, obj->isInBack(target, arc)); + return 1; + } + + /** + * The [WorldObject] plays music to a [Player] + * + * If no [Player] provided it will play the music to everyone near. + * This method does not interrupt previously played music. + * + * See also [WorldObject:PlayDistanceSound], [WorldObject:PlayDirectSound] + * + * @param uint32 music : entry of a music + * @param [Player] player = nil : [Player] to play the music to + */ + int PlayMusic(lua_State* L, WorldObject* obj) + { + uint32 musicid = Eluna::CHECKVAL(L, 2); + Player* player = Eluna::CHECKOBJ(L, 3, false); + + WorldPacket data(SMSG_PLAY_MUSIC, 4); + data << uint32(musicid); + if (player) + player->SendDirectMessage(data); + else + obj->SendMessageToSet(data, true); + return 0; + } + + /** + * The [WorldObject] plays a sound to a [Player] + * + * If no [Player] provided it will play the sound to everyone near. + * This method will play sound and does not interrupt prvious sound. + * + * See also [WorldObject:PlayDistanceSound], [WorldObject:PlayMusic] + * + * @param uint32 sound : entry of a sound + * @param [Player] player = nil : [Player] to play the sound to + */ + int PlayDirectSound(lua_State* L, WorldObject* obj) + { + uint32 soundId = Eluna::CHECKVAL(L, 2); + Player* player = Eluna::CHECKOBJ(L, 3, false); + if (!sSoundEntriesStore.LookupEntry(soundId)) + return 0; + + if (player) +#ifdef CATA + obj->PlayDirectSound(soundId, player); +#else + obj->PlayDirectSound(soundId, PlayPacketParameters(PLAY_TARGET, (Player const*)player)); +#endif + else + obj->PlayDirectSound(soundId); + return 0; + } + + /** + * The [WorldObject] plays a sound to a [Player] + * + * If no [Player] it will play the sound to everyone near. + * Sound will fade the further you are from the [WorldObject]. + * This method interrupts previously playing sound. + * + * See also [WorldObject:PlayDirectSound], [WorldObject:PlayMusic] + * + * @param uint32 sound : entry of a sound + * @param [Player] player = nil : [Player] to play the sound to + */ + int PlayDistanceSound(lua_State* L, WorldObject* obj) + { + uint32 soundId = Eluna::CHECKVAL(L, 2); + Player* player = Eluna::CHECKOBJ(L, 3, false); + if (!sSoundEntriesStore.LookupEntry(soundId)) + return 0; + + if (player) +#ifdef CATA + obj->PlayDistanceSound(soundId, player); +#else + obj->PlayDistanceSound(soundId, PlayPacketParameters(PLAY_TARGET, (Player const*)player)); +#endif + else + obj->PlayDistanceSound(soundId); + return 0; + } + + ElunaRegister WorldObjectMethods[] = + { + // Getters + { "GetName", &LuaWorldObject::GetName }, + { "GetMap", &LuaWorldObject::GetMap }, + { "GetInstanceId", &LuaWorldObject::GetInstanceId }, + { "GetAreaId", &LuaWorldObject::GetAreaId }, + { "GetZoneId", &LuaWorldObject::GetZoneId }, + { "GetMapId", &LuaWorldObject::GetMapId }, + { "GetX", &LuaWorldObject::GetX }, + { "GetY", &LuaWorldObject::GetY }, + { "GetZ", &LuaWorldObject::GetZ }, + { "GetO", &LuaWorldObject::GetO }, + { "GetLocation", &LuaWorldObject::GetLocation }, + { "GetPlayersInRange", &LuaWorldObject::GetPlayersInRange }, + { "GetCreaturesInRange", &LuaWorldObject::GetCreaturesInRange }, + { "GetGameObjectsInRange", &LuaWorldObject::GetGameObjectsInRange }, + { "GetNearestPlayer", &LuaWorldObject::GetNearestPlayer }, + { "GetNearestGameObject", &LuaWorldObject::GetNearestGameObject }, + { "GetNearestCreature", &LuaWorldObject::GetNearestCreature }, + { "GetNearObject", &LuaWorldObject::GetNearObject }, + { "GetNearObjects", &LuaWorldObject::GetNearObjects }, + { "GetDistance", &LuaWorldObject::GetDistance }, + { "GetExactDistance", &LuaWorldObject::GetExactDistance }, + { "GetDistance2d", &LuaWorldObject::GetDistance2d }, + { "GetExactDistance2d", &LuaWorldObject::GetExactDistance2d }, + { "GetRelativePoint", &LuaWorldObject::GetRelativePoint }, + { "GetAngle", &LuaWorldObject::GetAngle }, +#if defined(WOTLK) + { "GetPhaseMask", &LuaWorldObject::GetPhaseMask }, + { "SetPhaseMask", &LuaWorldObject::SetPhaseMask }, +#endif + + // Boolean + { "IsWithinLoS", &LuaWorldObject::IsWithinLoS }, + { "IsInMap", &LuaWorldObject::IsInMap }, + { "IsWithinDist3d", &LuaWorldObject::IsWithinDist3d }, + { "IsWithinDist2d", &LuaWorldObject::IsWithinDist2d }, + { "IsWithinDist", &LuaWorldObject::IsWithinDist }, + { "IsWithinDistInMap", &LuaWorldObject::IsWithinDistInMap }, + { "IsInRange", &LuaWorldObject::IsInRange }, + { "IsInRange2d", &LuaWorldObject::IsInRange2d }, + { "IsInRange3d", &LuaWorldObject::IsInRange3d }, + { "IsInFront", &LuaWorldObject::IsInFront }, + { "IsInBack", &LuaWorldObject::IsInBack }, + + // Other + { "SummonGameObject", &LuaWorldObject::SummonGameObject }, + { "SpawnCreature", &LuaWorldObject::SpawnCreature }, + { "SendPacket", &LuaWorldObject::SendPacket }, + { "RegisterEvent", &LuaWorldObject::RegisterEvent }, + { "RemoveEventById", &LuaWorldObject::RemoveEventById }, + { "RemoveEvents", &LuaWorldObject::RemoveEvents }, + { "PlayMusic", &LuaWorldObject::PlayMusic }, + { "PlayDirectSound", &LuaWorldObject::PlayDirectSound }, + { "PlayDistanceSound", &LuaWorldObject::PlayDistanceSound }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CMangos/WorldPacketMethods.h b/src/modules/Eluna/CMangos/WorldPacketMethods.h new file mode 100644 index 0000000000..3e24579477 --- /dev/null +++ b/src/modules/Eluna/CMangos/WorldPacketMethods.h @@ -0,0 +1,350 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef WORLDPACKETMETHODS_H +#define WORLDPACKETMETHODS_H + +/*** + * A packet used to pass messages between the server and a client. + * + * Each packet has an opcode that determines the type of message being sent, + * e.g. if a CMSG_LOGOUT_REQUEST packet is sent to the server, + * the client has sent a message that its [Player] wants to logout. + * + * The packet can contain further data, the format of which depends on the opcode. + * + * Inherits all methods from: none + */ +namespace LuaPacket +{ + /** + * Returns the opcode of the [WorldPacket]. + * + * @return uint16 opcode + */ + int GetOpcode(lua_State* L, WorldPacket* packet) + { + Eluna::Push(L, packet->GetOpcode()); + return 1; + } + + /** + * Returns the size of the [WorldPacket]. + * + * @return uint32 size + */ + int GetSize(lua_State* L, WorldPacket* packet) + { + Eluna::Push(L, packet->size()); + return 1; + } + + /** + * Sets the opcode of the [WorldPacket] to the specified opcode. + * + * @param [Opcodes] opcode : see Opcodes.h for all known opcodes + */ + int SetOpcode(lua_State* L, WorldPacket* packet) + { + uint32 opcode = Eluna::CHECKVAL(L, 2); + if (opcode >= NUM_MSG_TYPES) + return luaL_argerror(L, 2, "valid opcode expected"); +#ifdef CLASSIC + packet->SetOpcode((Opcodes)opcode); +#else + packet->SetOpcode((OpcodesList)opcode); +#endif + return 0; + } + + /** + * Reads and returns a signed 8-bit integer value from the [WorldPacket]. + * + * @return int8 value + */ + int ReadByte(lua_State* L, WorldPacket* packet) + { + int8 _byte; + (*packet) >> _byte; + Eluna::Push(L, _byte); + return 1; + } + + /** + * Reads and returns an unsigned 8-bit integer value from the [WorldPacket]. + * + * @return uint8 value + */ + int ReadUByte(lua_State* L, WorldPacket* packet) + { + uint8 _ubyte; + (*packet) >> _ubyte; + Eluna::Push(L, _ubyte); + return 1; + } + + /** + * Reads and returns a signed 16-bit integer value from the [WorldPacket]. + * + * @return int16 value + */ + int ReadShort(lua_State* L, WorldPacket* packet) + { + int16 _short; + (*packet) >> _short; + Eluna::Push(L, _short); + return 1; + } + + /** + * Reads and returns an unsigned 16-bit integer value from the [WorldPacket]. + * + * @return uint16 value + */ + int ReadUShort(lua_State* L, WorldPacket* packet) + { + uint16 _ushort; + (*packet) >> _ushort; + Eluna::Push(L, _ushort); + return 1; + } + + /** + * Reads and returns a signed 32-bit integer value from the [WorldPacket]. + * + * @return int32 value + */ + int ReadLong(lua_State* L, WorldPacket* packet) + { + int32 _long; + (*packet) >> _long; + Eluna::Push(L, _long); + return 1; + } + + /** + * Reads and returns an unsigned 32-bit integer value from the [WorldPacket]. + * + * @return uint32 value + */ + int ReadULong(lua_State* L, WorldPacket* packet) + { + uint32 _ulong; + (*packet) >> _ulong; + Eluna::Push(L, _ulong); + return 1; + } + + /** + * Reads and returns a single-precision floating-point value from the [WorldPacket]. + * + * @return float value + */ + int ReadFloat(lua_State* L, WorldPacket* packet) + { + float _val; + (*packet) >> _val; + Eluna::Push(L, _val); + return 1; + } + + /** + * Reads and returns a double-precision floating-point value from the [WorldPacket]. + * + * @return double value + */ + int ReadDouble(lua_State* L, WorldPacket* packet) + { + double _val; + (*packet) >> _val; + Eluna::Push(L, _val); + return 1; + } + + /** + * Reads and returns an unsigned 64-bit integer value from the [WorldPacket]. + * + * @return ObjectGuid value : value returned as string + */ + int ReadGUID(lua_State* L, WorldPacket* packet) + { + ObjectGuid guid; + (*packet) >> guid; + Eluna::Push(L, guid); + return 1; + } + + /** + * Reads and returns a string value from the [WorldPacket]. + * + * @return string value + */ + int ReadString(lua_State* L, WorldPacket* packet) + { + std::string _val; + (*packet) >> _val; + Eluna::Push(L, _val); + return 1; + } + + /** + * Writes an unsigned 64-bit integer value to the [WorldPacket]. + * + * @param ObjectGuid value : the value to be written to the [WorldPacket] + */ + int WriteGUID(lua_State* L, WorldPacket* packet) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + (*packet) << guid; + return 0; + } + + /** + * Writes a string to the [WorldPacket]. + * + * @param string value : the string to be written to the [WorldPacket] + */ + int WriteString(lua_State* L, WorldPacket* packet) + { + std::string _val = Eluna::CHECKVAL(L, 2); + (*packet) << _val; + return 0; + } + + /** + * Writes a signed 8-bit integer value to the [WorldPacket]. + * + * @param int8 value : the int8 value to be written to the [WorldPacket] + */ + int WriteByte(lua_State* L, WorldPacket* packet) + { + int8 byte = Eluna::CHECKVAL(L, 2); + (*packet) << byte; + return 0; + } + + /** + * Writes an unsigned 8-bit integer value to the [WorldPacket]. + * + * @param uint8 value : the uint8 value to be written to the [WorldPacket] + */ + int WriteUByte(lua_State* L, WorldPacket* packet) + { + uint8 byte = Eluna::CHECKVAL(L, 2); + (*packet) << byte; + return 0; + } + + /** + * Writes a signed 16-bit integer value to the [WorldPacket]. + * + * @param int16 value : the int16 value to be written to the [WorldPacket] + */ + int WriteShort(lua_State* L, WorldPacket* packet) + { + int16 _short = Eluna::CHECKVAL(L, 2); + (*packet) << _short; + return 0; + } + + /** + * Writes an unsigned 16-bit integer value to the [WorldPacket]. + * + * @param uint16 value : the uint16 value to be written to the [WorldPacket] + */ + int WriteUShort(lua_State* L, WorldPacket* packet) + { + uint16 _ushort = Eluna::CHECKVAL(L, 2); + (*packet) << _ushort; + return 0; + } + + /** + * Writes a signed 32-bit integer value to the [WorldPacket]. + * + * @param int32 value : the int32 value to be written to the [WorldPacket] + */ + int WriteLong(lua_State* L, WorldPacket* packet) + { + int32 _long = Eluna::CHECKVAL(L, 2); + (*packet) << _long; + return 0; + } + + /** + * Writes an unsigned 32-bit integer value to the [WorldPacket]. + * + * @param uint32 value : the uint32 value to be written to the [WorldPacket] + */ + int WriteULong(lua_State* L, WorldPacket* packet) + { + uint32 _ulong = Eluna::CHECKVAL(L, 2); + (*packet) << _ulong; + return 0; + } + + /** + * Writes a 32-bit floating-point value to the [WorldPacket]. + * + * @param float value : the float value to be written to the [WorldPacket] + */ + int WriteFloat(lua_State* L, WorldPacket* packet) + { + float _val = Eluna::CHECKVAL(L, 2); + (*packet) << _val; + return 0; + } + + /** + * Writes a 64-bit floating-point value to the [WorldPacket]. + * + * @param double value : the double value to be written to the [WorldPacket] + */ + int WriteDouble(lua_State* L, WorldPacket* packet) + { + double _val = Eluna::CHECKVAL(L, 2); + (*packet) << _val; + return 0; + } + + ElunaRegister PacketMethods[] = + { + // Getters + { "GetOpcode", &LuaPacket::GetOpcode }, + { "GetSize", &LuaPacket::GetSize }, + + // Setters + { "SetOpcode", &LuaPacket::SetOpcode }, + + // Readers + { "ReadByte", &LuaPacket::ReadByte }, + { "ReadUByte", &LuaPacket::ReadUByte }, + { "ReadShort", &LuaPacket::ReadShort }, + { "ReadUShort", &LuaPacket::ReadUShort }, + { "ReadLong", &LuaPacket::ReadLong }, + { "ReadULong", &LuaPacket::ReadULong }, + { "ReadGUID", &LuaPacket::ReadGUID }, + { "ReadString", &LuaPacket::ReadString }, + { "ReadFloat", &LuaPacket::ReadFloat }, + { "ReadDouble", &LuaPacket::ReadDouble }, + + // Writers + { "WriteByte", &LuaPacket::WriteByte }, + { "WriteUByte", &LuaPacket::WriteUByte }, + { "WriteShort", &LuaPacket::WriteShort }, + { "WriteUShort", &LuaPacket::WriteUShort }, + { "WriteLong", &LuaPacket::WriteLong }, + { "WriteULong", &LuaPacket::WriteULong }, + { "WriteGUID", &LuaPacket::WriteGUID }, + { "WriteString", &LuaPacket::WriteString }, + { "WriteFloat", &LuaPacket::WriteFloat }, + { "WriteDouble", &LuaPacket::WriteDouble }, + + { NULL, NULL } + }; +}; + +#endif diff --git a/src/modules/Eluna/ElunaCompat.cpp b/src/modules/Eluna/ElunaCompat.cpp new file mode 100644 index 0000000000..6285774829 --- /dev/null +++ b/src/modules/Eluna/ElunaCompat.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2010 - 2022 Eluna Lua Engine + * This program is free software licensed under GPL version 3 + * Please see the included DOCS/LICENSE.md for more information + */ + +#include "ElunaCompat.h" + +#if LUA_VERSION_NUM == 501 +const char* luaL_tolstring(lua_State* L, int idx, size_t* len) { + if (!luaL_callmeta(L, idx, "__tostring")) { + int t = lua_type(L, idx), tt = 0; + char const* name = NULL; + switch (t) { + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + case LUA_TSTRING: + case LUA_TNUMBER: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + if (lua_toboolean(L, idx)) + lua_pushliteral(L, "true"); + else + lua_pushliteral(L, "false"); + break; + default: + tt = luaL_getmetafield(L, idx, "__name"); + name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t); + lua_pushfstring(L, "%s: %p", name, lua_topointer(L, idx)); + if (tt != LUA_TNIL) + lua_replace(L, -2); + break; + } + } + else { + if (!lua_isstring(L, -1)) + luaL_error(L, "'__tostring' must return a string"); + } + return lua_tolstring(L, -1, len); +} + +int luaL_getsubtable(lua_State* L, int i, const char* name) { + int abs_i = lua_absindex(L, i); + luaL_checkstack(L, 3, "not enough stack slots"); + lua_pushstring(L, name); + lua_gettable(L, abs_i); + if (lua_istable(L, -1)) + return 1; + lua_pop(L, 1); + lua_newtable(L); + lua_pushstring(L, name); + lua_pushvalue(L, -2); + lua_settable(L, abs_i); + return 0; +} + +int lua_absindex(lua_State* L, int i) { + if (i < 0 && i > LUA_REGISTRYINDEX) + i += lua_gettop(L) + 1; + return i; +} +#endif diff --git a/src/modules/Eluna/ElunaCompat.h b/src/modules/Eluna/ElunaCompat.h new file mode 100644 index 0000000000..777d0f930e --- /dev/null +++ b/src/modules/Eluna/ElunaCompat.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2010 - 2022 Eluna Lua Engine + * This program is free software licensed under GPL version 3 + * Please see the included DOCS/LICENSE.md for more information + */ + +#ifndef ELUNACOMPAT_H +#define ELUNACOMPAT_H + +extern "C" +{ +#include "lua.h" +#include "lauxlib.h" +}; + +/* Compatibility layer for compiling with Lua 5.1 or LuaJIT */ +#if LUA_VERSION_NUM == 501 + int luaL_getsubtable(lua_State* L, int i, const char* name); + const char* luaL_tolstring(lua_State* L, int idx, size_t* len); + int lua_absindex(lua_State* L, int i); + #define lua_pushglobaltable(L) \ + lua_pushvalue((L), LUA_GLOBALSINDEX); + #define lua_rawlen(L, idx) \ + lua_objlen(L, idx); + #define lua_pushunsigned(L, u) \ + lua_pushinteger(L, u); + #define lua_load(L, buf_read, dec_buf, str, NULL) \ + lua_load(L, buf_read, dec_buf, str); +#endif +#endif diff --git a/src/modules/Eluna/ElunaCreatureAI.h b/src/modules/Eluna/ElunaCreatureAI.h index ac560f0956..b327af3ad2 100644 --- a/src/modules/Eluna/ElunaCreatureAI.h +++ b/src/modules/Eluna/ElunaCreatureAI.h @@ -16,6 +16,9 @@ struct ScriptedAI; #elif defined CMANGOS class CreatureAI; +#elif defined VMANGOS +class BasicAI; +typedef BasicAI ScriptedAI; #else class AggressorAI; typedef AggressorAI ScriptedAI; @@ -31,7 +34,7 @@ struct ElunaCreatureAI : CreatureAI bool justSpawned; // used to delay movementinform hook (WP hook) std::vector< std::pair > movepoints; -#if defined MANGOS || defined CMANGOS +#if defined MANGOS || defined CMANGOS || defined VMANGOS #define me m_creature #endif #ifndef CMANGOS @@ -51,7 +54,7 @@ struct ElunaCreatureAI : CreatureAI #endif { #ifdef TRINITY - //Spawns are handled by Creature.cpp - in function Creature::Update() + //Spawns are handled by Creature.cpp - in function Creature::Update() #else if (justSpawned) { @@ -78,7 +81,7 @@ struct ElunaCreatureAI : CreatureAI if (!sEluna->UpdateAI(me, diff)) { -#if defined TRINITY || AZEROTHCORE +#if defined TRINITY || AZEROTHCORE || VMANGOS if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)) ScriptedAI::UpdateAI(diff); #elif defined CMANGOS @@ -117,7 +120,9 @@ struct ElunaCreatureAI : CreatureAI // Called at any Damage from any attacker (before damage apply) #if defined AZEROTHCORE void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override -#elif defined(TRINITY) || CMANGOS +#elif ((defined (TRINITY) || CMANGOS) && !defined CATA) + void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damageType, SpellInfo const* spellInfo) override +#elif defined CATA && defined CMANGOS void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damageType, SpellInfo const* spellInfo) override #else void DamageTaken(Unit* attacker, uint32& damage) override @@ -127,7 +132,7 @@ struct ElunaCreatureAI : CreatureAI { #if defined AZEROTHCORE ScriptedAI::DamageTaken(attacker, damage, damagetype, damageSchoolMask); -#elif defined TRINITY +#elif defined TRINITY && !defined CATA ScriptedAI::DamageTaken(attacker, damage, damageType, spellInfo); #elif defined CMANGOS CreatureAI::DamageTaken(attacker, damage, damageType, spellInfo); @@ -288,7 +293,7 @@ struct ElunaCreatureAI : CreatureAI #endif } -#if !defined TRINITY && !AZEROTHCORE +#if !defined TRINITY && !AZEROTHCORE && !VMANGOS // Enables use of MoveInLineOfSight bool IsVisible(Unit* who) const override { @@ -310,6 +315,8 @@ struct ElunaCreatureAI : CreatureAI // Called when hit by a spell #if defined TRINITY void SpellHit(WorldObject* caster, SpellInfo const* spell) override +#elif defined VMANGOS + void SpellHit(Unit* caster, SpellInfo const* spell) #else void SpellHit(Unit* caster, SpellInfo const* spell) override #endif @@ -341,7 +348,7 @@ struct ElunaCreatureAI : CreatureAI #if defined TRINITY || AZEROTHCORE -#if defined TRINITY +#if defined TRINITY && !defined CATA // Called when the creature is summoned successfully by other creature void IsSummonedBy(WorldObject* summoner) override { diff --git a/src/modules/Eluna/ElunaEventMgr.h b/src/modules/Eluna/ElunaEventMgr.h index 013c8eae48..a1e39a6647 100644 --- a/src/modules/Eluna/ElunaEventMgr.h +++ b/src/modules/Eluna/ElunaEventMgr.h @@ -11,6 +11,8 @@ #include "Common.h" #ifdef TRINITY #include "Random.h" +#elif defined CMANGOS +#include "Util/Util.h" #else #include "Util.h" #endif diff --git a/src/modules/Eluna/ElunaIncludes.h b/src/modules/Eluna/ElunaIncludes.h index 54f738e76b..52b87c4219 100644 --- a/src/modules/Eluna/ElunaIncludes.h +++ b/src/modules/Eluna/ElunaIncludes.h @@ -16,6 +16,9 @@ #include "Chat.h" #include "Channel.h" #include "DBCStores.h" +#if defined CATA && defined TRINITY +#include "DB2Stores.h" +#endif #include "GameEventMgr.h" #include "GossipDef.h" #include "GridNotifiers.h" @@ -37,6 +40,7 @@ #include "SpellMgr.h" #include "TemporarySummon.h" #include "WorldSession.h" +#include "WorldPacket.h" #else #include "Accounts/AccountMgr.h" #include "AuctionHouse/AuctionHouseMgr.h" @@ -67,8 +71,8 @@ #include "Spells/SpellMgr.h" #include "Entities/TemporarySpawn.h" #include "Server/WorldSession.h" +#include "Server/WorldPacket.h" #endif -#include "WorldPacket.h" #if defined TRINITY #include "SpellHistory.h" @@ -76,9 +80,7 @@ #if defined AZEROTHCORE #include "MapMgr.h" -#elif defined CMANGOS -#include "Maps/MapManager.h" -#else +#elif !defined CMANGOS #include "MapManager.h" #endif @@ -96,10 +98,18 @@ #include "Bag.h" #else #include "Config/Config.h" -#ifdef CMANGOS +#if defined CMANGOS && defined CATA +#include "AI/BaseAI/AggressorAI.h" +#include "Server/SQLStorages.h" +#elif defined CMANGOS #include "AI/BaseAI/UnitAI.h" +#include "Server/SQLStorages.h" +#elif defined VMANGOS +#include "BasicAI.h" +#include "Bag.h" #else #include "AggressorAI.h" +#include "SQLStorages.h" #endif #include "BattleGroundMgr.h" #ifndef CMANGOS @@ -107,10 +117,10 @@ #else #include "Server/SQLStorages.h" #endif -#ifndef MANGOS -#include "revision.h" -#else +#ifdef MANGOS #include "GitRevision.h" +#else +#include "revision.h" #endif #endif @@ -130,7 +140,10 @@ #endif #endif -#ifndef CLASSIC +#if (defined(TRINITY) && defined(CATA)) +typedef OpcodeServer OpcodesList; + +#elif !defined CLASSIC typedef Opcodes OpcodesList; #endif @@ -141,16 +154,31 @@ typedef Opcodes OpcodesList; #ifdef MANGOS #define CORE_NAME "MaNGOS" #define CORE_VERSION REVISION_NR +//ifdef CATA +//define NUM_MSG_TYPES NUM_OPCODE_HANDLERS +//endif #endif #ifdef CMANGOS #define CORE_NAME "cMaNGOS" #define CORE_VERSION REVISION_DATE " " REVISION_ID +#ifdef CATA +#define NUM_MSG_TYPES MAX_OPCODE_TABLE_SIZE +#endif +#endif + +#ifdef VMANGOS +#define CORE_NAME "vMaNGOS" +#define CORE_VERSION REVISION_HASH +#define DEFAULT_LOCALE LOCALE_enUS #endif #ifdef TRINITY #define CORE_NAME "TrinityCore" #define REGEN_TIME_FULL +#ifdef CATA +#define NUM_MSG_TYPES NUM_OPCODE_HANDLERS +#endif #endif #ifdef AZEROTHCORE @@ -170,11 +198,6 @@ typedef Opcodes OpcodesList; #define eObjectAccessor() ObjectAccessor:: #endif -/*#ifdef CATA -#define NUM_MSG_TYPES NUM_OPCODE_HANDLERS -#endif -*/ - #if !defined TRINITY && !AZEROTHCORE #define eWorld (&sWorld) #define eMapMgr (&sMapMgr) @@ -189,10 +212,12 @@ typedef Opcodes OpcodesList; #define TOTAL_LOCALES MAX_LOCALE #define TARGETICONCOUNT TARGET_ICON_COUNT #define MAX_TALENT_SPECS MAX_TALENT_SPEC_COUNT +#ifndef VMANGOS #define TEAM_NEUTRAL TEAM_INDEX_NEUTRAL +#endif -#if (defined(TBC) || defined(WOTLK) || defined(CATA)) && !defined(MANGOS) +#if ((defined(CATA) && !defined(MANGOS)) || defined VMANGOS) #define PLAYER_FIELD_LIFETIME_HONORABLE_KILLS PLAYER_FIELD_LIFETIME_HONORBALE_KILLS #endif diff --git a/src/modules/Eluna/ElunaInstanceAI.h b/src/modules/Eluna/ElunaInstanceAI.h index 474b08cb29..9a11f2d8a6 100644 --- a/src/modules/Eluna/ElunaInstanceAI.h +++ b/src/modules/Eluna/ElunaInstanceAI.h @@ -92,6 +92,8 @@ class ElunaInstanceAI : public InstanceData return Save(); } const char* Save() const; +#elif defined VMANGOS + const char* Save() const; #else const char* Save() const override; #endif @@ -111,10 +113,18 @@ class ElunaInstanceAI : public InstanceData /* * These methods allow non-Lua scripts (e.g. DB, C++) to get/set instance data. */ +#ifndef VMANGOS uint32 GetData(uint32 key) const override; +#else + uint32 GetData(uint32 key) const; +#endif void SetData(uint32 key, uint32 value) override; +#ifndef VMANGOS uint64 GetData64(uint32 key) const override; +#else + uint64 GetData64(uint32 key) const; +#endif void SetData64(uint32 key, uint64 value) override; /* diff --git a/src/modules/Eluna/ElunaTemplate.h b/src/modules/Eluna/ElunaTemplate.h index fb92fa83fc..99adc81e27 100644 --- a/src/modules/Eluna/ElunaTemplate.h +++ b/src/modules/Eluna/ElunaTemplate.h @@ -15,6 +15,7 @@ extern "C" }; #include "LuaEngine.h" #include "ElunaUtility.h" +#include "ElunaCompat.h" #ifndef CMANGOS #include "SharedDefines.h" #else @@ -244,6 +245,7 @@ class ElunaTemplate lua_rawget(E->L, LUA_REGISTRYINDEX); ASSERT(lua_istable(E->L, -1)); + // load all core-specific methods for (; methodTable && methodTable->name && methodTable->mfunc; ++methodTable) { lua_pushstring(E->L, methodTable->name); diff --git a/src/modules/Eluna/ElunaUtility.cpp b/src/modules/Eluna/ElunaUtility.cpp index 1bb54cfe40..699a5f530f 100644 --- a/src/modules/Eluna/ElunaUtility.cpp +++ b/src/modules/Eluna/ElunaUtility.cpp @@ -17,14 +17,15 @@ #include "Entities/Unit.h" #include "Entities/GameObject.h" #include "Server/DBCStores.h" +#include "Util/Timer.h" #endif -#if defined(MANGOS) || CMANGOS +#if defined MANGOS #include "Timer.h" #endif uint32 ElunaUtil::GetCurrTime() { -#ifndef CMANGOS +#if !defined CMANGOS && !defined VMANGOS return getMSTime(); #else return WorldTimer::getMSTime(); @@ -33,7 +34,7 @@ uint32 ElunaUtil::GetCurrTime() uint32 ElunaUtil::GetTimeDiff(uint32 oldMSTime) { -#ifndef CMANGOS +#if !defined CMANGOS && !defined VMANGOS return GetMSTimeDiffToNow(oldMSTime); #else return WorldTimer::getMSTimeDiff(oldMSTime, WorldTimer::getMSTime()); @@ -66,7 +67,11 @@ ElunaUtil::WorldObjectInRangeCheck::WorldObjectInRangeCheck(bool nearest, WorldO if (GameObject const* go = i_obj->ToGameObject()) i_obj_unit = go->GetOwner(); if (!i_obj_unit) +#ifndef VMANGOS i_obj_fact = sFactionTemplateStore.LookupEntry(14); +#else + i_obj_fact = sObjectMgr.GetFactionTemplateEntry(14); +#endif } WorldObject const& ElunaUtil::WorldObjectInRangeCheck::GetFocusObject() const { @@ -96,7 +101,13 @@ bool ElunaUtil::WorldObjectInRangeCheck::operator()(WorldObject* u) { if (i_obj_fact) { -#if defined TRINITY || AZEROTHCORE || CMANGOS +#if ((defined TRINITY || AZEROTHCORE || CMANGOS || VMANGOS) && !defined CATA) + if ((i_obj_fact->IsHostileTo(*target->GetFactionTemplateEntry())) != (i_hostile == 1)) + return false; +#elif defined CATA && defined TRINITY + if ((i_obj_fact->IsHostileTo(target->GetFactionTemplateEntry())) != (i_hostile == 1)) + return false; +#elif defined CATA && defined CMANGOS if ((i_obj_fact->IsHostileTo(*target->GetFactionTemplateEntry())) != (i_hostile == 1)) return false; #else diff --git a/src/modules/Eluna/ElunaUtility.h b/src/modules/Eluna/ElunaUtility.h index 1c87262d0f..8530f1737b 100644 --- a/src/modules/Eluna/ElunaUtility.h +++ b/src/modules/Eluna/ElunaUtility.h @@ -49,13 +49,37 @@ typedef QueryResult ElunaQuery; #endif #ifdef TRINITY +#ifdef WOTLK +#include "fmt/printf.h" +#define ELUNA_LOG_TC_FMT(TC_LOG_MACRO, ...) \ + try { \ + std::string message = fmt::sprintf(__VA_ARGS__); \ + TC_LOG_MACRO("eluna", "{}", message); \ + } catch (const std::exception& e) { \ + TC_LOG_MACRO("eluna", "Failed to format log message: {}", e.what()); \ + } +#define ELUNA_LOG_INFO(...) ELUNA_LOG_TC_FMT(TC_LOG_INFO, __VA_ARGS__); +#define ELUNA_LOG_ERROR(...) ELUNA_LOG_TC_FMT(TC_LOG_ERROR, __VA_ARGS__); +#define ELUNA_LOG_DEBUG(...) ELUNA_LOG_TC_FMT(TC_LOG_DEBUG, __VA_ARGS__); +#else #define ELUNA_LOG_INFO(...) TC_LOG_INFO("eluna", __VA_ARGS__); #define ELUNA_LOG_ERROR(...) TC_LOG_ERROR("eluna", __VA_ARGS__); #define ELUNA_LOG_DEBUG(...) TC_LOG_DEBUG("eluna", __VA_ARGS__); +#endif #elif defined(AZEROTHCORE) #define ELUNA_LOG_INFO(...) LOG_INFO("eluna", __VA_ARGS__); #define ELUNA_LOG_ERROR(...) LOG_ERROR("eluna", __VA_ARGS__); #define ELUNA_LOG_DEBUG(...) LOG_DEBUG("eluna", __VA_ARGS__); +#elif VMANGOS +typedef QueryNamedResult ElunaQuery; +#define ASSERT MANGOS_ASSERT +#define ELUNA_LOG_INFO(...) sLog.Out(LOG_ELUNA, LOG_LVL_BASIC,__VA_ARGS__); +#define ELUNA_LOG_ERROR(...) sLog.Out(LOG_ELUNA, LOG_LVL_ERROR,__VA_ARGS__); +#define ELUNA_LOG_DEBUG(...) sLog.Out(LOG_ELUNA, LOG_LVL_DEBUG,__VA_ARGS__); +#define GET_GUID GetObjectGuid +#define GetGameObjectTemplate GetGameObjectInfo +#define GetItemTemplate GetItemPrototype +#define GetTemplate GetProto #else typedef QueryNamedResult ElunaQuery; #define ASSERT MANGOS_ASSERT @@ -68,7 +92,7 @@ typedef QueryNamedResult ElunaQuery; #define GetTemplate GetProto #endif -#if defined(TRINITY) || defined(AZEROTHCORE) || defined(MANGOS) || defined(CMANGOS) +#if defined(TRINITY) || defined(AZEROTHCORE) || defined(MANGOS) || defined(CMANGOS) || defined(VMANGOS) #ifndef MAKE_NEW_GUID #define MAKE_NEW_GUID(l, e, h) ObjectGuid(h, e, l) #endif diff --git a/src/modules/Eluna/GossipHooks.cpp b/src/modules/Eluna/GossipHooks.cpp index deabd4fc02..2ab298a7e5 100644 --- a/src/modules/Eluna/GossipHooks.cpp +++ b/src/modules/Eluna/GossipHooks.cpp @@ -32,7 +32,7 @@ using namespace Hooks; bool Eluna::OnGossipHello(Player* pPlayer, GameObject* pGameObject) { START_HOOK_WITH_RETVAL(GameObjectGossipBindings, GOSSIP_EVENT_ON_HELLO, pGameObject->GetEntry(), false); -#ifdef CMANGOS +#if defined CMANGOS && !defined(CATA) pPlayer->GetPlayerMenu()->ClearMenus(); #else pPlayer->PlayerTalkClass->ClearMenus(); @@ -45,7 +45,7 @@ bool Eluna::OnGossipHello(Player* pPlayer, GameObject* pGameObject) bool Eluna::OnGossipSelect(Player* pPlayer, GameObject* pGameObject, uint32 sender, uint32 action) { START_HOOK_WITH_RETVAL(GameObjectGossipBindings, GOSSIP_EVENT_ON_SELECT, pGameObject->GetEntry(), false); -#ifdef CMANGOS +#if defined CMANGOS && !defined(CATA) pPlayer->GetPlayerMenu()->ClearMenus(); #else pPlayer->PlayerTalkClass->ClearMenus(); @@ -60,7 +60,7 @@ bool Eluna::OnGossipSelect(Player* pPlayer, GameObject* pGameObject, uint32 send bool Eluna::OnGossipSelectCode(Player* pPlayer, GameObject* pGameObject, uint32 sender, uint32 action, const char* code) { START_HOOK_WITH_RETVAL(GameObjectGossipBindings, GOSSIP_EVENT_ON_SELECT, pGameObject->GetEntry(), false); -#ifdef CMANGOS +#if defined CMANGOS && !defined(CATA) pPlayer->GetPlayerMenu()->ClearMenus(); #else pPlayer->PlayerTalkClass->ClearMenus(); @@ -76,7 +76,7 @@ bool Eluna::OnGossipSelectCode(Player* pPlayer, GameObject* pGameObject, uint32 void Eluna::HandleGossipSelectOption(Player* pPlayer, uint32 menuId, uint32 sender, uint32 action, const std::string& code) { START_HOOK(PlayerGossipBindings, GOSSIP_EVENT_ON_SELECT, menuId); -#ifdef CMANGOS +#if defined CMANGOS && !defined(CATA) pPlayer->GetPlayerMenu()->ClearMenus(); #else pPlayer->PlayerTalkClass->ClearMenus(); @@ -97,7 +97,7 @@ void Eluna::HandleGossipSelectOption(Player* pPlayer, uint32 menuId, uint32 send bool Eluna::OnItemGossip(Player* pPlayer, Item* pItem, SpellCastTargets const& /*targets*/) { START_HOOK_WITH_RETVAL(ItemGossipBindings, GOSSIP_EVENT_ON_HELLO, pItem->GetEntry(), true); -#ifdef CMANGOS +#if defined CMANGOS && !defined(CATA) pPlayer->GetPlayerMenu()->ClearMenus(); #else pPlayer->PlayerTalkClass->ClearMenus(); @@ -110,7 +110,7 @@ bool Eluna::OnItemGossip(Player* pPlayer, Item* pItem, SpellCastTargets const& / void Eluna::HandleGossipSelectOption(Player* pPlayer, Item* pItem, uint32 sender, uint32 action, const std::string& code) { START_HOOK(ItemGossipBindings, GOSSIP_EVENT_ON_SELECT, pItem->GetEntry()); -#ifdef CMANGOS +#if defined CMANGOS && !defined(CATA) pPlayer->GetPlayerMenu()->ClearMenus(); #else pPlayer->PlayerTalkClass->ClearMenus(); @@ -131,7 +131,7 @@ void Eluna::HandleGossipSelectOption(Player* pPlayer, Item* pItem, uint32 sender bool Eluna::OnGossipHello(Player* pPlayer, Creature* pCreature) { START_HOOK_WITH_RETVAL(CreatureGossipBindings, GOSSIP_EVENT_ON_HELLO, pCreature->GetEntry(), false); -#ifdef CMANGOS +#if defined CMANGOS && !defined(CATA) pPlayer->GetPlayerMenu()->ClearMenus(); #else pPlayer->PlayerTalkClass->ClearMenus(); @@ -144,7 +144,7 @@ bool Eluna::OnGossipHello(Player* pPlayer, Creature* pCreature) bool Eluna::OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 sender, uint32 action) { START_HOOK_WITH_RETVAL(CreatureGossipBindings, GOSSIP_EVENT_ON_SELECT, pCreature->GetEntry(), false); -#ifdef CMANGOS +#if defined CMANGOS && !defined(CATA) auto original_menu = *pPlayer->GetPlayerMenu(); pPlayer->GetPlayerMenu()->ClearMenus(); #else @@ -157,7 +157,7 @@ bool Eluna::OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 sender, Push(action); auto preventDefault = CallAllFunctionsBool(CreatureGossipBindings, key, true); if (!preventDefault) { -#ifdef CMANGOS +#if defined CMANGOS && !defined(CATA) *pPlayer->GetPlayerMenu() = original_menu; #else *pPlayer->PlayerTalkClass = original_menu; @@ -169,7 +169,7 @@ bool Eluna::OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 sender, bool Eluna::OnGossipSelectCode(Player* pPlayer, Creature* pCreature, uint32 sender, uint32 action, const char* code) { START_HOOK_WITH_RETVAL(CreatureGossipBindings, GOSSIP_EVENT_ON_SELECT, pCreature->GetEntry(), false); -#ifdef CMANGOS +#if defined CMANGOS && !defined(CATA) auto original_menu = *pPlayer->GetPlayerMenu(); pPlayer->GetPlayerMenu()->ClearMenus(); #else @@ -183,7 +183,7 @@ bool Eluna::OnGossipSelectCode(Player* pPlayer, Creature* pCreature, uint32 send Push(code); auto preventDefault = CallAllFunctionsBool(CreatureGossipBindings, key, true); if (!preventDefault) { -#ifdef CMANGOS +#if defined CMANGOS &&!defined(CATA) *pPlayer->GetPlayerMenu() = original_menu; #else *pPlayer->PlayerTalkClass = original_menu; diff --git a/src/modules/Eluna/GroupHooks.cpp b/src/modules/Eluna/GroupHooks.cpp index f674957ad7..0e0646974c 100644 --- a/src/modules/Eluna/GroupHooks.cpp +++ b/src/modules/Eluna/GroupHooks.cpp @@ -20,6 +20,14 @@ using namespace Hooks; return;\ LOCK_ELUNA +#define START_HOOK_WITH_RETVAL(EVENT, RETVAL) \ + if (!IsEnabled())\ + return RETVAL;\ + auto key = EventKey(EVENT);\ + if (!GroupEventBindings->HasBindingsFor(key))\ + return RETVAL;\ + LOCK_ELUNA + void Eluna::OnAddMember(Group* group, ObjectGuid guid) { START_HOOK(GROUP_EVENT_ON_MEMBER_ADD); @@ -61,6 +69,16 @@ void Eluna::OnDisband(Group* group) CallAllFunctions(GroupEventBindings, key); } +#if defined (TRINITY) && defined (CATA) +void Eluna::OnCreate(Group* group, ObjectGuid leaderGuid, GroupFlags groupType) +{ + START_HOOK(GROUP_EVENT_ON_CREATE); + Push(group); + Push(leaderGuid); + Push(groupType); + CallAllFunctions(GroupEventBindings, key); +} +#else void Eluna::OnCreate(Group* group, ObjectGuid leaderGuid, GroupType groupType) { START_HOOK(GROUP_EVENT_ON_CREATE); @@ -69,3 +87,12 @@ void Eluna::OnCreate(Group* group, ObjectGuid leaderGuid, GroupType groupType) Push(groupType); CallAllFunctions(GroupEventBindings, key); } +#endif + +bool Eluna::OnMemberAccept(Group* group, Player* player) +{ + START_HOOK_WITH_RETVAL(GROUP_EVENT_ON_MEMBER_ACCEPT, true); + Push(group); + Push(player); + return CallAllFunctionsBool(GroupEventBindings, key, true); +} diff --git a/src/modules/Eluna/GuildHooks.cpp b/src/modules/Eluna/GuildHooks.cpp index 3662ef1f9a..3bf1b7260c 100644 --- a/src/modules/Eluna/GuildHooks.cpp +++ b/src/modules/Eluna/GuildHooks.cpp @@ -97,6 +97,35 @@ void Eluna::OnMemberWitdrawMoney(Guild* guild, Player* player, uint32& amount, b CleanUpStack(4); } +#ifdef CATA +void Eluna::OnMemberWitdrawMoney(Guild* guild, Player* player, uint64& amount, bool isRepair) +{ + START_HOOK(GUILD_EVENT_ON_MONEY_WITHDRAW); + Push(guild); + Push(player); + Push(amount); + Push(isRepair); // isRepair not a part of Mangos, implement? + int amountIndex = lua_gettop(L) - 1; + int n = SetupStack(GuildEventBindings, key, 4); + + while (n > 0) + { + int r = CallOneFunction(n--, 4, 1); + + if (lua_isnumber(L, r)) + { + amount = CHECKVAL(L, r); + // Update the stack for subsequent calls. + ReplaceArgument(amount, amountIndex); + } + + lua_pop(L, 1); + } + + CleanUpStack(4); +} +#endif + void Eluna::OnMemberDepositMoney(Guild* guild, Player* player, uint32& amount) { START_HOOK(GUILD_EVENT_ON_MONEY_DEPOSIT); @@ -123,6 +152,34 @@ void Eluna::OnMemberDepositMoney(Guild* guild, Player* player, uint32& amount) CleanUpStack(3); } +#ifdef CATA +void Eluna::OnMemberDepositMoney(Guild* guild, Player* player, uint64& amount) +{ + START_HOOK(GUILD_EVENT_ON_MONEY_DEPOSIT); + Push(guild); + Push(player); + Push(amount); + int amountIndex = lua_gettop(L); + int n = SetupStack(GuildEventBindings, key, 3); + + while (n > 0) + { + int r = CallOneFunction(n--, 3, 1); + + if (lua_isnumber(L, r)) + { + amount = CHECKVAL(L, r); + // Update the stack for subsequent calls. + ReplaceArgument(amount, amountIndex); + } + + lua_pop(L, 1); + } + + CleanUpStack(3); +} +#endif + void Eluna::OnItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId, bool isDestBank, uint8 destContainer, uint8 destSlotId) { diff --git a/src/modules/Eluna/Hooks.h b/src/modules/Eluna/Hooks.h index 4288d78c3e..e366e42974 100644 --- a/src/modules/Eluna/Hooks.h +++ b/src/modules/Eluna/Hooks.h @@ -145,7 +145,7 @@ namespace Hooks // AddOns ADDON_EVENT_ON_MESSAGE = 30, // (event, sender, type, prefix, msg, target) - target can be nil/whisper_target/guild/group/channel. Can return false - + WORLD_EVENT_ON_DELETE_CREATURE = 31, // (event, creature) WORLD_EVENT_ON_DELETE_GAMEOBJECT = 32, // (event, gameobject) @@ -201,9 +201,21 @@ namespace Hooks PLAYER_EVENT_ON_LOOT_MONEY = 37, // (event, player, amount) PLAYER_EVENT_ON_QUEST_ABANDON = 38, // (event, player, questId) PLAYER_EVENT_ON_LEARN_TALENTS = 39, // (event, player, talentId, talentRank, spellid) - // UNUSED = 40, // (event, player) - // UNUSED = 41, // (event, player) + PLAYER_EVENT_ON_ENVIRONMENTAL_DEATH = 40, // (event, player, environmentalDamageType) + PLAYER_EVENT_ON_TRADE_ACCEPT = 41, // (event, player, target) - Can return false to interrupt trade PLAYER_EVENT_ON_COMMAND = 42, // (event, player, command) - player is nil if command used from console. Can return false + PLAYER_EVENT_ON_SKILL_CHANGE = 43, // (event, player, skillId, skillValue) - Returns new skill level value + PLAYER_EVENT_ON_LEARN_SPELL = 44, // (event, player, spellId) + PLAYER_EVENT_ON_ACHIEVEMENT_COMPLETE = 45, // (event, player, achievementId) + // UNUSED = 46, // (event, player) + PLAYER_EVENT_ON_UPDATE_AREA = 47, // (event, player, oldArea, newArea) + PLAYER_EVENT_ON_TRADE_INIT = 48, // (event, player, target) - Can return false to interrupt trade + PLAYER_EVENT_ON_SEND_MAIL = 49, // (event, player, recipientGuid) - Can return false to interrupt sending + // UNUSED = 50, // (event, player) + // UNUSED = 51, // (event, player) + // UNUSED = 52, // (event, player) + // UNUSED = 53, // (event, player) + PLAYER_EVENT_ON_QUEST_STATUS_CHANGED = 54, // (event, player, questId, status) PLAYER_EVENT_COUNT }; @@ -235,6 +247,7 @@ namespace Hooks GROUP_EVENT_ON_LEADER_CHANGE = 4, // (event, group, newLeaderGuid, oldLeaderGuid) GROUP_EVENT_ON_DISBAND = 5, // (event, group) GROUP_EVENT_ON_CREATE = 6, // (event, group, leaderGuid, groupType) + GROUP_EVENT_ON_MEMBER_ACCEPT = 7, // (event, group, player) - Can return false to disable accepting GROUP_EVENT_COUNT }; @@ -319,6 +332,10 @@ namespace Hooks ITEM_EVENT_ON_QUEST_ACCEPT = 3, // (event, player, item, quest) - Can return true ITEM_EVENT_ON_EXPIRE = 4, // (event, player, itemid) - Can return true ITEM_EVENT_ON_REMOVE = 5, // (event, player, item) - Can return true + + // Custom + ITEM_EVENT_ON_ADD = 6, // (event, player, item) + ITEM_EVENT_COUNT }; diff --git a/src/modules/Eluna/ItemHooks.cpp b/src/modules/Eluna/ItemHooks.cpp index ddd02233b9..f6f0f98e2a 100644 --- a/src/modules/Eluna/ItemHooks.cpp +++ b/src/modules/Eluna/ItemHooks.cpp @@ -118,9 +118,17 @@ bool Eluna::OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targ bool Eluna::OnExpire(Player* pPlayer, ItemTemplate const* pProto) { +#if defined TRINITY && CATA + START_HOOK_WITH_RETVAL(ITEM_EVENT_ON_EXPIRE, pProto->BasicData->ID, false); +#else START_HOOK_WITH_RETVAL(ITEM_EVENT_ON_EXPIRE, pProto->ItemId, false); +#endif Push(pPlayer); +#if defined TRINITY && CATA + Push(pProto->BasicData->ID); +#else Push(pProto->ItemId); +#endif return CallAllFunctionsBool(ItemEventBindings, key); } @@ -131,3 +139,11 @@ bool Eluna::OnRemove(Player* pPlayer, Item* pItem) Push(pItem); return CallAllFunctionsBool(ItemEventBindings, key); } + +void Eluna::OnAdd(Player* pPlayer, Item* pItem) +{ + START_HOOK(ITEM_EVENT_ON_ADD, pItem->GetEntry()); + Push(pPlayer); + Push(pItem); + CallAllFunctions(ItemEventBindings, key); +} diff --git a/src/modules/Eluna/LuaEngine.cpp b/src/modules/Eluna/LuaEngine.cpp index cab758d9d1..e5b6fb42ac 100644 --- a/src/modules/Eluna/LuaEngine.cpp +++ b/src/modules/Eluna/LuaEngine.cpp @@ -30,9 +30,14 @@ #error Eluna could not determine platform #endif +#ifdef ELUNA_WINDOWS +#include +#include +#endif + // Some dummy includes containing BOOST_VERSION: // ObjectAccessor.h Config.h Log.h -#if !defined MANGOS +#if !defined MANGOS && !defined VMANGOS #define USING_BOOST #endif diff --git a/src/modules/Eluna/LuaEngine.h b/src/modules/Eluna/LuaEngine.h index 43fcb47d68..c40591cc24 100644 --- a/src/modules/Eluna/LuaEngine.h +++ b/src/modules/Eluna/LuaEngine.h @@ -378,11 +378,17 @@ class ELUNA_GAME_API Eluna void OnRepop(Player* pPlayer); void OnResurrect(Player* pPlayer); void OnQuestAbandon(Player* pPlayer, uint32 questId); + void OnQuestStatusChanged(Player* pPlayer, uint32 questId, uint8 status); void OnLearnTalents(Player* pPlayer, uint32 talentId, uint32 talentRank, uint32 spellid); + void OnSkillChange(Player* pPlayer, uint32 skillId, uint32 skillValue); + void OnLearnSpell(Player* pPlayer, uint32 spellid); InventoryResult OnCanUseItem(const Player* pPlayer, uint32 itemEntry); void OnLuaStateClose(); void OnLuaStateOpen(); bool OnAddonMessage(Player* sender, uint32 type, std::string& msg, Player* receiver, Guild* guild, Group* group, Channel* channel); + bool OnTradeInit(Player* trader, Player* tradee); + bool OnTradeAccept(Player* trader, Player* tradee); + bool OnSendMail(Player* sender, ObjectGuid recipientGuid); /* Item */ void OnDummyEffect(WorldObject* pCaster, uint32 spellId, SpellEffIndex effIndex, Item* pTarget); @@ -392,6 +398,7 @@ class ELUNA_GAME_API Eluna bool OnItemGossip(Player* pPlayer, Item* pItem, SpellCastTargets const& targets); bool OnExpire(Player* pPlayer, ItemTemplate const* pProto); bool OnRemove(Player* pPlayer, Item* item); + void OnAdd(Player* pPlayer, Item* item); void HandleGossipSelectOption(Player* pPlayer, Item* item, uint32 sender, uint32 action, const std::string& code); /* Creature */ @@ -460,10 +467,14 @@ class ELUNA_GAME_API Eluna void OnPVPKill(Player* pKiller, Player* pKilled); void OnCreatureKill(Player* pKiller, Creature* pKilled); void OnPlayerKilledByCreature(Creature* pKiller, Player* pKilled); + void OnPlayerKilledByEnvironment(Player* pKilled, uint8 damageType); void OnLevelChanged(Player* pPlayer, uint8 oldLevel); void OnFreeTalentPointsChanged(Player* pPlayer, uint32 newPoints); void OnTalentsReset(Player* pPlayer, bool noCost); void OnMoneyChanged(Player* pPlayer, int32& amount); +#ifdef CATA + void OnMoneyChanged(Player* pPlayer, int64& amount); +#endif void OnGiveXP(Player* pPlayer, uint32& amount, Unit* pVictim); void OnReputationChange(Player* pPlayer, uint32 factionID, int32& standing, bool incremental); void OnDuelRequest(Player* pTarget, Player* pChallenger); @@ -484,8 +495,10 @@ class ELUNA_GAME_API Eluna void OnSave(Player* pPlayer); void OnBindToInstance(Player* pPlayer, Difficulty difficulty, uint32 mapid, bool permanent); void OnUpdateZone(Player* pPlayer, uint32 newZone, uint32 newArea); + void OnUpdateArea(Player* pPlayer, uint32 oldArea, uint32 newArea); void OnMapChanged(Player* pPlayer); void HandleGossipSelectOption(Player* pPlayer, uint32 menuId, uint32 sender, uint32 action, const std::string& code); + void OnAchievementComplete(Player* pPlayer, uint32 achievementId); #ifndef CLASSIC #ifndef TBC @@ -518,7 +531,13 @@ class ELUNA_GAME_API Eluna void OnCreate(Guild* guild, Player* leader, const std::string& name); void OnDisband(Guild* guild); void OnMemberWitdrawMoney(Guild* guild, Player* player, uint32& amount, bool isRepair); +#ifdef CATA + void OnMemberWitdrawMoney(Guild* guild, Player* player, uint64& amount, bool isRepair); +#endif void OnMemberDepositMoney(Guild* guild, Player* player, uint32& amount); +#ifdef CATA + void OnMemberDepositMoney(Guild* guild, Player* player, uint64& amount); +#endif void OnItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId, bool isDestBank, uint8 destContainer, uint8 destSlotId); void OnEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank); void OnBankEvent(Guild* guild, uint8 eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId); @@ -529,7 +548,12 @@ class ELUNA_GAME_API Eluna void OnRemoveMember(Group* group, ObjectGuid guid, uint8 method); void OnChangeLeader(Group* group, ObjectGuid newLeaderGuid, ObjectGuid oldLeaderGuid); void OnDisband(Group* group); +#if defined (TRINITY) && defined (CATA) + void OnCreate(Group* group, ObjectGuid leaderGuid, GroupFlags groupType); +#else void OnCreate(Group* group, ObjectGuid leaderGuid, GroupType groupType); +#endif + bool OnMemberAccept(Group* group, Player* player); /* Map */ void OnCreate(Map* map); diff --git a/src/modules/Eluna/LuaFunctions.cpp b/src/modules/Eluna/LuaFunctions.cpp index d783ef950f..d1abe10ca8 100644 --- a/src/modules/Eluna/LuaFunctions.cpp +++ b/src/modules/Eluna/LuaFunctions.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2010 - 2016 Eluna Lua Engine +* Copyright (C) 2010 - 2023 Eluna Lua Engine * This program is free software licensed under GPL version 3 * Please see the included DOCS/LICENSE.md for more information */ @@ -37,1266 +37,6 @@ extern "C" #include "VehicleMethods.h" #include "BattleGroundMethods.h" -luaL_Reg GlobalMethods[] = -{ - // Hooks - { "RegisterPacketEvent", &LuaGlobalFunctions::RegisterPacketEvent }, - { "RegisterServerEvent", &LuaGlobalFunctions::RegisterServerEvent }, - { "RegisterPlayerEvent", &LuaGlobalFunctions::RegisterPlayerEvent }, - { "RegisterGuildEvent", &LuaGlobalFunctions::RegisterGuildEvent }, - { "RegisterGroupEvent", &LuaGlobalFunctions::RegisterGroupEvent }, - { "RegisterCreatureEvent", &LuaGlobalFunctions::RegisterCreatureEvent }, - { "RegisterUniqueCreatureEvent", &LuaGlobalFunctions::RegisterUniqueCreatureEvent }, - { "RegisterCreatureGossipEvent", &LuaGlobalFunctions::RegisterCreatureGossipEvent }, - { "RegisterGameObjectEvent", &LuaGlobalFunctions::RegisterGameObjectEvent }, - { "RegisterGameObjectGossipEvent", &LuaGlobalFunctions::RegisterGameObjectGossipEvent }, - { "RegisterItemEvent", &LuaGlobalFunctions::RegisterItemEvent }, - { "RegisterItemGossipEvent", &LuaGlobalFunctions::RegisterItemGossipEvent }, - { "RegisterPlayerGossipEvent", &LuaGlobalFunctions::RegisterPlayerGossipEvent }, - { "RegisterBGEvent", &LuaGlobalFunctions::RegisterBGEvent }, - { "RegisterMapEvent", &LuaGlobalFunctions::RegisterMapEvent }, - { "RegisterInstanceEvent", &LuaGlobalFunctions::RegisterInstanceEvent }, - - { "ClearBattleGroundEvents", &LuaGlobalFunctions::ClearBattleGroundEvents }, - { "ClearCreatureEvents", &LuaGlobalFunctions::ClearCreatureEvents }, - { "ClearUniqueCreatureEvents", &LuaGlobalFunctions::ClearUniqueCreatureEvents }, - { "ClearCreatureGossipEvents", &LuaGlobalFunctions::ClearCreatureGossipEvents }, - { "ClearGameObjectEvents", &LuaGlobalFunctions::ClearGameObjectEvents }, - { "ClearGameObjectGossipEvents", &LuaGlobalFunctions::ClearGameObjectGossipEvents }, - { "ClearGroupEvents", &LuaGlobalFunctions::ClearGroupEvents }, - { "ClearGuildEvents", &LuaGlobalFunctions::ClearGuildEvents }, - { "ClearItemEvents", &LuaGlobalFunctions::ClearItemEvents }, - { "ClearItemGossipEvents", &LuaGlobalFunctions::ClearItemGossipEvents }, - { "ClearPacketEvents", &LuaGlobalFunctions::ClearPacketEvents }, - { "ClearPlayerEvents", &LuaGlobalFunctions::ClearPlayerEvents }, - { "ClearPlayerGossipEvents", &LuaGlobalFunctions::ClearPlayerGossipEvents }, - { "ClearServerEvents", &LuaGlobalFunctions::ClearServerEvents }, - { "ClearMapEvents", &LuaGlobalFunctions::ClearMapEvents }, - { "ClearInstanceEvents", &LuaGlobalFunctions::ClearInstanceEvents }, - - // Getters - { "GetLuaEngine", &LuaGlobalFunctions::GetLuaEngine }, - { "GetCoreName", &LuaGlobalFunctions::GetCoreName }, - { "GetRealmID", &LuaGlobalFunctions::GetRealmID }, - { "GetCoreVersion", &LuaGlobalFunctions::GetCoreVersion }, - { "GetCoreExpansion", &LuaGlobalFunctions::GetCoreExpansion }, - { "GetQuest", &LuaGlobalFunctions::GetQuest }, - { "GetPlayerByGUID", &LuaGlobalFunctions::GetPlayerByGUID }, - { "GetPlayerByName", &LuaGlobalFunctions::GetPlayerByName }, - { "GetGameTime", &LuaGlobalFunctions::GetGameTime }, - { "GetPlayersInWorld", &LuaGlobalFunctions::GetPlayersInWorld }, - { "GetGuildByName", &LuaGlobalFunctions::GetGuildByName }, - { "GetGuildByLeaderGUID", &LuaGlobalFunctions::GetGuildByLeaderGUID }, - { "GetPlayerCount", &LuaGlobalFunctions::GetPlayerCount }, - { "GetPlayerGUID", &LuaGlobalFunctions::GetPlayerGUID }, - { "GetItemGUID", &LuaGlobalFunctions::GetItemGUID }, - { "GetObjectGUID", &LuaGlobalFunctions::GetObjectGUID }, - { "GetUnitGUID", &LuaGlobalFunctions::GetUnitGUID }, - { "GetGUIDLow", &LuaGlobalFunctions::GetGUIDLow }, - { "GetGUIDType", &LuaGlobalFunctions::GetGUIDType }, - { "GetGUIDEntry", &LuaGlobalFunctions::GetGUIDEntry }, - { "GetAreaName", &LuaGlobalFunctions::GetAreaName }, - { "bit_not", &LuaGlobalFunctions::bit_not }, - { "bit_xor", &LuaGlobalFunctions::bit_xor }, - { "bit_rshift", &LuaGlobalFunctions::bit_rshift }, - { "bit_lshift", &LuaGlobalFunctions::bit_lshift }, - { "bit_or", &LuaGlobalFunctions::bit_or }, - { "bit_and", &LuaGlobalFunctions::bit_and }, - { "GetItemLink", &LuaGlobalFunctions::GetItemLink }, - { "GetMapById", &LuaGlobalFunctions::GetMapById }, - { "GetCurrTime", &LuaGlobalFunctions::GetCurrTime }, - { "GetTimeDiff", &LuaGlobalFunctions::GetTimeDiff }, - { "PrintInfo", &LuaGlobalFunctions::PrintInfo }, - { "PrintError", &LuaGlobalFunctions::PrintError }, - { "PrintDebug", &LuaGlobalFunctions::PrintDebug }, - { "GetActiveGameEvents", &LuaGlobalFunctions::GetActiveGameEvents }, - - // Boolean - { "IsInventoryPos", &LuaGlobalFunctions::IsInventoryPos }, - { "IsEquipmentPos", &LuaGlobalFunctions::IsEquipmentPos }, - { "IsBankPos", &LuaGlobalFunctions::IsBankPos }, - { "IsBagPos", &LuaGlobalFunctions::IsBagPos }, - { "IsGameEventActive", &LuaGlobalFunctions::IsGameEventActive }, - - // Other - { "ReloadEluna", &LuaGlobalFunctions::ReloadEluna }, - { "RunCommand", &LuaGlobalFunctions::RunCommand }, - { "SendWorldMessage", &LuaGlobalFunctions::SendWorldMessage }, - { "WorldDBQuery", &LuaGlobalFunctions::WorldDBQuery }, - { "WorldDBExecute", &LuaGlobalFunctions::WorldDBExecute }, - { "CharDBQuery", &LuaGlobalFunctions::CharDBQuery }, - { "CharDBExecute", &LuaGlobalFunctions::CharDBExecute }, - { "AuthDBQuery", &LuaGlobalFunctions::AuthDBQuery }, - { "AuthDBExecute", &LuaGlobalFunctions::AuthDBExecute }, - { "CreateLuaEvent", &LuaGlobalFunctions::CreateLuaEvent }, - { "RemoveEventById", &LuaGlobalFunctions::RemoveEventById }, - { "RemoveEvents", &LuaGlobalFunctions::RemoveEvents }, - { "PerformIngameSpawn", &LuaGlobalFunctions::PerformIngameSpawn }, - { "CreatePacket", &LuaGlobalFunctions::CreatePacket }, - { "AddVendorItem", &LuaGlobalFunctions::AddVendorItem }, - { "VendorRemoveItem", &LuaGlobalFunctions::VendorRemoveItem }, - { "VendorRemoveAllItems", &LuaGlobalFunctions::VendorRemoveAllItems }, - { "Kick", &LuaGlobalFunctions::Kick }, - { "Ban", &LuaGlobalFunctions::Ban }, - { "SaveAllPlayers", &LuaGlobalFunctions::SaveAllPlayers }, - { "SendMail", &LuaGlobalFunctions::SendMail }, - { "AddTaxiPath", &LuaGlobalFunctions::AddTaxiPath }, - { "CreateInt64", &LuaGlobalFunctions::CreateLongLong }, - { "CreateUint64", &LuaGlobalFunctions::CreateULongLong }, - { "StartGameEvent", &LuaGlobalFunctions::StartGameEvent }, - { "StopGameEvent", &LuaGlobalFunctions::StopGameEvent }, - - { NULL, NULL } -}; - -ElunaRegister ObjectMethods[] = -{ - // Getters - { "GetEntry", &LuaObject::GetEntry }, - { "GetGUID", &LuaObject::GetGUID }, - { "GetGUIDLow", &LuaObject::GetGUIDLow }, - { "GetInt32Value", &LuaObject::GetInt32Value }, - { "GetUInt32Value", &LuaObject::GetUInt32Value }, - { "GetFloatValue", &LuaObject::GetFloatValue }, - { "GetByteValue", &LuaObject::GetByteValue }, - { "GetUInt16Value", &LuaObject::GetUInt16Value }, - { "GetUInt64Value", &LuaObject::GetUInt64Value }, - { "GetScale", &LuaObject::GetScale }, - { "GetTypeId", &LuaObject::GetTypeId }, - - // Setters - { "SetInt32Value", &LuaObject::SetInt32Value }, - { "SetUInt32Value", &LuaObject::SetUInt32Value }, - { "UpdateUInt32Value", &LuaObject::UpdateUInt32Value }, - { "SetFloatValue", &LuaObject::SetFloatValue }, - { "SetByteValue", &LuaObject::SetByteValue }, - { "SetUInt16Value", &LuaObject::SetUInt16Value }, - { "SetInt16Value", &LuaObject::SetInt16Value }, - { "SetUInt64Value", &LuaObject::SetUInt64Value }, - { "SetScale", &LuaObject::SetScale }, - { "SetFlag", &LuaObject::SetFlag }, - - // Boolean - { "IsInWorld", &LuaObject::IsInWorld }, - { "HasFlag", &LuaObject::HasFlag }, - - // Other - { "ToGameObject", &LuaObject::ToGameObject }, - { "ToUnit", &LuaObject::ToUnit }, - { "ToCreature", &LuaObject::ToCreature }, - { "ToPlayer", &LuaObject::ToPlayer }, - { "ToCorpse", &LuaObject::ToCorpse }, - { "RemoveFlag", &LuaObject::RemoveFlag }, - - { NULL, NULL } -}; - -ElunaRegister WorldObjectMethods[] = -{ - // Getters - { "GetName", &LuaWorldObject::GetName }, - { "GetMap", &LuaWorldObject::GetMap }, -#if (!defined(TBC) && !defined(CLASSIC)) - { "GetPhaseMask", &LuaWorldObject::GetPhaseMask }, - { "SetPhaseMask", &LuaWorldObject::SetPhaseMask }, -#endif - { "GetInstanceId", &LuaWorldObject::GetInstanceId }, - { "GetAreaId", &LuaWorldObject::GetAreaId }, - { "GetZoneId", &LuaWorldObject::GetZoneId }, - { "GetMapId", &LuaWorldObject::GetMapId }, - { "GetX", &LuaWorldObject::GetX }, - { "GetY", &LuaWorldObject::GetY }, - { "GetZ", &LuaWorldObject::GetZ }, - { "GetO", &LuaWorldObject::GetO }, - { "GetLocation", &LuaWorldObject::GetLocation }, - { "GetPlayersInRange", &LuaWorldObject::GetPlayersInRange }, - { "GetCreaturesInRange", &LuaWorldObject::GetCreaturesInRange }, - { "GetGameObjectsInRange", &LuaWorldObject::GetGameObjectsInRange }, - { "GetNearestPlayer", &LuaWorldObject::GetNearestPlayer }, - { "GetNearestGameObject", &LuaWorldObject::GetNearestGameObject }, - { "GetNearestCreature", &LuaWorldObject::GetNearestCreature }, - { "GetNearObject", &LuaWorldObject::GetNearObject }, - { "GetNearObjects", &LuaWorldObject::GetNearObjects }, - { "GetDistance", &LuaWorldObject::GetDistance }, - { "GetExactDistance", &LuaWorldObject::GetExactDistance }, - { "GetDistance2d", &LuaWorldObject::GetDistance2d }, - { "GetExactDistance2d", &LuaWorldObject::GetExactDistance2d }, - { "GetRelativePoint", &LuaWorldObject::GetRelativePoint }, - { "GetAngle", &LuaWorldObject::GetAngle }, - - // Boolean - { "IsWithinLoS", &LuaWorldObject::IsWithinLoS }, - { "IsInMap", &LuaWorldObject::IsInMap }, - { "IsWithinDist3d", &LuaWorldObject::IsWithinDist3d }, - { "IsWithinDist2d", &LuaWorldObject::IsWithinDist2d }, - { "IsWithinDist", &LuaWorldObject::IsWithinDist }, - { "IsWithinDistInMap", &LuaWorldObject::IsWithinDistInMap }, - { "IsInRange", &LuaWorldObject::IsInRange }, - { "IsInRange2d", &LuaWorldObject::IsInRange2d }, - { "IsInRange3d", &LuaWorldObject::IsInRange3d }, - { "IsInFront", &LuaWorldObject::IsInFront }, - { "IsInBack", &LuaWorldObject::IsInBack }, - - // Other - { "SummonGameObject", &LuaWorldObject::SummonGameObject }, - { "SpawnCreature", &LuaWorldObject::SpawnCreature }, - { "SendPacket", &LuaWorldObject::SendPacket }, - { "RegisterEvent", &LuaWorldObject::RegisterEvent }, - { "RemoveEventById", &LuaWorldObject::RemoveEventById }, - { "RemoveEvents", &LuaWorldObject::RemoveEvents }, - { "PlayMusic", &LuaWorldObject::PlayMusic }, - { "PlayDirectSound", &LuaWorldObject::PlayDirectSound }, - { "PlayDistanceSound", &LuaWorldObject::PlayDistanceSound }, - - { NULL, NULL } -}; - -ElunaRegister UnitMethods[] = -{ - // Getters - { "GetLevel", &LuaUnit::GetLevel }, - { "GetHealth", &LuaUnit::GetHealth }, - { "GetDisplayId", &LuaUnit::GetDisplayId }, - { "GetNativeDisplayId", &LuaUnit::GetNativeDisplayId }, - { "GetPower", &LuaUnit::GetPower }, - { "GetMaxPower", &LuaUnit::GetMaxPower }, - { "GetPowerType", &LuaUnit::GetPowerType }, - { "GetMaxHealth", &LuaUnit::GetMaxHealth }, - { "GetHealthPct", &LuaUnit::GetHealthPct }, - { "GetPowerPct", &LuaUnit::GetPowerPct }, - { "GetGender", &LuaUnit::GetGender }, - { "GetRace", &LuaUnit::GetRace }, - { "GetClass", &LuaUnit::GetClass }, - { "GetRaceMask", &LuaUnit::GetRaceMask }, - { "GetClassMask", &LuaUnit::GetClassMask }, - { "GetRaceAsString", &LuaUnit::GetRaceAsString }, - { "GetClassAsString", &LuaUnit::GetClassAsString }, - { "GetAura", &LuaUnit::GetAura }, - { "GetFaction", &LuaUnit::GetFaction }, - { "GetCurrentSpell", &LuaUnit::GetCurrentSpell }, - { "GetCreatureType", &LuaUnit::GetCreatureType }, - { "GetMountId", &LuaUnit::GetMountId }, - { "GetOwner", &LuaUnit::GetOwner }, - { "GetFriendlyUnitsInRange", &LuaUnit::GetFriendlyUnitsInRange }, - { "GetUnfriendlyUnitsInRange", &LuaUnit::GetUnfriendlyUnitsInRange }, - { "GetOwnerGUID", &LuaUnit::GetOwnerGUID }, - { "GetCreatorGUID", &LuaUnit::GetCreatorGUID }, - { "GetMinionGUID", &LuaUnit::GetPetGUID }, - { "GetCharmerGUID", &LuaUnit::GetCharmerGUID }, - { "GetCharmGUID", &LuaUnit::GetCharmGUID }, - { "GetPetGUID", &LuaUnit::GetPetGUID }, -#if (!defined(TBC) && !defined(CLASSIC)) - { "GetCritterGUID", &LuaUnit::GetCritterGUID }, -#endif - { "GetControllerGUID", &LuaUnit::GetControllerGUID }, - { "GetControllerGUIDS", &LuaUnit::GetControllerGUIDS }, - { "GetStandState", &LuaUnit::GetStandState }, - { "GetVictim", &LuaUnit::GetVictim }, - { "GetSpeed", &LuaUnit::GetSpeed }, - { "GetStat", &LuaUnit::GetStat }, - { "GetBaseSpellPower", &LuaUnit::GetBaseSpellPower }, -#if (!defined(TBC) && !defined(CLASSIC)) - { "GetVehicleKit", &LuaUnit::GetVehicleKit }, - // {"GetVehicle", &LuaUnit::GetVehicle}, // :GetVehicle() - UNDOCUMENTED - Gets the Vehicle kit of the vehicle the unit is on -#endif - { "GetMovementType", &LuaUnit::GetMovementType }, - - // Setters - { "SetFaction", &LuaUnit::SetFaction }, - { "SetLevel", &LuaUnit::SetLevel }, - { "SetHealth", &LuaUnit::SetHealth }, - { "SetMaxHealth", &LuaUnit::SetMaxHealth }, - { "SetPower", &LuaUnit::SetPower }, - { "SetMaxPower", &LuaUnit::SetMaxPower }, - { "SetPowerType", &LuaUnit::SetPowerType }, - { "SetDisplayId", &LuaUnit::SetDisplayId }, - { "SetNativeDisplayId", &LuaUnit::SetNativeDisplayId }, - { "SetFacing", &LuaUnit::SetFacing }, - { "SetFacingToObject", &LuaUnit::SetFacingToObject }, - { "SetSpeed", &LuaUnit::SetSpeed }, - // {"SetStunned", &LuaUnit::SetStunned}, // :SetStunned([enable]) - UNDOCUMENTED - Stuns or removes stun - {"SetRooted", &LuaUnit::SetRooted}, - {"SetConfused", &LuaUnit::SetConfused}, - {"SetFeared", &LuaUnit::SetFeared}, - { "SetPvP", &LuaUnit::SetPvP }, -#if (!defined(TBC) && !defined(CLASSIC)) - { "SetFFA", &LuaUnit::SetFFA }, - { "SetSanctuary", &LuaUnit::SetSanctuary }, -#endif - // {"SetCanFly", &LuaUnit::SetCanFly}, // :SetCanFly(apply) - UNDOCUMENTED - // {"SetVisible", &LuaUnit::SetVisible}, // :SetVisible(x) - UNDOCUMENTED - { "SetOwnerGUID", &LuaUnit::SetOwnerGUID }, - { "SetName", &LuaUnit::SetName }, - { "SetSheath", &LuaUnit::SetSheath }, - { "SetCreatorGUID", &LuaUnit::SetCreatorGUID }, - { "SetMinionGUID", &LuaUnit::SetPetGUID }, - { "SetPetGUID", &LuaUnit::SetPetGUID }, -#if (!defined(TBC) && !defined(CLASSIC)) - { "SetCritterGUID", &LuaUnit::SetCritterGUID }, -#endif - { "SetWaterWalk", &LuaUnit::SetWaterWalk }, - { "SetStandState", &LuaUnit::SetStandState }, - { "SetInCombatWith", &LuaUnit::SetInCombatWith }, - { "ModifyPower", &LuaUnit::ModifyPower }, - - // Boolean - { "IsAlive", &LuaUnit::IsAlive }, - { "IsDead", &LuaUnit::IsDead }, - { "IsDying", &LuaUnit::IsDying }, - { "IsPvPFlagged", &LuaUnit::IsPvPFlagged }, - { "IsInCombat", &LuaUnit::IsInCombat }, - { "IsBanker", &LuaUnit::IsBanker }, - { "IsBattleMaster", &LuaUnit::IsBattleMaster }, - { "IsCharmed", &LuaUnit::IsCharmed }, - { "IsArmorer", &LuaUnit::IsArmorer }, - { "IsAttackingPlayer", &LuaUnit::IsAttackingPlayer }, - { "IsInWater", &LuaUnit::IsInWater }, - { "IsUnderWater", &LuaUnit::IsUnderWater }, - { "IsAuctioneer", &LuaUnit::IsAuctioneer }, - { "IsGuildMaster", &LuaUnit::IsGuildMaster }, - { "IsInnkeeper", &LuaUnit::IsInnkeeper }, - { "IsTrainer", &LuaUnit::IsTrainer }, - { "IsGossip", &LuaUnit::IsGossip }, - { "IsTaxi", &LuaUnit::IsTaxi }, - { "IsSpiritHealer", &LuaUnit::IsSpiritHealer }, - { "IsSpiritGuide", &LuaUnit::IsSpiritGuide }, - { "IsTabardDesigner", &LuaUnit::IsTabardDesigner }, - { "IsServiceProvider", &LuaUnit::IsServiceProvider }, - { "IsSpiritService", &LuaUnit::IsSpiritService }, - { "HealthBelowPct", &LuaUnit::HealthBelowPct }, - { "HealthAbovePct", &LuaUnit::HealthAbovePct }, - { "IsMounted", &LuaUnit::IsMounted }, - { "AttackStop", &LuaUnit::AttackStop }, - { "Attack", &LuaUnit::Attack }, - // {"IsVisible", &LuaUnit::IsVisible}, // :IsVisible() - UNDOCUMENTED - // {"IsMoving", &LuaUnit::IsMoving}, // :IsMoving() - UNDOCUMENTED - // {"IsFlying", &LuaUnit::IsFlying}, // :IsFlying() - UNDOCUMENTED - { "IsStopped", &LuaUnit::IsStopped }, - { "HasUnitState", &LuaUnit::HasUnitState }, - { "IsQuestGiver", &LuaUnit::IsQuestGiver }, - { "IsInAccessiblePlaceFor", &LuaUnit::IsInAccessiblePlaceFor }, - { "IsVendor", &LuaUnit::IsVendor }, - { "IsRooted", &LuaUnit::IsRooted }, - { "IsFullHealth", &LuaUnit::IsFullHealth }, - { "HasAura", &LuaUnit::HasAura }, - { "IsCasting", &LuaUnit::IsCasting }, - { "IsStandState", &LuaUnit::IsStandState }, -#ifndef CLASSIC - { "IsOnVehicle", &LuaUnit::IsOnVehicle }, -#endif - - // Other - { "AddAura", &LuaUnit::AddAura }, - { "RemoveAura", &LuaUnit::RemoveAura }, - { "RemoveAllAuras", &LuaUnit::RemoveAllAuras }, -#if !defined(CLASSIC) - { "RemoveArenaAuras", &LuaUnit::RemoveArenaAuras }, -#endif - { "ClearInCombat", &LuaUnit::ClearInCombat }, - { "DeMorph", &LuaUnit::DeMorph }, - { "SendUnitWhisper", &LuaUnit::SendUnitWhisper }, - { "SendUnitEmote", &LuaUnit::SendUnitEmote }, - { "SendUnitSay", &LuaUnit::SendUnitSay }, - { "SendUnitYell", &LuaUnit::SendUnitYell }, - { "CastSpell", &LuaUnit::CastSpell }, - { "CastCustomSpell", &LuaUnit::CastCustomSpell }, - { "CastSpellAoF", &LuaUnit::CastSpellAoF }, - { "Kill", &LuaUnit::Kill }, - { "StopSpellCast", &LuaUnit::StopSpellCast }, - { "InterruptSpell", &LuaUnit::InterruptSpell }, - { "SendChatMessageToPlayer", &LuaUnit::SendChatMessageToPlayer }, - { "PerformEmote", &LuaUnit::PerformEmote }, - { "EmoteState", &LuaUnit::EmoteState }, - { "CountPctFromCurHealth", &LuaUnit::CountPctFromCurHealth }, - { "CountPctFromMaxHealth", &LuaUnit::CountPctFromMaxHealth }, - { "Dismount", &LuaUnit::Dismount }, - { "Mount", &LuaUnit::Mount }, - // {"RestoreDisplayId", &LuaUnit::RestoreDisplayId}, // :RestoreDisplayId() - UNDOCUMENTED - // {"RestoreFaction", &LuaUnit::RestoreFaction}, // :RestoreFaction() - UNDOCUMENTED - // {"RemoveBindSightAuras", &LuaUnit::RemoveBindSightAuras}, // :RemoveBindSightAuras() - UNDOCUMENTED - // {"RemoveCharmAuras", &LuaUnit::RemoveCharmAuras}, // :RemoveCharmAuras() - UNDOCUMENTED - { "ClearThreatList", &LuaUnit::ClearThreatList }, - { "ClearUnitState", &LuaUnit::ClearUnitState }, - { "AddUnitState", &LuaUnit::AddUnitState }, - // {"DisableMelee", &LuaUnit::DisableMelee}, // :DisableMelee([disable]) - UNDOCUMENTED - if true, enables - // {"SummonGuardian", &LuaUnit::SummonGuardian}, // :SummonGuardian(entry, x, y, z, o[, duration]) - UNDOCUMENTED - summons a guardian to location. Scales with summoner, is friendly to him and guards him. - { "NearTeleport", &LuaUnit::NearTeleport }, - { "MoveIdle", &LuaUnit::MoveIdle }, - { "MoveRandom", &LuaUnit::MoveRandom }, - { "MoveHome", &LuaUnit::MoveHome }, - { "MoveFollow", &LuaUnit::MoveFollow }, - { "MoveChase", &LuaUnit::MoveChase }, - { "MoveConfused", &LuaUnit::MoveConfused }, - { "MoveFleeing", &LuaUnit::MoveFleeing }, - { "MoveTo", &LuaUnit::MoveTo }, -#if (!defined(TBC) && !defined(CLASSIC)) - { "MoveJump", &LuaUnit::MoveJump }, -#endif - { "MoveStop", &LuaUnit::MoveStop }, - { "MoveExpire", &LuaUnit::MoveExpire }, - { "MoveClear", &LuaUnit::MoveClear }, - { "DealDamage", &LuaUnit::DealDamage }, - { "DealHeal", &LuaUnit::DealHeal }, - { "AddThreat", &LuaUnit::AddThreat }, - - { NULL, NULL } -}; - -ElunaRegister PlayerMethods[] = -{ - // Getters - { "GetSelection", &LuaPlayer::GetSelection }, - { "GetGMRank", &LuaPlayer::GetGMRank }, - { "GetGuildId", &LuaPlayer::GetGuildId }, - { "GetCoinage", &LuaPlayer::GetCoinage }, - { "GetTeam", &LuaPlayer::GetTeam }, - { "GetItemCount", &LuaPlayer::GetItemCount }, - { "GetGroup", &LuaPlayer::GetGroup }, - { "GetGuild", &LuaPlayer::GetGuild }, - { "GetAccountId", &LuaPlayer::GetAccountId }, - { "GetAccountName", &LuaPlayer::GetAccountName }, -#if defined (TBC) || defined (WOTLK) - { "GetArenaPoints", &LuaPlayer::GetArenaPoints }, - { "GetHonorPoints", &LuaPlayer::GetHonorPoints }, -#endif - { "GetLifetimeKills", &LuaPlayer::GetLifetimeKills }, - { "GetPlayerIP", &LuaPlayer::GetPlayerIP }, - { "GetLevelPlayedTime", &LuaPlayer::GetLevelPlayedTime }, - { "GetTotalPlayedTime", &LuaPlayer::GetTotalPlayedTime }, - { "GetItemByPos", &LuaPlayer::GetItemByPos }, - { "GetItemByEntry", &LuaPlayer::GetItemByEntry }, - { "GetItemByGUID", &LuaPlayer::GetItemByGUID }, - { "GetMailItem", &LuaPlayer::GetMailItem }, - { "GetReputation", &LuaPlayer::GetReputation }, - { "GetEquippedItemBySlot", &LuaPlayer::GetEquippedItemBySlot }, - { "GetQuestLevel", &LuaPlayer::GetQuestLevel }, - { "GetChatTag", &LuaPlayer::GetChatTag }, - { "GetRestBonus", &LuaPlayer::GetRestBonus }, -#ifdef WOTLK - { "GetPhaseMaskForSpawn", &LuaPlayer::GetPhaseMaskForSpawn }, -#endif - { "GetReqKillOrCastCurrentCount", &LuaPlayer::GetReqKillOrCastCurrentCount }, - { "GetQuestStatus", &LuaPlayer::GetQuestStatus }, - { "GetInGameTime", &LuaPlayer::GetInGameTime }, - { "GetComboPoints", &LuaPlayer::GetComboPoints }, - { "GetComboTarget", &LuaPlayer::GetComboTarget }, - { "GetGuildName", &LuaPlayer::GetGuildName }, - { "GetFreeTalentPoints", &LuaPlayer::GetFreeTalentPoints }, -#if (!defined(TBC) && !defined(CLASSIC)) - { "GetActiveSpec", &LuaPlayer::GetActiveSpec }, - { "GetSpecsCount", &LuaPlayer::GetSpecsCount }, -#endif - { "GetSpellCooldownDelay", &LuaPlayer::GetSpellCooldownDelay }, - { "GetGuildRank", &LuaPlayer::GetGuildRank }, - { "GetDifficulty", &LuaPlayer::GetDifficulty }, - { "GetHealthBonusFromStamina", &LuaPlayer::GetHealthBonusFromStamina }, - { "GetManaBonusFromIntellect", &LuaPlayer::GetManaBonusFromIntellect }, - { "GetMaxSkillValue", &LuaPlayer::GetMaxSkillValue }, - { "GetPureMaxSkillValue", &LuaPlayer::GetPureMaxSkillValue }, - { "GetSkillValue", &LuaPlayer::GetSkillValue }, - { "GetBaseSkillValue", &LuaPlayer::GetBaseSkillValue }, - { "GetPureSkillValue", &LuaPlayer::GetPureSkillValue }, - { "GetSkillPermBonusValue", &LuaPlayer::GetSkillPermBonusValue }, - { "GetSkillTempBonusValue", &LuaPlayer::GetSkillTempBonusValue }, - { "GetReputationRank", &LuaPlayer::GetReputationRank }, - { "GetDrunkValue", &LuaPlayer::GetDrunkValue }, - { "GetBattlegroundId", &LuaPlayer::GetBattlegroundId }, - { "GetBattlegroundTypeId", &LuaPlayer::GetBattlegroundTypeId }, - { "GetXPRestBonus", &LuaPlayer::GetXPRestBonus }, - { "GetGroupInvite", &LuaPlayer::GetGroupInvite }, - { "GetSubGroup", &LuaPlayer::GetSubGroup }, - { "GetNextRandomRaidMember", &LuaPlayer::GetNextRandomRaidMember }, - { "GetOriginalGroup", &LuaPlayer::GetOriginalGroup }, - { "GetOriginalSubGroup", &LuaPlayer::GetOriginalSubGroup }, -#if defined(TRINITY) || AZEROTHCORE - { "GetChampioningFaction", &LuaPlayer::GetChampioningFaction }, -#endif - { "GetLatency", &LuaPlayer::GetLatency }, - // {"GetRecruiterId", &LuaPlayer::GetRecruiterId}, // :GetRecruiterId() - UNDOCUMENTED - Returns player's recruiter's ID - { "GetDbLocaleIndex", &LuaPlayer::GetDbLocaleIndex }, - { "GetDbcLocale", &LuaPlayer::GetDbcLocale }, - { "GetCorpse", &LuaPlayer::GetCorpse }, - { "GetGossipTextId", &LuaPlayer::GetGossipTextId }, - { "GetQuestRewardStatus", &LuaPlayer::GetQuestRewardStatus }, -#if defined(CLASSIC) || defined(TBC) || defined(WOTLK) - { "GetShieldBlockValue", &LuaPlayer::GetShieldBlockValue }, -#endif -#ifdef CLASSIC - { "GetHonorStoredKills", &LuaPlayer::GetHonorStoredKills }, - { "GetRankPoints", &LuaPlayer::GetRankPoints }, - { "GetHonorLastWeekStandingPos", &LuaPlayer::GetHonorLastWeekStandingPos }, -#endif - - // Setters - { "AdvanceSkillsToMax", &LuaPlayer::AdvanceSkillsToMax }, - { "AdvanceSkill", &LuaPlayer::AdvanceSkill }, - { "AdvanceAllSkills", &LuaPlayer::AdvanceAllSkills }, - { "AddLifetimeKills", &LuaPlayer::AddLifetimeKills }, - { "SetCoinage", &LuaPlayer::SetCoinage }, -#ifndef CLASSIC - { "SetKnownTitle", &LuaPlayer::SetKnownTitle }, - { "UnsetKnownTitle", &LuaPlayer::UnsetKnownTitle }, -#endif - { "SetBindPoint", &LuaPlayer::SetBindPoint }, -#if defined(TBC) || defined(WOTLK) - { "SetArenaPoints", &LuaPlayer::SetArenaPoints }, - { "SetHonorPoints", &LuaPlayer::SetHonorPoints }, -#endif -#ifdef CLASSIC - { "SetHonorStoredKills", &LuaPlayer::SetHonorStoredKills }, - { "SetRankPoints", &LuaPlayer::SetRankPoints }, - { "SetHonorLastWeekStandingPos", &LuaPlayer::SetHonorLastWeekStandingPos }, -#endif - { "SetLifetimeKills", &LuaPlayer::SetLifetimeKills }, - { "SetGameMaster", &LuaPlayer::SetGameMaster }, - { "SetGMChat", &LuaPlayer::SetGMChat }, - { "SetTaxiCheat", &LuaPlayer::SetTaxiCheat }, - { "SetGMVisible", &LuaPlayer::SetGMVisible }, - { "SetPvPDeath", &LuaPlayer::SetPvPDeath }, - { "SetAcceptWhispers", &LuaPlayer::SetAcceptWhispers }, - { "SetRestBonus", &LuaPlayer::SetRestBonus }, - { "SetQuestStatus", &LuaPlayer::SetQuestStatus }, - { "SetReputation", &LuaPlayer::SetReputation }, - { "SetFreeTalentPoints", &LuaPlayer::SetFreeTalentPoints }, - { "SetGuildRank", &LuaPlayer::SetGuildRank }, - // {"SetMovement", &LuaPlayer::SetMovement}, // :SetMovement(type) - UNDOCUMENTED - Sets player's movement type - { "SetSkill", &LuaPlayer::SetSkill }, - { "SetFactionForRace", &LuaPlayer::SetFactionForRace }, - { "SetDrunkValue", &LuaPlayer::SetDrunkValue }, - { "SetAtLoginFlag", &LuaPlayer::SetAtLoginFlag }, - { "SetPlayerLock", &LuaPlayer::SetPlayerLock }, - { "SetGender", &LuaPlayer::SetGender }, - { "SetSheath", &LuaPlayer::SetSheath }, -#if !defined TRINITY && !AZEROTHCORE - { "SetFFA", &LuaPlayer::SetFFA }, -#endif - - // Boolean - { "IsInGroup", &LuaPlayer::IsInGroup }, - { "IsInGuild", &LuaPlayer::IsInGuild }, - { "IsGM", &LuaPlayer::IsGM }, - { "IsImmuneToDamage", &LuaPlayer::IsImmuneToDamage }, - { "IsAlliance", &LuaPlayer::IsAlliance }, - { "IsHorde", &LuaPlayer::IsHorde }, -#ifndef CLASSIC - { "HasTitle", &LuaPlayer::HasTitle }, -#endif - { "HasItem", &LuaPlayer::HasItem }, - { "Teleport", &LuaPlayer::Teleport }, - { "AddItem", &LuaPlayer::AddItem }, -#ifndef CLASSIC - { "IsInArenaTeam", &LuaPlayer::IsInArenaTeam }, -#endif - { "CanCompleteQuest", &LuaPlayer::CanCompleteQuest }, - { "CanEquipItem", &LuaPlayer::CanEquipItem }, - { "IsFalling", &LuaPlayer::IsFalling }, - { "ToggleAFK", &LuaPlayer::ToggleAFK }, - { "ToggleDND", &LuaPlayer::ToggleDND }, - { "IsAFK", &LuaPlayer::IsAFK }, - { "IsDND", &LuaPlayer::IsDND }, - { "IsAcceptingWhispers", &LuaPlayer::IsAcceptingWhispers }, - { "IsGMChat", &LuaPlayer::IsGMChat }, - { "IsTaxiCheater", &LuaPlayer::IsTaxiCheater }, - { "IsGMVisible", &LuaPlayer::IsGMVisible }, - { "HasQuest", &LuaPlayer::HasQuest }, - { "InBattlegroundQueue", &LuaPlayer::InBattlegroundQueue }, - // {"IsImmuneToEnvironmentalDamage", &LuaPlayer::IsImmuneToEnvironmentalDamage}, // :IsImmuneToEnvironmentalDamage() - UNDOCUMENTED - Returns true if the player is immune to environmental damage - { "CanSpeak", &LuaPlayer::CanSpeak }, - { "HasAtLoginFlag", &LuaPlayer::HasAtLoginFlag }, - // {"InRandomLfgDungeon", &LuaPlayer::InRandomLfgDungeon}, // :InRandomLfgDungeon() - UNDOCUMENTED - Returns true if the player is in a random LFG dungeon - // {"HasPendingBind", &LuaPlayer::HasPendingBind}, // :HasPendingBind() - UNDOCUMENTED - Returns true if the player has a pending instance bind -#if (!defined(TBC) && !defined(CLASSIC)) - { "HasAchieved", &LuaPlayer::HasAchieved }, -#if defined(TRINITY) || defined(AZEROTHCORE) - { "SetAchievement", &LuaPlayer::SetAchievement }, -#endif -#endif - { "CanUninviteFromGroup", &LuaPlayer::CanUninviteFromGroup }, - { "IsRested", &LuaPlayer::IsRested }, - // {"CanFlyInZone", &LuaPlayer::CanFlyInZone}, // :CanFlyInZone(mapid, zone) - UNDOCUMENTED - Returns true if the player can fly in the area - // {"IsNeverVisible", &LuaPlayer::IsNeverVisible}, // :IsNeverVisible() - UNDOCUMENTED - Returns true if the player is never visible - { "IsVisibleForPlayer", &LuaPlayer::IsVisibleForPlayer }, - // {"IsUsingLfg", &LuaPlayer::IsUsingLfg}, // :IsUsingLfg() - UNDOCUMENTED - Returns true if the player is using LFG - { "HasQuestForItem", &LuaPlayer::HasQuestForItem }, - { "HasQuestForGO", &LuaPlayer::HasQuestForGO }, - { "CanShareQuest", &LuaPlayer::CanShareQuest }, - // {"HasReceivedQuestReward", &LuaPlayer::HasReceivedQuestReward}, // :HasReceivedQuestReward(entry) - UNDOCUMENTED - Returns true if the player has recieved the quest's reward -#if (!defined(TBC) && !defined(CLASSIC)) - { "HasTalent", &LuaPlayer::HasTalent }, -#endif - { "IsInSameGroupWith", &LuaPlayer::IsInSameGroupWith }, - { "IsInSameRaidWith", &LuaPlayer::IsInSameRaidWith }, - { "IsGroupVisibleFor", &LuaPlayer::IsGroupVisibleFor }, - { "HasSkill", &LuaPlayer::HasSkill }, - { "IsHonorOrXPTarget", &LuaPlayer::IsHonorOrXPTarget }, - { "CanParry", &LuaPlayer::CanParry }, - { "CanBlock", &LuaPlayer::CanBlock }, -#if (!defined(TBC) && !defined(CLASSIC)) - { "CanTitanGrip", &LuaPlayer::CanTitanGrip }, -#endif - { "InBattleground", &LuaPlayer::InBattleground }, -#ifndef CLASSIC - { "InArena", &LuaPlayer::InArena }, -#endif - // {"IsOutdoorPvPActive", &LuaPlayer::IsOutdoorPvPActive}, // :IsOutdoorPvPActive() - UNDOCUMENTED - Returns true if the player is outdoor pvp active - // {"IsARecruiter", &LuaPlayer::IsARecruiter}, // :IsARecruiter() - UNDOCUMENTED - Returns true if the player is a recruiter - { "CanUseItem", &LuaPlayer::CanUseItem }, - { "HasSpell", &LuaPlayer::HasSpell }, - { "HasSpellCooldown", &LuaPlayer::HasSpellCooldown }, - { "IsInWater", &LuaPlayer::IsInWater }, -#ifndef CLASSIC - { "CanFly", &LuaPlayer::CanFly }, -#endif - { "IsMoving", &LuaPlayer::IsMoving }, -#ifndef CLASSIC - { "IsFlying", &LuaPlayer::IsFlying }, -#endif - - // Gossip - { "GossipMenuAddItem", &LuaPlayer::GossipMenuAddItem }, - { "GossipSendMenu", &LuaPlayer::GossipSendMenu }, - { "GossipComplete", &LuaPlayer::GossipComplete }, - { "GossipClearMenu", &LuaPlayer::GossipClearMenu }, - - // Other - { "SendBroadcastMessage", &LuaPlayer::SendBroadcastMessage }, - { "SendAreaTriggerMessage", &LuaPlayer::SendAreaTriggerMessage }, - { "SendNotification", &LuaPlayer::SendNotification }, - { "SendPacket", &LuaPlayer::SendPacket }, - { "SendAddonMessage", &LuaPlayer::SendAddonMessage }, - { "ModifyMoney", &LuaPlayer::ModifyMoney }, - { "LearnSpell", &LuaPlayer::LearnSpell }, - { "LearnTalent", &LuaPlayer::LearnTalent }, -#if !defined(CLASSIC) - { "RemoveArenaSpellCooldowns", &LuaPlayer::RemoveArenaSpellCooldowns }, -#endif - { "RemoveItem", &LuaPlayer::RemoveItem }, - { "RemoveLifetimeKills", &LuaPlayer::RemoveLifetimeKills }, - { "ResurrectPlayer", &LuaPlayer::ResurrectPlayer }, - { "EquipItem", &LuaPlayer::EquipItem }, - { "ResetSpellCooldown", &LuaPlayer::ResetSpellCooldown }, - { "ResetTypeCooldowns", &LuaPlayer::ResetTypeCooldowns }, - { "ResetAllCooldowns", &LuaPlayer::ResetAllCooldowns }, - { "GiveXP", &LuaPlayer::GiveXP }, // :GiveXP(xp[, victim, pureXP, triggerHook]) - UNDOCUMENTED - Gives XP to the player. If pure is false, bonuses are count in. If triggerHook is false, GiveXp hook is not triggered. - // {"RemovePet", &LuaPlayer::RemovePet}, // :RemovePet([mode, returnreagent]) - UNDOCUMENTED - Removes the player's pet. Mode determines if the pet is saved and how - // {"SummonPet", &LuaPlayer::SummonPet}, // :SummonPet(entry, x, y, z, o, petType, despwtime) - Summons a pet for the player - { "Say", &LuaPlayer::Say }, - { "Yell", &LuaPlayer::Yell }, - { "TextEmote", &LuaPlayer::TextEmote }, - { "Whisper", &LuaPlayer::Whisper }, - { "CompleteQuest", &LuaPlayer::CompleteQuest }, - { "IncompleteQuest", &LuaPlayer::IncompleteQuest }, - { "FailQuest", &LuaPlayer::FailQuest }, - { "AddQuest", &LuaPlayer::AddQuest }, - { "RemoveQuest", &LuaPlayer::RemoveQuest }, - // {"RemoveActiveQuest", &LuaPlayer::RemoveActiveQuest}, // :RemoveActiveQuest(entry) - UNDOCUMENTED - Removes an active quest - // {"RemoveRewardedQuest", &LuaPlayer::RemoveRewardedQuest}, // :RemoveRewardedQuest(entry) - UNDOCUMENTED - Removes a rewarded quest - { "AreaExploredOrEventHappens", &LuaPlayer::AreaExploredOrEventHappens }, - { "GroupEventHappens", &LuaPlayer::GroupEventHappens }, - { "KilledMonsterCredit", &LuaPlayer::KilledMonsterCredit }, - // {"KilledPlayerCredit", &LuaPlayer::KilledPlayerCredit}, // :KilledPlayerCredit() - UNDOCUMENTED - Satisfies a player kill for the player - // {"KillGOCredit", &LuaPlayer::KillGOCredit}, // :KillGOCredit(GOEntry[, GUID]) - UNDOCUMENTED - Credits the player for destroying a GO, guid is optional - { "TalkedToCreature", &LuaPlayer::TalkedToCreature }, -#if (!defined(TBC) && !defined(CLASSIC)) - { "ResetPetTalents", &LuaPlayer::ResetPetTalents }, -#endif - { "AddComboPoints", &LuaPlayer::AddComboPoints }, - // {"GainSpellComboPoints", &LuaPlayer::GainSpellComboPoints}, // :GainSpellComboPoints(amount) - UNDOCUMENTED - Player gains spell combo points - { "ClearComboPoints", &LuaPlayer::ClearComboPoints }, - { "RemoveSpell", &LuaPlayer::RemoveSpell }, - { "ResetTalents", &LuaPlayer::ResetTalents }, - { "ResetTalentsCost", &LuaPlayer::ResetTalentsCost }, - // {"AddTalent", &LuaPlayer::AddTalent}, // :AddTalent(spellid, spec, learning) - UNDOCUMENTED - Adds a talent spell for the player to given spec - { "RemoveFromGroup", &LuaPlayer::RemoveFromGroup }, - { "KillPlayer", &LuaPlayer::KillPlayer }, - { "DurabilityLossAll", &LuaPlayer::DurabilityLossAll }, - { "DurabilityLoss", &LuaPlayer::DurabilityLoss }, - { "DurabilityPointsLoss", &LuaPlayer::DurabilityPointsLoss }, - { "DurabilityPointsLossAll", &LuaPlayer::DurabilityPointsLossAll }, - { "DurabilityPointLossForEquipSlot", &LuaPlayer::DurabilityPointLossForEquipSlot }, - { "DurabilityRepairAll", &LuaPlayer::DurabilityRepairAll }, - { "DurabilityRepair", &LuaPlayer::DurabilityRepair }, -#if defined(TBC) || defined(WOTLK) - { "ModifyHonorPoints", &LuaPlayer::ModifyHonorPoints }, - { "ModifyArenaPoints", &LuaPlayer::ModifyArenaPoints }, -#endif - { "LeaveBattleground", &LuaPlayer::LeaveBattleground }, - // {"BindToInstance", &LuaPlayer::BindToInstance}, // :BindToInstance() - UNDOCUMENTED - Binds the player to the current instance - { "UnbindInstance", &LuaPlayer::UnbindInstance }, - { "UnbindAllInstances", &LuaPlayer::UnbindAllInstances }, - { "RemoveFromBattlegroundRaid", &LuaPlayer::RemoveFromBattlegroundRaid }, -#if (!defined(TBC) && !defined(CLASSIC)) - { "ResetAchievements", &LuaPlayer::ResetAchievements }, -#endif - { "KickPlayer", &LuaPlayer::KickPlayer }, - { "LogoutPlayer", &LuaPlayer::LogoutPlayer }, - { "SendTrainerList", &LuaPlayer::SendTrainerList }, - { "SendListInventory", &LuaPlayer::SendListInventory }, - { "SendShowBank", &LuaPlayer::SendShowBank }, - { "SendTabardVendorActivate", &LuaPlayer::SendTabardVendorActivate }, - { "SendSpiritResurrect", &LuaPlayer::SendSpiritResurrect }, - { "SendTaxiMenu", &LuaPlayer::SendTaxiMenu }, - { "SendUpdateWorldState", &LuaPlayer::SendUpdateWorldState }, - { "RewardQuest", &LuaPlayer::RewardQuest }, - { "SendAuctionMenu", &LuaPlayer::SendAuctionMenu }, - { "SendShowMailBox", &LuaPlayer::SendShowMailBox }, - { "StartTaxi", &LuaPlayer::StartTaxi }, - { "GossipSendPOI", &LuaPlayer::GossipSendPOI }, - { "GossipAddQuests", &LuaPlayer::GossipAddQuests }, - { "SendQuestTemplate", &LuaPlayer::SendQuestTemplate }, - { "SpawnBones", &LuaPlayer::SpawnBones }, - { "RemovedInsignia", &LuaPlayer::RemovedInsignia }, - { "SendGuildInvite", &LuaPlayer::SendGuildInvite }, - { "Mute", &LuaPlayer::Mute }, - { "SummonPlayer", &LuaPlayer::SummonPlayer }, - { "SaveToDB", &LuaPlayer::SaveToDB }, - { "GroupInvite", &LuaPlayer::GroupInvite }, - { "GroupCreate", &LuaPlayer::GroupCreate }, - { "SendCinematicStart", &LuaPlayer::SendCinematicStart }, -#if !defined(CLASSIC) && !defined(TBC) - { "SendMovieStart", &LuaPlayer::SendMovieStart }, -#endif -#ifdef CLASSIC - { "UpdateHonor", &LuaPlayer::UpdateHonor }, - { "ResetHonor", &LuaPlayer::ResetHonor }, - { "ClearHonorInfo", &LuaPlayer::ClearHonorInfo }, -#endif - - { NULL, NULL } -}; - -ElunaRegister CreatureMethods[] = -{ - // Getters - { "GetAITarget", &LuaCreature::GetAITarget }, - { "GetAITargets", &LuaCreature::GetAITargets }, - { "GetAITargetsCount", &LuaCreature::GetAITargetsCount }, - { "GetHomePosition", &LuaCreature::GetHomePosition }, - { "GetCorpseDelay", &LuaCreature::GetCorpseDelay }, - { "GetCreatureSpellCooldownDelay", &LuaCreature::GetCreatureSpellCooldownDelay }, - { "GetScriptId", &LuaCreature::GetScriptId }, - { "GetAIName", &LuaCreature::GetAIName }, - { "GetScriptName", &LuaCreature::GetScriptName }, -#ifndef AZEROTHCORE - { "GetAttackDistance", &LuaCreature::GetAttackDistance }, -#endif - { "GetAggroRange", &LuaCreature::GetAggroRange }, - { "GetDefaultMovementType", &LuaCreature::GetDefaultMovementType }, - { "GetRespawnDelay", &LuaCreature::GetRespawnDelay }, - { "GetWanderRadius", &LuaCreature::GetWanderRadius }, - { "GetCurrentWaypointId", &LuaCreature::GetCurrentWaypointId }, -#if defined(TRINITY) || AZEROTHCORE - { "GetWaypointPath", &LuaCreature::GetWaypointPath }, - { "GetLootMode", &LuaCreature::GetLootMode }, -#endif - { "GetLootRecipient", &LuaCreature::GetLootRecipient }, - { "GetLootRecipientGroup", &LuaCreature::GetLootRecipientGroup }, - { "GetNPCFlags", &LuaCreature::GetNPCFlags }, - { "GetExtraFlags", &LuaCreature::GetExtraFlags }, -#if defined(CLASSIC) || defined(TBC) || defined(WOTLK) - { "GetShieldBlockValue", &LuaCreature::GetShieldBlockValue }, -#endif - { "GetDBTableGUIDLow", &LuaCreature::GetDBTableGUIDLow }, - { "GetCreatureFamily", &LuaCreature::GetCreatureFamily }, - - // Setters -#if defined(TRINITY) || defined(AZEROTHCORE) - { "SetRegeneratingHealth", &LuaCreature::SetRegeneratingHealth }, -#endif - { "SetHover", &LuaCreature::SetHover }, - { "SetDisableGravity", &LuaCreature::SetDisableGravity }, - { "SetAggroEnabled", &LuaCreature::SetAggroEnabled }, - { "SetNoCallAssistance", &LuaCreature::SetNoCallAssistance }, - { "SetNoSearchAssistance", &LuaCreature::SetNoSearchAssistance }, - { "SetDefaultMovementType", &LuaCreature::SetDefaultMovementType }, - { "SetRespawnDelay", &LuaCreature::SetRespawnDelay }, - { "SetWanderRadius", &LuaCreature::SetWanderRadius }, - { "SetInCombatWithZone", &LuaCreature::SetInCombatWithZone }, - { "SetDisableReputationGain", &LuaCreature::SetDisableReputationGain }, -#if defined(TRINITY) || AZEROTHCORE - { "SetLootMode", &LuaCreature::SetLootMode }, -#endif - { "SetNPCFlags", &LuaCreature::SetNPCFlags }, -#if defined(TRINITY) || AZEROTHCORE - { "SetReactState", &LuaCreature::SetReactState }, -#endif - { "SetDeathState", &LuaCreature::SetDeathState }, - { "SetWalk", &LuaCreature::SetWalk }, - { "SetHomePosition", &LuaCreature::SetHomePosition }, - { "SetEquipmentSlots", &LuaCreature::SetEquipmentSlots }, - - // Boolean - { "IsRegeneratingHealth", &LuaCreature::IsRegeneratingHealth }, -#if defined(TRINITY) || defined(AZEROTHCORE) - { "IsDungeonBoss", &LuaCreature::IsDungeonBoss }, -#endif - { "IsWorldBoss", &LuaCreature::IsWorldBoss }, - { "IsRacialLeader", &LuaCreature::IsRacialLeader }, - { "IsCivilian", &LuaCreature::IsCivilian }, -#if defined(TRINITY) || AZEROTHCORE - { "IsTrigger", &LuaCreature::IsTrigger }, -#endif - { "IsGuard", &LuaCreature::IsGuard }, - { "IsElite", &LuaCreature::IsElite }, - { "IsInEvadeMode", &LuaCreature::IsInEvadeMode }, - { "HasCategoryCooldown", &LuaCreature::HasCategoryCooldown }, - { "CanWalk", &LuaCreature::CanWalk }, - { "CanSwim", &LuaCreature::CanSwim }, - { "CanAggro", &LuaCreature::CanAggro }, -#if defined(TRINITY) || AZEROTHCORE - { "CanStartAttack", &LuaCreature::CanStartAttack }, -#endif - { "HasSearchedAssistance", &LuaCreature::HasSearchedAssistance }, - { "IsTappedBy", &LuaCreature::IsTappedBy }, - { "HasLootRecipient", &LuaCreature::HasLootRecipient }, - { "CanAssistTo", &LuaCreature::CanAssistTo }, - { "IsTargetableForAttack", &LuaCreature::IsTargetableForAttack }, - { "CanCompleteQuest", &LuaCreature::CanCompleteQuest }, - { "IsReputationGainDisabled", &LuaCreature::IsReputationGainDisabled }, -#if defined(TRINITY) || AZEROTHCORE - { "IsDamageEnoughForLootingAndReward", &LuaCreature::IsDamageEnoughForLootingAndReward }, - { "HasLootMode", &LuaCreature::HasLootMode }, -#endif - { "HasSpell", &LuaCreature::HasSpell }, - { "HasQuest", &LuaCreature::HasQuest }, - { "HasSpellCooldown", &LuaCreature::HasSpellCooldown }, - { "CanFly", &LuaCreature::CanFly }, - - // Other - { "FleeToGetAssistance", &LuaCreature::FleeToGetAssistance }, - { "CallForHelp", &LuaCreature::CallForHelp }, - { "CallAssistance", &LuaCreature::CallAssistance }, - { "RemoveCorpse", &LuaCreature::RemoveCorpse }, - { "DespawnOrUnsummon", &LuaCreature::DespawnOrUnsummon }, - { "Respawn", &LuaCreature::Respawn }, - { "AttackStart", &LuaCreature::AttackStart }, -#if defined(TRINITY) || AZEROTHCORE - { "AddLootMode", &LuaCreature::AddLootMode }, - { "ResetLootMode", &LuaCreature::ResetLootMode }, - { "RemoveLootMode", &LuaCreature::RemoveLootMode }, -#endif - { "SaveToDB", &LuaCreature::SaveToDB }, - { "SelectVictim", &LuaCreature::SelectVictim }, - { "MoveWaypoint", &LuaCreature::MoveWaypoint }, - { "UpdateEntry", &LuaCreature::UpdateEntry }, - - { NULL, NULL } -}; - -ElunaRegister GameObjectMethods[] = -{ - // Getters - { "GetDisplayId", &LuaGameObject::GetDisplayId }, - { "GetGoState", &LuaGameObject::GetGoState }, - { "GetLootState", &LuaGameObject::GetLootState }, - { "GetLootRecipient", &LuaGameObject::GetLootRecipient }, - { "GetLootRecipientGroup", &LuaGameObject::GetLootRecipientGroup }, - { "GetDBTableGUIDLow", &LuaGameObject::GetDBTableGUIDLow }, - - // Setters - { "SetGoState", &LuaGameObject::SetGoState }, - { "SetLootState", &LuaGameObject::SetLootState }, - { "SetRespawnTime", &LuaGameObject::SetRespawnTime }, - - // Boolean - { "IsTransport", &LuaGameObject::IsTransport }, - // {"IsDestructible", &LuaGameObject::IsDestructible}, // :IsDestructible() - UNDOCUMENTED - { "IsActive", &LuaGameObject::IsActive }, - { "HasQuest", &LuaGameObject::HasQuest }, - { "IsSpawned", &LuaGameObject::IsSpawned }, - - // Other - { "RemoveFromWorld", &LuaGameObject::RemoveFromWorld }, - { "UseDoorOrButton", &LuaGameObject::UseDoorOrButton }, - { "Despawn", &LuaGameObject::Despawn }, - { "Respawn", &LuaGameObject::Respawn }, - { "SaveToDB", &LuaGameObject::SaveToDB }, - - { NULL, NULL } -}; - -ElunaRegister ItemMethods[] = -{ - // Getters - { "GetOwnerGUID", &LuaItem::GetOwnerGUID }, - { "GetOwner", &LuaItem::GetOwner }, - { "GetCount", &LuaItem::GetCount }, - { "GetMaxStackCount", &LuaItem::GetMaxStackCount }, - { "GetSlot", &LuaItem::GetSlot }, - { "GetBagSlot", &LuaItem::GetBagSlot }, - { "GetEnchantmentId", &LuaItem::GetEnchantmentId }, - { "GetSpellId", &LuaItem::GetSpellId }, - { "GetSpellTrigger", &LuaItem::GetSpellTrigger }, - { "GetItemLink", &LuaItem::GetItemLink }, - { "GetClass", &LuaItem::GetClass }, - { "GetSubClass", &LuaItem::GetSubClass }, - { "GetName", &LuaItem::GetName }, - { "GetDisplayId", &LuaItem::GetDisplayId }, - { "GetQuality", &LuaItem::GetQuality }, - { "GetBuyCount", &LuaItem::GetBuyCount }, - { "GetBuyPrice", &LuaItem::GetBuyPrice }, - { "GetSellPrice", &LuaItem::GetSellPrice }, - { "GetInventoryType", &LuaItem::GetInventoryType }, - { "GetAllowableClass", &LuaItem::GetAllowableClass }, - { "GetAllowableRace", &LuaItem::GetAllowableRace }, - { "GetItemLevel", &LuaItem::GetItemLevel }, - { "GetRequiredLevel", &LuaItem::GetRequiredLevel }, -#ifdef WOTLK - { "GetStatsCount", &LuaItem::GetStatsCount }, -#endif - { "GetRandomProperty", &LuaItem::GetRandomProperty }, -#ifndef CLASSIC - { "GetRandomSuffix", &LuaItem::GetRandomSuffix }, -#endif - { "GetItemSet", &LuaItem::GetItemSet }, - { "GetBagSize", &LuaItem::GetBagSize }, - - // Setters - { "SetOwner", &LuaItem::SetOwner }, - { "SetBinding", &LuaItem::SetBinding }, - { "SetCount", &LuaItem::SetCount }, - - // Boolean - { "IsSoulBound", &LuaItem::IsSoulBound }, -#if (!defined(TBC) && !defined(CLASSIC)) - { "IsBoundAccountWide", &LuaItem::IsBoundAccountWide }, -#endif - { "IsBoundByEnchant", &LuaItem::IsBoundByEnchant }, - { "IsNotBoundToPlayer", &LuaItem::IsNotBoundToPlayer }, - { "IsLocked", &LuaItem::IsLocked }, - { "IsBag", &LuaItem::IsBag }, -#ifndef CLASSIC - { "IsCurrencyToken", &LuaItem::IsCurrencyToken }, -#endif - { "IsNotEmptyBag", &LuaItem::IsNotEmptyBag }, - { "IsBroken", &LuaItem::IsBroken }, - { "CanBeTraded", &LuaItem::CanBeTraded }, - { "IsInTrade", &LuaItem::IsInTrade }, - { "IsInBag", &LuaItem::IsInBag }, - { "IsEquipped", &LuaItem::IsEquipped }, - { "HasQuest", &LuaItem::HasQuest }, - { "IsPotion", &LuaItem::IsPotion }, -#if defined(WOTLK) - { "IsWeaponVellum", &LuaItem::IsWeaponVellum }, - { "IsArmorVellum", &LuaItem::IsArmorVellum }, -#endif - { "IsConjuredConsumable", &LuaItem::IsConjuredConsumable }, - //{"IsRefundExpired", &LuaItem::IsRefundExpired}, // :IsRefundExpired() - UNDOCUMENTED - Returns true if the item's refund time has expired - { "SetEnchantment", &LuaItem::SetEnchantment }, - { "ClearEnchantment", &LuaItem::ClearEnchantment }, - - // Other - { "SaveToDB", &LuaItem::SaveToDB }, - - { NULL, NULL } -}; - -ElunaRegister AuraMethods[] = -{ - // Getters - { "GetCaster", &LuaAura::GetCaster }, - { "GetCasterGUID", &LuaAura::GetCasterGUID }, - { "GetCasterLevel", &LuaAura::GetCasterLevel }, - { "GetDuration", &LuaAura::GetDuration }, - { "GetMaxDuration", &LuaAura::GetMaxDuration }, - { "GetAuraId", &LuaAura::GetAuraId }, - { "GetStackAmount", &LuaAura::GetStackAmount }, - { "GetOwner", &LuaAura::GetOwner }, - - // Setters - { "SetDuration", &LuaAura::SetDuration }, - { "SetMaxDuration", &LuaAura::SetMaxDuration }, - { "SetStackAmount", &LuaAura::SetStackAmount }, - - // Other - { "Remove", &LuaAura::Remove }, - - { NULL, NULL } -}; - -ElunaRegister SpellMethods[] = -{ - // Getters - { "GetCaster", &LuaSpell::GetCaster }, - { "GetCastTime", &LuaSpell::GetCastTime }, - { "GetEntry", &LuaSpell::GetEntry }, - { "GetDuration", &LuaSpell::GetDuration }, - { "GetPowerCost", &LuaSpell::GetPowerCost }, - { "GetTargetDest", &LuaSpell::GetTargetDest }, - { "GetTarget", &LuaSpell::GetTarget }, - - // Setters - { "SetAutoRepeat", &LuaSpell::SetAutoRepeat }, - - // Boolean - { "IsAutoRepeat", &LuaSpell::IsAutoRepeat }, - - // Other - { "Cancel", &LuaSpell::Cancel }, - { "Cast", &LuaSpell::Cast }, - { "Finish", &LuaSpell::Finish }, - - { NULL, NULL } -}; - -ElunaRegister QuestMethods[] = -{ - // Getters - { "GetId", &LuaQuest::GetId }, - { "GetLevel", &LuaQuest::GetLevel }, - // {"GetMaxLevel", &LuaQuest::GetMaxLevel}, // :GetMaxLevel() - UNDOCUMENTED - Returns the quest's max level - { "GetMinLevel", &LuaQuest::GetMinLevel }, - { "GetNextQuestId", &LuaQuest::GetNextQuestId }, - { "GetPrevQuestId", &LuaQuest::GetPrevQuestId }, - { "GetNextQuestInChain", &LuaQuest::GetNextQuestInChain }, - { "GetFlags", &LuaQuest::GetFlags }, - { "GetType", &LuaQuest::GetType }, - - // Boolean - { "HasFlag", &LuaQuest::HasFlag }, -#ifndef CLASSIC - { "IsDaily", &LuaQuest::IsDaily }, -#endif - { "IsRepeatable", &LuaQuest::IsRepeatable }, - - { NULL, NULL } -}; - -ElunaRegister GroupMethods[] = -{ - // Getters - { "GetMembers", &LuaGroup::GetMembers }, - { "GetLeaderGUID", &LuaGroup::GetLeaderGUID }, - { "GetGUID", &LuaGroup::GetGUID }, - { "GetMemberGroup", &LuaGroup::GetMemberGroup }, - { "GetMemberGUID", &LuaGroup::GetMemberGUID }, - { "GetMembersCount", &LuaGroup::GetMembersCount }, - - // Setters - { "SetLeader", &LuaGroup::SetLeader }, - { "SetMembersGroup", &LuaGroup::SetMembersGroup }, - { "SetTargetIcon", &LuaGroup::SetTargetIcon }, - - // Boolean - { "IsLeader", &LuaGroup::IsLeader }, - { "AddMember", &LuaGroup::AddMember }, - { "RemoveMember", &LuaGroup::RemoveMember }, - { "Disband", &LuaGroup::Disband }, - { "IsFull", &LuaGroup::IsFull }, -#if !(defined(CLASSIC) || defined(TBC)) - { "IsLFGGroup", &LuaGroup::IsLFGGroup }, -#endif - { "IsRaidGroup", &LuaGroup::IsRaidGroup }, - { "IsBGGroup", &LuaGroup::IsBGGroup }, - // {"IsBFGroup", &LuaGroup::IsBFGroup}, // :IsBFGroup() - UNDOCUMENTED - Returns true if the group is a battlefield group - { "IsMember", &LuaGroup::IsMember }, - { "IsAssistant", &LuaGroup::IsAssistant }, - { "SameSubGroup", &LuaGroup::SameSubGroup }, - { "HasFreeSlotSubGroup", &LuaGroup::HasFreeSlotSubGroup }, - - // Other - { "SendPacket", &LuaGroup::SendPacket }, - // {"ConvertToLFG", &LuaGroup::ConvertToLFG}, // :ConvertToLFG() - UNDOCUMENTED - Converts the group to an LFG group - { "ConvertToRaid", &LuaGroup::ConvertToRaid }, - - { NULL, NULL } -}; - -ElunaRegister GuildMethods[] = -{ - // Getters - { "GetMembers", &LuaGuild::GetMembers }, - { "GetLeader", &LuaGuild::GetLeader }, - { "GetLeaderGUID", &LuaGuild::GetLeaderGUID }, - { "GetId", &LuaGuild::GetId }, - { "GetName", &LuaGuild::GetName }, - { "GetMOTD", &LuaGuild::GetMOTD }, - { "GetInfo", &LuaGuild::GetInfo }, - { "GetMemberCount", &LuaGuild::GetMemberCount }, - - // Setters -#ifndef CLASSIC - { "SetBankTabText", &LuaGuild::SetBankTabText }, -#endif - { "SetMemberRank", &LuaGuild::SetMemberRank }, -#if defined(CLASSIC) || defined(TBC) || defined(WOTLK) - { "SetLeader", &LuaGuild::SetLeader }, -#endif - - // Other - { "SendPacket", &LuaGuild::SendPacket }, - { "SendPacketToRanked", &LuaGuild::SendPacketToRanked }, - { "Disband", &LuaGuild::Disband }, - { "AddMember", &LuaGuild::AddMember }, - { "DeleteMember", &LuaGuild::DeleteMember }, - - { NULL, NULL } -}; - -#ifndef CLASSIC -#ifndef TBC -ElunaRegister VehicleMethods[] = -{ - // Getters - { "GetOwner", &LuaVehicle::GetOwner }, - { "GetEntry", &LuaVehicle::GetEntry }, - { "GetPassenger", &LuaVehicle::GetPassenger }, - - // Boolean - { "IsOnBoard", &LuaVehicle::IsOnBoard }, - - // Other - { "AddPassenger", &LuaVehicle::AddPassenger }, - { "RemovePassenger", &LuaVehicle::RemovePassenger }, - - { NULL, NULL } -}; -#endif -#endif - -ElunaRegister QueryMethods[] = -{ - // Getters - { "GetColumnCount", &LuaQuery::GetColumnCount }, - { "GetRowCount", &LuaQuery::GetRowCount }, - { "GetRow", &LuaQuery::GetRow }, - { "GetBool", &LuaQuery::GetBool }, - { "GetUInt8", &LuaQuery::GetUInt8 }, - { "GetUInt16", &LuaQuery::GetUInt16 }, - { "GetUInt32", &LuaQuery::GetUInt32 }, - { "GetUInt64", &LuaQuery::GetUInt64 }, - { "GetInt8", &LuaQuery::GetInt8 }, - { "GetInt16", &LuaQuery::GetInt16 }, - { "GetInt32", &LuaQuery::GetInt32 }, - { "GetInt64", &LuaQuery::GetInt64 }, - { "GetFloat", &LuaQuery::GetFloat }, - { "GetDouble", &LuaQuery::GetDouble }, - { "GetString", &LuaQuery::GetString }, - - // Boolean - { "NextRow", &LuaQuery::NextRow }, - { "IsNull", &LuaQuery::IsNull }, - - { NULL, NULL } -}; - -ElunaRegister PacketMethods[] = -{ - // Getters - { "GetOpcode", &LuaPacket::GetOpcode }, - { "GetSize", &LuaPacket::GetSize }, - - // Setters - { "SetOpcode", &LuaPacket::SetOpcode }, - - // Readers - { "ReadByte", &LuaPacket::ReadByte }, - { "ReadUByte", &LuaPacket::ReadUByte }, - { "ReadShort", &LuaPacket::ReadShort }, - { "ReadUShort", &LuaPacket::ReadUShort }, - { "ReadLong", &LuaPacket::ReadLong }, - { "ReadULong", &LuaPacket::ReadULong }, - { "ReadGUID", &LuaPacket::ReadGUID }, - { "ReadString", &LuaPacket::ReadString }, - { "ReadFloat", &LuaPacket::ReadFloat }, - { "ReadDouble", &LuaPacket::ReadDouble }, - - // Writers - { "WriteByte", &LuaPacket::WriteByte }, - { "WriteUByte", &LuaPacket::WriteUByte }, - { "WriteShort", &LuaPacket::WriteShort }, - { "WriteUShort", &LuaPacket::WriteUShort }, - { "WriteLong", &LuaPacket::WriteLong }, - { "WriteULong", &LuaPacket::WriteULong }, - { "WriteGUID", &LuaPacket::WriteGUID }, - { "WriteString", &LuaPacket::WriteString }, - { "WriteFloat", &LuaPacket::WriteFloat }, - { "WriteDouble", &LuaPacket::WriteDouble }, - - { NULL, NULL } -}; - -ElunaRegister MapMethods[] = -{ - // Getters - { "GetName", &LuaMap::GetName }, - { "GetDifficulty", &LuaMap::GetDifficulty }, - { "GetInstanceId", &LuaMap::GetInstanceId }, - { "GetInstanceData", &LuaMap::GetInstanceData }, - { "GetPlayerCount", &LuaMap::GetPlayerCount }, - { "GetPlayers", &LuaMap::GetPlayers }, - { "GetMapId", &LuaMap::GetMapId }, - { "GetAreaId", &LuaMap::GetAreaId }, - { "GetHeight", &LuaMap::GetHeight }, - { "GetWorldObject", &LuaMap::GetWorldObject }, - - // Setters - { "SetWeather", &LuaMap::SetWeather }, - - // Boolean -#ifndef CLASSIC - { "IsArena", &LuaMap::IsArena }, -#endif - { "IsBattleground", &LuaMap::IsBattleground }, - { "IsDungeon", &LuaMap::IsDungeon }, - { "IsEmpty", &LuaMap::IsEmpty }, -#ifndef CLASSIC - { "IsHeroic", &LuaMap::IsHeroic }, -#endif - { "IsRaid", &LuaMap::IsRaid }, - - // Other - { "SaveInstanceData", &LuaMap::SaveInstanceData }, - - { NULL, NULL } -}; - -ElunaRegister CorpseMethods[] = -{ - // Getters - { "GetOwnerGUID", &LuaCorpse::GetOwnerGUID }, - { "GetGhostTime", &LuaCorpse::GetGhostTime }, - { "GetType", &LuaCorpse::GetType }, - - // Other - { "ResetGhostTime", &LuaCorpse::ResetGhostTime }, - { "SaveToDB", &LuaCorpse::SaveToDB }, - - { NULL, NULL } -}; - -ElunaRegister AuctionMethods[] = -{ - { NULL, NULL } -}; - -ElunaRegister BattleGroundMethods[] = -{ - // Getters - { "GetName", &LuaBattleGround::GetName }, - { "GetAlivePlayersCountByTeam", &LuaBattleGround::GetAlivePlayersCountByTeam }, - { "GetMap", &LuaBattleGround::GetMap }, - { "GetBonusHonorFromKillCount", &LuaBattleGround::GetBonusHonorFromKillCount }, -#ifndef AZEROTHCORE - { "GetBracketId", &LuaBattleGround::GetBracketId }, -#endif - { "GetEndTime", &LuaBattleGround::GetEndTime }, - { "GetFreeSlotsForTeam", &LuaBattleGround::GetFreeSlotsForTeam }, - { "GetInstanceId", &LuaBattleGround::GetInstanceId }, - { "GetMapId", &LuaBattleGround::GetMapId }, - { "GetTypeId", &LuaBattleGround::GetTypeId }, - { "GetMaxLevel", &LuaBattleGround::GetMaxLevel }, - { "GetMinLevel", &LuaBattleGround::GetMinLevel }, - { "GetMaxPlayers", &LuaBattleGround::GetMaxPlayers }, - { "GetMinPlayers", &LuaBattleGround::GetMinPlayers }, - { "GetMaxPlayersPerTeam", &LuaBattleGround::GetMaxPlayersPerTeam }, - { "GetMinPlayersPerTeam", &LuaBattleGround::GetMinPlayersPerTeam }, - { "GetWinner", &LuaBattleGround::GetWinner }, - { "GetStatus", &LuaBattleGround::GetStatus }, - - { NULL, NULL } -}; - #if (!defined(TBC) && !defined(CLASSIC)) // fix compile error about accessing vehicle destructor template<> int ElunaTemplate::CollectGarbage(lua_State* L) @@ -1359,82 +99,79 @@ template<> int ElunaTemplate::ToString(lua_State* L) void RegisterFunctions(Eluna* E) { - ElunaGlobal::SetMethods(E, GlobalMethods); + ElunaGlobal::SetMethods(E, LuaGlobalFunctions::GlobalMethods); ElunaTemplate::Register(E, "Object"); - ElunaTemplate::SetMethods(E, ObjectMethods); + ElunaTemplate::SetMethods(E, LuaObject::ObjectMethods); ElunaTemplate::Register(E, "WorldObject"); - ElunaTemplate::SetMethods(E, ObjectMethods); - ElunaTemplate::SetMethods(E, WorldObjectMethods); + ElunaTemplate::SetMethods(E, LuaObject::ObjectMethods); + ElunaTemplate::SetMethods(E, LuaWorldObject::WorldObjectMethods); ElunaTemplate::Register(E, "Unit"); - ElunaTemplate::SetMethods(E, ObjectMethods); - ElunaTemplate::SetMethods(E, WorldObjectMethods); - ElunaTemplate::SetMethods(E, UnitMethods); + ElunaTemplate::SetMethods(E, LuaObject::ObjectMethods); + ElunaTemplate::SetMethods(E, LuaWorldObject::WorldObjectMethods); + ElunaTemplate::SetMethods(E, LuaUnit::UnitMethods); ElunaTemplate::Register(E, "Player"); - ElunaTemplate::SetMethods(E, ObjectMethods); - ElunaTemplate::SetMethods(E, WorldObjectMethods); - ElunaTemplate::SetMethods(E, UnitMethods); - ElunaTemplate::SetMethods(E, PlayerMethods); + ElunaTemplate::SetMethods(E, LuaObject::ObjectMethods); + ElunaTemplate::SetMethods(E, LuaWorldObject::WorldObjectMethods); + ElunaTemplate::SetMethods(E, LuaUnit::UnitMethods); + ElunaTemplate::SetMethods(E, LuaPlayer::PlayerMethods); ElunaTemplate::Register(E, "Creature"); - ElunaTemplate::SetMethods(E, ObjectMethods); - ElunaTemplate::SetMethods(E, WorldObjectMethods); - ElunaTemplate::SetMethods(E, UnitMethods); - ElunaTemplate::SetMethods(E, CreatureMethods); + ElunaTemplate::SetMethods(E, LuaObject::ObjectMethods); + ElunaTemplate::SetMethods(E, LuaWorldObject::WorldObjectMethods); + ElunaTemplate::SetMethods(E, LuaUnit::UnitMethods); + ElunaTemplate::SetMethods(E, LuaCreature::CreatureMethods); ElunaTemplate::Register(E, "GameObject"); - ElunaTemplate::SetMethods(E, ObjectMethods); - ElunaTemplate::SetMethods(E, WorldObjectMethods); - ElunaTemplate::SetMethods(E, GameObjectMethods); + ElunaTemplate::SetMethods(E, LuaObject::ObjectMethods); + ElunaTemplate::SetMethods(E, LuaWorldObject::WorldObjectMethods); + ElunaTemplate::SetMethods(E, LuaGameObject::GameObjectMethods); ElunaTemplate::Register(E, "Corpse"); - ElunaTemplate::SetMethods(E, ObjectMethods); - ElunaTemplate::SetMethods(E, WorldObjectMethods); - ElunaTemplate::SetMethods(E, CorpseMethods); + ElunaTemplate::SetMethods(E, LuaObject::ObjectMethods); + ElunaTemplate::SetMethods(E, LuaWorldObject::WorldObjectMethods); + ElunaTemplate::SetMethods(E, LuaCorpse::CorpseMethods); ElunaTemplate::Register(E, "Item"); - ElunaTemplate::SetMethods(E, ObjectMethods); - ElunaTemplate::SetMethods(E, ItemMethods); + ElunaTemplate::SetMethods(E, LuaObject::ObjectMethods); + ElunaTemplate::SetMethods(E, LuaItem::ItemMethods); #ifndef CLASSIC #ifndef TBC ElunaTemplate::Register(E, "Vehicle"); - ElunaTemplate::SetMethods(E, VehicleMethods); + ElunaTemplate::SetMethods(E, LuaVehicle::VehicleMethods); #endif #endif ElunaTemplate::Register(E, "Group"); - ElunaTemplate::SetMethods(E, GroupMethods); + ElunaTemplate::SetMethods(E, LuaGroup::GroupMethods); ElunaTemplate::Register(E, "Guild"); - ElunaTemplate::SetMethods(E, GuildMethods); + ElunaTemplate::SetMethods(E, LuaGuild::GuildMethods); ElunaTemplate::Register(E, "Aura"); - ElunaTemplate::SetMethods(E, AuraMethods); + ElunaTemplate::SetMethods(E, LuaAura::AuraMethods); ElunaTemplate::Register(E, "Spell"); - ElunaTemplate::SetMethods(E, SpellMethods); + ElunaTemplate::SetMethods(E, LuaSpell::SpellMethods); ElunaTemplate::Register(E, "Quest"); - ElunaTemplate::SetMethods(E, QuestMethods); + ElunaTemplate::SetMethods(E, LuaQuest::QuestMethods); ElunaTemplate::Register(E, "Map"); - ElunaTemplate::SetMethods(E, MapMethods); - - ElunaTemplate::Register(E, "AuctionHouseEntry"); - ElunaTemplate::SetMethods(E, AuctionMethods); + ElunaTemplate::SetMethods(E, LuaMap::MapMethods); ElunaTemplate::Register(E, "BattleGround"); - ElunaTemplate::SetMethods(E, BattleGroundMethods); + ElunaTemplate::SetMethods(E, LuaBattleGround::BattleGroundMethods); ElunaTemplate::Register(E, "WorldPacket", true); - ElunaTemplate::SetMethods(E, PacketMethods); + ElunaTemplate::SetMethods(E, LuaPacket::PacketMethods); ElunaTemplate::Register(E, "ElunaQuery", true); - ElunaTemplate::SetMethods(E, QueryMethods); + ElunaTemplate::SetMethods(E, LuaQuery::QueryMethods); ElunaTemplate::Register(E, "long long", true); diff --git a/src/modules/Eluna/AuraMethods.h b/src/modules/Eluna/Mangos/AuraMethods.h similarity index 88% rename from src/modules/Eluna/AuraMethods.h rename to src/modules/Eluna/Mangos/AuraMethods.h index c25637c5b1..0d03d53654 100644 --- a/src/modules/Eluna/AuraMethods.h +++ b/src/modules/Eluna/Mangos/AuraMethods.h @@ -213,5 +213,28 @@ namespace LuaAura Eluna::CHECKOBJ(L, 1)->Invalidate(); return 0; } + + ElunaRegister AuraMethods[] = + { + // Getters + { "GetCaster", &LuaAura::GetCaster }, + { "GetCasterGUID", &LuaAura::GetCasterGUID }, + { "GetCasterLevel", &LuaAura::GetCasterLevel }, + { "GetDuration", &LuaAura::GetDuration }, + { "GetMaxDuration", &LuaAura::GetMaxDuration }, + { "GetAuraId", &LuaAura::GetAuraId }, + { "GetStackAmount", &LuaAura::GetStackAmount }, + { "GetOwner", &LuaAura::GetOwner }, + + // Setters + { "SetDuration", &LuaAura::SetDuration }, + { "SetMaxDuration", &LuaAura::SetMaxDuration }, + { "SetStackAmount", &LuaAura::SetStackAmount }, + + // Other + { "Remove", &LuaAura::Remove }, + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/Mangos/BattleGroundMethods.h b/src/modules/Eluna/Mangos/BattleGroundMethods.h new file mode 100644 index 0000000000..82176e4a6e --- /dev/null +++ b/src/modules/Eluna/Mangos/BattleGroundMethods.h @@ -0,0 +1,281 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef BATTLEGROUNDMETHODS_H +#define BATTLEGROUNDMETHODS_H + +/*** + * Contains the state of a battleground, e.g. Warsong Gulch, Arathi Basin, etc. + * + * Inherits all methods from: none + */ +namespace LuaBattleGround +{ + /** + * Returns the name of the [BattleGround]. + * + * @return string name + */ + int GetName(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetName()); + return 1; + } + + /** + * Returns the amount of alive players in the [BattleGround] by the team ID. + * + * @param [Team] team : team ID + * @return uint32 count + */ + int GetAlivePlayersCountByTeam(lua_State* L, BattleGround* bg) + { + uint32 team = Eluna::CHECKVAL(L, 2); + +#ifndef AZEROTHCORE + Eluna::Push(L, bg->GetAlivePlayersCountByTeam((Team)team)); +#else + Eluna::Push(L, bg->GetAlivePlayersCountByTeam((TeamId)team)); +#endif + return 1; + } + + /** + * Returns the [Map] of the [BattleGround]. + * + * @return [Map] map + */ + int GetMap(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, static_cast(bg->GetBgMap())); + return 1; + } + + /** + * Returns the bonus honor given by amount of kills in the specific [BattleGround]. + * + * @param uint32 kills : amount of kills + * @return uint32 bonusHonor + */ + int GetBonusHonorFromKillCount(lua_State* L, BattleGround* bg) + { + uint32 kills = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, bg->GetBonusHonorFromKill(kills)); + return 1; + } + +#ifndef AZEROTHCORE + /** + * Returns the bracket ID of the specific [BattleGround]. + * + * @return [BattleGroundBracketId] bracketId + */ + int GetBracketId(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetBracketId()); + return 1; + } +#endif + + /** + * Returns the end time of the [BattleGround]. + * + * @return uint32 endTime + */ + int GetEndTime(lua_State* L, BattleGround* bg) + { +#ifdef CATA + Eluna::Push(L, bg->GetRemainingTime()); +#else + Eluna::Push(L, bg->GetEndTime()); +#endif + return 1; + } + + /** + * Returns the amount of free slots for the selected team in the specific [BattleGround]. + * + * @param [Team] team : team ID + * @return uint32 freeSlots + */ + int GetFreeSlotsForTeam(lua_State* L, BattleGround* bg) + { + uint32 team = Eluna::CHECKVAL(L, 2); + +#ifndef AZEROTHCORE + Eluna::Push(L, bg->GetFreeSlotsForTeam((Team)team)); +#else + Eluna::Push(L, bg->GetFreeSlotsForTeam((TeamId)team)); +#endif + return 1; + } + + /** + * Returns the instance ID of the [BattleGround]. + * + * @return uint32 instanceId + */ + int GetInstanceId(lua_State* L, BattleGround* bg) + { +#ifdef CMANGOS + Eluna::Push(L, bg->GetInstanceId()); +#else + Eluna::Push(L, bg->GetInstanceID()); +#endif + return 1; + } + + /** + * Returns the map ID of the [BattleGround]. + * + * @return uint32 mapId + */ + int GetMapId(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMapId()); + return 1; + } + + /** + * Returns the type ID of the [BattleGround]. + * + * @return [BattleGroundTypeId] typeId + */ + int GetTypeId(lua_State* L, BattleGround* bg) + { +#ifdef CMANGOS + Eluna::Push(L, bg->GetTypeId()); +#elif !AZEROTHCORE + Eluna::Push(L, bg->GetTypeID()); +#else + Eluna::Push(L, bg->GetBgTypeID()); +#endif + return 1; + } + + /** + * Returns the max allowed [Player] level of the specific [BattleGround]. + * + * @return uint32 maxLevel + */ + int GetMaxLevel(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMaxLevel()); + return 1; + } + + /** + * Returns the minimum allowed [Player] level of the specific [BattleGround]. + * + * @return uint32 minLevel + */ + int GetMinLevel(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMinLevel()); + return 1; + } + + /** + * Returns the maximum allowed [Player] count of the specific [BattleGround]. + * + * @return uint32 maxPlayerCount + */ + int GetMaxPlayers(lua_State* L, BattleGround* bg) + { +#ifndef AZEROTHCORE + Eluna::Push(L, bg->GetMaxPlayers()); +#else + Eluna::Push(L, bg->GetMaxPlayersPerTeam() * 2); +#endif + return 1; + } + + /** + * Returns the minimum allowed [Player] count of the specific [BattleGround]. + * + * @return uint32 minPlayerCount + */ + int GetMinPlayers(lua_State* L, BattleGround* bg) + { +#ifndef AZEROTHCORE + Eluna::Push(L, bg->GetMinPlayers()); +#else + Eluna::Push(L, bg->GetMaxPlayersPerTeam() * 2); +#endif + return 1; + } + + /** + * Returns the maximum allowed [Player] count per team of the specific [BattleGround]. + * + * @return uint32 maxTeamPlayerCount + */ + int GetMaxPlayersPerTeam(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMaxPlayersPerTeam()); + return 1; + } + + /** + * Returns the minimum allowed [Player] count per team of the specific [BattleGround]. + * + * @return uint32 minTeamPlayerCount + */ + int GetMinPlayersPerTeam(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMinPlayersPerTeam()); + return 1; + } + + /** + * Returns the winning team of the specific [BattleGround]. + * + * @return [Team] team + */ + int GetWinner(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetWinner()); + return 1; + } + + /** + * Returns the status of the specific [BattleGround]. + * + * @return [BattleGroundStatus] status + */ + int GetStatus(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetStatus()); + return 1; + } + + ElunaRegister BattleGroundMethods[] = + { + // Getters + { "GetName", &LuaBattleGround::GetName }, + { "GetAlivePlayersCountByTeam", &LuaBattleGround::GetAlivePlayersCountByTeam }, + { "GetMap", &LuaBattleGround::GetMap }, + { "GetBonusHonorFromKillCount", &LuaBattleGround::GetBonusHonorFromKillCount }, + { "GetBracketId", &LuaBattleGround::GetBracketId }, + { "GetEndTime", &LuaBattleGround::GetEndTime }, + { "GetFreeSlotsForTeam", &LuaBattleGround::GetFreeSlotsForTeam }, + { "GetInstanceId", &LuaBattleGround::GetInstanceId }, + { "GetMapId", &LuaBattleGround::GetMapId }, + { "GetTypeId", &LuaBattleGround::GetTypeId }, + { "GetMaxLevel", &LuaBattleGround::GetMaxLevel }, + { "GetMinLevel", &LuaBattleGround::GetMinLevel }, + { "GetMaxPlayers", &LuaBattleGround::GetMaxPlayers }, + { "GetMinPlayers", &LuaBattleGround::GetMinPlayers }, + { "GetMaxPlayersPerTeam", &LuaBattleGround::GetMaxPlayersPerTeam }, + { "GetMinPlayersPerTeam", &LuaBattleGround::GetMinPlayersPerTeam }, + { "GetWinner", &LuaBattleGround::GetWinner }, + { "GetStatus", &LuaBattleGround::GetStatus }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/CorpseMethods.h b/src/modules/Eluna/Mangos/CorpseMethods.h similarity index 82% rename from src/modules/Eluna/CorpseMethods.h rename to src/modules/Eluna/Mangos/CorpseMethods.h index aba7d20774..13188331fe 100644 --- a/src/modules/Eluna/CorpseMethods.h +++ b/src/modules/Eluna/Mangos/CorpseMethods.h @@ -77,5 +77,19 @@ namespace LuaCorpse corpse->SaveToDB(); return 0; } + + ElunaRegister CorpseMethods[] = + { + // Getters + { "GetOwnerGUID", &LuaCorpse::GetOwnerGUID }, + { "GetGhostTime", &LuaCorpse::GetGhostTime }, + { "GetType", &LuaCorpse::GetType }, + + // Other + { "ResetGhostTime", &LuaCorpse::ResetGhostTime }, + { "SaveToDB", &LuaCorpse::SaveToDB }, + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/CreatureMethods.h b/src/modules/Eluna/Mangos/CreatureMethods.h similarity index 89% rename from src/modules/Eluna/CreatureMethods.h rename to src/modules/Eluna/Mangos/CreatureMethods.h index a29c3374ea..0bdd62927e 100644 --- a/src/modules/Eluna/CreatureMethods.h +++ b/src/modules/Eluna/Mangos/CreatureMethods.h @@ -902,7 +902,7 @@ namespace LuaCreature /** * Returns the number of [Unit]s in this [Creature]'s threat list. * - * @return int targetsCount + * @return double targetsCount */ int GetAITargetsCount(lua_State* L, Creature* creature) { @@ -913,7 +913,7 @@ namespace LuaCreature #elif defined(CMANGOS) Eluna::Push(L, creature->getThreatManager().getThreatList().size()); #else - Eluna::Push(L, creature->GetThreatManager().getThreatList().size()); + Eluna::Push(L, (double)creature->GetThreatManager().getThreatList().size()); #endif return 1; } @@ -1499,5 +1499,105 @@ namespace LuaCreature #endif return 1; } + + ElunaRegister CreatureMethods[] = + { + // Getters + { "GetAITarget", &LuaCreature::GetAITarget }, + { "GetAITargets", &LuaCreature::GetAITargets }, + { "GetAITargetsCount", &LuaCreature::GetAITargetsCount }, + { "GetHomePosition", &LuaCreature::GetHomePosition }, + { "GetCorpseDelay", &LuaCreature::GetCorpseDelay }, + { "GetCreatureSpellCooldownDelay", &LuaCreature::GetCreatureSpellCooldownDelay }, + { "GetScriptId", &LuaCreature::GetScriptId }, + { "GetAIName", &LuaCreature::GetAIName }, + { "GetScriptName", &LuaCreature::GetScriptName }, + { "GetAttackDistance", &LuaCreature::GetAttackDistance }, + { "GetAggroRange", &LuaCreature::GetAggroRange }, + { "GetDefaultMovementType", &LuaCreature::GetDefaultMovementType }, + { "GetRespawnDelay", &LuaCreature::GetRespawnDelay }, + { "GetWanderRadius", &LuaCreature::GetWanderRadius }, + { "GetCurrentWaypointId", &LuaCreature::GetCurrentWaypointId }, + { "GetLootRecipient", &LuaCreature::GetLootRecipient }, + { "GetLootRecipientGroup", &LuaCreature::GetLootRecipientGroup }, + { "GetNPCFlags", &LuaCreature::GetNPCFlags }, + { "GetExtraFlags", &LuaCreature::GetExtraFlags }, +#if !defined(CATA) + { "GetShieldBlockValue", &LuaCreature::GetShieldBlockValue }, +#endif + { "GetDBTableGUIDLow", &LuaCreature::GetDBTableGUIDLow }, + { "GetCreatureFamily", &LuaCreature::GetCreatureFamily }, + + // Setters + { "SetHover", &LuaCreature::SetHover }, + { "SetDisableGravity", &LuaCreature::SetDisableGravity }, + { "SetAggroEnabled", &LuaCreature::SetAggroEnabled }, + { "SetNoCallAssistance", &LuaCreature::SetNoCallAssistance }, + { "SetNoSearchAssistance", &LuaCreature::SetNoSearchAssistance }, + { "SetDefaultMovementType", &LuaCreature::SetDefaultMovementType }, + { "SetRespawnDelay", &LuaCreature::SetRespawnDelay }, + { "SetWanderRadius", &LuaCreature::SetWanderRadius }, + { "SetInCombatWithZone", &LuaCreature::SetInCombatWithZone }, + { "SetDisableReputationGain", &LuaCreature::SetDisableReputationGain }, + { "SetNPCFlags", &LuaCreature::SetNPCFlags }, + { "SetDeathState", &LuaCreature::SetDeathState }, + { "SetWalk", &LuaCreature::SetWalk }, + { "SetHomePosition", &LuaCreature::SetHomePosition }, + { "SetEquipmentSlots", &LuaCreature::SetEquipmentSlots }, + + // Boolean + { "IsRegeneratingHealth", &LuaCreature::IsRegeneratingHealth }, + { "IsWorldBoss", &LuaCreature::IsWorldBoss }, + { "IsRacialLeader", &LuaCreature::IsRacialLeader }, + { "IsCivilian", &LuaCreature::IsCivilian }, + { "IsGuard", &LuaCreature::IsGuard }, + { "IsElite", &LuaCreature::IsElite }, + { "IsInEvadeMode", &LuaCreature::IsInEvadeMode }, + { "HasCategoryCooldown", &LuaCreature::HasCategoryCooldown }, + { "CanWalk", &LuaCreature::CanWalk }, + { "CanSwim", &LuaCreature::CanSwim }, + { "CanAggro", &LuaCreature::CanAggro }, + { "HasSearchedAssistance", &LuaCreature::HasSearchedAssistance }, + { "IsTappedBy", &LuaCreature::IsTappedBy }, + { "HasLootRecipient", &LuaCreature::HasLootRecipient }, + { "CanAssistTo", &LuaCreature::CanAssistTo }, + { "IsTargetableForAttack", &LuaCreature::IsTargetableForAttack }, + { "CanCompleteQuest", &LuaCreature::CanCompleteQuest }, + { "IsReputationGainDisabled", &LuaCreature::IsReputationGainDisabled }, + { "HasSpell", &LuaCreature::HasSpell }, + { "HasQuest", &LuaCreature::HasQuest }, + { "HasSpellCooldown", &LuaCreature::HasSpellCooldown }, + { "CanFly", &LuaCreature::CanFly }, + + // Other + { "FleeToGetAssistance", &LuaCreature::FleeToGetAssistance }, + { "CallForHelp", &LuaCreature::CallForHelp }, + { "CallAssistance", &LuaCreature::CallAssistance }, + { "RemoveCorpse", &LuaCreature::RemoveCorpse }, + { "DespawnOrUnsummon", &LuaCreature::DespawnOrUnsummon }, + { "Respawn", &LuaCreature::Respawn }, + { "AttackStart", &LuaCreature::AttackStart }, + { "SaveToDB", &LuaCreature::SaveToDB }, + { "SelectVictim", &LuaCreature::SelectVictim }, + { "MoveWaypoint", &LuaCreature::MoveWaypoint }, + { "UpdateEntry", &LuaCreature::UpdateEntry }, + + // Not implemented methods + { "GetWaypointPath", nullptr }, // not implemented + { "GetLootMode", nullptr }, // not implemented + { "SetRegeneratingHealth", nullptr }, // not implemented + { "SetLootMode", nullptr }, // not implemented + { "SetReactState", nullptr }, // not implemented + { "IsDungeonBoss", nullptr }, // not implemented + { "IsTrigger", nullptr }, // not implemented + { "CanStartAttack", nullptr }, // not implemented + { "IsDamageEnoughForLootingAndReward", nullptr }, // not implemented + { "HasLootMode", nullptr }, // not implemented + { "AddLootMode", nullptr }, // not implemented + { "ResetLootMode", nullptr }, // not implemented + { "RemoveLootMode", nullptr }, // not implemented + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/ElunaQueryMethods.h b/src/modules/Eluna/Mangos/ElunaQueryMethods.h similarity index 92% rename from src/modules/Eluna/ElunaQueryMethods.h rename to src/modules/Eluna/Mangos/ElunaQueryMethods.h index 47c05d48f0..ced7898947 100644 --- a/src/modules/Eluna/ElunaQueryMethods.h +++ b/src/modules/Eluna/Mangos/ElunaQueryMethods.h @@ -367,6 +367,32 @@ namespace LuaQuery lua_settop(L, tbl); return 1; } + + ElunaRegister QueryMethods[] = + { + // Getters + { "GetColumnCount", &LuaQuery::GetColumnCount }, + { "GetRowCount", &LuaQuery::GetRowCount }, + { "GetRow", &LuaQuery::GetRow }, + { "GetBool", &LuaQuery::GetBool }, + { "GetUInt8", &LuaQuery::GetUInt8 }, + { "GetUInt16", &LuaQuery::GetUInt16 }, + { "GetUInt32", &LuaQuery::GetUInt32 }, + { "GetUInt64", &LuaQuery::GetUInt64 }, + { "GetInt8", &LuaQuery::GetInt8 }, + { "GetInt16", &LuaQuery::GetInt16 }, + { "GetInt32", &LuaQuery::GetInt32 }, + { "GetInt64", &LuaQuery::GetInt64 }, + { "GetFloat", &LuaQuery::GetFloat }, + { "GetDouble", &LuaQuery::GetDouble }, + { "GetString", &LuaQuery::GetString }, + + // Boolean + { "NextRow", &LuaQuery::NextRow }, + { "IsNull", &LuaQuery::IsNull }, + + { NULL, NULL } + }; }; #undef RESULT diff --git a/src/modules/Eluna/GameObjectMethods.h b/src/modules/Eluna/Mangos/GameObjectMethods.h similarity index 87% rename from src/modules/Eluna/GameObjectMethods.h rename to src/modules/Eluna/Mangos/GameObjectMethods.h index b9e02286f7..f82487d098 100644 --- a/src/modules/Eluna/GameObjectMethods.h +++ b/src/modules/Eluna/Mangos/GameObjectMethods.h @@ -342,5 +342,39 @@ namespace LuaGameObject go->SetRespawnTime(respawn); return 0; } + + ElunaRegister GameObjectMethods[] = + { + // Getters + { "GetDisplayId", &LuaGameObject::GetDisplayId }, + { "GetGoState", &LuaGameObject::GetGoState }, + { "GetLootState", &LuaGameObject::GetLootState }, + { "GetLootRecipient", &LuaGameObject::GetLootRecipient }, + { "GetLootRecipientGroup", &LuaGameObject::GetLootRecipientGroup }, + { "GetDBTableGUIDLow", &LuaGameObject::GetDBTableGUIDLow }, + + // Setters + { "SetGoState", &LuaGameObject::SetGoState }, + { "SetLootState", &LuaGameObject::SetLootState }, + { "SetRespawnTime", &LuaGameObject::SetRespawnTime }, + + // Boolean + { "IsTransport", &LuaGameObject::IsTransport }, + { "IsActive", &LuaGameObject::IsActive }, + { "HasQuest", &LuaGameObject::HasQuest }, + { "IsSpawned", &LuaGameObject::IsSpawned }, + + // Other + { "RemoveFromWorld", &LuaGameObject::RemoveFromWorld }, + { "UseDoorOrButton", &LuaGameObject::UseDoorOrButton }, + { "Despawn", &LuaGameObject::Despawn }, + { "Respawn", &LuaGameObject::Respawn }, + { "SaveToDB", &LuaGameObject::SaveToDB }, + + // Not implemented methods + { "IsDestructible", nullptr }, // Not implemented + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/GlobalMethods.h b/src/modules/Eluna/Mangos/GlobalMethods.h similarity index 94% rename from src/modules/Eluna/GlobalMethods.h rename to src/modules/Eluna/Mangos/GlobalMethods.h index f7abb852e4..647fd997a4 100644 --- a/src/modules/Eluna/GlobalMethods.h +++ b/src/modules/Eluna/Mangos/GlobalMethods.h @@ -8,13 +8,10 @@ #define GLOBALMETHODS_H #include "BindingMap.h" -#ifdef MANGOS -#include "ElunaIncludes.h" -#endif + #ifdef AZEROTHCORE #include "BanMgr.h" -#include "ElunaIncludes.h" enum BanMode { @@ -85,10 +82,10 @@ namespace LuaGlobalFunctions */ int GetCoreVersion(lua_State* L) { -#ifndef MANGOS - Eluna::Push(L, CORE_VERSION); -#else +#ifdef MANGOS Eluna::Push(L, GitRevision::GetProjectRevision()); +#else + Eluna::Push(L, CORE_VERSION); #endif return 1; } @@ -369,10 +366,10 @@ namespace LuaGlobalFunctions * Low GUID is an ID to distinct the objects of the same type. * * [Player] and [Creature] for example can have the same low GUID but not GUID. - * + * * On TrinityCore all low GUIDs are different for all objects of the same type. * For example creatures in instances are assigned new GUIDs when the Map is created. - * + * * On MaNGOS and cMaNGOS low GUIDs are unique only on the same map. * For example creatures in instances use the same low GUID assigned for that spawn in the database. * This is why to identify a creature you have to know the instanceId and low GUID. See [Map:GetIntstanceId] @@ -1230,6 +1227,8 @@ namespace LuaGlobalFunctions eWorld->QueueCliCommand(new CliCommandHolder(nullptr, command, [](void*, std::string_view) {}, [](void*, bool) {})); #elif defined MANGOS eWorld->QueueCliCommand(new CliCommandHolder(0, SEC_CONSOLE, nullptr, command, nullptr, nullptr)); +#elif defined CMANGOS + eWorld->QueueCliCommand(new CliCommandHolder(0, SEC_CONSOLE, command, nullptr, nullptr)); #endif return 0; } @@ -1559,8 +1558,11 @@ namespace LuaGlobalFunctions Eluna::Push(L); return 1; } - +#ifdef CMANGOS + if (!pCreature->Create(lowguid, lowguid, pos, cinfo)) +#else if (!pCreature->Create(lowguid, pos, cinfo)) +#endif { delete pCreature; Eluna::Push(L); @@ -1613,7 +1615,7 @@ namespace LuaGlobalFunctions #ifndef CMANGOS if (!pCreature->Create(map->GenerateLocalLowGuid(cinfo->GetHighGuid()), pos, cinfo, TEAM_NONE)) #else - if (!pCreature->Create(map->GenerateLocalLowGuid(cinfo->GetHighGuid()), pos, cinfo)) + if (!pCreature->Create(map->GenerateLocalLowGuid(cinfo->GetHighGuid()), map->GenerateLocalLowGuid(cinfo->GetHighGuid()), pos, cinfo)) #endif { delete pCreature; @@ -1661,8 +1663,12 @@ namespace LuaGlobalFunctions } GameObject* pGameObj = new GameObject; -#if (defined(TBC) || defined(CLASSIC)) +#if ((defined(TBC) || defined(CLASSIC)) && !defined(CMANGOS)) if (!pGameObj->Create(db_lowGUID, gInfo->id, map, x, y, z, o)) +#elif ((defined(TBC) || defined(CLASSIC)) && defined(CMANGOS)) + if (!pGameObj->Create(db_lowGUID, db_lowGUID, gInfo->id, map, x, y, z, o)) +#elif defined CMANGOS + if (!pGameObj->Create(db_lowGUID, db_lowGUID, gInfo->id, map, phase, x, y, z, o)) #else if (!pGameObj->Create(db_lowGUID, gInfo->id, map, phase, x, y, z, o)) #endif @@ -1709,8 +1715,12 @@ namespace LuaGlobalFunctions { GameObject* pGameObj = new GameObject; -#if (defined(TBC) || defined(CLASSIC)) +#if ((defined(TBC) || defined(CLASSIC)) && !defined(CMANGOS)) if (!pGameObj->Create(map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), entry, map, x, y, z, o)) +#elif ((defined(TBC) || defined(CLASSIC)) && defined(CMANGOS)) + if (!pGameObj->Create(map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), entry, map, x, y, z, o)) +#elif defined CMANGOS + if (!pGameObj->Create(map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), entry, map, phase, x, y, z, o)) #else if (!pGameObj->Create(map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), entry, map, phase, x, y, z, o)) #endif @@ -2300,7 +2310,7 @@ namespace LuaGlobalFunctions /** * Adds a taxi path to a specified map, returns the used pathId. - * + * * Note that the first taxi point needs to be near the player when he starts the taxi path. * The function should also be used only **once** per path added so use it on server startup for example. * @@ -3259,5 +3269,117 @@ namespace LuaGlobalFunctions return 0; } + + luaL_Reg GlobalMethods[] = + { + // Hooks + { "RegisterPacketEvent", &LuaGlobalFunctions::RegisterPacketEvent }, + { "RegisterServerEvent", &LuaGlobalFunctions::RegisterServerEvent }, + { "RegisterPlayerEvent", &LuaGlobalFunctions::RegisterPlayerEvent }, + { "RegisterGuildEvent", &LuaGlobalFunctions::RegisterGuildEvent }, + { "RegisterGroupEvent", &LuaGlobalFunctions::RegisterGroupEvent }, + { "RegisterCreatureEvent", &LuaGlobalFunctions::RegisterCreatureEvent }, + { "RegisterUniqueCreatureEvent", &LuaGlobalFunctions::RegisterUniqueCreatureEvent }, + { "RegisterCreatureGossipEvent", &LuaGlobalFunctions::RegisterCreatureGossipEvent }, + { "RegisterGameObjectEvent", &LuaGlobalFunctions::RegisterGameObjectEvent }, + { "RegisterGameObjectGossipEvent", &LuaGlobalFunctions::RegisterGameObjectGossipEvent }, + { "RegisterItemEvent", &LuaGlobalFunctions::RegisterItemEvent }, + { "RegisterItemGossipEvent", &LuaGlobalFunctions::RegisterItemGossipEvent }, + { "RegisterPlayerGossipEvent", &LuaGlobalFunctions::RegisterPlayerGossipEvent }, + { "RegisterBGEvent", &LuaGlobalFunctions::RegisterBGEvent }, + { "RegisterMapEvent", &LuaGlobalFunctions::RegisterMapEvent }, + { "RegisterInstanceEvent", &LuaGlobalFunctions::RegisterInstanceEvent }, + + { "ClearBattleGroundEvents", &LuaGlobalFunctions::ClearBattleGroundEvents }, + { "ClearCreatureEvents", &LuaGlobalFunctions::ClearCreatureEvents }, + { "ClearUniqueCreatureEvents", &LuaGlobalFunctions::ClearUniqueCreatureEvents }, + { "ClearCreatureGossipEvents", &LuaGlobalFunctions::ClearCreatureGossipEvents }, + { "ClearGameObjectEvents", &LuaGlobalFunctions::ClearGameObjectEvents }, + { "ClearGameObjectGossipEvents", &LuaGlobalFunctions::ClearGameObjectGossipEvents }, + { "ClearGroupEvents", &LuaGlobalFunctions::ClearGroupEvents }, + { "ClearGuildEvents", &LuaGlobalFunctions::ClearGuildEvents }, + { "ClearItemEvents", &LuaGlobalFunctions::ClearItemEvents }, + { "ClearItemGossipEvents", &LuaGlobalFunctions::ClearItemGossipEvents }, + { "ClearPacketEvents", &LuaGlobalFunctions::ClearPacketEvents }, + { "ClearPlayerEvents", &LuaGlobalFunctions::ClearPlayerEvents }, + { "ClearPlayerGossipEvents", &LuaGlobalFunctions::ClearPlayerGossipEvents }, + { "ClearServerEvents", &LuaGlobalFunctions::ClearServerEvents }, + { "ClearMapEvents", &LuaGlobalFunctions::ClearMapEvents }, + { "ClearInstanceEvents", &LuaGlobalFunctions::ClearInstanceEvents }, + + // Getters + { "GetLuaEngine", &LuaGlobalFunctions::GetLuaEngine }, + { "GetCoreName", &LuaGlobalFunctions::GetCoreName }, + { "GetRealmID", &LuaGlobalFunctions::GetRealmID }, + { "GetCoreVersion", &LuaGlobalFunctions::GetCoreVersion }, + { "GetCoreExpansion", &LuaGlobalFunctions::GetCoreExpansion }, + { "GetQuest", &LuaGlobalFunctions::GetQuest }, + { "GetPlayerByGUID", &LuaGlobalFunctions::GetPlayerByGUID }, + { "GetPlayerByName", &LuaGlobalFunctions::GetPlayerByName }, + { "GetGameTime", &LuaGlobalFunctions::GetGameTime }, + { "GetPlayersInWorld", &LuaGlobalFunctions::GetPlayersInWorld }, + { "GetGuildByName", &LuaGlobalFunctions::GetGuildByName }, + { "GetGuildByLeaderGUID", &LuaGlobalFunctions::GetGuildByLeaderGUID }, + { "GetPlayerCount", &LuaGlobalFunctions::GetPlayerCount }, + { "GetPlayerGUID", &LuaGlobalFunctions::GetPlayerGUID }, + { "GetItemGUID", &LuaGlobalFunctions::GetItemGUID }, + { "GetObjectGUID", &LuaGlobalFunctions::GetObjectGUID }, + { "GetUnitGUID", &LuaGlobalFunctions::GetUnitGUID }, + { "GetGUIDLow", &LuaGlobalFunctions::GetGUIDLow }, + { "GetGUIDType", &LuaGlobalFunctions::GetGUIDType }, + { "GetGUIDEntry", &LuaGlobalFunctions::GetGUIDEntry }, + { "GetAreaName", &LuaGlobalFunctions::GetAreaName }, + { "bit_not", &LuaGlobalFunctions::bit_not }, + { "bit_xor", &LuaGlobalFunctions::bit_xor }, + { "bit_rshift", &LuaGlobalFunctions::bit_rshift }, + { "bit_lshift", &LuaGlobalFunctions::bit_lshift }, + { "bit_or", &LuaGlobalFunctions::bit_or }, + { "bit_and", &LuaGlobalFunctions::bit_and }, + { "GetItemLink", &LuaGlobalFunctions::GetItemLink }, + { "GetMapById", &LuaGlobalFunctions::GetMapById }, + { "GetCurrTime", &LuaGlobalFunctions::GetCurrTime }, + { "GetTimeDiff", &LuaGlobalFunctions::GetTimeDiff }, + { "PrintInfo", &LuaGlobalFunctions::PrintInfo }, + { "PrintError", &LuaGlobalFunctions::PrintError }, + { "PrintDebug", &LuaGlobalFunctions::PrintDebug }, + { "GetActiveGameEvents", &LuaGlobalFunctions::GetActiveGameEvents }, + + // Boolean + { "IsInventoryPos", &LuaGlobalFunctions::IsInventoryPos }, + { "IsEquipmentPos", &LuaGlobalFunctions::IsEquipmentPos }, + { "IsBankPos", &LuaGlobalFunctions::IsBankPos }, + { "IsBagPos", &LuaGlobalFunctions::IsBagPos }, + { "IsGameEventActive", &LuaGlobalFunctions::IsGameEventActive }, + + // Other + { "ReloadEluna", &LuaGlobalFunctions::ReloadEluna }, + { "RunCommand", &LuaGlobalFunctions::RunCommand }, + { "SendWorldMessage", &LuaGlobalFunctions::SendWorldMessage }, + { "WorldDBQuery", &LuaGlobalFunctions::WorldDBQuery }, + { "WorldDBExecute", &LuaGlobalFunctions::WorldDBExecute }, + { "CharDBQuery", &LuaGlobalFunctions::CharDBQuery }, + { "CharDBExecute", &LuaGlobalFunctions::CharDBExecute }, + { "AuthDBQuery", &LuaGlobalFunctions::AuthDBQuery }, + { "AuthDBExecute", &LuaGlobalFunctions::AuthDBExecute }, + { "CreateLuaEvent", &LuaGlobalFunctions::CreateLuaEvent }, + { "RemoveEventById", &LuaGlobalFunctions::RemoveEventById }, + { "RemoveEvents", &LuaGlobalFunctions::RemoveEvents }, + { "PerformIngameSpawn", &LuaGlobalFunctions::PerformIngameSpawn }, + { "CreatePacket", &LuaGlobalFunctions::CreatePacket }, + { "AddVendorItem", &LuaGlobalFunctions::AddVendorItem }, + { "VendorRemoveItem", &LuaGlobalFunctions::VendorRemoveItem }, + { "VendorRemoveAllItems", &LuaGlobalFunctions::VendorRemoveAllItems }, + { "Kick", &LuaGlobalFunctions::Kick }, + { "Ban", &LuaGlobalFunctions::Ban }, + { "SaveAllPlayers", &LuaGlobalFunctions::SaveAllPlayers }, + { "SendMail", &LuaGlobalFunctions::SendMail }, + { "AddTaxiPath", &LuaGlobalFunctions::AddTaxiPath }, + { "CreateInt64", &LuaGlobalFunctions::CreateLongLong }, + { "CreateUint64", &LuaGlobalFunctions::CreateULongLong }, + { "StartGameEvent", &LuaGlobalFunctions::StartGameEvent }, + { "StopGameEvent", &LuaGlobalFunctions::StopGameEvent }, + + { NULL, NULL } + }; } #endif diff --git a/src/modules/Eluna/GroupMethods.h b/src/modules/Eluna/Mangos/GroupMethods.h similarity index 86% rename from src/modules/Eluna/GroupMethods.h rename to src/modules/Eluna/Mangos/GroupMethods.h index b61658c7c3..ddbb78af85 100644 --- a/src/modules/Eluna/GroupMethods.h +++ b/src/modules/Eluna/Mangos/GroupMethods.h @@ -52,7 +52,7 @@ namespace LuaGroup return 1; } #endif - + /** * Returns 'true' if the [Group] is a raid [Group] * @@ -76,7 +76,7 @@ namespace LuaGroup int IsBGGroup(lua_State* L, Group* group) { #ifdef CMANGOS - Eluna::Push(L, group->IsBattleGroup()); + Eluna::Push(L, group->IsBattleGroup()); #else Eluna::Push(L, group->isBGGroup()); #endif @@ -425,6 +425,49 @@ namespace LuaGroup group->ConvertToLFG(); return 0; }*/ + + ElunaRegister GroupMethods[] = + { + // Getters + { "GetMembers", &LuaGroup::GetMembers }, + { "GetLeaderGUID", &LuaGroup::GetLeaderGUID }, + { "GetGUID", &LuaGroup::GetGUID }, + { "GetMemberGroup", &LuaGroup::GetMemberGroup }, + { "GetMemberGUID", &LuaGroup::GetMemberGUID }, + { "GetMembersCount", &LuaGroup::GetMembersCount }, + + // Setters + { "SetLeader", &LuaGroup::SetLeader }, + { "SetMembersGroup", &LuaGroup::SetMembersGroup }, + { "SetTargetIcon", &LuaGroup::SetTargetIcon }, + + // Boolean + { "IsLeader", &LuaGroup::IsLeader }, + { "AddMember", &LuaGroup::AddMember }, + { "RemoveMember", &LuaGroup::RemoveMember }, + { "Disband", &LuaGroup::Disband }, + { "IsFull", &LuaGroup::IsFull }, + { "IsRaidGroup", &LuaGroup::IsRaidGroup }, + { "IsBGGroup", &LuaGroup::IsBGGroup }, + { "IsMember", &LuaGroup::IsMember }, + { "IsAssistant", &LuaGroup::IsAssistant }, + { "SameSubGroup", &LuaGroup::SameSubGroup }, + { "HasFreeSlotSubGroup", &LuaGroup::HasFreeSlotSubGroup }, +#if !(defined(CLASSIC) || defined(TBC)) + { "IsLFGGroup", &LuaGroup::IsLFGGroup }, +#endif + // Other + { "SendPacket", &LuaGroup::SendPacket }, + { "ConvertToRaid", &LuaGroup::ConvertToRaid }, + + // Not implemented methods + { "IsBFGroup", nullptr }, // not implemented + { "ConvertToLFG", nullptr }, // not implemented + { "GetMemberFlags", nullptr }, // not implemented + { "SetMemberFlag", nullptr }, // not implemented + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/GuildMethods.h b/src/modules/Eluna/Mangos/GuildMethods.h similarity index 89% rename from src/modules/Eluna/GuildMethods.h rename to src/modules/Eluna/Mangos/GuildMethods.h index ba9863fc3b..d6525a09d7 100644 --- a/src/modules/Eluna/GuildMethods.h +++ b/src/modules/Eluna/Mangos/GuildMethods.h @@ -301,5 +301,36 @@ namespace LuaGuild #endif return 0; } + + ElunaRegister GuildMethods[] = + { + // Getters + { "GetMembers", &LuaGuild::GetMembers }, + { "GetLeader", &LuaGuild::GetLeader }, + { "GetLeaderGUID", &LuaGuild::GetLeaderGUID }, + { "GetId", &LuaGuild::GetId }, + { "GetName", &LuaGuild::GetName }, + { "GetMOTD", &LuaGuild::GetMOTD }, + { "GetInfo", &LuaGuild::GetInfo }, + { "GetMemberCount", &LuaGuild::GetMemberCount }, + + // Setters + { "SetMemberRank", &LuaGuild::SetMemberRank }, +#if !defined(CATA) + { "SetLeader", &LuaGuild::SetLeader }, +#endif +#ifndef CLASSIC + { "SetBankTabText", &LuaGuild::SetBankTabText }, +#endif + + // Other + { "SendPacket", &LuaGuild::SendPacket }, + { "SendPacketToRanked", &LuaGuild::SendPacketToRanked }, + { "Disband", &LuaGuild::Disband }, + { "AddMember", &LuaGuild::AddMember }, + { "DeleteMember", &LuaGuild::DeleteMember }, + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/ItemMethods.h b/src/modules/Eluna/Mangos/ItemMethods.h similarity index 86% rename from src/modules/Eluna/ItemMethods.h rename to src/modules/Eluna/Mangos/ItemMethods.h index da05364a28..489cbe012e 100644 --- a/src/modules/Eluna/ItemMethods.h +++ b/src/modules/Eluna/Mangos/ItemMethods.h @@ -764,5 +764,83 @@ namespace LuaItem #endif return 0; } + + ElunaRegister ItemMethods[] = + { + // Getters + { "GetOwnerGUID", &LuaItem::GetOwnerGUID }, + { "GetOwner", &LuaItem::GetOwner }, + { "GetCount", &LuaItem::GetCount }, + { "GetMaxStackCount", &LuaItem::GetMaxStackCount }, + { "GetSlot", &LuaItem::GetSlot }, + { "GetBagSlot", &LuaItem::GetBagSlot }, + { "GetEnchantmentId", &LuaItem::GetEnchantmentId }, + { "GetSpellId", &LuaItem::GetSpellId }, + { "GetSpellTrigger", &LuaItem::GetSpellTrigger }, + { "GetItemLink", &LuaItem::GetItemLink }, + { "GetClass", &LuaItem::GetClass }, + { "GetSubClass", &LuaItem::GetSubClass }, + { "GetName", &LuaItem::GetName }, + { "GetDisplayId", &LuaItem::GetDisplayId }, + { "GetQuality", &LuaItem::GetQuality }, + { "GetBuyCount", &LuaItem::GetBuyCount }, + { "GetBuyPrice", &LuaItem::GetBuyPrice }, + { "GetSellPrice", &LuaItem::GetSellPrice }, + { "GetInventoryType", &LuaItem::GetInventoryType }, + { "GetAllowableClass", &LuaItem::GetAllowableClass }, + { "GetAllowableRace", &LuaItem::GetAllowableRace }, + { "GetItemLevel", &LuaItem::GetItemLevel }, + { "GetRequiredLevel", &LuaItem::GetRequiredLevel }, + { "GetRandomProperty", &LuaItem::GetRandomProperty }, + { "GetItemSet", &LuaItem::GetItemSet }, + { "GetBagSize", &LuaItem::GetBagSize }, +#ifndef CLASSIC + { "GetRandomSuffix", &LuaItem::GetRandomSuffix }, +#endif +#ifdef WOTLK + { "GetStatsCount", &LuaItem::GetStatsCount }, +#endif + + // Setters + { "SetOwner", &LuaItem::SetOwner }, + { "SetBinding", &LuaItem::SetBinding }, + { "SetCount", &LuaItem::SetCount }, + + // Boolean + { "IsSoulBound", &LuaItem::IsSoulBound }, + { "IsBoundByEnchant", &LuaItem::IsBoundByEnchant }, + { "IsNotBoundToPlayer", &LuaItem::IsNotBoundToPlayer }, + { "IsLocked", &LuaItem::IsLocked }, + { "IsBag", &LuaItem::IsBag }, + { "IsNotEmptyBag", &LuaItem::IsNotEmptyBag }, + { "IsBroken", &LuaItem::IsBroken }, + { "CanBeTraded", &LuaItem::CanBeTraded }, + { "IsInTrade", &LuaItem::IsInTrade }, + { "IsInBag", &LuaItem::IsInBag }, + { "IsEquipped", &LuaItem::IsEquipped }, + { "HasQuest", &LuaItem::HasQuest }, + { "IsPotion", &LuaItem::IsPotion }, + { "IsConjuredConsumable", &LuaItem::IsConjuredConsumable }, + { "SetEnchantment", &LuaItem::SetEnchantment }, + { "ClearEnchantment", &LuaItem::ClearEnchantment }, +#ifndef CLASSIC + { "IsCurrencyToken", &LuaItem::IsCurrencyToken }, +#endif +#if (!defined(TBC) && !defined(CLASSIC)) + { "IsBoundAccountWide", &LuaItem::IsBoundAccountWide }, +#endif +#if defined(WOTLK) + { "IsWeaponVellum", &LuaItem::IsWeaponVellum }, + { "IsArmorVellum", &LuaItem::IsArmorVellum }, +#endif + + // Other + { "SaveToDB", &LuaItem::SaveToDB }, + + // Not implemented methods + { "IsRefundExpired", nullptr }, // not implemented + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/MapMethods.h b/src/modules/Eluna/Mangos/MapMethods.h similarity index 90% rename from src/modules/Eluna/MapMethods.h rename to src/modules/Eluna/Mangos/MapMethods.h index 085940df85..38db9f0884 100644 --- a/src/modules/Eluna/MapMethods.h +++ b/src/modules/Eluna/Mangos/MapMethods.h @@ -369,5 +369,37 @@ namespace LuaMap lua_settop(L, tbl); return 1; } + + ElunaRegister MapMethods[] = + { + // Getters + { "GetName", &LuaMap::GetName }, + { "GetDifficulty", &LuaMap::GetDifficulty }, + { "GetInstanceId", &LuaMap::GetInstanceId }, + { "GetInstanceData", &LuaMap::GetInstanceData }, + { "GetPlayerCount", &LuaMap::GetPlayerCount }, + { "GetPlayers", &LuaMap::GetPlayers }, + { "GetMapId", &LuaMap::GetMapId }, + { "GetAreaId", &LuaMap::GetAreaId }, + { "GetHeight", &LuaMap::GetHeight }, + { "GetWorldObject", &LuaMap::GetWorldObject }, + + // Setters + { "SetWeather", &LuaMap::SetWeather }, + + // Boolean + { "IsBattleground", &LuaMap::IsBattleground }, + { "IsDungeon", &LuaMap::IsDungeon }, + { "IsEmpty", &LuaMap::IsEmpty }, + { "IsRaid", &LuaMap::IsRaid }, +#ifndef CLASSIC + { "IsArena", &LuaMap::IsArena }, + { "IsHeroic", &LuaMap::IsHeroic }, +#endif + // Other + { "SaveInstanceData", &LuaMap::SaveInstanceData }, + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/ObjectMethods.h b/src/modules/Eluna/Mangos/ObjectMethods.h similarity index 88% rename from src/modules/Eluna/ObjectMethods.h rename to src/modules/Eluna/Mangos/ObjectMethods.h index 6419956e54..7bdd5db096 100644 --- a/src/modules/Eluna/ObjectMethods.h +++ b/src/modules/Eluna/Mangos/ObjectMethods.h @@ -156,14 +156,14 @@ namespace LuaObject /** * Returns the GUID of the [Object]. - * + * * GUID is an unique identifier for the object. - * + * * However on MaNGOS and cMangos creatures and gameobjects inside different maps can share * the same GUID but not on the same map. - * + * * On TrinityCore this value is unique across all maps - * + * * @return ObjectGuid guid */ int GetGUID(lua_State* L, Object* obj) @@ -174,10 +174,10 @@ namespace LuaObject /** * Returns the low-part of the [Object]'s GUID. - * + * * On TrinityCore all low GUIDs are different for all objects of the same type. * For example creatures in instances are assigned new GUIDs when the Map is created. - * + * * On MaNGOS and cMaNGOS low GUIDs are unique only on the same map. * For example creatures in instances use the same low GUID assigned for that spawn in the database. * This is why to identify a creature you have to know the instanceId and low GUID. See [Map:GetIntstanceId] @@ -460,5 +460,47 @@ namespace LuaObject Eluna::Push(L, obj->ToPlayer()); return 1; } + + ElunaRegister ObjectMethods[] = + { + // Getters + { "GetEntry", &LuaObject::GetEntry }, + { "GetGUID", &LuaObject::GetGUID }, + { "GetGUIDLow", &LuaObject::GetGUIDLow }, + { "GetInt32Value", &LuaObject::GetInt32Value }, + { "GetUInt32Value", &LuaObject::GetUInt32Value }, + { "GetFloatValue", &LuaObject::GetFloatValue }, + { "GetByteValue", &LuaObject::GetByteValue }, + { "GetUInt16Value", &LuaObject::GetUInt16Value }, + { "GetUInt64Value", &LuaObject::GetUInt64Value }, + { "GetScale", &LuaObject::GetScale }, + { "GetTypeId", &LuaObject::GetTypeId }, + + // Setters + { "SetInt32Value", &LuaObject::SetInt32Value }, + { "SetUInt32Value", &LuaObject::SetUInt32Value }, + { "UpdateUInt32Value", &LuaObject::UpdateUInt32Value }, + { "SetFloatValue", &LuaObject::SetFloatValue }, + { "SetByteValue", &LuaObject::SetByteValue }, + { "SetUInt16Value", &LuaObject::SetUInt16Value }, + { "SetInt16Value", &LuaObject::SetInt16Value }, + { "SetUInt64Value", &LuaObject::SetUInt64Value }, + { "SetScale", &LuaObject::SetScale }, + { "SetFlag", &LuaObject::SetFlag }, + + // Boolean + { "IsInWorld", &LuaObject::IsInWorld }, + { "HasFlag", &LuaObject::HasFlag }, + + // Other + { "ToGameObject", &LuaObject::ToGameObject }, + { "ToUnit", &LuaObject::ToUnit }, + { "ToCreature", &LuaObject::ToCreature }, + { "ToPlayer", &LuaObject::ToPlayer }, + { "ToCorpse", &LuaObject::ToCorpse }, + { "RemoveFlag", &LuaObject::RemoveFlag }, + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/PlayerMethods.h b/src/modules/Eluna/Mangos/PlayerMethods.h similarity index 88% rename from src/modules/Eluna/PlayerMethods.h rename to src/modules/Eluna/Mangos/PlayerMethods.h index ef33d1bc3d..c2e546f909 100644 --- a/src/modules/Eluna/PlayerMethods.h +++ b/src/modules/Eluna/Mangos/PlayerMethods.h @@ -150,7 +150,7 @@ namespace LuaPlayer return 1; } #endif - + /** * Returns 'true' if the [Player] has the given amount of item entry specified, 'false' otherwise. * @@ -167,7 +167,7 @@ namespace LuaPlayer Eluna::Push(L, player->HasItemCount(itemId, count, check_bank)); return 1; } - + /** * Returns 'true' if the [Player] has a quest for the item entry specified, 'false' otherwise. * @@ -181,7 +181,7 @@ namespace LuaPlayer Eluna::Push(L, player->HasQuestForItem(entry)); return 1; } - + /** * Returns 'true' if the [Player] can use the item or item entry specified, 'false' otherwise. * @@ -441,7 +441,7 @@ namespace LuaPlayer return 1; } #endif - + /** * Returns 'true' if the [Player] is immune to everything. * @@ -1436,7 +1436,7 @@ namespace LuaPlayer Eluna::Push(L, player->GetItemByEntry(entry)); return 1; } - + /** * Returns the database textID of the [WorldObject]'s gossip header text for the [Player] * @@ -1508,7 +1508,7 @@ namespace LuaPlayer Eluna::Push(L, player->GetTeamId()); return 1; } - + /** * Returns amount of the specified [Item] the [Player] has. * @@ -1674,7 +1674,7 @@ namespace LuaPlayer Eluna::Push(L, ChatHandler(player->GetSession()).GetNearbyGameObject()); return 1; }*/ - + /** * Locks the player controls and disallows all movement and casting. * @@ -2186,7 +2186,7 @@ namespace LuaPlayer return 0; } #endif - + /** * Shows the mailbox window to the player from specified guid. * @@ -2397,7 +2397,7 @@ namespace LuaPlayer player->GetSession()->SendShowBank(obj->GET_GUID()); return 0; } - + /** * Sends a vendor window to the [Player] from the [WorldObject] specified. * @@ -2749,11 +2749,15 @@ namespace LuaPlayer { bool no_cost = Eluna::CHECKVAL(L, 2, true); +//#ifdef CATA +// player->ResetTalents(no_cost); +//#else #ifdef TRINITY player->ResetTalents(no_cost); #else player->resetTalents(no_cost); #endif +//#endif #if (!defined(TBC) && !defined(CLASSIC)) player->SendTalentsInfoData(false); #endif @@ -3318,7 +3322,7 @@ namespace LuaPlayer player->AutoUnequipOffhandIfNeed(); return 1; } - + /** * Returns true if the player can equip the given [Item] or item entry to the given slot, false otherwise. * @@ -3496,7 +3500,7 @@ namespace LuaPlayer player->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, currentKills + val); return 0; } - + /** * Adds the given amount of the specified item entry to the player. * @@ -3531,7 +3535,7 @@ namespace LuaPlayer #endif return 1; } - + /** * Removes the given amount of the specified [Item] from the player. * @@ -3834,9 +3838,9 @@ namespace LuaPlayer /** * Adds a new item to the gossip menu shown to the [Player] on next call to [Player:GossipSendMenu]. * - * sender and intid are numbers which are passed directly to the gossip selection handler. Internally they are partly used for the database gossip handling. - * code specifies whether to show a box to insert text to. The player inserted text is passed to the gossip selection handler. - * money specifies an amount of money the player needs to have to click the option. An error message is shown if the player doesn't have enough money. + * sender and intid are numbers which are passed directly to the gossip selection handler. Internally they are partly used for the database gossip handling. + * code specifies whether to show a box to insert text to. The player inserted text is passed to the gossip selection handler. + * money specifies an amount of money the player needs to have to click the option. An error message is shown if the player doesn't have enough money. * Note that the money amount is only checked client side and is not removed from the player either. You will need to check again in your code before taking action. * * See also: [Player:GossipSendMenu], [Player:GossipAddQuests], [Player:GossipComplete], [Player:GossipClearMenu] @@ -3930,7 +3934,7 @@ namespace LuaPlayer * Clears the [Player]s current gossip item list. * * See also: [Player:GossipMenuAddItem], [Player:GossipSendMenu], [Player:GossipAddQuests], [Player:GossipComplete] - * + * * Note: This is needed when you show a gossip menu without using gossip hello or select hooks which do this automatically. * Usually this is needed when using [Player] is the sender of a Gossip Menu. */ @@ -4289,5 +4293,314 @@ namespace LuaPlayer player->RemovePet(player->GetPet(), (PetSaveMode)mode, returnreagent); return 0; }*/ + + ElunaRegister PlayerMethods[] = + { + // Getters + { "GetSelection", &LuaPlayer::GetSelection }, + { "GetGMRank", &LuaPlayer::GetGMRank }, + { "GetGuildId", &LuaPlayer::GetGuildId }, + { "GetCoinage", &LuaPlayer::GetCoinage }, + { "GetTeam", &LuaPlayer::GetTeam }, + { "GetItemCount", &LuaPlayer::GetItemCount }, + { "GetGroup", &LuaPlayer::GetGroup }, + { "GetGuild", &LuaPlayer::GetGuild }, + { "GetAccountId", &LuaPlayer::GetAccountId }, + { "GetAccountName", &LuaPlayer::GetAccountName }, + { "GetLifetimeKills", &LuaPlayer::GetLifetimeKills }, + { "GetPlayerIP", &LuaPlayer::GetPlayerIP }, + { "GetLevelPlayedTime", &LuaPlayer::GetLevelPlayedTime }, + { "GetTotalPlayedTime", &LuaPlayer::GetTotalPlayedTime }, + { "GetItemByPos", &LuaPlayer::GetItemByPos }, + { "GetItemByEntry", &LuaPlayer::GetItemByEntry }, + { "GetItemByGUID", &LuaPlayer::GetItemByGUID }, + { "GetMailItem", &LuaPlayer::GetMailItem }, + { "GetReputation", &LuaPlayer::GetReputation }, + { "GetEquippedItemBySlot", &LuaPlayer::GetEquippedItemBySlot }, + { "GetQuestLevel", &LuaPlayer::GetQuestLevel }, + { "GetChatTag", &LuaPlayer::GetChatTag }, + { "GetRestBonus", &LuaPlayer::GetRestBonus }, + { "GetReqKillOrCastCurrentCount", &LuaPlayer::GetReqKillOrCastCurrentCount }, + { "GetQuestStatus", &LuaPlayer::GetQuestStatus }, + { "GetInGameTime", &LuaPlayer::GetInGameTime }, + { "GetComboPoints", &LuaPlayer::GetComboPoints }, + { "GetComboTarget", &LuaPlayer::GetComboTarget }, + { "GetGuildName", &LuaPlayer::GetGuildName }, + { "GetFreeTalentPoints", &LuaPlayer::GetFreeTalentPoints }, + { "GetSpellCooldownDelay", &LuaPlayer::GetSpellCooldownDelay }, + { "GetGuildRank", &LuaPlayer::GetGuildRank }, + { "GetDifficulty", &LuaPlayer::GetDifficulty }, + { "GetHealthBonusFromStamina", &LuaPlayer::GetHealthBonusFromStamina }, + { "GetManaBonusFromIntellect", &LuaPlayer::GetManaBonusFromIntellect }, + { "GetMaxSkillValue", &LuaPlayer::GetMaxSkillValue }, + { "GetPureMaxSkillValue", &LuaPlayer::GetPureMaxSkillValue }, + { "GetSkillValue", &LuaPlayer::GetSkillValue }, + { "GetBaseSkillValue", &LuaPlayer::GetBaseSkillValue }, + { "GetPureSkillValue", &LuaPlayer::GetPureSkillValue }, + { "GetSkillPermBonusValue", &LuaPlayer::GetSkillPermBonusValue }, + { "GetSkillTempBonusValue", &LuaPlayer::GetSkillTempBonusValue }, + { "GetReputationRank", &LuaPlayer::GetReputationRank }, + { "GetDrunkValue", &LuaPlayer::GetDrunkValue }, + { "GetBattlegroundId", &LuaPlayer::GetBattlegroundId }, + { "GetBattlegroundTypeId", &LuaPlayer::GetBattlegroundTypeId }, + { "GetXPRestBonus", &LuaPlayer::GetXPRestBonus }, + { "GetGroupInvite", &LuaPlayer::GetGroupInvite }, + { "GetSubGroup", &LuaPlayer::GetSubGroup }, + { "GetNextRandomRaidMember", &LuaPlayer::GetNextRandomRaidMember }, + { "GetOriginalGroup", &LuaPlayer::GetOriginalGroup }, + { "GetOriginalSubGroup", &LuaPlayer::GetOriginalSubGroup }, + { "GetLatency", &LuaPlayer::GetLatency }, + { "GetDbLocaleIndex", &LuaPlayer::GetDbLocaleIndex }, + { "GetDbcLocale", &LuaPlayer::GetDbcLocale }, + { "GetCorpse", &LuaPlayer::GetCorpse }, + { "GetGossipTextId", &LuaPlayer::GetGossipTextId }, + { "GetQuestRewardStatus", &LuaPlayer::GetQuestRewardStatus }, +#if !defined(CATA) + { "GetShieldBlockValue", &LuaPlayer::GetShieldBlockValue }, +#endif +#if defined(CLASSIC) + { "GetHonorStoredKills", &LuaPlayer::GetHonorStoredKills }, + { "GetRankPoints", &LuaPlayer::GetRankPoints }, + { "GetHonorLastWeekStandingPos", &LuaPlayer::GetHonorLastWeekStandingPos }, +#endif +#if defined(TBC) || defined (WOTLK) + { "GetArenaPoints", &LuaPlayer::GetArenaPoints }, + { "GetHonorPoints", &LuaPlayer::GetHonorPoints }, +#endif +#ifdef WOTLK + { "GetPhaseMaskForSpawn", &LuaPlayer::GetPhaseMaskForSpawn }, +#endif +#if (!defined(TBC) && !defined(CLASSIC)) + { "GetActiveSpec", &LuaPlayer::GetActiveSpec }, + { "GetSpecsCount", &LuaPlayer::GetSpecsCount }, +#endif + + // Setters + { "AdvanceSkillsToMax", &LuaPlayer::AdvanceSkillsToMax }, + { "AdvanceSkill", &LuaPlayer::AdvanceSkill }, + { "AdvanceAllSkills", &LuaPlayer::AdvanceAllSkills }, + { "AddLifetimeKills", &LuaPlayer::AddLifetimeKills }, + { "SetCoinage", &LuaPlayer::SetCoinage }, + { "SetBindPoint", &LuaPlayer::SetBindPoint }, + { "SetLifetimeKills", &LuaPlayer::SetLifetimeKills }, + { "SetGameMaster", &LuaPlayer::SetGameMaster }, + { "SetGMChat", &LuaPlayer::SetGMChat }, + { "SetTaxiCheat", &LuaPlayer::SetTaxiCheat }, + { "SetGMVisible", &LuaPlayer::SetGMVisible }, + { "SetPvPDeath", &LuaPlayer::SetPvPDeath }, + { "SetAcceptWhispers", &LuaPlayer::SetAcceptWhispers }, + { "SetRestBonus", &LuaPlayer::SetRestBonus }, + { "SetQuestStatus", &LuaPlayer::SetQuestStatus }, + { "SetReputation", &LuaPlayer::SetReputation }, + { "SetFreeTalentPoints", &LuaPlayer::SetFreeTalentPoints }, + { "SetGuildRank", &LuaPlayer::SetGuildRank }, + { "SetSkill", &LuaPlayer::SetSkill }, + { "SetFactionForRace", &LuaPlayer::SetFactionForRace }, + { "SetDrunkValue", &LuaPlayer::SetDrunkValue }, + { "SetAtLoginFlag", &LuaPlayer::SetAtLoginFlag }, + { "SetPlayerLock", &LuaPlayer::SetPlayerLock }, + { "SetGender", &LuaPlayer::SetGender }, + { "SetSheath", &LuaPlayer::SetSheath }, +#if defined(CLASSIC) + { "SetHonorStoredKills", &LuaPlayer::SetHonorStoredKills }, + { "SetRankPoints", &LuaPlayer::SetRankPoints }, + { "SetHonorLastWeekStandingPos", &LuaPlayer::SetHonorLastWeekStandingPos }, +#endif +#ifndef CLASSIC + { "SetKnownTitle", &LuaPlayer::SetKnownTitle }, + { "UnsetKnownTitle", &LuaPlayer::UnsetKnownTitle }, +#endif +#if defined(TBC) || defined(WOTLK) + { "SetArenaPoints", &LuaPlayer::SetArenaPoints }, + { "SetHonorPoints", &LuaPlayer::SetHonorPoints }, +#endif + + // Boolean + { "IsInGroup", &LuaPlayer::IsInGroup }, + { "IsInGuild", &LuaPlayer::IsInGuild }, + { "IsGM", &LuaPlayer::IsGM }, + { "IsImmuneToDamage", &LuaPlayer::IsImmuneToDamage }, + { "IsAlliance", &LuaPlayer::IsAlliance }, + { "IsHorde", &LuaPlayer::IsHorde }, + { "HasItem", &LuaPlayer::HasItem }, + { "Teleport", &LuaPlayer::Teleport }, + { "AddItem", &LuaPlayer::AddItem }, + { "CanCompleteQuest", &LuaPlayer::CanCompleteQuest }, + { "CanEquipItem", &LuaPlayer::CanEquipItem }, + { "IsFalling", &LuaPlayer::IsFalling }, + { "ToggleAFK", &LuaPlayer::ToggleAFK }, + { "ToggleDND", &LuaPlayer::ToggleDND }, + { "IsAFK", &LuaPlayer::IsAFK }, + { "IsDND", &LuaPlayer::IsDND }, + { "IsAcceptingWhispers", &LuaPlayer::IsAcceptingWhispers }, + { "IsGMChat", &LuaPlayer::IsGMChat }, + { "IsTaxiCheater", &LuaPlayer::IsTaxiCheater }, + { "IsGMVisible", &LuaPlayer::IsGMVisible }, + { "HasQuest", &LuaPlayer::HasQuest }, + { "InBattlegroundQueue", &LuaPlayer::InBattlegroundQueue }, + { "CanSpeak", &LuaPlayer::CanSpeak }, + { "HasAtLoginFlag", &LuaPlayer::HasAtLoginFlag }, + { "CanUninviteFromGroup", &LuaPlayer::CanUninviteFromGroup }, + { "IsRested", &LuaPlayer::IsRested }, + { "IsVisibleForPlayer", &LuaPlayer::IsVisibleForPlayer }, + { "HasQuestForItem", &LuaPlayer::HasQuestForItem }, + { "HasQuestForGO", &LuaPlayer::HasQuestForGO }, + { "CanShareQuest", &LuaPlayer::CanShareQuest }, + { "IsInSameGroupWith", &LuaPlayer::IsInSameGroupWith }, + { "IsInSameRaidWith", &LuaPlayer::IsInSameRaidWith }, + { "IsGroupVisibleFor", &LuaPlayer::IsGroupVisibleFor }, + { "HasSkill", &LuaPlayer::HasSkill }, + { "IsHonorOrXPTarget", &LuaPlayer::IsHonorOrXPTarget }, + { "CanParry", &LuaPlayer::CanParry }, + { "CanBlock", &LuaPlayer::CanBlock }, + { "InBattleground", &LuaPlayer::InBattleground }, + { "CanUseItem", &LuaPlayer::CanUseItem }, + { "HasSpell", &LuaPlayer::HasSpell }, + { "HasSpellCooldown", &LuaPlayer::HasSpellCooldown }, + { "IsInWater", &LuaPlayer::IsInWater }, + { "IsMoving", &LuaPlayer::IsMoving }, +#ifndef CLASSIC + { "HasTitle", &LuaPlayer::HasTitle }, + { "IsInArenaTeam", &LuaPlayer::IsInArenaTeam }, + { "InArena", &LuaPlayer::InArena }, + { "CanFly", &LuaPlayer::CanFly }, + { "IsFlying", &LuaPlayer::IsFlying }, +#endif +#if (!defined(TBC) && !defined(CLASSIC)) + { "HasAchieved", &LuaPlayer::HasAchieved }, + { "HasTalent", &LuaPlayer::HasTalent }, + { "CanTitanGrip", &LuaPlayer::CanTitanGrip }, +#endif + + + // Gossip + { "GossipMenuAddItem", &LuaPlayer::GossipMenuAddItem }, + { "GossipSendMenu", &LuaPlayer::GossipSendMenu }, + { "GossipComplete", &LuaPlayer::GossipComplete }, + { "GossipClearMenu", &LuaPlayer::GossipClearMenu }, + + // Other + { "SendBroadcastMessage", &LuaPlayer::SendBroadcastMessage }, + { "SendAreaTriggerMessage", &LuaPlayer::SendAreaTriggerMessage }, + { "SendNotification", &LuaPlayer::SendNotification }, + { "SendPacket", &LuaPlayer::SendPacket }, + { "SendAddonMessage", &LuaPlayer::SendAddonMessage }, + { "ModifyMoney", &LuaPlayer::ModifyMoney }, + { "LearnSpell", &LuaPlayer::LearnSpell }, + { "LearnTalent", &LuaPlayer::LearnTalent }, + { "RemoveItem", &LuaPlayer::RemoveItem }, + { "RemoveLifetimeKills", &LuaPlayer::RemoveLifetimeKills }, + { "ResurrectPlayer", &LuaPlayer::ResurrectPlayer }, + { "EquipItem", &LuaPlayer::EquipItem }, + { "ResetSpellCooldown", &LuaPlayer::ResetSpellCooldown }, + { "ResetTypeCooldowns", &LuaPlayer::ResetTypeCooldowns }, + { "ResetAllCooldowns", &LuaPlayer::ResetAllCooldowns }, + { "GiveXP", &LuaPlayer::GiveXP }, + { "Say", &LuaPlayer::Say }, + { "Yell", &LuaPlayer::Yell }, + { "TextEmote", &LuaPlayer::TextEmote }, + { "Whisper", &LuaPlayer::Whisper }, + { "CompleteQuest", &LuaPlayer::CompleteQuest }, + { "IncompleteQuest", &LuaPlayer::IncompleteQuest }, + { "FailQuest", &LuaPlayer::FailQuest }, + { "AddQuest", &LuaPlayer::AddQuest }, + { "RemoveQuest", &LuaPlayer::RemoveQuest }, + { "AreaExploredOrEventHappens", &LuaPlayer::AreaExploredOrEventHappens }, + { "GroupEventHappens", &LuaPlayer::GroupEventHappens }, + { "KilledMonsterCredit", &LuaPlayer::KilledMonsterCredit }, + { "TalkedToCreature", &LuaPlayer::TalkedToCreature }, + { "AddComboPoints", &LuaPlayer::AddComboPoints }, + { "ClearComboPoints", &LuaPlayer::ClearComboPoints }, + { "RemoveSpell", &LuaPlayer::RemoveSpell }, + { "ResetTalents", &LuaPlayer::ResetTalents }, + { "ResetTalentsCost", &LuaPlayer::ResetTalentsCost }, + { "RemoveFromGroup", &LuaPlayer::RemoveFromGroup }, + { "KillPlayer", &LuaPlayer::KillPlayer }, + { "DurabilityLossAll", &LuaPlayer::DurabilityLossAll }, + { "DurabilityLoss", &LuaPlayer::DurabilityLoss }, + { "DurabilityPointsLoss", &LuaPlayer::DurabilityPointsLoss }, + { "DurabilityPointsLossAll", &LuaPlayer::DurabilityPointsLossAll }, + { "DurabilityPointLossForEquipSlot", &LuaPlayer::DurabilityPointLossForEquipSlot }, + { "DurabilityRepairAll", &LuaPlayer::DurabilityRepairAll }, + { "DurabilityRepair", &LuaPlayer::DurabilityRepair }, + { "LeaveBattleground", &LuaPlayer::LeaveBattleground }, + { "UnbindInstance", &LuaPlayer::UnbindInstance }, + { "UnbindAllInstances", &LuaPlayer::UnbindAllInstances }, + { "RemoveFromBattlegroundRaid", &LuaPlayer::RemoveFromBattlegroundRaid }, + { "KickPlayer", &LuaPlayer::KickPlayer }, + { "LogoutPlayer", &LuaPlayer::LogoutPlayer }, + { "SendTrainerList", &LuaPlayer::SendTrainerList }, + { "SendListInventory", &LuaPlayer::SendListInventory }, + { "SendShowBank", &LuaPlayer::SendShowBank }, + { "SendTabardVendorActivate", &LuaPlayer::SendTabardVendorActivate }, + { "SendSpiritResurrect", &LuaPlayer::SendSpiritResurrect }, + { "SendTaxiMenu", &LuaPlayer::SendTaxiMenu }, + { "SendUpdateWorldState", &LuaPlayer::SendUpdateWorldState }, + { "RewardQuest", &LuaPlayer::RewardQuest }, + { "SendAuctionMenu", &LuaPlayer::SendAuctionMenu }, + { "SendShowMailBox", &LuaPlayer::SendShowMailBox }, + { "StartTaxi", &LuaPlayer::StartTaxi }, + { "GossipSendPOI", &LuaPlayer::GossipSendPOI }, + { "GossipAddQuests", &LuaPlayer::GossipAddQuests }, + { "SendQuestTemplate", &LuaPlayer::SendQuestTemplate }, + { "SpawnBones", &LuaPlayer::SpawnBones }, + { "RemovedInsignia", &LuaPlayer::RemovedInsignia }, + { "SendGuildInvite", &LuaPlayer::SendGuildInvite }, + { "Mute", &LuaPlayer::Mute }, + { "SummonPlayer", &LuaPlayer::SummonPlayer }, + { "SaveToDB", &LuaPlayer::SaveToDB }, + { "GroupInvite", &LuaPlayer::GroupInvite }, + { "GroupCreate", &LuaPlayer::GroupCreate }, + { "SendCinematicStart", &LuaPlayer::SendCinematicStart }, +#if defined(CLASSIC) + { "UpdateHonor", &LuaPlayer::UpdateHonor }, + { "ResetHonor", &LuaPlayer::ResetHonor }, + { "ClearHonorInfo", &LuaPlayer::ClearHonorInfo }, +#endif +#ifndef CLASSIC + { "RemoveArenaSpellCooldowns", &LuaPlayer::RemoveArenaSpellCooldowns }, +#endif +#if (!defined(TBC) && !defined(CLASSIC)) + { "ResetPetTalents", &LuaPlayer::ResetPetTalents }, + { "ResetAchievements", &LuaPlayer::ResetAchievements }, + { "SendMovieStart", &LuaPlayer::SendMovieStart }, +#endif +#if defined(TBC) || defined(WOTLK) + { "ModifyHonorPoints", &LuaPlayer::ModifyHonorPoints }, + { "ModifyArenaPoints", &LuaPlayer::ModifyArenaPoints }, +#endif + + // Not implemented methods + { "GetChampioningFaction", nullptr }, // not implemented + { "GetRecruiterId", nullptr }, // not implemented + { "SetMovement", nullptr }, // not implemented + { "SetFFA", nullptr }, // not implemented + { "IsImmuneToEnvironmentalDamage", nullptr }, // not implemented + { "InRandomLfgDungeon", nullptr }, // not implemented + { "HasPendingBind", nullptr }, // not implemented + { "CanFlyInZone", nullptr }, // not implemented + { "IsNeverVisible", nullptr }, // not implemented, + { "IsUsingLfg", nullptr }, // not implemented, + { "HasReceivedQuestReward", nullptr }, // not implemented, + { "IsOutdoorPvPActive", nullptr }, // not implemented, + { "IsARecruiter", nullptr }, // not implemented, + { "RemovePet", nullptr }, // not implemented + { "SummonPet", nullptr }, // not implemented + { "RemoveActiveQuest", nullptr }, // not implemented + { "RemoveRewardedQuest", nullptr }, // not implemented + { "KilledPlayerCredit", nullptr }, // not implemented + { "KillGOCredit", nullptr }, // not implemented + { "GainSpellComboPoints", nullptr }, // not implemented + { "AddTalent", nullptr }, // not implemented + { "BindToInstance", nullptr }, // not implemented + { "SetAchievement", nullptr }, // not implemented + { "GetMailCount", nullptr }, // not implemented + { "GetXP", nullptr }, // not implemented + { "GetXPForNextLevel", nullptr }, // not implemented + { "CanCompleteRepeatableQuest", nullptr }, // not implemented + { "CanRewardQuest", nullptr }, // not implemented + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/QuestMethods.h b/src/modules/Eluna/Mangos/QuestMethods.h similarity index 88% rename from src/modules/Eluna/QuestMethods.h rename to src/modules/Eluna/Mangos/QuestMethods.h index 7ca026b9d6..31b7d79f07 100644 --- a/src/modules/Eluna/QuestMethods.h +++ b/src/modules/Eluna/Mangos/QuestMethods.h @@ -183,5 +183,30 @@ namespace LuaQuest Eluna::Push(L, quest->GetMaxLevel()); return 1; }*/ + + ElunaRegister QuestMethods[] = + { + // Getters + { "GetId", &LuaQuest::GetId }, + { "GetLevel", &LuaQuest::GetLevel }, + { "GetMinLevel", &LuaQuest::GetMinLevel }, + { "GetNextQuestId", &LuaQuest::GetNextQuestId }, + { "GetPrevQuestId", &LuaQuest::GetPrevQuestId }, + { "GetNextQuestInChain", &LuaQuest::GetNextQuestInChain }, + { "GetFlags", &LuaQuest::GetFlags }, + { "GetType", &LuaQuest::GetType }, + + // Boolean + { "HasFlag", &LuaQuest::HasFlag }, + { "IsRepeatable", &LuaQuest::IsRepeatable }, +#ifndef CLASSIC + { "IsDaily", &LuaQuest::IsDaily }, +#endif + + // Not implemented methods + { "GetMaxLevel", nullptr }, // not implemented + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/SpellMethods.h b/src/modules/Eluna/Mangos/SpellMethods.h similarity index 87% rename from src/modules/Eluna/SpellMethods.h rename to src/modules/Eluna/Mangos/SpellMethods.h index 2036c0084f..19e3855750 100644 --- a/src/modules/Eluna/SpellMethods.h +++ b/src/modules/Eluna/Mangos/SpellMethods.h @@ -189,5 +189,30 @@ namespace LuaSpell spell->finish(); return 0; } + + ElunaRegister SpellMethods[] = + { + // Getters + { "GetCaster", &LuaSpell::GetCaster }, + { "GetCastTime", &LuaSpell::GetCastTime }, + { "GetEntry", &LuaSpell::GetEntry }, + { "GetDuration", &LuaSpell::GetDuration }, + { "GetPowerCost", &LuaSpell::GetPowerCost }, + { "GetTargetDest", &LuaSpell::GetTargetDest }, + { "GetTarget", &LuaSpell::GetTarget }, + + // Setters + { "SetAutoRepeat", &LuaSpell::SetAutoRepeat }, + + // Boolean + { "IsAutoRepeat", &LuaSpell::IsAutoRepeat }, + + // Other + { "Cancel", &LuaSpell::Cancel }, + { "Cast", &LuaSpell::Cast }, + { "Finish", &LuaSpell::Finish }, + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/UnitMethods.h b/src/modules/Eluna/Mangos/UnitMethods.h similarity index 90% rename from src/modules/Eluna/UnitMethods.h rename to src/modules/Eluna/Mangos/UnitMethods.h index d6ca9abb93..355420b6ce 100644 --- a/src/modules/Eluna/UnitMethods.h +++ b/src/modules/Eluna/Mangos/UnitMethods.h @@ -1265,7 +1265,7 @@ namespace LuaUnit Acore::UnitListSearcher searcher(unit, list, checker); Cell::VisitAllObjects(unit, searcher, range); #elif CMANGOS - MaNGOS::AnyFriendlyUnitInObjectRangeCheck checker(unit, nullptr, range); + MaNGOS::AnyFriendlyUnitInObjectRangeCheck checker(unit, range); MaNGOS::UnitListSearcher searcher(list, checker); Cell::VisitGridObjects(unit, searcher, range); #else @@ -2465,7 +2465,7 @@ namespace LuaUnit return 0; #ifdef CMANGOS - unit->CastSpell(target, spell, TRIGGERED_OLD_TRIGGERED); + unit->CastSpell(target, spell, triggered ? TRIGGERED_OLD_TRIGGERED : 0); #else unit->CastSpell(target, spell, triggered); #endif @@ -2527,7 +2527,7 @@ namespace LuaUnit * @param float y * @param float z * @param uint32 spell : entry of a spell - * @param bool triggered = false : if true the spell is instant and has no cost + * @param bool triggered = true : if true the spell is instant and has no cost */ int CastSpellAoF(lua_State* L, Unit* unit) { @@ -2537,7 +2537,7 @@ namespace LuaUnit uint32 spell = Eluna::CHECKVAL(L, 5); bool triggered = Eluna::CHECKVAL(L, 6, true); #ifdef CMANGOS - unit->CastSpell(_x, _y, _z, spell, TRIGGERED_OLD_TRIGGERED); + unit->CastSpell(_x, _y, _z, spell, triggered ? TRIGGERED_OLD_TRIGGERED : 0); #endif #ifdef MANGOS unit->CastSpell(_x, _y, _z, spell, triggered); @@ -2645,10 +2645,11 @@ namespace LuaUnit for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) { -#ifndef CATA - uint8 eff = spellEntry->Effect[i]; +#if defined(CATA) + SpellEffectEntry const* effectEntry = spellEntry->GetSpellEffect(SpellEffectIndex(i)); + uint8 eff = effectEntry->Effect; #else - uint8 eff = SpellEffectIndex(0); + uint8 eff = spellEntry->Effect[i]; #endif #ifndef CMANGOS if (eff >= TOTAL_SPELL_EFFECTS) @@ -3114,5 +3115,194 @@ namespace LuaUnit Eluna::Push(L, summon); return 1; }*/ + + ElunaRegister UnitMethods[] = + { + // Getters + { "GetLevel", &LuaUnit::GetLevel }, + { "GetHealth", &LuaUnit::GetHealth }, + { "GetDisplayId", &LuaUnit::GetDisplayId }, + { "GetNativeDisplayId", &LuaUnit::GetNativeDisplayId }, + { "GetPower", &LuaUnit::GetPower }, + { "GetMaxPower", &LuaUnit::GetMaxPower }, + { "GetPowerType", &LuaUnit::GetPowerType }, + { "GetMaxHealth", &LuaUnit::GetMaxHealth }, + { "GetHealthPct", &LuaUnit::GetHealthPct }, + { "GetPowerPct", &LuaUnit::GetPowerPct }, + { "GetGender", &LuaUnit::GetGender }, + { "GetRace", &LuaUnit::GetRace }, + { "GetClass", &LuaUnit::GetClass }, + { "GetRaceMask", &LuaUnit::GetRaceMask }, + { "GetClassMask", &LuaUnit::GetClassMask }, + { "GetRaceAsString", &LuaUnit::GetRaceAsString }, + { "GetClassAsString", &LuaUnit::GetClassAsString }, + { "GetAura", &LuaUnit::GetAura }, + { "GetFaction", &LuaUnit::GetFaction }, + { "GetCurrentSpell", &LuaUnit::GetCurrentSpell }, + { "GetCreatureType", &LuaUnit::GetCreatureType }, + { "GetMountId", &LuaUnit::GetMountId }, + { "GetOwner", &LuaUnit::GetOwner }, + { "GetFriendlyUnitsInRange", &LuaUnit::GetFriendlyUnitsInRange }, + { "GetUnfriendlyUnitsInRange", &LuaUnit::GetUnfriendlyUnitsInRange }, + { "GetOwnerGUID", &LuaUnit::GetOwnerGUID }, + { "GetCreatorGUID", &LuaUnit::GetCreatorGUID }, + { "GetMinionGUID", &LuaUnit::GetPetGUID }, + { "GetCharmerGUID", &LuaUnit::GetCharmerGUID }, + { "GetCharmGUID", &LuaUnit::GetCharmGUID }, + { "GetPetGUID", &LuaUnit::GetPetGUID }, + { "GetControllerGUID", &LuaUnit::GetControllerGUID }, + { "GetControllerGUIDS", &LuaUnit::GetControllerGUIDS }, + { "GetStandState", &LuaUnit::GetStandState }, + { "GetVictim", &LuaUnit::GetVictim }, + { "GetSpeed", &LuaUnit::GetSpeed }, + { "GetStat", &LuaUnit::GetStat }, + { "GetBaseSpellPower", &LuaUnit::GetBaseSpellPower }, + { "GetMovementType", &LuaUnit::GetMovementType }, +#if (!defined(TBC) && !defined(CLASSIC)) + { "GetVehicleKit", &LuaUnit::GetVehicleKit }, + { "GetCritterGUID", &LuaUnit::GetCritterGUID }, +#endif + + // Setters + { "SetFaction", &LuaUnit::SetFaction }, + { "SetLevel", &LuaUnit::SetLevel }, + { "SetHealth", &LuaUnit::SetHealth }, + { "SetMaxHealth", &LuaUnit::SetMaxHealth }, + { "SetPower", &LuaUnit::SetPower }, + { "SetMaxPower", &LuaUnit::SetMaxPower }, + { "SetPowerType", &LuaUnit::SetPowerType }, + { "SetDisplayId", &LuaUnit::SetDisplayId }, + { "SetNativeDisplayId", &LuaUnit::SetNativeDisplayId }, + { "SetFacing", &LuaUnit::SetFacing }, + { "SetFacingToObject", &LuaUnit::SetFacingToObject }, + { "SetSpeed", &LuaUnit::SetSpeed }, + { "SetRooted", &LuaUnit::SetRooted}, + { "SetConfused", &LuaUnit::SetConfused}, + { "SetFeared", &LuaUnit::SetFeared}, + { "SetPvP", &LuaUnit::SetPvP }, + { "SetOwnerGUID", &LuaUnit::SetOwnerGUID }, + { "SetName", &LuaUnit::SetName }, + { "SetSheath", &LuaUnit::SetSheath }, + { "SetCreatorGUID", &LuaUnit::SetCreatorGUID }, + { "SetMinionGUID", &LuaUnit::SetPetGUID }, + { "SetPetGUID", &LuaUnit::SetPetGUID }, + { "SetWaterWalk", &LuaUnit::SetWaterWalk }, + { "SetStandState", &LuaUnit::SetStandState }, + { "SetInCombatWith", &LuaUnit::SetInCombatWith }, + { "ModifyPower", &LuaUnit::ModifyPower }, +#if (!defined(TBC) && !defined(CLASSIC)) + { "SetFFA", &LuaUnit::SetFFA }, + { "SetSanctuary", &LuaUnit::SetSanctuary }, + { "SetCritterGUID", &LuaUnit::SetCritterGUID }, +#endif + + // Boolean + { "IsAlive", &LuaUnit::IsAlive }, + { "IsDead", &LuaUnit::IsDead }, + { "IsDying", &LuaUnit::IsDying }, + { "IsPvPFlagged", &LuaUnit::IsPvPFlagged }, + { "IsInCombat", &LuaUnit::IsInCombat }, + { "IsBanker", &LuaUnit::IsBanker }, + { "IsBattleMaster", &LuaUnit::IsBattleMaster }, + { "IsCharmed", &LuaUnit::IsCharmed }, + { "IsArmorer", &LuaUnit::IsArmorer }, + { "IsAttackingPlayer", &LuaUnit::IsAttackingPlayer }, + { "IsInWater", &LuaUnit::IsInWater }, + { "IsUnderWater", &LuaUnit::IsUnderWater }, + { "IsAuctioneer", &LuaUnit::IsAuctioneer }, + { "IsGuildMaster", &LuaUnit::IsGuildMaster }, + { "IsInnkeeper", &LuaUnit::IsInnkeeper }, + { "IsTrainer", &LuaUnit::IsTrainer }, + { "IsGossip", &LuaUnit::IsGossip }, + { "IsTaxi", &LuaUnit::IsTaxi }, + { "IsSpiritHealer", &LuaUnit::IsSpiritHealer }, + { "IsSpiritGuide", &LuaUnit::IsSpiritGuide }, + { "IsTabardDesigner", &LuaUnit::IsTabardDesigner }, + { "IsServiceProvider", &LuaUnit::IsServiceProvider }, + { "IsSpiritService", &LuaUnit::IsSpiritService }, + { "HealthBelowPct", &LuaUnit::HealthBelowPct }, + { "HealthAbovePct", &LuaUnit::HealthAbovePct }, + { "IsMounted", &LuaUnit::IsMounted }, + { "AttackStop", &LuaUnit::AttackStop }, + { "Attack", &LuaUnit::Attack }, + { "IsStopped", &LuaUnit::IsStopped }, + { "HasUnitState", &LuaUnit::HasUnitState }, + { "IsQuestGiver", &LuaUnit::IsQuestGiver }, + { "IsInAccessiblePlaceFor", &LuaUnit::IsInAccessiblePlaceFor }, + { "IsVendor", &LuaUnit::IsVendor }, + { "IsRooted", &LuaUnit::IsRooted }, + { "IsFullHealth", &LuaUnit::IsFullHealth }, + { "HasAura", &LuaUnit::HasAura }, + { "IsCasting", &LuaUnit::IsCasting }, + { "IsStandState", &LuaUnit::IsStandState }, +#if !defined(CLASSIC) + { "IsOnVehicle", &LuaUnit::IsOnVehicle }, +#endif + + // Other + { "AddAura", &LuaUnit::AddAura }, + { "RemoveAura", &LuaUnit::RemoveAura }, + { "RemoveAllAuras", &LuaUnit::RemoveAllAuras }, + { "ClearInCombat", &LuaUnit::ClearInCombat }, + { "DeMorph", &LuaUnit::DeMorph }, + { "SendUnitWhisper", &LuaUnit::SendUnitWhisper }, + { "SendUnitEmote", &LuaUnit::SendUnitEmote }, + { "SendUnitSay", &LuaUnit::SendUnitSay }, + { "SendUnitYell", &LuaUnit::SendUnitYell }, + { "CastSpell", &LuaUnit::CastSpell }, + { "CastCustomSpell", &LuaUnit::CastCustomSpell }, + { "CastSpellAoF", &LuaUnit::CastSpellAoF }, + { "Kill", &LuaUnit::Kill }, + { "StopSpellCast", &LuaUnit::StopSpellCast }, + { "InterruptSpell", &LuaUnit::InterruptSpell }, + { "SendChatMessageToPlayer", &LuaUnit::SendChatMessageToPlayer }, + { "PerformEmote", &LuaUnit::PerformEmote }, + { "EmoteState", &LuaUnit::EmoteState }, + { "CountPctFromCurHealth", &LuaUnit::CountPctFromCurHealth }, + { "CountPctFromMaxHealth", &LuaUnit::CountPctFromMaxHealth }, + { "Dismount", &LuaUnit::Dismount }, + { "Mount", &LuaUnit::Mount }, + { "ClearThreatList", &LuaUnit::ClearThreatList }, + { "ClearUnitState", &LuaUnit::ClearUnitState }, + { "AddUnitState", &LuaUnit::AddUnitState }, + { "NearTeleport", &LuaUnit::NearTeleport }, + { "MoveIdle", &LuaUnit::MoveIdle }, + { "MoveRandom", &LuaUnit::MoveRandom }, + { "MoveHome", &LuaUnit::MoveHome }, + { "MoveFollow", &LuaUnit::MoveFollow }, + { "MoveChase", &LuaUnit::MoveChase }, + { "MoveConfused", &LuaUnit::MoveConfused }, + { "MoveFleeing", &LuaUnit::MoveFleeing }, + { "MoveTo", &LuaUnit::MoveTo }, + { "MoveStop", &LuaUnit::MoveStop }, + { "MoveExpire", &LuaUnit::MoveExpire }, + { "MoveClear", &LuaUnit::MoveClear }, + { "DealDamage", &LuaUnit::DealDamage }, + { "DealHeal", &LuaUnit::DealHeal }, + { "AddThreat", &LuaUnit::AddThreat }, +#if !defined(CLASSIC) + { "RemoveArenaAuras", &LuaUnit::RemoveArenaAuras }, +#endif +#if (!defined(TBC) && !defined(CLASSIC)) + { "MoveJump", &LuaUnit::MoveJump }, +#endif + + // Not implemented mehtods + { "GetVehicle", nullptr }, // not implemented + { "SetStunned", nullptr }, // not implemented + { "SetCanFly", nullptr }, // not implemented + { "SetVisible", nullptr }, // not implemented + { "IsVisible", nullptr }, // not implemented, + { "IsMoving", nullptr }, // not implemented + { "IsFlying", nullptr }, // not implemented + { "RestoreDisplayId", nullptr }, // not implemented + { "RestoreFaction", nullptr }, // not implemented + { "RemoveBindSightAuras", nullptr }, // not implemented + { "RemoveCharmAuras", nullptr }, // not implemented + { "DisableMelee", nullptr }, // not implemented + { "SummonGuardian", nullptr }, // not implemented + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/VehicleMethods.h b/src/modules/Eluna/Mangos/VehicleMethods.h similarity index 85% rename from src/modules/Eluna/VehicleMethods.h rename to src/modules/Eluna/Mangos/VehicleMethods.h index 3bbfea5d77..628e7175c1 100644 --- a/src/modules/Eluna/VehicleMethods.h +++ b/src/modules/Eluna/Mangos/VehicleMethods.h @@ -110,6 +110,23 @@ namespace LuaVehicle #endif return 0; } + + ElunaRegister VehicleMethods[] = + { + // Getters + { "GetOwner", &LuaVehicle::GetOwner }, + { "GetEntry", &LuaVehicle::GetEntry }, + { "GetPassenger", &LuaVehicle::GetPassenger }, + + // Boolean + { "IsOnBoard", &LuaVehicle::IsOnBoard }, + + // Other + { "AddPassenger", &LuaVehicle::AddPassenger }, + { "RemovePassenger", &LuaVehicle::RemovePassenger }, + + { NULL, NULL } + }; } #endif // CLASSIC diff --git a/src/modules/Eluna/WorldObjectMethods.h b/src/modules/Eluna/Mangos/WorldObjectMethods.h similarity index 93% rename from src/modules/Eluna/WorldObjectMethods.h rename to src/modules/Eluna/Mangos/WorldObjectMethods.h index de6a27312a..deb6c49a80 100644 --- a/src/modules/Eluna/WorldObjectMethods.h +++ b/src/modules/Eluna/Mangos/WorldObjectMethods.h @@ -1237,5 +1237,65 @@ namespace LuaWorldObject obj->PlayDistanceSound(soundId); return 0; } + + ElunaRegister WorldObjectMethods[] = + { + // Getters + { "GetName", &LuaWorldObject::GetName }, + { "GetMap", &LuaWorldObject::GetMap }, +#if (!defined(TBC) && !defined(CLASSIC)) + { "GetPhaseMask", &LuaWorldObject::GetPhaseMask }, + { "SetPhaseMask", &LuaWorldObject::SetPhaseMask }, +#endif + { "GetInstanceId", &LuaWorldObject::GetInstanceId }, + { "GetAreaId", &LuaWorldObject::GetAreaId }, + { "GetZoneId", &LuaWorldObject::GetZoneId }, + { "GetMapId", &LuaWorldObject::GetMapId }, + { "GetX", &LuaWorldObject::GetX }, + { "GetY", &LuaWorldObject::GetY }, + { "GetZ", &LuaWorldObject::GetZ }, + { "GetO", &LuaWorldObject::GetO }, + { "GetLocation", &LuaWorldObject::GetLocation }, + { "GetPlayersInRange", &LuaWorldObject::GetPlayersInRange }, + { "GetCreaturesInRange", &LuaWorldObject::GetCreaturesInRange }, + { "GetGameObjectsInRange", &LuaWorldObject::GetGameObjectsInRange }, + { "GetNearestPlayer", &LuaWorldObject::GetNearestPlayer }, + { "GetNearestGameObject", &LuaWorldObject::GetNearestGameObject }, + { "GetNearestCreature", &LuaWorldObject::GetNearestCreature }, + { "GetNearObject", &LuaWorldObject::GetNearObject }, + { "GetNearObjects", &LuaWorldObject::GetNearObjects }, + { "GetDistance", &LuaWorldObject::GetDistance }, + { "GetExactDistance", &LuaWorldObject::GetExactDistance }, + { "GetDistance2d", &LuaWorldObject::GetDistance2d }, + { "GetExactDistance2d", &LuaWorldObject::GetExactDistance2d }, + { "GetRelativePoint", &LuaWorldObject::GetRelativePoint }, + { "GetAngle", &LuaWorldObject::GetAngle }, + + // Boolean + { "IsWithinLoS", &LuaWorldObject::IsWithinLoS }, + { "IsInMap", &LuaWorldObject::IsInMap }, + { "IsWithinDist3d", &LuaWorldObject::IsWithinDist3d }, + { "IsWithinDist2d", &LuaWorldObject::IsWithinDist2d }, + { "IsWithinDist", &LuaWorldObject::IsWithinDist }, + { "IsWithinDistInMap", &LuaWorldObject::IsWithinDistInMap }, + { "IsInRange", &LuaWorldObject::IsInRange }, + { "IsInRange2d", &LuaWorldObject::IsInRange2d }, + { "IsInRange3d", &LuaWorldObject::IsInRange3d }, + { "IsInFront", &LuaWorldObject::IsInFront }, + { "IsInBack", &LuaWorldObject::IsInBack }, + + // Other + { "SummonGameObject", &LuaWorldObject::SummonGameObject }, + { "SpawnCreature", &LuaWorldObject::SpawnCreature }, + { "SendPacket", &LuaWorldObject::SendPacket }, + { "RegisterEvent", &LuaWorldObject::RegisterEvent }, + { "RemoveEventById", &LuaWorldObject::RemoveEventById }, + { "RemoveEvents", &LuaWorldObject::RemoveEvents }, + { "PlayMusic", &LuaWorldObject::PlayMusic }, + { "PlayDirectSound", &LuaWorldObject::PlayDirectSound }, + { "PlayDistanceSound", &LuaWorldObject::PlayDistanceSound }, + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/WorldPacketMethods.h b/src/modules/Eluna/Mangos/WorldPacketMethods.h similarity index 86% rename from src/modules/Eluna/WorldPacketMethods.h rename to src/modules/Eluna/Mangos/WorldPacketMethods.h index fbe27919a4..8eaddba6d4 100644 --- a/src/modules/Eluna/WorldPacketMethods.h +++ b/src/modules/Eluna/Mangos/WorldPacketMethods.h @@ -309,6 +309,42 @@ namespace LuaPacket (*packet) << _val; return 0; } + + ElunaRegister PacketMethods[] = + { + // Getters + { "GetOpcode", &LuaPacket::GetOpcode }, + { "GetSize", &LuaPacket::GetSize }, + + // Setters + { "SetOpcode", &LuaPacket::SetOpcode }, + + // Readers + { "ReadByte", &LuaPacket::ReadByte }, + { "ReadUByte", &LuaPacket::ReadUByte }, + { "ReadShort", &LuaPacket::ReadShort }, + { "ReadUShort", &LuaPacket::ReadUShort }, + { "ReadLong", &LuaPacket::ReadLong }, + { "ReadULong", &LuaPacket::ReadULong }, + { "ReadGUID", &LuaPacket::ReadGUID }, + { "ReadString", &LuaPacket::ReadString }, + { "ReadFloat", &LuaPacket::ReadFloat }, + { "ReadDouble", &LuaPacket::ReadDouble }, + + // Writers + { "WriteByte", &LuaPacket::WriteByte }, + { "WriteUByte", &LuaPacket::WriteUByte }, + { "WriteShort", &LuaPacket::WriteShort }, + { "WriteUShort", &LuaPacket::WriteUShort }, + { "WriteLong", &LuaPacket::WriteLong }, + { "WriteULong", &LuaPacket::WriteULong }, + { "WriteGUID", &LuaPacket::WriteGUID }, + { "WriteString", &LuaPacket::WriteString }, + { "WriteFloat", &LuaPacket::WriteFloat }, + { "WriteDouble", &LuaPacket::WriteDouble }, + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/PacketHooks.cpp b/src/modules/Eluna/PacketHooks.cpp index d11f3fa056..eb1610abd9 100644 --- a/src/modules/Eluna/PacketHooks.cpp +++ b/src/modules/Eluna/PacketHooks.cpp @@ -106,7 +106,13 @@ void Eluna::OnPacketReceiveAny(Player* player, WorldPacket& packet, bool& result if (lua_isuserdata(L, r + 1)) if (WorldPacket* data = CHECKOBJ(L, r + 1, false)) + { +#ifdef VMANGOS + packet = std::move(*data); +#else packet = *data; +#endif + } lua_pop(L, 2); } @@ -130,7 +136,13 @@ void Eluna::OnPacketReceiveOne(Player* player, WorldPacket& packet, bool& result if (lua_isuserdata(L, r + 1)) if (WorldPacket* data = CHECKOBJ(L, r + 1, false)) + { +#ifdef VMANGOS + packet = std::move(*data); +#else packet = *data; +#endif + } lua_pop(L, 2); } diff --git a/src/modules/Eluna/PlayerHooks.cpp b/src/modules/Eluna/PlayerHooks.cpp index 0ef56f6d6b..32d3a83776 100644 --- a/src/modules/Eluna/PlayerHooks.cpp +++ b/src/modules/Eluna/PlayerHooks.cpp @@ -39,6 +39,40 @@ void Eluna::OnLearnTalents(Player* pPlayer, uint32 talentId, uint32 talentRank, CallAllFunctions(PlayerEventBindings, key); } +void Eluna::OnSkillChange(Player* pPlayer, uint32 skillId, uint32 skillValue) +{ + START_HOOK(PLAYER_EVENT_ON_SKILL_CHANGE); + Push(pPlayer); + Push(skillId); + Push(skillValue); + int valueIndex = lua_gettop(L) - 1; + int n = SetupStack(PlayerEventBindings, key, 3); + + while (n > 0) + { + int r = CallOneFunction(n--, 3, 1); + + if (lua_isnumber(L, r)) + { + skillValue = CHECKVAL(L, r); + // Update the stack for subsequent calls. + ReplaceArgument(skillValue, valueIndex); + } + + lua_pop(L, 1); + } + + CleanUpStack(3); +} + +void Eluna::OnLearnSpell(Player* pPlayer, uint32 spellId) +{ + START_HOOK(PLAYER_EVENT_ON_LEARN_SPELL); + Push(pPlayer); + Push(spellId); + CallAllFunctions(PlayerEventBindings, key); +} + bool Eluna::OnCommand(Player* player, const char* text) { // If from console, player is NULL @@ -106,6 +140,15 @@ void Eluna::OnQuestAbandon(Player* pPlayer, uint32 questId) CallAllFunctions(PlayerEventBindings, key); } +void Eluna::OnQuestStatusChanged(Player* pPlayer, uint32 questId, uint8 status) +{ + START_HOOK(PLAYER_EVENT_ON_QUEST_STATUS_CHANGED); + Push(pPlayer); + Push(questId); + Push(status); + CallAllFunctions(PlayerEventBindings, key); +} + void Eluna::OnEquip(Player* pPlayer, Item* pItem, uint8 bag, uint8 slot) { START_HOOK(PLAYER_EVENT_ON_EQUIP); @@ -176,6 +219,14 @@ void Eluna::OnPlayerKilledByCreature(Creature* pKiller, Player* pKilled) CallAllFunctions(PlayerEventBindings, key); } +void Eluna::OnPlayerKilledByEnvironment(Player* pKilled, uint8 damageType) +{ + START_HOOK(PLAYER_EVENT_ON_ENVIRONMENTAL_DEATH); + Push(pKilled); + Push(damageType); + CallAllFunctions(PlayerEventBindings, key); +} + void Eluna::OnLevelChanged(Player* pPlayer, uint8 oldLevel) { START_HOOK(PLAYER_EVENT_ON_LEVEL_CHANGE); @@ -225,6 +276,33 @@ void Eluna::OnMoneyChanged(Player* pPlayer, int32& amount) CleanUpStack(2); } +#ifdef CATA +void Eluna::OnMoneyChanged(Player* pPlayer, int64& amount) +{ + START_HOOK(PLAYER_EVENT_ON_MONEY_CHANGE); + Push(pPlayer); + Push(amount); + int amountIndex = lua_gettop(L); + int n = SetupStack(PlayerEventBindings, key, 2); + + while (n > 0) + { + int r = CallOneFunction(n--, 2, 1); + + if (lua_isnumber(L, r)) + { + amount = CHECKVAL(L, r); + // Update the stack for subsequent calls. + ReplaceArgument(amount, amountIndex); + } + + lua_pop(L, 1); + } + + CleanUpStack(2); +} +#endif + void Eluna::OnGiveXP(Player* pPlayer, uint32& amount, Unit* pVictim) { START_HOOK(PLAYER_EVENT_ON_GIVE_XP); @@ -384,6 +462,15 @@ void Eluna::OnUpdateZone(Player* pPlayer, uint32 newZone, uint32 newArea) CallAllFunctions(PlayerEventBindings, key); } +void Eluna::OnUpdateArea(Player* pPlayer, uint32 oldArea, uint32 newArea) +{ + START_HOOK(PLAYER_EVENT_ON_UPDATE_AREA); + Push(pPlayer); + Push(oldArea); + Push(newArea); + CallAllFunctions(PlayerEventBindings, key); +} + void Eluna::OnMapChanged(Player* player) { START_HOOK(PLAYER_EVENT_ON_MAP_CHANGE); @@ -391,6 +478,38 @@ void Eluna::OnMapChanged(Player* player) CallAllFunctions(PlayerEventBindings, key); } +void Eluna::OnAchievementComplete(Player* player, uint32 achievementId) +{ + START_HOOK(PLAYER_EVENT_ON_ACHIEVEMENT_COMPLETE); + Push(player); + Push(achievementId); + CallAllFunctions(PlayerEventBindings, key); +} + +bool Eluna::OnTradeInit(Player* trader, Player* tradee) +{ + START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_TRADE_INIT, true); + Push(trader); + Push(tradee); + return CallAllFunctionsBool(PlayerEventBindings, key, true); +} + +bool Eluna::OnTradeAccept(Player* trader, Player* tradee) +{ + START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_TRADE_ACCEPT, true); + Push(trader); + Push(tradee); + return CallAllFunctionsBool(PlayerEventBindings, key, true); +} + +bool Eluna::OnSendMail(Player* sender, ObjectGuid recipientGuid) +{ + START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_SEND_MAIL, true); + Push(sender); + Push(recipientGuid); + return CallAllFunctionsBool(PlayerEventBindings, key, true); +} + bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg) { if (lang == LANG_ADDON) diff --git a/src/modules/Eluna/README.md b/src/modules/Eluna/README.md index 51c6c8dac3..8cd1a97a85 100644 --- a/src/modules/Eluna/README.md +++ b/src/modules/Eluna/README.md @@ -3,7 +3,7 @@ ## About Eluna Lua Engine © is a lua engine embedded to World of Warcraft emulators. Eluna supports MaNGOS, CMaNGOS, TrinityCore and AzerothCore. -We are currently working hard to make Eluna better from inside and outside. +We are currently working hard to make Eluna better from inside and outside. If you are having trouble with installation or scripts, please feel free to open an issue. For documentation and reference see [Eluna API](http://elunaluaengine.github.io/) and [Lua reference manual](http://www.lua.org/manual/5.2/). @@ -32,21 +32,22 @@ You can join the official Eluna Discord server, where you'll be able to find res ## Source Eluna source code: [Source](https://github.com/ElunaLuaEngine/Eluna) -Core forks with required modifications for Eluna: -[![Build Status](https://api.travis-ci.org/mangoszero/server.svg)](https://travis-ci.org/mangoszero/server) [Official MaNGOS Zero with Eluna](https://github.com/mangoszero/server) -[![Build Status](https://api.travis-ci.org/mangosone/server.svg)](https://travis-ci.org/mangosone/server) [Official MaNGOS One with Eluna](https://github.com/mangosone/server) -[![Build Status](https://api.travis-ci.org/mangostwo/server.svg)](https://travis-ci.org/mangostwo/server) [Official MaNGOS Two with Eluna](https://github.com/mangostwo/server) +Core sources and forks with required modifications for Eluna: -[![Build Status](https://travis-ci.org/ElunaLuaEngine/ElunaTrinityWotlk.png?branch=master)](https://travis-ci.org/ElunaLuaEngine/ElunaTrinityWotlk) [Eluna TrinityCore WotLK](https://github.com/ElunaLuaEngine/ElunaTrinityWotlk) +[TrinityCore WotLK](https://github.com/ElunaLuaEngine/ElunaTrinityWotlk) [![automerge](https://github.com/ElunaLuaEngine/ElunaTrinityWotlk/actions/workflows/auto-merge.yml/badge.svg)](https://github.com/ElunaLuaEngine/ElunaTrinityWotlk/actions/workflows/auto-merge.yml) -[Eluna cMaNGOS Classic](https://github.com/Niam5/Eluna-CMaNGOS-Classic) - maintained by [Niam5](https://github.com/Niam5) -[Eluna cMaNGOS TBC](https://github.com/Niam5/Eluna-CMaNGOS-TBC) - maintained by [Niam5](https://github.com/Niam5) -[Eluna cMaNGOS WoTLK](https://github.com/Niam5/Eluna-CMaNGOS-WotLK) - maintained by [Niam5](https://github.com/Niam5) +[Official MaNGOS Zero with Eluna](https://github.com/mangoszero/server) +[Official MaNGOS One with Eluna](https://github.com/mangosone/server) +[Official MaNGOS Two with Eluna](https://github.com/mangostwo/server) -Core plugin modules for Eluna: +[Eluna cMaNGOS Classic](https://github.com/Niam5/Eluna-CMaNGOS-Classic) - maintained by [Niam5](https://github.com/Niam5) +[Eluna cMaNGOS TBC](https://github.com/Niam5/Eluna-CMaNGOS-TBC) - maintained by [Niam5](https://github.com/Niam5) +[Eluna cMaNGOS WoTLK](https://github.com/Niam5/Eluna-CMaNGOS-WotLK) - maintained by [Niam5](https://github.com/Niam5) -- [AzerothCore Eluna Module](https://github.com/azerothcore/mod-eluna-lua-engine) +[AzerothCore Eluna Module](https://github.com/azerothcore/mod-eluna) + +[Cataclysm Preservation Project](https://github.com/Niam5/ElunaCataPreservation) - maintained by [Niam5](https://github.com/Niam5) ## Links diff --git a/src/modules/Eluna/ServerHooks.cpp b/src/modules/Eluna/ServerHooks.cpp index 537bedb85c..de36faf919 100644 --- a/src/modules/Eluna/ServerHooks.cpp +++ b/src/modules/Eluna/ServerHooks.cpp @@ -122,7 +122,7 @@ bool Eluna::OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* pTrigger) Push(pTrigger->entry); #else Push(pTrigger->id); - + #endif return CallAllFunctionsBool(ServerEventBindings, key); } diff --git a/src/modules/Eluna/TrinityCore/AuraMethods.h b/src/modules/Eluna/TrinityCore/AuraMethods.h new file mode 100644 index 0000000000..d8add26853 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/AuraMethods.h @@ -0,0 +1,195 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef AURAMETHODS_H +#define AURAMETHODS_H + +/*** + * The persistent effect of a [Spell] that remains on a [Unit] after the [Spell] + * has been cast. + * + * As an example, if you cast a damage-over-time spell on a target, an [Aura] is + * put on the target that deals damage continuously. + * + * [Aura]s on your player are displayed in-game as a series of icons to the left + * of the mini-map. + * + * Inherits all methods from: none + */ +namespace LuaAura +{ + /** + * Returns the [Unit] that casted the [Spell] that caused this [Aura] to be applied. + * + * @return [Unit] caster + */ + int GetCaster(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetCaster()); + return 1; + } + + /** + * Returns the GUID of the [Unit] that casted the [Spell] that caused this [Aura] to be applied. + * + * @return string caster_guid : the GUID of the Unit as a decimal string + */ + int GetCasterGUID(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetCasterGUID()); + return 1; + } + + /** + * Returns the level of the [Unit] that casted the [Spell] that caused this [Aura] to be applied. + * + * @return uint32 caster_level + */ + int GetCasterLevel(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetCaster()->GetLevel()); + return 1; + } + + /** + * Returns the amount of time left until the [Aura] expires. + * + * @return int32 duration : amount of time left in milliseconds + */ + int GetDuration(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetDuration()); + return 1; + } + + /** + * Returns the ID of the [Spell] that caused this [Aura] to be applied. + * + * @return uint32 aura_id + */ + int GetAuraId(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetId()); + return 1; + } + + /** + * Returns the amount of time this [Aura] lasts when applied. + * + * To determine how much time has passed since this Aura was applied, + * subtract the result of [Aura]:GetDuration from the result of this method. + * + * @return int32 max_duration : the maximum duration of the Aura, in milliseconds + */ + int GetMaxDuration(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetMaxDuration()); + return 1; + } + + /** + * Returns the number of times the [Aura] has "stacked". + * + * This is the same as the number displayed on the [Aura]'s icon in-game. + * + * @return uint32 stack_amount + */ + int GetStackAmount(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetStackAmount()); + return 1; + } + + /** + * Returns the [Unit] that the [Aura] has been applied to. + * + * @return [Unit] owner + */ + int GetOwner(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetOwner()); + return 1; + } + + /** + * Change the amount of time before the [Aura] expires. + * + * @param int32 duration : the new duration of the Aura, in milliseconds + */ + int SetDuration(lua_State* L, Aura* aura) + { + int32 duration = Eluna::CHECKVAL(L, 2); + + aura->SetDuration(duration); + return 0; + } + + /** + * Change the maximum amount of time before the [Aura] expires. + * + * This does not affect the current duration of the [Aura], but if the [Aura] + * is reset to the maximum duration, it will instead change to `duration`. + * + * @param int32 duration : the new maximum duration of the Aura, in milliseconds + */ + int SetMaxDuration(lua_State* L, Aura* aura) + { + int32 duration = Eluna::CHECKVAL(L, 2); + + aura->SetMaxDuration(duration); + return 0; + } + + /** + * Change the amount of times the [Aura] has "stacked" on the [Unit]. + * + * If `amount` is greater than or equal to the current number of stacks, + * then the [Aura] has its duration reset to the maximum duration. + * + * @param uint32 amount + */ + int SetStackAmount(lua_State* L, Aura* aura) + { + uint8 amount = Eluna::CHECKVAL(L, 2); + + aura->SetStackAmount(amount); + return 0; + } + + /** + * Remove this [Aura] from the [Unit] it is applied to. + */ + int Remove(lua_State* L, Aura* aura) + { + aura->Remove(); + Eluna::CHECKOBJ(L, 1)->Invalidate(); + return 0; + } + + ElunaRegister AuraMethods[] = + { + // Getters + { "GetCaster", &LuaAura::GetCaster }, + { "GetCasterGUID", &LuaAura::GetCasterGUID }, + { "GetCasterLevel", &LuaAura::GetCasterLevel }, + { "GetDuration", &LuaAura::GetDuration }, + { "GetMaxDuration", &LuaAura::GetMaxDuration }, + { "GetAuraId", &LuaAura::GetAuraId }, + { "GetStackAmount", &LuaAura::GetStackAmount }, + { "GetOwner", &LuaAura::GetOwner }, + + // Setters + { "SetDuration", &LuaAura::SetDuration }, + { "SetMaxDuration", &LuaAura::SetMaxDuration }, + { "SetStackAmount", &LuaAura::SetStackAmount }, + + // Other + { "Remove", &LuaAura::Remove }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/BattleGroundMethods.h b/src/modules/Eluna/TrinityCore/BattleGroundMethods.h new file mode 100644 index 0000000000..6ce153d821 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/BattleGroundMethods.h @@ -0,0 +1,253 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef BATTLEGROUNDMETHODS_H +#define BATTLEGROUNDMETHODS_H + +/*** + * Contains the state of a battleground, e.g. Warsong Gulch, Arathi Basin, etc. + * + * Inherits all methods from: none + */ +namespace LuaBattleGround +{ + /** + * Returns the name of the [BattleGround]. + * + * @return string name + */ + int GetName(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetName()); + return 1; + } + + /** + * Returns the amount of alive players in the [BattleGround] by the team ID. + * + * @param [Team] team : team ID + * @return uint32 count + */ + int GetAlivePlayersCountByTeam(lua_State* L, BattleGround* bg) + { + uint32 team = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, bg->GetAlivePlayersCountByTeam((Team)team)); + return 1; + } + + /** + * Returns the [Map] of the [BattleGround]. + * + * @return [Map] map + */ + int GetMap(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, static_cast(bg->GetBgMap())); + return 1; + } + + /** + * Returns the bonus honor given by amount of kills in the specific [BattleGround]. + * + * @param uint32 kills : amount of kills + * @return uint32 bonusHonor + */ + int GetBonusHonorFromKillCount(lua_State* L, BattleGround* bg) + { + uint32 kills = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, bg->GetBonusHonorFromKill(kills)); + return 1; + } + + /** + * Returns the bracket ID of the specific [BattleGround]. + * + * @return [BattleGroundBracketId] bracketId + */ + int GetBracketId(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetBracketId()); + return 1; + } + + /** + * Returns the end time of the [BattleGround]. + * + * @return uint32 endTime + */ + int GetEndTime(lua_State* L, BattleGround* bg) + { +#ifdef CATA + Eluna::Push(L, bg->GetRemainingTime()); +#else + Eluna::Push(L, bg->GetEndTime()); +#endif + return 1; + } + + /** + * Returns the amount of free slots for the selected team in the specific [BattleGround]. + * + * @param [Team] team : team ID + * @return uint32 freeSlots + */ + int GetFreeSlotsForTeam(lua_State* L, BattleGround* bg) + { + uint32 team = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, bg->GetFreeSlotsForTeam((Team)team)); + return 1; + } + + /** + * Returns the instance ID of the [BattleGround]. + * + * @return uint32 instanceId + */ + int GetInstanceId(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetInstanceID()); + return 1; + } + + /** + * Returns the map ID of the [BattleGround]. + * + * @return uint32 mapId + */ + int GetMapId(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMapId()); + return 1; + } + + /** + * Returns the type ID of the [BattleGround]. + * + * @return [BattleGroundTypeId] typeId + */ + int GetTypeId(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetTypeID()); + return 1; + } + + /** + * Returns the max allowed [Player] level of the specific [BattleGround]. + * + * @return uint32 maxLevel + */ + int GetMaxLevel(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMaxLevel()); + return 1; + } + + /** + * Returns the minimum allowed [Player] level of the specific [BattleGround]. + * + * @return uint32 minLevel + */ + int GetMinLevel(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMinLevel()); + return 1; + } + + /** + * Returns the maximum allowed [Player] count of the specific [BattleGround]. + * + * @return uint32 maxPlayerCount + */ + int GetMaxPlayers(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMaxPlayers()); + return 1; + } + + /** + * Returns the minimum allowed [Player] count of the specific [BattleGround]. + * + * @return uint32 minPlayerCount + */ + int GetMinPlayers(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMinPlayers()); + return 1; + } + + /** + * Returns the maximum allowed [Player] count per team of the specific [BattleGround]. + * + * @return uint32 maxTeamPlayerCount + */ + int GetMaxPlayersPerTeam(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMaxPlayersPerTeam()); + return 1; + } + + /** + * Returns the minimum allowed [Player] count per team of the specific [BattleGround]. + * + * @return uint32 minTeamPlayerCount + */ + int GetMinPlayersPerTeam(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetMinPlayersPerTeam()); + return 1; + } + + /** + * Returns the winning team of the specific [BattleGround]. + * + * @return [Team] team + */ + int GetWinner(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetWinner()); + return 1; + } + + /** + * Returns the status of the specific [BattleGround]. + * + * @return [BattleGroundStatus] status + */ + int GetStatus(lua_State* L, BattleGround* bg) + { + Eluna::Push(L, bg->GetStatus()); + return 1; + } + + ElunaRegister BattleGroundMethods[] = + { + // Getters + { "GetName", &LuaBattleGround::GetName }, + { "GetAlivePlayersCountByTeam", &LuaBattleGround::GetAlivePlayersCountByTeam }, + { "GetMap", &LuaBattleGround::GetMap }, + { "GetBonusHonorFromKillCount", &LuaBattleGround::GetBonusHonorFromKillCount }, + { "GetBracketId", &LuaBattleGround::GetBracketId }, + { "GetEndTime", &LuaBattleGround::GetEndTime }, + { "GetFreeSlotsForTeam", &LuaBattleGround::GetFreeSlotsForTeam }, + { "GetInstanceId", &LuaBattleGround::GetInstanceId }, + { "GetMapId", &LuaBattleGround::GetMapId }, + { "GetTypeId", &LuaBattleGround::GetTypeId }, + { "GetMaxLevel", &LuaBattleGround::GetMaxLevel }, + { "GetMinLevel", &LuaBattleGround::GetMinLevel }, + { "GetMaxPlayers", &LuaBattleGround::GetMaxPlayers }, + { "GetMinPlayers", &LuaBattleGround::GetMinPlayers }, + { "GetMaxPlayersPerTeam", &LuaBattleGround::GetMaxPlayersPerTeam }, + { "GetMinPlayersPerTeam", &LuaBattleGround::GetMinPlayersPerTeam }, + { "GetWinner", &LuaBattleGround::GetWinner }, + { "GetStatus", &LuaBattleGround::GetStatus }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/CorpseMethods.h b/src/modules/Eluna/TrinityCore/CorpseMethods.h new file mode 100644 index 0000000000..4e724e4a59 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/CorpseMethods.h @@ -0,0 +1,91 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef CORPSEMETHODS_H +#define CORPSEMETHODS_H + +/*** + * The remains of a [Player] that has died. + * + * Inherits all methods from: [Object], [WorldObject] + */ +namespace LuaCorpse +{ + /** + * Returns the GUID of the [Player] that left the [Corpse] behind. + * + * @return ObjectGuid ownerGUID + */ + int GetOwnerGUID(lua_State* L, Corpse* corpse) + { + Eluna::Push(L, corpse->GetOwnerGUID()); + return 1; + } + + /** + * Returns the time when the [Player] became a ghost and spawned this [Corpse]. + * + * @return uint32 ghostTime + */ + int GetGhostTime(lua_State* L, Corpse* corpse) + { + Eluna::Push(L, corpse->GetGhostTime()); + return 1; + } + + /** + * Returns the [CorpseType] of a [Corpse]. + * + * enum CorpseType + * { + * CORPSE_BONES = 0, + * CORPSE_RESURRECTABLE_PVE = 1, + * CORPSE_RESURRECTABLE_PVP = 2 + * }; + * + * @return [CorpseType] corpseType + */ + int GetType(lua_State* L, Corpse* corpse) + { + Eluna::Push(L, corpse->GetType()); + return 1; + } + + /** + * Sets the "ghost time" to the current time. + * + * See [Corpse:GetGhostTime]. + */ + int ResetGhostTime(lua_State* /*L*/, Corpse* corpse) + { + corpse->ResetGhostTime(); + return 0; + } + + /** + * Saves the [Corpse] to the database. + */ + int SaveToDB(lua_State* /*L*/, Corpse* corpse) + { + corpse->SaveToDB(); + return 0; + } + + ElunaRegister CorpseMethods[] = + { + // Getters + { "GetOwnerGUID", &LuaCorpse::GetOwnerGUID }, + { "GetGhostTime", &LuaCorpse::GetGhostTime }, + { "GetType", &LuaCorpse::GetType }, + + // Other + { "ResetGhostTime", &LuaCorpse::ResetGhostTime }, + { "SaveToDB", &LuaCorpse::SaveToDB }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/CreatureMethods.h b/src/modules/Eluna/TrinityCore/CreatureMethods.h new file mode 100644 index 0000000000..9a2cd3a130 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/CreatureMethods.h @@ -0,0 +1,1361 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef CREATUREMETHODS_H +#define CREATUREMETHODS_H + +/*** + * Non-[Player] controlled [Unit]s (i.e. NPCs). + * + * Inherits all methods from: [Object], [WorldObject], [Unit] + */ +namespace LuaCreature +{ + /** + * Returns `true` if the [Creature] can regenerate health, + * and returns `false` otherwise. + * + * @return bool isRegenerating + */ + int IsRegeneratingHealth(lua_State* L, Creature* creature) + { +#ifdef CATA + Eluna::Push(L, creature->isRegeneratingHealth()); +#else + Eluna::Push(L, creature->CanRegenerateHealth()); +#endif + return 1; + } + + /** + * Sets whether the [Creature] can regenerate health or not. + * + * @param bool enable = true : `true` to enable health regeneration, `false` to disable it + */ + int SetRegeneratingHealth(lua_State* L, Creature* creature) + { + bool enable = Eluna::CHECKVAL(L, 2, true); + + creature->SetRegenerateHealth(enable); + return 0; + } + + /** + * Returns `true` if the [Creature] is set to not give reputation when killed, + * and returns `false` otherwise. + * + * @return bool reputationDisabled + */ + int IsReputationGainDisabled(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsReputationGainDisabled()); + return 1; + } + + /** + * Returns `true` if the [Creature] completes the [Quest] with the ID `questID`, + * and returns `false` otherwise. + * + * @param uint32 questID : the ID of a [Quest] + * @return bool completesQuest + */ + int CanCompleteQuest(lua_State* L, Creature* creature) + { + uint32 quest_id = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->hasInvolvedQuest(quest_id)); + return 1; + } + + /** + * Returns `true` if the [Creature] can be targeted for attack, + * and returns `false` otherwise. + * + * @param bool mustBeDead = false : if `true`, only returns `true` if the [Creature] is also dead. Otherwise, it must be alive. + * @return bool targetable + */ + int IsTargetableForAttack(lua_State* L, Creature* creature) + { + bool mustBeDead = Eluna::CHECKVAL(L, 2, false); + + Eluna::Push(L, creature->isTargetableForAttack(mustBeDead)); + return 1; + } + + /** + * Returns `true` if the [Creature] can assist `friend` in combat against `enemy`, + * and returns `false` otherwise. + * + * @param [Unit] friend : the Unit we will be assisting + * @param [Unit] enemy : the Unit that we would attack if we assist `friend` + * @param bool checkFaction = true : if `true`, the [Creature] must be the same faction as `friend` to assist + * @return bool canAssist + */ + int CanAssistTo(lua_State* L, Creature* creature) + { + Unit* u = Eluna::CHECKOBJ(L, 2); + Unit* enemy = Eluna::CHECKOBJ(L, 3); + bool checkfaction = Eluna::CHECKVAL(L, 4, true); + + Eluna::Push(L, creature->CanAssistTo(u, enemy, checkfaction)); + return 1; + } + + /** + * Returns `true` if the [Creature] has searched for combat assistance already, + * and returns `false` otherwise. + * + * @return bool searchedForAssistance + */ + int HasSearchedAssistance(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->HasSearchedAssistance()); + return 1; + } + + /** + * Returns `true` if the [Creature] will give its loot to `player`, + * and returns `false` otherwise. + * + * @return bool tapped + */ + int IsTappedBy(lua_State* L, Creature* creature) + { + Player* player = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, creature->isTappedBy(player)); + return 1; + } + + /** + * Returns `true` if the [Creature] will give its loot to a [Player] or [Group], + * and returns `false` otherwise. + * + * @return bool hasLootRecipient + */ + int HasLootRecipient(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->hasLootRecipient()); + return 1; + } + + /** + * Returns `true` if the [Creature] can start attacking nearby hostile [Unit]s, + * and returns `false` otherwise. + * + * @return bool canAggro + */ + int CanAggro(lua_State* L, Creature* creature) + { + Eluna::Push(L, !creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)); + return 1; + } + + /** + * Returns `true` if the [Creature] can move through deep water, + * and returns `false` otherwise. + * + * @return bool canSwim + */ + int CanSwim(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->CanSwim()); + return 1; + } + + /** + * Returns `true` if the [Creature] can move on land, + * and returns `false` otherwise. + * + * @return bool canWalk + */ + int CanWalk(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->CanWalk()); + return 1; + } + + /** + * Returns `true` if the [Creature] is returning to its spawn position from combat, + * and returns `false` otherwise. + * + * @return bool inEvadeMode + */ + int IsInEvadeMode(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsInEvadeMode()); + return 1; + } + + /** + * Returns `true` if the [Creature]'s rank is Elite or Rare Elite, + * and returns `false` otherwise. + * + * @return bool isElite + */ + int IsElite(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->isElite()); + return 1; + } + + /** + * Returns `true` if the [Creature] is a city guard, + * and returns `false` otherwise. + * + * @return bool isGuard + */ + int IsGuard(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsGuard()); + return 1; + } + + /** + * Returns `true` if the [Creature] is a civilian, + * and returns `false` otherwise. + * + * @return bool isCivilian + */ + int IsCivilian(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsCivilian()); + return 1; + } + + /** + * Returns `true` if the [Creature] is the leader of a player faction, + * and returns `false` otherwise. + * + * @return bool isLeader + */ + int IsRacialLeader(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsRacialLeader()); + return 1; + } + + /** + * Returns `true` if the [Creature]'s flags_extra includes Dungeon Boss (0x1000000), + * and returns `false` otherwise. + * + * @return bool isDungeonBoss + */ + int IsDungeonBoss(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsDungeonBoss()); + return 1; + } + + + /** + * Returns `true` if the [Creature]'s rank is Boss, + * and returns `false` otherwise. + * + * @return bool isWorldBoss + */ + int IsWorldBoss(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->isWorldBoss()); + return 1; + } + + /** + * Returns `true` if the [Creature] cannot cast `spellId` due to a category cooldown, + * and returns `false` otherwise. + * + * @param uint32 spellId : the ID of a [Spell] + * @return bool hasCooldown + */ + int HasCategoryCooldown(lua_State* L, Creature* creature) + { + uint32 spell = Eluna::CHECKVAL(L, 2); + + if (const SpellInfo* info = sSpellMgr->GetSpellInfo(spell)) + Eluna::Push(L, info->GetCategory() && creature->GetSpellHistory()->HasCooldown(spell)); + else + Eluna::Push(L, false); + + return 1; + } + + /** + * Returns `true` if the [Creature] can cast `spellId` when mind-controlled, + * and returns `false` otherwise. + * + * @param uint32 spellId : the ID of a [Spell] + * @return bool hasSpell + */ + int HasSpell(lua_State* L, Creature* creature) + { + uint32 id = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->HasSpell(id)); + return 1; + } + + /** + * Returns `true` if the [Creature] starts the [Quest] `questId`, + * and returns `false` otherwise. + * + * @param uint32 questId : the ID of a [Quest] + * @return bool hasQuest + */ + int HasQuest(lua_State* L, Creature* creature) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->hasQuest(questId)); + return 1; + } + + /** + * Returns `true` if the [Creature] has `spellId` on cooldown, + * and returns `false` otherwise. + * + * @param uint32 spellId : the ID of a [Spell] + * @return bool hasCooldown + */ + int HasSpellCooldown(lua_State* L, Creature* creature) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->GetSpellHistory()->HasCooldown(spellId)); + return 1; + } + + /** + * Returns `true` if the [Creature] can fly, + * and returns `false` otherwise. + * + * @return bool canFly + */ + int CanFly(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->CanFly()); + return 1; + } + + /** + * Returns `true` if the [Creature] is an invisible trigger, + * and returns `false` otherwise. + * + * @return bool canFly + */ + int IsTrigger(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsTrigger()); + return 1; + } + + /** + * Returns true if the [Creature] is damaged enough for looting + * + * @return bool isDamagedEnough + */ + int IsDamageEnoughForLootingAndReward(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsDamageEnoughForLootingAndReward()); + return 1; + } + + /** + * Returns true if the [Creature] can start attacking specified target + * + * Does not work on most targets + * + * @param [Unit] target + * @param bool force = true : force [Creature] to attack + */ + int CanStartAttack(lua_State* L, Creature* creature) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + bool force = Eluna::CHECKVAL(L, 3, true); + + Eluna::Push(L, creature->CanStartAttack(target, force)); + return 1; + } + + /** + * Returns true if [Creature] has the specified loot mode + * + * @param uint16 lootMode + * @return bool hasLootMode + */ + int HasLootMode(lua_State* L, Creature* creature) + { + uint16 lootMode = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->HasLootMode(lootMode)); + return 1; + } + + /** + * Returns the time it takes for this [Creature] to respawn once killed. + * + * This value does not usually change over a [Creature]'s lifespan, + * but can be modified by [Creature:SetRespawnDelay]. + * + * @return uint32 respawnDelay : the respawn delay, in seconds + */ + int GetRespawnDelay(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetRespawnDelay()); + return 1; + } + + /** + * Returns the radius the [Creature] is permitted to wander from its + * respawn point. + * + * @return float wanderRadius + */ + int GetWanderRadius(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetWanderDistance()); + return 1; + } + + /** + * Returns the current waypoint path ID of the [Creature]. + * + * @return uint32 pathId + */ + int GetWaypointPath(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetWaypointPath()); + return 1; + } + + /** + * Returns the current waypoint ID of the [Creature]. + * + * @return uint32 wpId + */ + int GetCurrentWaypointId(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetCurrentWaypointInfo().first); + return 1; + } + + /** + * Returns the default movement type for this [Creature]. + * + * @return [MovementGeneratorType] defaultMovementType + */ + int GetDefaultMovementType(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetDefaultMovementType()); + return 1; + } + + /** + * Returns the aggro range of the [Creature] for `target`. + * + * @param [Unit] target + * @return float aggroRange + */ + int GetAggroRange(lua_State* L, Creature* creature) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, creature->GetAggroRange(target)); + return 1; + } + + /** + * Returns the effective aggro range of the [Creature] for `target`. + * + * If this is smaller than the minimum aggro range set in the config file, + * that is used as the aggro range instead. + * + * @param [Unit] target + * @return float attackDistance + */ + int GetAttackDistance(lua_State* L, Creature* creature) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, creature->GetAttackDistance(target)); + return 1; + } + + + /** + * Returns the [Group] that can loot this [Creature]. + * + * @return [Group] lootRecipientGroup : the group or `nil` + */ + int GetLootRecipientGroup(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetLootRecipientGroup()); + return 1; + } + + /** + * Returns the [Player] that can loot this [Creature]. + * + * @return [Player] lootRecipient : the player or `nil` + */ + int GetLootRecipient(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetLootRecipient()); + return 1; + } + + /** + * Returns the [Creature]'s script name. + * + * This is used by the core to apply C++ scripts to the Creature. + * + * It is not used by Eluna. Eluna will override AI scripts. + * + * @return string scriptName + */ + int GetScriptName(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetScriptName()); + return 1; + } + + /** + * Returns the [Creature]'s AI name. + * + * This is used by the core to assign the Creature's default AI. + * + * If the Creature is scripted by Eluna, the AI is overriden. + * + * @return string AIName + */ + int GetAIName(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetAIName()); + return 1; + } + + /** + * Returns the [Creature]'s script ID. + * + * Every C++ script name is assigned a unique ID by the core. + * This returns the ID for this [Creature]'s script name. + * + * @return uint32 scriptID + */ + int GetScriptId(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetScriptId()); + return 1; + } + + /** + * Returns the [Creature]'s cooldown for `spellID`. + * + * @param uint32 spellID + * @return uint32 cooldown : the cooldown, in milliseconds + */ + int GetCreatureSpellCooldownDelay(lua_State* L, Creature* creature) + { + uint32 spell = Eluna::CHECKVAL(L, 2); + + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell)) + Eluna::Push(L, creature->GetSpellHistory()->GetRemainingCooldown(spellInfo)); + else + Eluna::Push(L, 0); + + return 1; + } + + /** + * Returns the delay between when the [Creature] dies and when its body despawns. + * + * @return uint32 corpseDelay : the delay, in seconds + */ + int GetCorpseDelay(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetCorpseDelay()); + return 1; + } + + /** + * Returns position the [Creature] returns to when evading from combat + * or respawning. + * + * @return float x + * @return float y + * @return float z + * @return float o + */ + int GetHomePosition(lua_State* L, Creature* creature) + { + float x, y, z, o; + creature->GetHomePosition(x, y, z, o); + + Eluna::Push(L, x); + Eluna::Push(L, y); + Eluna::Push(L, z); + Eluna::Push(L, o); + return 4; + } + + /** + * Sets the position the [Creature] returns to when evading from combat + * or respawning. + * + * @param float x + * @param float y + * @param float z + * @param float o + */ + int SetHomePosition(lua_State* L, Creature* creature) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float o = Eluna::CHECKVAL(L, 5); + + creature->SetHomePosition(x, y, z, o); + return 0; + } + + enum SelectAggroTarget + { + SELECT_TARGET_RANDOM = 0, // Just selects a random target + SELECT_TARGET_TOPAGGRO, // Selects targes from top aggro to bottom + SELECT_TARGET_BOTTOMAGGRO, // Selects targets from bottom aggro to top + SELECT_TARGET_NEAREST, + SELECT_TARGET_FARTHEST + }; + + /** + * Returns a target from the [Creature]'s threat list based on the + * supplied arguments. + * + * enum SelectAggroTarget + * { + * SELECT_TARGET_RANDOM = 0, //Just selects a random target + * SELECT_TARGET_TOPAGGRO, //Selects targets from top aggro to bottom + * SELECT_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top + * SELECT_TARGET_NEAREST, + * SELECT_TARGET_FARTHEST + * }; + * + * For example, if you wanted to select the third-farthest [Player] + * within 50 yards that has the [Aura] "Corrupted Blood" (ID 24328), + * you could use this function like so: + * + * target = creature:GetAITarget(4, true, 3, 50, 24328) + * + * @param [SelectAggroTarget] targetType : how the threat list should be sorted + * @param bool playerOnly = false : if `true`, skips targets that aren't [Player]s + * @param uint32 position = 0 : used as an offset into the threat list. If `targetType` is random, used as the number of players from top of aggro to choose from + * @param float distance = 0.0 : if positive, the maximum distance for the target. If negative, the minimum distance + * @param int32 aura = 0 : if positive, the target must have this [Aura]. If negative, the the target must not have this Aura + * @return [Unit] target : the target, or `nil` + */ + int GetAITarget(lua_State* L, Creature* creature) + { + uint32 targetType = Eluna::CHECKVAL(L, 2); + bool playerOnly = Eluna::CHECKVAL(L, 3, false); + uint32 position = Eluna::CHECKVAL(L, 4, 0); + float dist = Eluna::CHECKVAL(L, 5, 0.0f); + int32 aura = Eluna::CHECKVAL(L, 6, 0); + + auto const& threatlist = creature->GetThreatManager().GetSortedThreatList(); + std::list targetList; + for (ThreatReference const* itr : threatlist) + { + Unit* target = itr->GetVictim(); + if (!target) + continue; + if (playerOnly && target->GetTypeId() != TYPEID_PLAYER) + continue; + if (aura > 0 && !target->HasAura(aura)) + continue; + else if (aura < 0 && target->HasAura(-aura)) + continue; + if (dist > 0.0f && !creature->IsWithinDist(target, dist)) + continue; + else if (dist < 0.0f && creature->IsWithinDist(target, -dist)) + continue; + targetList.push_back(target); + } + + if (targetList.empty()) + return 1; + if (position >= targetList.size()) + return 1; + + if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) + targetList.sort(ElunaUtil::ObjectDistanceOrderPred(creature)); + + switch (targetType) + { + case SELECT_TARGET_NEAREST: + case SELECT_TARGET_TOPAGGRO: + { + std::list::const_iterator itr = targetList.begin(); + if (position) + std::advance(itr, position); + Eluna::Push(L, *itr); + } + break; + case SELECT_TARGET_FARTHEST: + case SELECT_TARGET_BOTTOMAGGRO: + { + std::list::reverse_iterator ritr = targetList.rbegin(); + if (position) + std::advance(ritr, position); + Eluna::Push(L, *ritr); + } + break; + case SELECT_TARGET_RANDOM: + { + std::list::const_iterator itr = targetList.begin(); + if (position) + std::advance(itr, urand(0, position)); + else + std::advance(itr, urand(0, targetList.size() - 1)); + Eluna::Push(L, *itr); + } + break; + default: + luaL_argerror(L, 2, "SelectAggroTarget expected"); + break; + } + + return 1; + } + + /** + * Returns all [Unit]s in the [Creature]'s threat list. + * + * @return table targets + */ + int GetAITargets(lua_State* L, Creature* creature) + { + auto const& threatlist = creature->GetThreatManager().GetSortedThreatList(); + + lua_createtable(L, creature->GetThreatManager().GetThreatListSize(), 0); + int tbl = lua_gettop(L); + + uint32 i = 0; + for (ThreatReference const* itr : threatlist) + { + Unit* target = itr->GetVictim(); + if (!target) + continue; + Eluna::Push(L, target); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns the number of [Unit]s in this [Creature]'s threat list. + * + * @return double targetsCount + */ + int GetAITargetsCount(lua_State* L, Creature* creature) + { + Eluna::Push(L, (double)creature->GetThreatManager().GetThreatListSize()); + return 1; + } + + /** + * Returns the [Creature]'s NPC flags. + * + * These are used to control whether the NPC is a vendor, can repair items, + * can give quests, etc. + * + * @return [NPCFlags] npcFlags + */ + int GetNPCFlags(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetUInt32Value(UNIT_NPC_FLAGS)); + return 1; + } + + /** + * Returns the [Creature]'s Extra flags. + * + * These are used to control whether the NPC is a civilian, uses pathfinding, + * if it's a guard, etc. + * + * @return [ExtraFlags] extraFlags + */ + int GetExtraFlags(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetCreatureTemplate()->flags_extra); + return 1; + } + +#ifndef CATA + /** + * Returns the [Creature]'s shield block value. + * + * @return uint32 shieldBlockValue + */ + int GetShieldBlockValue(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetShieldBlockValue()); + return 1; + } +#endif + + int GetLootMode(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetLootMode()); + return 1; + } + + + /** + * Returns the guid of the [Creature] that is used as the ID in the database + * + * @return uint32 dbguid + */ + int GetDBTableGUIDLow(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetSpawnId()); + return 1; + } + + /** + * Sets the [Creature]'s NPC flags to `flags`. + * + * @param [NPCFlags] flags + */ + int SetNPCFlags(lua_State* L, Creature* creature) + { + uint32 flags = Eluna::CHECKVAL(L, 2); + + creature->SetUInt32Value(UNIT_NPC_FLAGS, flags); + return 0; + } + + /** + * Sets the [Creature]'s ReactState to `state`. + * + * @param [ReactState] state + */ + int SetReactState(lua_State* L, Creature* creature) + { + uint32 state = Eluna::CHECKVAL(L, 2); + + creature->SetReactState((ReactStates)state); + return 0; + } + + /** + * Makes the [Creature] able to fly if enabled. + * + * @param bool disable + */ + int SetDisableGravity(lua_State* L, Creature* creature) + { + bool disable = Eluna::CHECKVAL(L, 2); + + creature->SetDisableGravity(disable); + return 0; + } + + int SetLootMode(lua_State* L, Creature* creature) + { + uint16 lootMode = Eluna::CHECKVAL(L, 2); + + creature->SetLootMode(lootMode); + return 0; + } + + /** + * Sets the [Creature]'s death state to `deathState`. + * + * @param [DeathState] deathState + */ + int SetDeathState(lua_State* L, Creature* creature) + { + int32 state = Eluna::CHECKVAL(L, 2); + + creature->setDeathState((DeathState)state); + return 0; + } + + /** + * Sets whether the [Creature] is currently walking or running. + * + * @param bool enable = true : `true` to enable walking, `false` for running + */ + int SetWalk(lua_State* L, Creature* creature) // TODO: Move same to Player ? + { + bool enable = Eluna::CHECKVAL(L, 2, true); + + creature->SetWalk(enable); + return 0; + } + + /** + * Equips given [Item]s to the [Unit]. Using 0 removes the equipped [Item] + * + * @param uint32 main_hand : main hand [Item]'s entry + * @param uint32 off_hand : off hand [Item]'s entry + * @param uint32 ranged : ranged [Item]'s entry + */ + int SetEquipmentSlots(lua_State* L, Creature* creature) + { + uint32 main_hand = Eluna::CHECKVAL(L, 2); + uint32 off_hand = Eluna::CHECKVAL(L, 3); + uint32 ranged = Eluna::CHECKVAL(L, 4); + + creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, main_hand); + creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, off_hand); + creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, ranged); + return 0; + } + + /** + * Sets whether the [Creature] can be aggroed. + * + * @param bool allow = true : `true` to allow aggro, `false` to disable aggro + */ + int SetAggroEnabled(lua_State* L, Creature* creature) + { + bool allow = Eluna::CHECKVAL(L, 2, true); + + if (allow) + creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC); + else + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC); + + return 0; + } + + /** + * Sets whether the [Creature] gives reputation or not. + * + * @param bool disable = true : `true` to disable reputation, `false` to enable + */ + int SetDisableReputationGain(lua_State* L, Creature* creature) + { + bool disable = Eluna::CHECKVAL(L, 2, true); + + creature->SetDisableReputationGain(disable); + return 0; + } + + /** + * Sets the [Creature] as in combat with all [Player]s in the dungeon instance. + * + * This is used by raid bosses to prevent Players from using out-of-combat + * actions once the encounter has begun. + */ + int SetInCombatWithZone(lua_State* /*L*/, Creature* creature) + { + if (creature->IsAIEnabled()) + creature->AI()->DoZoneInCombat(); + + return 0; + } + + /** + * Sets the distance the [Creature] can wander from it's spawn point. + * + * @param float distance + */ + int SetWanderRadius(lua_State* L, Creature* creature) + { + float dist = Eluna::CHECKVAL(L, 2); + + creature->SetWanderDistance(dist); + return 0; + } + + /** + * Sets the time it takes for the [Creature] to respawn when killed. + * + * @param uint32 delay : the delay, in seconds + */ + int SetRespawnDelay(lua_State* L, Creature* creature) + { + uint32 delay = Eluna::CHECKVAL(L, 2); + + creature->SetRespawnDelay(delay); + return 0; + } + + /** + * Sets the default movement type of the [Creature]. + * + * @param [MovementGeneratorType] type + */ + int SetDefaultMovementType(lua_State* L, Creature* creature) + { + int32 type = Eluna::CHECKVAL(L, 2); + + creature->SetDefaultMovementType((MovementGeneratorType)type); + return 0; + } + + /** + * Sets whether the [Creature] can search for assistance at low health or not. + * + * @param bool enable = true : `true` to disable searching, `false` to allow + */ + int SetNoSearchAssistance(lua_State* L, Creature* creature) + { + bool val = Eluna::CHECKVAL(L, 2, true); + + creature->SetNoSearchAssistance(val); + return 0; + } + + /** + * Sets whether the [Creature] can call nearby enemies for help in combat or not. + * + * @param bool enable = true : `true` to disable calling for help, `false` to enable + */ + int SetNoCallAssistance(lua_State* L, Creature* creature) + { + bool val = Eluna::CHECKVAL(L, 2, true); + + creature->SetNoCallAssistance(val); + return 0; + } + + /** + * Sets whether the creature is hovering / levitating or not. + * + * @param bool enable = true : `true` to enable hovering, `false` to disable + */ + int SetHover(lua_State* L, Creature* creature) + { + bool enable = Eluna::CHECKVAL(L, 2, true); + + creature->SetHover(enable); + return 0; + } + + /** + * Despawn this [Creature]. + * + * @param uint32 delay = 0 : dely to despawn in milliseconds + */ + int DespawnOrUnsummon(lua_State* L, Creature* creature) + { + uint32 msTimeToDespawn = Eluna::CHECKVAL(L, 2, 0); + + creature->DespawnOrUnsummon(Milliseconds(msTimeToDespawn)); + return 0; + } + + /** + * Respawn this [Creature]. + */ + int Respawn(lua_State* /*L*/, Creature* creature) + { + creature->Respawn(); + return 0; + } + + /** + * Remove this [Creature]'s corpse. + */ + int RemoveCorpse(lua_State* /*L*/, Creature* creature) + { + creature->RemoveCorpse(); + return 0; + } + + /** + * Make the [Creature] start following its waypoint path. + */ + int MoveWaypoint(lua_State* /*L*/, Creature* creature) + { + creature->GetMotionMaster()->MovePath(creature->GetWaypointPath(), true); + return 0; + } + + /** + * Make the [Creature] call for assistance in combat from other nearby [Creature]s. + */ + int CallAssistance(lua_State* /*L*/, Creature* creature) + { + creature->CallAssistance(); + return 0; + } + + /** + * Make the [Creature] call for help in combat from friendly [Creature]s within `radius`. + * + * @param float radius + */ + int CallForHelp(lua_State* L, Creature* creature) + { + float radius = Eluna::CHECKVAL(L, 2); + + creature->CallForHelp(radius); + return 0; + } + + /** + * Make the [Creature] flee combat to get assistance from a nearby friendly [Creature]. + */ + int FleeToGetAssistance(lua_State* /*L*/, Creature* creature) + { + creature->DoFleeToGetAssistance(); + return 0; + } + + /** + * Make the [Creature] attack `target`. + * + * @param [Unit] target + */ + int AttackStart(lua_State* L, Creature* creature) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + + creature->AI()->AttackStart(target); + return 0; + } + + /** + * Save the [Creature] in the database. + */ + int SaveToDB(lua_State* /*L*/, Creature* creature) + { + creature->SaveToDB(); + return 0; + } + + /** + * Make the [Creature] try to find a new target. + * + * This should be called every update cycle for the Creature's AI. + */ + int SelectVictim(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->SelectVictim()); + return 1; + } + + /** + * Transform the [Creature] into another Creature. + * + * @param uint32 entry : the Creature ID to transform into + * @param uint32 dataGUIDLow = 0 : use this Creature's model and equipment instead of the defaults + */ + int UpdateEntry(lua_State* L, Creature* creature) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + uint32 dataGuidLow = Eluna::CHECKVAL(L, 3, 0); + + creature->UpdateEntry(entry, dataGuidLow ? eObjectMgr->GetCreatureData(dataGuidLow) : NULL); + return 0; + } + + /** + * Resets [Creature]'s loot mode to default + */ + int ResetLootMode(lua_State* /*L*/, Creature* creature) + { + creature->ResetLootMode(); + return 0; + } + + /** + * Removes specified loot mode from [Creature] + * + * @param uint16 lootMode + */ + int RemoveLootMode(lua_State* L, Creature* creature) + { + uint16 lootMode = Eluna::CHECKVAL(L, 2); + + creature->RemoveLootMode(lootMode); + return 0; + } + + /** + * Adds a loot mode to the [Creature] + * + * @param uint16 lootMode + */ + int AddLootMode(lua_State* L, Creature* creature) + { + uint16 lootMode = Eluna::CHECKVAL(L, 2); + + creature->AddLootMode(lootMode); + return 0; + } + + /** + * Returns the [Creature]'s creature family ID (enumerated in CreatureFamily.dbc). + * + *
+     * enum CreatureFamily
+     * {
+     *     CREATURE_FAMILY_NONE                = 0,    // TrinityCore only
+     *     CREATURE_FAMILY_WOLF                = 1,
+     *     CREATURE_FAMILY_CAT                 = 2,
+     *     CREATURE_FAMILY_SPIDER              = 3,
+     *     CREATURE_FAMILY_BEAR                = 4,
+     *     CREATURE_FAMILY_BOAR                = 5,
+     *     CREATURE_FAMILY_CROCOLISK           = 6,
+     *     CREATURE_FAMILY_CARRION_BIRD        = 7,
+     *     CREATURE_FAMILY_CRAB                = 8,
+     *     CREATURE_FAMILY_GORILLA             = 9,
+     *     CREATURE_FAMILY_HORSE_CUSTOM        = 10,   // Does not exist in DBC but used for horse like beasts in DB
+     *     CREATURE_FAMILY_RAPTOR              = 11,
+     *     CREATURE_FAMILY_TALLSTRIDER         = 12,
+     *     CREATURE_FAMILY_FELHUNTER           = 15,
+     *     CREATURE_FAMILY_VOIDWALKER          = 16,
+     *     CREATURE_FAMILY_SUCCUBUS            = 17,
+     *     CREATURE_FAMILY_DOOMGUARD           = 19,
+     *     CREATURE_FAMILY_SCORPID             = 20,
+     *     CREATURE_FAMILY_TURTLE              = 21,
+     *     CREATURE_FAMILY_IMP                 = 23,
+     *     CREATURE_FAMILY_BAT                 = 24,
+     *     CREATURE_FAMILY_HYENA               = 25,
+     *     CREATURE_FAMILY_BIRD_OF_PREY        = 26,   // Named CREATURE_FAMILY_OWL in Mangos
+     *     CREATURE_FAMILY_WIND_SERPENT        = 27,
+     *     CREATURE_FAMILY_REMOTE_CONTROL      = 28,
+     *     CREATURE_FAMILY_FELGUARD            = 29,   // This and below is TBC+
+     *     CREATURE_FAMILY_DRAGONHAWK          = 30,
+     *     CREATURE_FAMILY_RAVAGER             = 31,
+     *     CREATURE_FAMILY_WARP_STALKER        = 32,
+     *     CREATURE_FAMILY_SPOREBAT            = 33,
+     *     CREATURE_FAMILY_NETHER_RAY          = 34,
+     *     CREATURE_FAMILY_SERPENT             = 35,
+     *     CREATURE_FAMILY_SEA_LION            = 36,   // TBC only
+     *     CREATURE_FAMILY_MOTH                = 37,   // This and below is WotLK+
+     *     CREATURE_FAMILY_CHIMAERA            = 38,
+     *     CREATURE_FAMILY_DEVILSAUR           = 39,
+     *     CREATURE_FAMILY_GHOUL               = 40,
+     *     CREATURE_FAMILY_SILITHID            = 41,
+     *     CREATURE_FAMILY_WORM                = 42,
+     *     CREATURE_FAMILY_RHINO               = 43,
+     *     CREATURE_FAMILY_WASP                = 44,
+     *     CREATURE_FAMILY_CORE_HOUND          = 45,
+     *     CREATURE_FAMILY_SPIRIT_BEAST        = 46
+     * };
+     * 
+ * + * @return [CreatureFamily] creatureFamily + */ + int GetCreatureFamily(lua_State* L, Creature* creature) + { + uint32 entry = creature->GetEntry(); + + CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(entry); + if (cInfo) + Eluna::Push(L, cInfo->family); + + return 1; + } + + ElunaRegister CreatureMethods[] = + { + // Getters + { "GetAITarget", &LuaCreature::GetAITarget }, + { "GetAITargets", &LuaCreature::GetAITargets }, + { "GetAITargetsCount", &LuaCreature::GetAITargetsCount }, + { "GetHomePosition", &LuaCreature::GetHomePosition }, + { "GetCorpseDelay", &LuaCreature::GetCorpseDelay }, + { "GetCreatureSpellCooldownDelay", &LuaCreature::GetCreatureSpellCooldownDelay }, + { "GetScriptId", &LuaCreature::GetScriptId }, + { "GetAIName", &LuaCreature::GetAIName }, + { "GetScriptName", &LuaCreature::GetScriptName }, + { "GetAttackDistance", &LuaCreature::GetAttackDistance }, + { "GetAggroRange", &LuaCreature::GetAggroRange }, + { "GetDefaultMovementType", &LuaCreature::GetDefaultMovementType }, + { "GetRespawnDelay", &LuaCreature::GetRespawnDelay }, + { "GetWanderRadius", &LuaCreature::GetWanderRadius }, + { "GetCurrentWaypointId", &LuaCreature::GetCurrentWaypointId }, + { "GetWaypointPath", &LuaCreature::GetWaypointPath }, + { "GetLootMode", &LuaCreature::GetLootMode }, + { "GetLootRecipient", &LuaCreature::GetLootRecipient }, + { "GetLootRecipientGroup", &LuaCreature::GetLootRecipientGroup }, + { "GetNPCFlags", &LuaCreature::GetNPCFlags }, + { "GetExtraFlags", &LuaCreature::GetExtraFlags }, +#ifndef CATA + { "GetShieldBlockValue", &LuaCreature::GetShieldBlockValue }, +#else + { "GetShieldBlockValue", nullptr }, +#endif + { "GetDBTableGUIDLow", &LuaCreature::GetDBTableGUIDLow }, + { "GetCreatureFamily", &LuaCreature::GetCreatureFamily }, + + // Setters + { "SetRegeneratingHealth", &LuaCreature::SetRegeneratingHealth }, + { "SetHover", &LuaCreature::SetHover }, + { "SetDisableGravity", &LuaCreature::SetDisableGravity }, + { "SetAggroEnabled", &LuaCreature::SetAggroEnabled }, + { "SetNoCallAssistance", &LuaCreature::SetNoCallAssistance }, + { "SetNoSearchAssistance", &LuaCreature::SetNoSearchAssistance }, + { "SetDefaultMovementType", &LuaCreature::SetDefaultMovementType }, + { "SetRespawnDelay", &LuaCreature::SetRespawnDelay }, + { "SetWanderRadius", &LuaCreature::SetWanderRadius }, + { "SetInCombatWithZone", &LuaCreature::SetInCombatWithZone }, + { "SetDisableReputationGain", &LuaCreature::SetDisableReputationGain }, + { "SetLootMode", &LuaCreature::SetLootMode }, + { "SetNPCFlags", &LuaCreature::SetNPCFlags }, + { "SetReactState", &LuaCreature::SetReactState }, + { "SetDeathState", &LuaCreature::SetDeathState }, + { "SetWalk", &LuaCreature::SetWalk }, + { "SetHomePosition", &LuaCreature::SetHomePosition }, + { "SetEquipmentSlots", &LuaCreature::SetEquipmentSlots }, + + // Boolean + { "IsRegeneratingHealth", &LuaCreature::IsRegeneratingHealth }, + { "IsDungeonBoss", &LuaCreature::IsDungeonBoss }, + { "IsWorldBoss", &LuaCreature::IsWorldBoss }, + { "IsRacialLeader", &LuaCreature::IsRacialLeader }, + { "IsCivilian", &LuaCreature::IsCivilian }, + { "IsTrigger", &LuaCreature::IsTrigger }, + { "IsGuard", &LuaCreature::IsGuard }, + { "IsElite", &LuaCreature::IsElite }, + { "IsInEvadeMode", &LuaCreature::IsInEvadeMode }, + { "HasCategoryCooldown", &LuaCreature::HasCategoryCooldown }, + { "CanWalk", &LuaCreature::CanWalk }, + { "CanSwim", &LuaCreature::CanSwim }, + { "CanAggro", &LuaCreature::CanAggro }, + { "CanStartAttack", &LuaCreature::CanStartAttack }, + { "HasSearchedAssistance", &LuaCreature::HasSearchedAssistance }, + { "IsTappedBy", &LuaCreature::IsTappedBy }, + { "HasLootRecipient", &LuaCreature::HasLootRecipient }, + { "CanAssistTo", &LuaCreature::CanAssistTo }, + { "IsTargetableForAttack", &LuaCreature::IsTargetableForAttack }, + { "CanCompleteQuest", &LuaCreature::CanCompleteQuest }, + { "IsReputationGainDisabled", &LuaCreature::IsReputationGainDisabled }, + { "IsDamageEnoughForLootingAndReward", &LuaCreature::IsDamageEnoughForLootingAndReward }, + { "HasLootMode", &LuaCreature::HasLootMode }, + { "HasSpell", &LuaCreature::HasSpell }, + { "HasQuest", &LuaCreature::HasQuest }, + { "HasSpellCooldown", &LuaCreature::HasSpellCooldown }, + { "CanFly", &LuaCreature::CanFly }, + + // Other + { "FleeToGetAssistance", &LuaCreature::FleeToGetAssistance }, + { "CallForHelp", &LuaCreature::CallForHelp }, + { "CallAssistance", &LuaCreature::CallAssistance }, + { "RemoveCorpse", &LuaCreature::RemoveCorpse }, + { "DespawnOrUnsummon", &LuaCreature::DespawnOrUnsummon }, + { "Respawn", &LuaCreature::Respawn }, + { "AttackStart", &LuaCreature::AttackStart }, + { "AddLootMode", &LuaCreature::AddLootMode }, + { "ResetLootMode", &LuaCreature::ResetLootMode }, + { "RemoveLootMode", &LuaCreature::RemoveLootMode }, + { "SaveToDB", &LuaCreature::SaveToDB }, + { "SelectVictim", &LuaCreature::SelectVictim }, + { "MoveWaypoint", &LuaCreature::MoveWaypoint }, + { "UpdateEntry", &LuaCreature::UpdateEntry }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/ElunaQueryMethods.h b/src/modules/Eluna/TrinityCore/ElunaQueryMethods.h new file mode 100644 index 0000000000..99587f54f5 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/ElunaQueryMethods.h @@ -0,0 +1,342 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef QUERYMETHODS_H +#define QUERYMETHODS_H + +#define RESULT (*result) + +/*** + * The result of a database query. + * + * E.g. the return value of [Global:WorldDBQuery]. + * + * Inherits all methods from: none + */ +namespace LuaQuery +{ + static void CheckFields(lua_State* L, ElunaQuery* result) + { + uint32 field = Eluna::CHECKVAL(L, 2); + uint32 count = RESULT->GetFieldCount(); + if (field >= count) + { + char arr[256]; + sprintf(arr, "trying to access invalid field index %u. There are %u fields available and the indexes start from 0", field, count); + luaL_argerror(L, 2, arr); + } + } + + /** + * Returns `true` if the specified column of the current row is `NULL`, otherwise `false`. + * + * @param uint32 column + * @return bool isNull + */ + int IsNull(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + + Eluna::Push(L, RESULT->Fetch()[col].IsNull()); + return 1; + } + + /** + * Returns the number of columns in the result set. + * + * @return uint32 columnCount + */ + int GetColumnCount(lua_State* L, ElunaQuery* result) + { + Eluna::Push(L, RESULT->GetFieldCount()); + return 1; + } + + /** + * Returns the number of rows in the result set. + * + * @return uint32 rowCount + */ + int GetRowCount(lua_State* L, ElunaQuery* result) + { + if (RESULT->GetRowCount() > (uint32)-1) + Eluna::Push(L, (uint32)-1); + else + Eluna::Push(L, (uint32)(RESULT->GetRowCount())); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a boolean. + * + * @param uint32 column + * @return bool data + */ + int GetBool(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetBool()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to an unsigned 8-bit integer. + * + * @param uint32 column + * @return uint8 data + */ + int GetUInt8(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetUInt8()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to an unsigned 16-bit integer. + * + * @param uint32 column + * @return uint16 data + */ + int GetUInt16(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetUInt16()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to an unsigned 32-bit integer. + * + * @param uint32 column + * @return uint32 data + */ + int GetUInt32(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetUInt32()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to an unsigned 64-bit integer. + * + * @param uint32 column + * @return uint64 data + */ + int GetUInt64(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetUInt64()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a signed 8-bit integer. + * + * @param uint32 column + * @return int8 data + */ + int GetInt8(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetInt8()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a signed 16-bit integer. + * + * @param uint32 column + * @return int16 data + */ + int GetInt16(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetInt16()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a signed 32-bit integer. + * + * @param uint32 column + * @return int32 data + */ + int GetInt32(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetInt32()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a signed 64-bit integer. + * + * @param uint32 column + * @return int64 data + */ + int GetInt64(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetInt64()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a 32-bit floating point value. + * + * @param uint32 column + * @return float data + */ + int GetFloat(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetFloat()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a 64-bit floating point value. + * + * @param uint32 column + * @return double data + */ + int GetDouble(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetDouble()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a string. + * + * @param uint32 column + * @return string data + */ + int GetString(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + + Eluna::Push(L, RESULT->Fetch()[col].GetCString()); + return 1; + } + + /** + * Advances the [ElunaQuery] to the next row in the result set. + * + * *Do not* call this immediately after a query, or you'll skip the first row. + * + * Returns `false` if there was no new row, otherwise `true`. + * + * @return bool hadNextRow + */ + int NextRow(lua_State* L, ElunaQuery* result) + { + Eluna::Push(L, RESULT->NextRow()); + return 1; + } + + /** + * Returns a table from the current row where keys are field names and values are the row's values. + * + * All numerical values will be numbers and everything else is returned as a string. + * + * **For example,** the query: + * + * SELECT entry, name FROM creature_template + * + * would result in a table like: + * + * { entry = 123, name = "some creature name" } + * + * To move to next row use [ElunaQuery:NextRow]. + * + * @return table rowData : table filled with row columns and data where `T[column] = data` + */ + int GetRow(lua_State* L, ElunaQuery* result) + { + uint32 col = RESULT->GetFieldCount(); + Field* row = RESULT->Fetch(); + + lua_createtable(L, 0, col); + int tbl = lua_gettop(L); + + for (uint32 i = 0; i < col; ++i) + { + Eluna::Push(L, RESULT->GetFieldName(i)); + + const char* str = row[i].GetCString(); + if (row[i].IsNull() || !str) + Eluna::Push(L); + else + { + // MYSQL_TYPE_LONGLONG Interpreted as string for lua + switch (row[i].GetType()) + { + case DatabaseFieldTypes::Int8: + case DatabaseFieldTypes::Int16: + case DatabaseFieldTypes::Int32: + case DatabaseFieldTypes::Int64: + case DatabaseFieldTypes::Float: + case DatabaseFieldTypes::Double: + Eluna::Push(L, strtod(str, NULL)); + break; + default: + Eluna::Push(L, str); + break; + } + } + lua_rawset(L, tbl); + } + + lua_settop(L, tbl); + return 1; + } + + ElunaRegister QueryMethods[] = + { + // Getters + { "GetColumnCount", &LuaQuery::GetColumnCount }, + { "GetRowCount", &LuaQuery::GetRowCount }, + { "GetRow", &LuaQuery::GetRow }, + { "GetBool", &LuaQuery::GetBool }, + { "GetUInt8", &LuaQuery::GetUInt8 }, + { "GetUInt16", &LuaQuery::GetUInt16 }, + { "GetUInt32", &LuaQuery::GetUInt32 }, + { "GetUInt64", &LuaQuery::GetUInt64 }, + { "GetInt8", &LuaQuery::GetInt8 }, + { "GetInt16", &LuaQuery::GetInt16 }, + { "GetInt32", &LuaQuery::GetInt32 }, + { "GetInt64", &LuaQuery::GetInt64 }, + { "GetFloat", &LuaQuery::GetFloat }, + { "GetDouble", &LuaQuery::GetDouble }, + { "GetString", &LuaQuery::GetString }, + + // Boolean + { "NextRow", &LuaQuery::NextRow }, + { "IsNull", &LuaQuery::IsNull }, + + { NULL, NULL } + }; +}; +#undef RESULT + +#endif diff --git a/src/modules/Eluna/TrinityCore/GameObjectMethods.h b/src/modules/Eluna/TrinityCore/GameObjectMethods.h new file mode 100644 index 0000000000..2cf1b7a6ad --- /dev/null +++ b/src/modules/Eluna/TrinityCore/GameObjectMethods.h @@ -0,0 +1,347 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef GAMEOBJECTMETHODS_H +#define GAMEOBJECTMETHODS_H + +/*** + * Inherits all methods from: [Object], [WorldObject] + */ +namespace LuaGameObject +{ + /** + * Returns 'true' if the [GameObject] can give the specified [Quest] + * + * @param uint32 questId : quest entry Id to check + * @return bool hasQuest + */ + int HasQuest(lua_State* L, GameObject* go) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, go->hasQuest(questId)); + return 1; + } + + /** + * Returns 'true' if the [GameObject] is spawned + * + * @return bool isSpawned + */ + int IsSpawned(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->isSpawned()); + return 1; + } + + /** + * Returns 'true' if the [GameObject] is a transport + * + * @return bool isTransport + */ + int IsTransport(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->IsTransport()); + return 1; + } + + /** + * Returns 'true' if the [GameObject] is active + * + * @return bool isActive + */ + int IsActive(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->isActiveObject()); + return 1; + } + + int IsDestructible(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->IsDestructibleBuilding()); + return 1; + } + + /** + * Returns display ID of the [GameObject] + * + * @return uint32 displayId + */ + int GetDisplayId(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetDisplayId()); + return 1; + } + + /** + * Returns the state of a [GameObject] + * Below are client side [GOState]s off of 3.3.5a + * + *
+     * enum GOState
+     * {
+     *     GO_STATE_ACTIVE             = 0,                        // show in world as used and not reset (closed door open)
+     *     GO_STATE_READY              = 1,                        // show in world as ready (closed door close)
+     *     GO_STATE_ACTIVE_ALTERNATIVE = 2                         // show in world as used in alt way and not reset (closed door open by cannon fire)
+     * };
+     * 
+ * + * @return [GOState] goState + */ + int GetGoState(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetGoState()); + return 1; + } + + /** + * Returns the [LootState] of a [GameObject] + * Below are [LootState]s off of 3.3.5a + * + *
+     * enum LootState
+     * {
+     *     GO_NOT_READY = 0,
+     *     GO_READY,                                               // can be ready but despawned, and then not possible activate until spawn
+     *     GO_ACTIVATED,
+     *     GO_JUST_DEACTIVATED
+     * };
+     * 
+ * + * @return [LootState] lootState + */ + int GetLootState(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->getLootState()); + return 1; + } + + /** + * Returns the [Player] that can loot the [GameObject] + * + * Not the original looter and may be nil. + * + * @return [Player] player + */ + int GetLootRecipient(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetLootRecipient()); + return 1; + } + + /** + * Returns the [Group] that can loot the [GameObject] + * + * Not the original looter and may be nil. + * + * @return [Group] group + */ + int GetLootRecipientGroup(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetLootRecipientGroup()); + return 1; + } + + /** + * Returns the guid of the [GameObject] that is used as the ID in the database + * + * @return uint32 dbguid + */ + int GetDBTableGUIDLow(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetSpawnId()); + return 1; + } + + /** + * Sets the state of a [GameObject] + * + *
+     * enum GOState
+     * {
+     *     GO_STATE_ACTIVE             = 0,                        // show in world as used and not reset (closed door open)
+     *     GO_STATE_READY              = 1,                        // show in world as ready (closed door close)
+     *     GO_STATE_ACTIVE_ALTERNATIVE = 2                         // show in world as used in alt way and not reset (closed door open by cannon fire)
+     * };
+     * 
+ * + * @param [GOState] state : all available go states can be seen above + */ + int SetGoState(lua_State* L, GameObject* go) + { + uint32 state = Eluna::CHECKVAL(L, 2, 0); + + if (state == 0) + go->SetGoState(GO_STATE_ACTIVE); + else if (state == 1) + go->SetGoState(GO_STATE_READY); + else if (state == 2) + { +#ifndef CATA + go->SetGoState(GO_STATE_DESTROYED); +#else + go->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); +#endif + } + + return 0; + } + + /** + * Sets the [LootState] of a [GameObject] + * Below are [LootState]s off of 3.3.5a + * + *
+     * enum LootState
+     * {
+     *     GO_NOT_READY = 0,
+     *     GO_READY,                                               // can be ready but despawned, and then not possible activate until spawn
+     *     GO_ACTIVATED,
+     *     GO_JUST_DEACTIVATED
+     * };
+     * 
+ * + * @param [LootState] state : all available loot states can be seen above + */ + int SetLootState(lua_State* L, GameObject* go) + { + uint32 state = Eluna::CHECKVAL(L, 2, 0); + + if (state == 0) + go->SetLootState(GO_NOT_READY); + else if (state == 1) + go->SetLootState(GO_READY); + else if (state == 2) + go->SetLootState(GO_ACTIVATED); + else if (state == 3) + go->SetLootState(GO_JUST_DEACTIVATED); + + return 0; + } + + /** + * Saves [GameObject] to the database + * + */ + int SaveToDB(lua_State* /*L*/, GameObject* go) + { + go->SaveToDB(); + return 0; + } + + /** + * Removes [GameObject] from the world + * + * The object is no longer reachable after this and it is not respawned. + * + * @param bool deleteFromDB : if true, it will delete the [GameObject] from the database + */ + int RemoveFromWorld(lua_State* L, GameObject* go) + { + bool deldb = Eluna::CHECKVAL(L, 2, false); + + // cs_gobject.cpp copy paste + ObjectGuid ownerGuid = go->GetOwnerGUID(); + if (ownerGuid) + { + Unit* owner = eObjectAccessor()GetUnit(*go, ownerGuid); + if (!owner || !ownerGuid.IsPlayer()) + return 0; + + owner->RemoveGameObject(go, false); + } + + if (deldb) + GameObject::DeleteFromDB(go->GetSpawnId()); + + go->SetRespawnTime(0); + go->Delete(); + + Eluna::CHECKOBJ(L, 1)->Invalidate(); + return 0; + } + + /** + * Activates a door or a button/lever + * + * @param uint32 delay = 0 : cooldown time in seconds to restore the [GameObject] back to normal. 0 for infinite duration + */ + int UseDoorOrButton(lua_State* L, GameObject* go) + { + uint32 delay = Eluna::CHECKVAL(L, 2, 0); + + go->UseDoorOrButton(delay); + return 0; + } + + /** + * Despawns a [GameObject] + * + * The gameobject may be automatically respawned by the core + */ + int Despawn(lua_State* /*L*/, GameObject* go) + { + go->SetLootState(GO_JUST_DEACTIVATED); + return 0; + } + + /** + * Respawns a [GameObject] + */ + int Respawn(lua_State* /*L*/, GameObject* go) + { + go->Respawn(); + return 0; + } + + /** + * Sets the respawn or despawn time for the gameobject. + * + * Respawn time is also used as despawn time depending on gameobject settings + * + * @param int32 delay = 0 : cooldown time in seconds to respawn or despawn the object. 0 means never + */ + int SetRespawnTime(lua_State* L, GameObject* go) + { + int32 respawn = Eluna::CHECKVAL(L, 2); + + go->SetRespawnTime(respawn); + return 0; + } + + ElunaRegister GameObjectMethods[] = + { + // Getters + { "GetDisplayId", &LuaGameObject::GetDisplayId }, + { "GetGoState", &LuaGameObject::GetGoState }, + { "GetLootState", &LuaGameObject::GetLootState }, + { "GetLootRecipient", &LuaGameObject::GetLootRecipient }, + { "GetLootRecipientGroup", &LuaGameObject::GetLootRecipientGroup }, + { "GetDBTableGUIDLow", &LuaGameObject::GetDBTableGUIDLow }, + + // Setters + { "SetGoState", &LuaGameObject::SetGoState }, + { "SetLootState", &LuaGameObject::SetLootState }, + { "SetRespawnTime", &LuaGameObject::SetRespawnTime }, + + // Boolean + { "IsTransport", &LuaGameObject::IsTransport }, + { "IsDestructible", &LuaGameObject::IsDestructible }, + { "IsActive", &LuaGameObject::IsActive }, + { "HasQuest", &LuaGameObject::HasQuest }, + { "IsSpawned", &LuaGameObject::IsSpawned }, + + // Other + { "RemoveFromWorld", &LuaGameObject::RemoveFromWorld }, + { "UseDoorOrButton", &LuaGameObject::UseDoorOrButton }, + { "Despawn", &LuaGameObject::Despawn }, + { "Respawn", &LuaGameObject::Respawn }, + { "SaveToDB", &LuaGameObject::SaveToDB }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/GlobalMethods.h b/src/modules/Eluna/TrinityCore/GlobalMethods.h new file mode 100644 index 0000000000..fde19dc247 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/GlobalMethods.h @@ -0,0 +1,3017 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef GLOBALMETHODS_H +#define GLOBALMETHODS_H + +#include "BindingMap.h" + +/*** + * These functions can be used anywhere at any time, including at start-up. + */ +namespace LuaGlobalFunctions +{ + /** + * Returns Lua engine's name. + * + * Always returns "ElunaEngine" on Eluna. + * + * @return string engineName + */ + int GetLuaEngine(lua_State* L) + { + Eluna::Push(L, "ElunaEngine"); + return 1; + } + + /** + * Returns emulator's name. + * + * The result will be either `MaNGOS`, `cMaNGOS`, or `TrinityCore`. + * + * @return string coreName + */ + int GetCoreName(lua_State* L) + { + Eluna::Push(L, CORE_NAME); + return 1; + } + + /** + * Returns emulator .conf RealmID + * + * - for MaNGOS returns the realmID as it is stored in the core. + * - for TrinityCore returns the realmID as it is in the conf file. + * @return uint32 realm ID + */ + + int GetRealmID(lua_State* L) + { + Eluna::Push(L, sConfigMgr->GetIntDefault("RealmID", 1)); + return 1; + } + + /** + * Returns emulator version + * + * - For TrinityCore returns the date of the last revision, e.g. `2015-08-26 22:53:12 +0300` + * - For cMaNGOS returns the date and time of the last revision, e.g. `2015-09-06 13:18:50` + * - for MaNGOS returns the version number as string, e.g. `21000` + * + * @return string version + */ + int GetCoreVersion(lua_State* L) + { + Eluna::Push(L, CORE_VERSION); + return 1; + } + + /** + * Returns emulator's supported expansion. + * + * Expansion is 0 for pre-TBC, 1 for TBC, 2 for WotLK, and 3 for Cataclysm. + * + * @return int32 expansion + */ + int GetCoreExpansion(lua_State* L) + { +#ifdef WOTLK + Eluna::Push(L, 2); +#elif CATA + Eluna::Push(L, 3); +#endif + return 1; + } + + /** + * Returns [Quest] template + * + * @param uint32 questId : [Quest] entry ID + * @return [Quest] quest + */ + int GetQuest(lua_State* L) + { + uint32 questId = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, eObjectMgr->GetQuestTemplate(questId)); + return 1; + } + + /** + * Finds and Returns [Player] by guid if found + * + * @param ObjectGuid guid : guid of the [Player], you can get it with [Object:GetGUID] + * @return [Player] player + */ + int GetPlayerByGUID(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, eObjectAccessor()FindPlayer(guid)); + return 1; + } + + /** + * Finds and Returns [Player] by name if found + * + * @param string name : name of the [Player] + * @return [Player] player + */ + int GetPlayerByName(lua_State* L) + { + const char* name = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, eObjectAccessor()FindPlayerByName(name)); + return 1; + } + + /** + * Returns game time in seconds + * + * @return uint32 time + */ + int GetGameTime(lua_State* L) + { + Eluna::Push(L, GameTime::GetGameTime()); + return 1; + } + + /** + * Returns a table with all the current [Player]s in the world + * + * Does not return players that may be teleporting or otherwise not on any map. + * + * enum TeamId + * { + * TEAM_ALLIANCE = 0, + * TEAM_HORDE = 1, + * TEAM_NEUTRAL = 2 + * }; + * + * @param [TeamId] team = TEAM_NEUTRAL : optional check team of the [Player], Alliance, Horde or Neutral (All) + * @param bool onlyGM = false : optional check if GM only + * @return table worldPlayers + */ + int GetPlayersInWorld(lua_State* L) + { + uint32 team = Eluna::CHECKVAL(L, 1, TEAM_NEUTRAL); + bool onlyGM = Eluna::CHECKVAL(L, 2, false); + + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 i = 0; + + std::shared_lock lock(*HashMapHolder::GetLock()); + const HashMapHolder::MapType& m = eObjectAccessor()GetPlayers(); + for (HashMapHolder::MapType::const_iterator it = m.begin(); it != m.end(); ++it) + { + if (Player* player = it->second) + { + if (!player->IsInWorld()) + continue; + + if ((team == TEAM_NEUTRAL || player->GetTeamId() == team) && (!onlyGM || player->IsGameMaster())) + { + Eluna::Push(L, player); + lua_rawseti(L, tbl, ++i); + } + } + } + + lua_settop(L, tbl); // push table to top of stack + return 1; + } + + /** + * Returns a [Guild] by name. + * + * @param string name + * @return [Guild] guild : the Guild, or `nil` if it doesn't exist + */ + int GetGuildByName(lua_State* L) + { + const char* name = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, eGuildMgr->GetGuildByName(name)); + return 1; + } + + /** + * Returns a [Map] by ID. + * + * @param uint32 mapId : see [Map.dbc](https://github.com/cmangos/issues/wiki/Map.dbc) + * @param uint32 instanceId = 0 : required if the map is an instance, otherwise don't pass anything + * @return [Map] map : the Map, or `nil` if it doesn't exist + */ + int GetMapById(lua_State* L) + { + uint32 mapid = Eluna::CHECKVAL(L, 1); + uint32 instance = Eluna::CHECKVAL(L, 2, 0); + + Eluna::Push(L, eMapMgr->FindMap(mapid, instance)); + return 1; + } + + /** + * Returns [Guild] by the leader's GUID + * + * @param ObjectGuid guid : the guid of a [Guild] leader + * @return [Guild] guild, or `nil` if it doesn't exist + */ + int GetGuildByLeaderGUID(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, eGuildMgr->GetGuildByLeader(guid)); + return 1; + } + + /** + * Returns the amount of [Player]s in the world. + * + * @return uint32 count + */ + int GetPlayerCount(lua_State* L) + { + Eluna::Push(L, eWorld->GetActiveSessionCount()); + return 1; + } + + /** + * Builds a [Player]'s GUID + * + * [Player] GUID consist of low GUID and type ID + * + * [Player] and [Creature] for example can have the same low GUID but not GUID. + * + * @param uint32 lowguid : low GUID of the [Player] + * @return ObjectGuid guid + */ + int GetPlayerGUID(lua_State* L) + { + uint32 lowguid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, MAKE_NEW_GUID(lowguid, 0, HIGHGUID_PLAYER)); + return 1; + } + + /** + * Builds an [Item]'s GUID. + * + * [Item] GUID consist of low GUID and type ID + * [Player] and [Item] for example can have the same low GUID but not GUID. + * + * @param uint32 lowguid : low GUID of the [Item] + * @return ObjectGuid guid + */ + int GetItemGUID(lua_State* L) + { + uint32 lowguid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, MAKE_NEW_GUID(lowguid, 0, HIGHGUID_ITEM)); + return 1; + } + + /** + * Builds a [GameObject]'s GUID. + * + * A GameObject's GUID consist of entry ID, low GUID and type ID + * + * A [Player] and GameObject for example can have the same low GUID but not GUID. + * + * @param uint32 lowguid : low GUID of the [GameObject] + * @param uint32 entry : entry ID of the [GameObject] + * @return ObjectGuid guid + */ + int GetObjectGUID(lua_State* L) + { + uint32 lowguid = Eluna::CHECKVAL(L, 1); + uint32 entry = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, MAKE_NEW_GUID(lowguid, entry, HIGHGUID_GAMEOBJECT)); + return 1; + } + + /** + * Builds a [Creature]'s GUID. + * + * [Creature] GUID consist of entry ID, low GUID and type ID + * + * [Player] and [Creature] for example can have the same low GUID but not GUID. + * + * @param uint32 lowguid : low GUID of the [Creature] + * @param uint32 entry : entry ID of the [Creature] + * @return ObjectGuid guid + */ + int GetUnitGUID(lua_State* L) + { + uint32 lowguid = Eluna::CHECKVAL(L, 1); + uint32 entry = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, MAKE_NEW_GUID(lowguid, entry, HIGHGUID_UNIT)); + return 1; + } + + /** + * Returns the low GUID from a GUID. + * + * A GUID consists of a low GUID, type ID, and possibly an entry ID depending on the type ID. + * + * Low GUID is an ID to distinct the objects of the same type. + * + * [Player] and [Creature] for example can have the same low GUID but not GUID. + * + * On TrinityCore all low GUIDs are different for all objects of the same type. + * For example creatures in instances are assigned new GUIDs when the Map is created. + * + * On MaNGOS and cMaNGOS low GUIDs are unique only on the same map. + * For example creatures in instances use the same low GUID assigned for that spawn in the database. + * This is why to identify a creature you have to know the instanceId and low GUID. See [Map:GetIntstanceId] + * + * @param ObjectGuid guid : GUID of an [Object] + * @return uint32 lowguid : low GUID of the [Object] + */ + int GetGUIDLow(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, guid.GetCounter()); + return 1; + } + + /** + * Returns an chat link for an [Item]. + * + * enum LocaleConstant + * { + * LOCALE_enUS = 0, + * LOCALE_koKR = 1, + * LOCALE_frFR = 2, + * LOCALE_deDE = 3, + * LOCALE_zhCN = 4, + * LOCALE_zhTW = 5, + * LOCALE_esES = 6, + * LOCALE_esMX = 7, + * LOCALE_ruRU = 8 + * }; + * + * @param uint32 entry : entry ID of an [Item] + * @param [LocaleConstant] locale = DEFAULT_LOCALE : locale to return the [Item] name in + * @return string itemLink + */ + int GetItemLink(lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const ItemTemplate* temp = eObjectMgr->GetItemTemplate(entry); + if (!temp) + return luaL_argerror(L, 1, "valid ItemEntry expected"); + +#ifdef CATA + std::string name = temp->ExtendedData->Display->Str[locale]; +#else + std::string name = temp->Name1; +#endif + if (ItemLocale const* il = eObjectMgr->GetItemLocale(entry)) + ObjectMgr::GetLocaleString(il->Name, static_cast(locale), name); + + std::ostringstream oss; +#ifdef CATA + oss << "|c" << std::hex << ItemQualityColors[temp->ExtendedData->Quality] << std::dec << +#else + oss << "|c" << std::hex << ItemQualityColors[temp->Quality] << std::dec << +#endif + "|Hitem:" << entry << ":0:" << + "0:0:0:0:" << + "0:0:0:0|h[" << name << "]|h|r"; + + Eluna::Push(L, oss.str()); + return 1; + } + + /** + * Returns the type ID from a GUID. + * + * Type ID is different for each type ([Player], [Creature], [GameObject], etc.). + * + * GUID consist of entry ID, low GUID, and type ID. + * + * @param ObjectGuid guid : GUID of an [Object] + * @return int32 typeId : type ID of the [Object] + */ + int GetGUIDType(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, static_cast(guid.GetHigh())); + return 1; + } + + /** + * Returns the entry ID from a GUID. + * + * GUID consist of entry ID, low GUID, and type ID. + * + * @param ObjectGuid guid : GUID of an [Creature] or [GameObject] + * @return uint32 entry : entry ID, or `0` if `guid` is not a [Creature] or [GameObject] + */ + int GetGUIDEntry(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, guid.GetEntry()); + return 1; + } + + /** + * Returns the area or zone's name. + * + * enum LocaleConstant + * { + * LOCALE_enUS = 0, + * LOCALE_koKR = 1, + * LOCALE_frFR = 2, + * LOCALE_deDE = 3, + * LOCALE_zhCN = 4, + * LOCALE_zhTW = 5, + * LOCALE_esES = 6, + * LOCALE_esMX = 7, + * LOCALE_ruRU = 8 + * }; + * + * @param uint32 areaOrZoneId : area ID or zone ID + * @param [LocaleConstant] locale = DEFAULT_LOCALE : locale to return the name in + * @return string areaOrZoneName + */ + int GetAreaName(lua_State* L) + { + uint32 areaOrZoneId = Eluna::CHECKVAL(L, 1); + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaOrZoneId); + if (!areaEntry) + return luaL_argerror(L, 1, "valid Area or Zone ID expected"); + + Eluna::Push(L, areaEntry->AreaName[locale]); + return 1; + } + + /** + * Returns the currently active game events. + * + * @return table activeEvents + */ + int GetActiveGameEvents(lua_State* L) + { + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 counter = 1; + GameEventMgr::ActiveEvents const& activeEvents = eGameEventMgr->GetActiveEventList(); + + for (GameEventMgr::ActiveEvents::const_iterator i = activeEvents.begin(); i != activeEvents.end(); ++i) + { + Eluna::Push(L, *i); + lua_rawseti(L, tbl, counter); + + counter++; + } + + lua_settop(L, tbl); + return 1; + } + + static int RegisterEntryHelper(lua_State* L, int regtype) + { + uint32 id = Eluna::CHECKVAL(L, 1); + uint32 ev = Eluna::CHECKVAL(L, 2); + luaL_checktype(L, 3, LUA_TFUNCTION); + uint32 shots = Eluna::CHECKVAL(L, 4, 0); + + lua_pushvalue(L, 3); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef >= 0) + return Eluna::GetEluna(L)->Register(L, regtype, id, ObjectGuid(), 0, ev, functionRef, shots); + else + luaL_argerror(L, 3, "unable to make a ref to function"); + return 0; + } + + static int RegisterEventHelper(lua_State* L, int regtype) + { + uint32 ev = Eluna::CHECKVAL(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + uint32 shots = Eluna::CHECKVAL(L, 3, 0); + + lua_pushvalue(L, 2); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef >= 0) + return Eluna::GetEluna(L)->Register(L, regtype, 0, ObjectGuid(), 0, ev, functionRef, shots); + else + luaL_argerror(L, 2, "unable to make a ref to function"); + return 0; + } + + static int RegisterUniqueHelper(lua_State* L, int regtype) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + uint32 instanceId = Eluna::CHECKVAL(L, 2); + uint32 ev = Eluna::CHECKVAL(L, 3); + luaL_checktype(L, 4, LUA_TFUNCTION); + uint32 shots = Eluna::CHECKVAL(L, 5, 0); + + lua_pushvalue(L, 4); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef >= 0) + return Eluna::GetEluna(L)->Register(L, regtype, 0, guid, instanceId, ev, functionRef, shots); + else + luaL_argerror(L, 4, "unable to make a ref to function"); + return 0; + } + + /** + * Registers a server event handler. + * + * enum ServerEvents + * { + * // Server + * SERVER_EVENT_ON_NETWORK_START = 1, // Not Implemented + * SERVER_EVENT_ON_NETWORK_STOP = 2, // Not Implemented + * SERVER_EVENT_ON_SOCKET_OPEN = 3, // Not Implemented + * SERVER_EVENT_ON_SOCKET_CLOSE = 4, // Not Implemented + * SERVER_EVENT_ON_PACKET_RECEIVE = 5, // (event, packet, player) - Player only if accessible. Can return false, newPacket + * SERVER_EVENT_ON_PACKET_RECEIVE_UNKNOWN = 6, // Not Implemented + * SERVER_EVENT_ON_PACKET_SEND = 7, // (event, packet, player) - Player only if accessible. Can return false + * + * // World + * WORLD_EVENT_ON_OPEN_STATE_CHANGE = 8, // (event, open) - Needs core support on Mangos + * WORLD_EVENT_ON_CONFIG_LOAD = 9, // (event, reload) + * // UNUSED = 10, + * WORLD_EVENT_ON_SHUTDOWN_INIT = 11, // (event, code, mask) + * WORLD_EVENT_ON_SHUTDOWN_CANCEL = 12, // (event) + * WORLD_EVENT_ON_UPDATE = 13, // (event, diff) + * WORLD_EVENT_ON_STARTUP = 14, // (event) + * WORLD_EVENT_ON_SHUTDOWN = 15, // (event) + * + * // Eluna + * ELUNA_EVENT_ON_LUA_STATE_CLOSE = 16, // (event) - triggers just before shutting down eluna (on shutdown and restart) + * + * // Map + * MAP_EVENT_ON_CREATE = 17, // (event, map) + * MAP_EVENT_ON_DESTROY = 18, // (event, map) + * MAP_EVENT_ON_GRID_LOAD = 19, // Not Implemented + * MAP_EVENT_ON_GRID_UNLOAD = 20, // Not Implemented + * MAP_EVENT_ON_PLAYER_ENTER = 21, // (event, map, player) + * MAP_EVENT_ON_PLAYER_LEAVE = 22, // (event, map, player) + * MAP_EVENT_ON_UPDATE = 23, // (event, map, diff) + * + * // Area trigger + * TRIGGER_EVENT_ON_TRIGGER = 24, // (event, player, triggerId) - Can return true + * + * // Weather + * WEATHER_EVENT_ON_CHANGE = 25, // (event, zoneId, state, grade) + * + * // Auction house + * AUCTION_EVENT_ON_ADD = 26, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) + * AUCTION_EVENT_ON_REMOVE = 27, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) + * AUCTION_EVENT_ON_SUCCESSFUL = 28, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) + * AUCTION_EVENT_ON_EXPIRE = 29, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) + * + * // AddOns + * ADDON_EVENT_ON_MESSAGE = 30, // (event, sender, type, prefix, msg, target) - target can be nil/whisper_target/guild/group/channel. Can return false + * + * WORLD_EVENT_ON_DELETE_CREATURE = 31, // (event, creature) + * WORLD_EVENT_ON_DELETE_GAMEOBJECT = 32, // (event, gameobject) + * + * // Eluna + * ELUNA_EVENT_ON_LUA_STATE_OPEN = 33, // (event) - triggers after all scripts are loaded + * + * GAME_EVENT_START = 34, // (event, gameeventid) + * GAME_EVENT_STOP = 35, // (event, gameeventid) + * }; + * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : server event ID, refer to ServerEvents above + * @param function function : function that will be called when the event occurs + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterServerEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_SERVER); + } + + /** + * Registers a [Player] event handler. + * + *
+     * enum PlayerEvents
+     * {
+     *     PLAYER_EVENT_ON_CHARACTER_CREATE        =     1,        // (event, player)
+     *     PLAYER_EVENT_ON_CHARACTER_DELETE        =     2,        // (event, guid)
+     *     PLAYER_EVENT_ON_LOGIN                   =     3,        // (event, player)
+     *     PLAYER_EVENT_ON_LOGOUT                  =     4,        // (event, player)
+     *     PLAYER_EVENT_ON_SPELL_CAST              =     5,        // (event, player, spell, skipCheck)
+     *     PLAYER_EVENT_ON_KILL_PLAYER             =     6,        // (event, killer, killed)
+     *     PLAYER_EVENT_ON_KILL_CREATURE           =     7,        // (event, killer, killed)
+     *     PLAYER_EVENT_ON_KILLED_BY_CREATURE      =     8,        // (event, killer, killed)
+     *     PLAYER_EVENT_ON_DUEL_REQUEST            =     9,        // (event, target, challenger)
+     *     PLAYER_EVENT_ON_DUEL_START              =     10,       // (event, player1, player2)
+     *     PLAYER_EVENT_ON_DUEL_END                =     11,       // (event, winner, loser, type)
+     *     PLAYER_EVENT_ON_GIVE_XP                 =     12,       // (event, player, amount, victim) - Can return new XP amount
+     *     PLAYER_EVENT_ON_LEVEL_CHANGE            =     13,       // (event, player, oldLevel)
+     *     PLAYER_EVENT_ON_MONEY_CHANGE            =     14,       // (event, player, amount) - Can return new money amount
+     *     PLAYER_EVENT_ON_REPUTATION_CHANGE       =     15,       // (event, player, factionId, standing, incremental) - Can return new standing
+     *     PLAYER_EVENT_ON_TALENTS_CHANGE          =     16,       // (event, player, points)
+     *     PLAYER_EVENT_ON_TALENTS_RESET           =     17,       // (event, player, noCost)
+     *     PLAYER_EVENT_ON_CHAT                    =     18,       // (event, player, msg, Type, lang) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_WHISPER                 =     19,       // (event, player, msg, Type, lang, receiver) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_GROUP_CHAT              =     20,       // (event, player, msg, Type, lang, group) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_GUILD_CHAT              =     21,       // (event, player, msg, Type, lang, guild) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_CHANNEL_CHAT            =     22,       // (event, player, msg, Type, lang, channel) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_EMOTE                   =     23,       // (event, player, emote) - Not triggered on any known emote
+     *     PLAYER_EVENT_ON_TEXT_EMOTE              =     24,       // (event, player, textEmote, emoteNum, guid)
+     *     PLAYER_EVENT_ON_SAVE                    =     25,       // (event, player)
+     *     PLAYER_EVENT_ON_BIND_TO_INSTANCE        =     26,       // (event, player, difficulty, mapid, permanent)
+     *     PLAYER_EVENT_ON_UPDATE_ZONE             =     27,       // (event, player, newZone, newArea)
+     *     PLAYER_EVENT_ON_MAP_CHANGE              =     28,       // (event, player)
+     *
+     *     // Custom
+     *     PLAYER_EVENT_ON_EQUIP                   =     29,       // (event, player, item, bag, slot)
+     *     PLAYER_EVENT_ON_FIRST_LOGIN             =     30,       // (event, player)
+     *     PLAYER_EVENT_ON_CAN_USE_ITEM            =     31,       // (event, player, itemEntry) - Can return InventoryResult enum value
+     *     PLAYER_EVENT_ON_LOOT_ITEM               =     32,       // (event, player, item, count)
+     *     PLAYER_EVENT_ON_ENTER_COMBAT            =     33,       // (event, player, enemy)
+     *     PLAYER_EVENT_ON_LEAVE_COMBAT            =     34,       // (event, player)
+     *     PLAYER_EVENT_ON_REPOP                   =     35,       // (event, player)
+     *     PLAYER_EVENT_ON_RESURRECT               =     36,       // (event, player)
+     *     PLAYER_EVENT_ON_LOOT_MONEY              =     37,       // (event, player, amount)
+     *     PLAYER_EVENT_ON_QUEST_ABANDON           =     38,       // (event, player, questId)
+     *     PLAYER_EVENT_ON_LEARN_TALENTS           =     39,       // (event, player, talentId, talentRank, spellid)
+     *     PLAYER_EVENT_ON_ENVIRONMENTAL_DEATH     =     40,       // (event, player, environmentalDamageType)
+     *     PLAYER_EVENT_ON_TRADE_ACCEPT            =     41,       // (event, player, target) - Can return false to interrupt trade
+     *     PLAYER_EVENT_ON_COMMAND                 =     42,       // (event, player, command) - player is nil if command used from console. Can return false
+     *     PLAYER_EVENT_ON_SKILL_CHANGE            =     43,       // (event, player, skillId, skillValue) - Returns new skill level value
+     *     PLAYER_EVENT_ON_LEARN_SPELL             =     44,       // (event, player, spellId)
+     *     PLAYER_EVENT_ON_ACHIEVEMENT_COMPLETE    =     45,       // (event, player, achievementId)
+     *     // UNUSED                               =     46,       // (event, player)
+     *     PLAYER_EVENT_ON_UPDATE_AREA             =     47,       // (event, player, oldArea, newArea)
+     *     PLAYER_EVENT_ON_TRADE_INIT              =     48,       // (event, player, target) - Can return false to interrupt trade
+     *     PLAYER_EVENT_ON_SEND_MAIL               =     49,       // (event, player, recipientGuid) - Can return false to interrupt sending
+     *     // UNUSED                               =     50,       // (event, player)
+     *     // UNUSED                               =     51,       // (event, player)
+     *     // UNUSED                               =     52,       // (event, player)
+     *     // UNUSED                               =     53,       // (event, player)
+     *     PLAYER_EVENT_ON_QUEST_STATUS_CHANGED    =     54,       // (event, player, questId, status)
+     * };
+     * 
+ * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : [Player] event Id, refer to PlayerEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterPlayerEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_PLAYER); + } + + /** + * Registers a [Guild] event handler. + * + *
+     * enum GuildEvents
+     * {
+     *     // Guild
+     *     GUILD_EVENT_ON_ADD_MEMBER               =     1,       // (event, guild, player, rank)
+     *     GUILD_EVENT_ON_REMOVE_MEMBER            =     2,       // (event, guild, player, isDisbanding)
+     *     GUILD_EVENT_ON_MOTD_CHANGE              =     3,       // (event, guild, newMotd)
+     *     GUILD_EVENT_ON_INFO_CHANGE              =     4,       // (event, guild, newInfo)
+     *     GUILD_EVENT_ON_CREATE                   =     5,       // (event, guild, leader, name)  // Not on TC
+     *     GUILD_EVENT_ON_DISBAND                  =     6,       // (event, guild)
+     *     GUILD_EVENT_ON_MONEY_WITHDRAW           =     7,       // (event, guild, player, amount, isRepair) - Can return new money amount
+     *     GUILD_EVENT_ON_MONEY_DEPOSIT            =     8,       // (event, guild, player, amount) - Can return new money amount
+     *     GUILD_EVENT_ON_ITEM_MOVE                =     9,       // (event, guild, player, item, isSrcBank, srcContainer, srcSlotId, isDestBank, destContainer, destSlotId)   // TODO
+     *     GUILD_EVENT_ON_EVENT                    =     10,      // (event, guild, eventType, plrGUIDLow1, plrGUIDLow2, newRank)  // TODO
+     *     GUILD_EVENT_ON_BANK_EVENT               =     11,      // (event, guild, eventType, tabId, playerGUIDLow, itemOrMoney, itemStackCount, destTabId)
+     *
+     *     GUILD_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : [Guild] event Id, refer to GuildEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterGuildEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_GUILD); + } + + /** + * Registers a [Group] event handler. + * + *
+     * enum GroupEvents
+     * {
+     *     // Group
+     *     GROUP_EVENT_ON_MEMBER_ADD               =     1,       // (event, group, guid)
+     *     GROUP_EVENT_ON_MEMBER_INVITE            =     2,       // (event, group, guid)
+     *     GROUP_EVENT_ON_MEMBER_REMOVE            =     3,       // (event, group, guid, method, kicker, reason)
+     *     GROUP_EVENT_ON_LEADER_CHANGE            =     4,       // (event, group, newLeaderGuid, oldLeaderGuid)
+     *     GROUP_EVENT_ON_DISBAND                  =     5,       // (event, group)
+     *     GROUP_EVENT_ON_CREATE                   =     6,       // (event, group, leaderGuid, groupType)
+     *     GROUP_EVENT_ON_MEMBER_ACCEPT            =     7,       // (event, group, player) - Can return false to disable accepting
+     *
+     *     GROUP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : [Group] event Id, refer to GroupEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterGroupEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_GROUP); + } + + /** + * Registers a [BattleGround] event handler. + * + *
+     * enum BGEvents
+     * {
+     *     BG_EVENT_ON_START                               = 1,    // (event, bg, bgId, instanceId) - Needs to be added to TC
+     *     BG_EVENT_ON_END                                 = 2,    // (event, bg, bgId, instanceId, winner) - Needs to be added to TC
+     *     BG_EVENT_ON_CREATE                              = 3,    // (event, bg, bgId, instanceId) - Needs to be added to TC
+     *     BG_EVENT_ON_PRE_DESTROY                         = 4,    // (event, bg, bgId, instanceId) - Needs to be added to TC
+     *     BG_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : [BattleGround] event Id, refer to BGEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterBGEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_BG); + } + + /** + * Registers a [WorldPacket] event handler. + * + *
+     * enum PacketEvents
+     * {
+     *     PACKET_EVENT_ON_PACKET_RECEIVE          =     5,       // (event, packet, player) - Player only if accessible. Can return false, newPacket
+     *     PACKET_EVENT_ON_PACKET_RECEIVE_UNKNOWN  =     6,       // Not Implemented
+     *     PACKET_EVENT_ON_PACKET_SEND             =     7,       // (event, packet, player) - Player only if accessible. Can return false
+     *
+     *     PACKET_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : opcode + * @param uint32 event : packet event Id, refer to PacketEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterPacketEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_PACKET); + } + + /** + * Registers a [Creature] gossip event handler. + * + *
+     * enum GossipEvents
+     * {
+     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
+     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
+     *     GOSSIP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [Creature] entry Id + * @param uint32 event : [Creature] gossip event Id, refer to GossipEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterCreatureGossipEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_CREATURE_GOSSIP); + } + + /** + * Registers a [GameObject] gossip event handler. + * + *
+     * enum GossipEvents
+     * {
+     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
+     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
+     *     GOSSIP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [GameObject] entry Id + * @param uint32 event : [GameObject] gossip event Id, refer to GossipEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterGameObjectGossipEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_GAMEOBJECT_GOSSIP); + } + + /** + * Registers an [Item] event handler. + * + *
+     * enum ItemEvents
+     * {
+     *     ITEM_EVENT_ON_DUMMY_EFFECT                      = 1,    // (event, caster, spellid, effindex, item)
+     *     ITEM_EVENT_ON_USE                               = 2,    // (event, player, item, target) - Can return false to stop the spell casting
+     *     ITEM_EVENT_ON_QUEST_ACCEPT                      = 3,    // (event, player, item, quest) - Can return true
+     *     ITEM_EVENT_ON_EXPIRE                            = 4,    // (event, player, itemid) - Can return true
+     *     ITEM_EVENT_ON_REMOVE                            = 5,    // (event, player, item) - Can return true
+     *     ITEM_EVENT_ON_ADD                               = 6,    // (event, player, item)
+     *     ITEM_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [Item] entry Id + * @param uint32 event : [Item] event Id, refer to ItemEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterItemEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_ITEM); + } + + /** + * Registers an [Item] gossip event handler. + * + *
+     * enum GossipEvents
+     * {
+     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
+     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
+     *     GOSSIP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [Item] entry Id + * @param uint32 event : [Item] gossip event Id, refer to GossipEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterItemGossipEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_ITEM_GOSSIP); + } + + /** + * Registers a [Map] event handler for all instance of a [Map]. + * + *
+     * enum InstanceEvents
+     * {
+     *     INSTANCE_EVENT_ON_INITIALIZE                    = 1,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_ON_LOAD                          = 2,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_ON_UPDATE                        = 3,    // (event, instance_data, map, diff)
+     *     INSTANCE_EVENT_ON_PLAYER_ENTER                  = 4,    // (event, instance_data, map, player)
+     *     INSTANCE_EVENT_ON_CREATURE_CREATE               = 5,    // (event, instance_data, map, creature)
+     *     INSTANCE_EVENT_ON_GAMEOBJECT_CREATE             = 6,    // (event, instance_data, map, go)
+     *     INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS   = 7,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_COUNT
+     * };
+     * 
+ * + * @param uint32 map_id : ID of a [Map] + * @param uint32 event : [Map] event ID, refer to MapEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + */ + int RegisterMapEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_MAP); + } + + /** + * Registers a [Map] event handler for one instance of a [Map]. + * + *
+     * enum InstanceEvents
+     * {
+     *     INSTANCE_EVENT_ON_INITIALIZE                    = 1,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_ON_LOAD                          = 2,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_ON_UPDATE                        = 3,    // (event, instance_data, map, diff)
+     *     INSTANCE_EVENT_ON_PLAYER_ENTER                  = 4,    // (event, instance_data, map, player)
+     *     INSTANCE_EVENT_ON_CREATURE_CREATE               = 5,    // (event, instance_data, map, creature)
+     *     INSTANCE_EVENT_ON_GAMEOBJECT_CREATE             = 6,    // (event, instance_data, map, go)
+     *     INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS   = 7,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_COUNT
+     * };
+     * 
+ * + * @param uint32 instance_id : ID of an instance of a [Map] + * @param uint32 event : [Map] event ID, refer to MapEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + */ + int RegisterInstanceEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_INSTANCE); + } + + /** + * Registers a [Player] gossip event handler. + * + * Note that you can not use `GOSSIP_EVENT_ON_HELLO` with this hook. It does nothing since players dont have an "on hello". + * + *
+     * enum GossipEvents
+     * {
+     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
+     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
+     *     GOSSIP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (menu_id, event, function) + * @proto cancel = (menu_id, event, function, shots) + * + * @param uint32 menu_id : [Player] gossip menu Id + * @param uint32 event : [Player] gossip event Id, refer to GossipEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterPlayerGossipEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_PLAYER_GOSSIP); + } + + /** + * Registers a [Creature] event handler. + * + *
+     * enum CreatureEvents
+     * {
+     *     CREATURE_EVENT_ON_ENTER_COMBAT                    = 1,  // (event, creature, target) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_LEAVE_COMBAT                    = 2,  // (event, creature) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_TARGET_DIED                     = 3,  // (event, creature, victim) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_DIED                            = 4,  // (event, creature, killer) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SPAWN                           = 5,  // (event, creature) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_REACH_WP                        = 6,  // (event, creature, type, id) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_AIUPDATE                        = 7,  // (event, creature, diff) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_RECEIVE_EMOTE                   = 8,  // (event, creature, player, emoteid) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_DAMAGE_TAKEN                    = 9,  // (event, creature, attacker, damage) - Can return true to stop normal action, can return new damage as second return value.
+     *     CREATURE_EVENT_ON_PRE_COMBAT                      = 10, // (event, creature, target) - Can return true to stop normal action
+     *     // UNUSED
+     *     CREATURE_EVENT_ON_OWNER_ATTACKED                  = 12, // (event, creature, target) - Can return true to stop normal action            // Not on mangos
+     *     CREATURE_EVENT_ON_OWNER_ATTACKED_AT               = 13, // (event, creature, attacker) - Can return true to stop normal action          // Not on mangos
+     *     CREATURE_EVENT_ON_HIT_BY_SPELL                    = 14, // (event, creature, caster, spellid) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SPELL_HIT_TARGET                = 15, // (event, creature, target, spellid) - Can return true to stop normal action
+     *     // UNUSED                                         = 16, // (event, creature)
+     *     // UNUSED                                         = 17, // (event, creature)
+     *     // UNUSED                                         = 18, // (event, creature)
+     *     CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE          = 19, // (event, creature, summon) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN       = 20, // (event, creature, summon) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED          = 21, // (event, creature, summon, killer) - Can return true to stop normal action    // Not on mangos
+     *     CREATURE_EVENT_ON_SUMMONED                        = 22, // (event, creature, summoner) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_RESET                           = 23, // (event, creature)
+     *     CREATURE_EVENT_ON_REACH_HOME                      = 24, // (event, creature) - Can return true to stop normal action
+     *     // UNUSED                                         = 25, // (event, creature)
+     *     CREATURE_EVENT_ON_CORPSE_REMOVED                  = 26, // (event, creature, respawndelay) - Can return true to stop normal action, can return new respawndelay as second return value
+     *     CREATURE_EVENT_ON_MOVE_IN_LOS                     = 27, // (event, creature, unit) - Can return true to stop normal action. Does not actually check LOS, just uses the sight range
+     *     // UNUSED                                         = 28, // (event, creature)
+     *     // UNUSED                                         = 29, // (event, creature)
+     *     CREATURE_EVENT_ON_DUMMY_EFFECT                    = 30, // (event, caster, spellid, effindex, creature)
+     *     CREATURE_EVENT_ON_QUEST_ACCEPT                    = 31, // (event, player, creature, quest) - Can return true
+     *     // UNUSED                                         = 32, // (event, creature)
+     *     // UNUSED                                         = 33, // (event, creature)
+     *     CREATURE_EVENT_ON_QUEST_REWARD                    = 34, // (event, player, creature, quest, opt) - Can return true
+     *     CREATURE_EVENT_ON_DIALOG_STATUS                   = 35, // (event, player, creature)
+     *     CREATURE_EVENT_ON_ADD                             = 36, // (event, creature)
+     *     CREATURE_EVENT_ON_REMOVE                          = 37, // (event, creature)
+     *     CREATURE_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : the ID of one or more [Creature]s + * @param uint32 event : refer to CreatureEvents above + * @param function function : function that will be called when the event occurs + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterCreatureEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_CREATURE); + } + + /** + * Registers a [Creature] event handler for a *single* [Creature]. + * + *
+     * enum CreatureEvents
+     * {
+     *     CREATURE_EVENT_ON_ENTER_COMBAT                    = 1,  // (event, creature, target) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_LEAVE_COMBAT                    = 2,  // (event, creature) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_TARGET_DIED                     = 3,  // (event, creature, victim) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_DIED                            = 4,  // (event, creature, killer) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SPAWN                           = 5,  // (event, creature) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_REACH_WP                        = 6,  // (event, creature, type, id) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_AIUPDATE                        = 7,  // (event, creature, diff) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_RECEIVE_EMOTE                   = 8,  // (event, creature, player, emoteid) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_DAMAGE_TAKEN                    = 9,  // (event, creature, attacker, damage) - Can return true to stop normal action, can return new damage as second return value.
+     *     CREATURE_EVENT_ON_PRE_COMBAT                      = 10, // (event, creature, target) - Can return true to stop normal action
+     *     // UNUSED
+     *     CREATURE_EVENT_ON_OWNER_ATTACKED                  = 12, // (event, creature, target) - Can return true to stop normal action            // Not on mangos
+     *     CREATURE_EVENT_ON_OWNER_ATTACKED_AT               = 13, // (event, creature, attacker) - Can return true to stop normal action          // Not on mangos
+     *     CREATURE_EVENT_ON_HIT_BY_SPELL                    = 14, // (event, creature, caster, spellid) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SPELL_HIT_TARGET                = 15, // (event, creature, target, spellid) - Can return true to stop normal action
+     *     // UNUSED                                         = 16, // (event, creature)
+     *     // UNUSED                                         = 17, // (event, creature)
+     *     // UNUSED                                         = 18, // (event, creature)
+     *     CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE          = 19, // (event, creature, summon) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN       = 20, // (event, creature, summon) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED          = 21, // (event, creature, summon, killer) - Can return true to stop normal action    // Not on mangos
+     *     CREATURE_EVENT_ON_SUMMONED                        = 22, // (event, creature, summoner) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_RESET                           = 23, // (event, creature)
+     *     CREATURE_EVENT_ON_REACH_HOME                      = 24, // (event, creature) - Can return true to stop normal action
+     *     // UNUSED                                         = 25, // (event, creature)
+     *     CREATURE_EVENT_ON_CORPSE_REMOVED                  = 26, // (event, creature, respawndelay) - Can return true to stop normal action, can return new respawndelay as second return value
+     *     CREATURE_EVENT_ON_MOVE_IN_LOS                     = 27, // (event, creature, unit) - Can return true to stop normal action. Does not actually check LOS, just uses the sight range
+     *     // UNUSED                                         = 28, // (event, creature)
+     *     // UNUSED                                         = 29, // (event, creature)
+     *     CREATURE_EVENT_ON_DUMMY_EFFECT                    = 30, // (event, caster, spellid, effindex, creature)
+     *     CREATURE_EVENT_ON_QUEST_ACCEPT                    = 31, // (event, player, creature, quest) - Can return true
+     *     // UNUSED                                         = 32, // (event, creature)
+     *     // UNUSED                                         = 33, // (event, creature)
+     *     CREATURE_EVENT_ON_QUEST_REWARD                    = 34, // (event, player, creature, quest, opt) - Can return true
+     *     CREATURE_EVENT_ON_DIALOG_STATUS                   = 35, // (event, player, creature)
+     *     CREATURE_EVENT_ON_ADD                             = 36, // (event, creature)
+     *     CREATURE_EVENT_ON_REMOVE                          = 37, // (event, creature)
+     *     CREATURE_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (guid, instance_id, event, function) + * @proto cancel = (guid, instance_id, event, function, shots) + * + * @param ObjectGuid guid : the GUID of a single [Creature] + * @param uint32 instance_id : the instance ID of a single [Creature] + * @param uint32 event : refer to CreatureEvents above + * @param function function : function that will be called when the event occurs + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterUniqueCreatureEvent(lua_State* L) + { + return RegisterUniqueHelper(L, Hooks::REGTYPE_CREATURE); + } + + /** + * Registers a [GameObject] event handler. + * + *
+     * enum GameObjectEvents
+     * {
+     *     GAMEOBJECT_EVENT_ON_AIUPDATE                    = 1,    // (event, go, diff)
+     *     GAMEOBJECT_EVENT_ON_SPAWN                       = 2,    // (event, go)
+     *     GAMEOBJECT_EVENT_ON_DUMMY_EFFECT                = 3,    // (event, caster, spellid, effindex, go) - Can return true to stop normal action
+     *     GAMEOBJECT_EVENT_ON_QUEST_ACCEPT                = 4,    // (event, player, go, quest) - Can return true to stop normal action
+     *     GAMEOBJECT_EVENT_ON_QUEST_REWARD                = 5,    // (event, player, go, quest, opt) - Can return true to stop normal action
+     *     GAMEOBJECT_EVENT_ON_DIALOG_STATUS               = 6,    // (event, player, go)
+     *     GAMEOBJECT_EVENT_ON_DESTROYED                   = 7,    // (event, go, attacker)
+     *     GAMEOBJECT_EVENT_ON_DAMAGED                     = 8,    // (event, go, attacker)
+     *     GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE           = 9,    // (event, go, state)
+     *     GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED            = 10,   // (event, go, state)
+     *     // UNUSED                                       = 11,   // (event, gameobject)
+     *     GAMEOBJECT_EVENT_ON_ADD                         = 12,   // (event, gameobject)
+     *     GAMEOBJECT_EVENT_ON_REMOVE                      = 13,   // (event, gameobject)
+     *     GAMEOBJECT_EVENT_ON_USE                         = 14,   // (event, go, player) - Can return true to stop normal action
+     *     GAMEOBJECT_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [GameObject] entry Id + * @param uint32 event : [GameObject] event Id, refer to GameObjectEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterGameObjectEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_GAMEOBJECT); + } + + /** + * Reloads the Lua engine. + */ + int ReloadEluna(lua_State* /*L*/) + { + Eluna::ReloadEluna(); + return 0; + } + + /** + * Runs a command. + * + * @param string command : the command to run + */ + int RunCommand(lua_State* L) + { + const char* command = Eluna::CHECKVAL(L, 1); + // ignores output of the command +#ifdef CATA + eWorld->QueueCliCommand(new CliCommandHolder(nullptr, command, nullptr, [](void*, bool) {})); +#else + eWorld->QueueCliCommand(new CliCommandHolder(nullptr, command, [](void*, std::string_view) {}, [](void*, bool) {})); +#endif + return 0; + } + + /** + * Sends a message to all [Player]s online. + * + * @param string message : message to send + */ + int SendWorldMessage(lua_State* L) + { + const char* message = Eluna::CHECKVAL(L, 1); + eWorld->SendServerMessage(SERVER_MSG_STRING, message); + return 0; + } + + /** + * Executes a SQL query on the world database and returns an [ElunaQuery]. + * + * The query is always executed synchronously + * (i.e. execution halts until the query has finished and then results are returned). + * + * local Q = WorldDBQuery("SELECT entry, name FROM creature_template LIMIT 10") + * if Q then + * repeat + * local entry, name = Q:GetUInt32(0), Q:GetString(1) + * print(entry, name) + * until not Q:NextRow() + * end + * + * @param string sql : query to execute + * @return [ElunaQuery] results or nil if no rows found or nil if no rows found + */ + int WorldDBQuery(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + + ElunaQuery result = WorldDatabase.Query(query); + if (result) + Eluna::Push(L, new ElunaQuery(result)); + else + Eluna::Push(L); + + return 1; + } + + /** + * Executes a SQL query on the world database. + * + * The query may be executed *asynchronously* (at a later, unpredictable time). + * If you need to execute the query synchronously, use [Global:WorldDBQuery] instead. + * + * Any results produced are ignored. + * If you need results from the query, use [Global:WorldDBQuery] instead. + * + * WorldDBExecute("DELETE FROM my_table") + * + * @param string sql : query to execute + */ + int WorldDBExecute(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + WorldDatabase.Execute(query); + return 0; + } + + /** + * Executes a SQL query on the character database and returns an [ElunaQuery]. + * + * The query is always executed synchronously + * (i.e. execution halts until the query has finished and then results are returned). + * + * For an example see [Global:WorldDBQuery]. + * + * @param string sql : query to execute + * @return [ElunaQuery] results or nil if no rows found + */ + int CharDBQuery(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + + QueryResult result = CharacterDatabase.Query(query); + if (result) + Eluna::Push(L, new QueryResult(result)); + else + Eluna::Push(L); + + return 1; + } + + /** + * Executes a SQL query on the character database. + * + * The query may be executed *asynchronously* (at a later, unpredictable time). + * If you need to execute the query synchronously, use [Global:CharDBQuery] instead. + * + * Any results produced are ignored. + * If you need results from the query, use [Global:CharDBQuery] instead. + * + * CharDBExecute("DELETE FROM my_table") + * + * @param string sql : query to execute + */ + int CharDBExecute(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + CharacterDatabase.Execute(query); + return 0; + } + + /** + * Executes a SQL query on the login database and returns an [ElunaQuery]. + * + * The query is always executed synchronously + * (i.e. execution halts until the query has finished and then results are returned). + * + * For an example see [Global:WorldDBQuery]. + * + * @param string sql : query to execute + * @return [ElunaQuery] results or nil if no rows found + */ + int AuthDBQuery(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + + QueryResult result = LoginDatabase.Query(query); + if (result) + Eluna::Push(L, new QueryResult(result)); + else + Eluna::Push(L); + + return 1; + } + + /** + * Executes a SQL query on the login database. + * + * The query may be executed *asynchronously* (at a later, unpredictable time). + * If you need to execute the query synchronously, use [Global:AuthDBQuery] instead. + * + * Any results produced are ignored. + * If you need results from the query, use [Global:AuthDBQuery] instead. + * + * AuthDBExecute("DELETE FROM my_table") + * + * @param string sql : query to execute + */ + int AuthDBExecute(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + LoginDatabase.Execute(query); + return 0; + } + + /** + * Registers a global timed event. + * + * When the passed function is called, the parameters `(eventId, delay, repeats)` are passed to it. + * + * Repeats will decrease on each call if the event does not repeat indefinitely + * + * @proto eventId = (function, delay) + * @proto eventId = (function, delaytable) + * @proto eventId = (function, delay, repeats) + * @proto eventId = (function, delaytable, repeats) + * + * @param function function : function to trigger when the time has passed + * @param uint32 delay : set time in milliseconds for the event to trigger + * @param table delaytable : a table `{min, max}` containing the minimum and maximum delay time + * @param uint32 repeats = 1 : how many times for the event to repeat, 0 is infinite + * @return int eventId : unique ID for the timed event used to cancel it or nil + */ + int CreateLuaEvent(lua_State* L) + { + luaL_checktype(L, 1, LUA_TFUNCTION); + uint32 min, max; + if (lua_istable(L, 2)) + { + Eluna::Push(L, 1); + lua_gettable(L, 2); + min = Eluna::CHECKVAL(L, -1); + Eluna::Push(L, 2); + lua_gettable(L, 2); + max = Eluna::CHECKVAL(L, -1); + lua_pop(L, 2); + } + else + min = max = Eluna::CHECKVAL(L, 2); + uint32 repeats = Eluna::CHECKVAL(L, 3, 1); + + if (min > max) + return luaL_argerror(L, 2, "min is bigger than max delay"); + + lua_pushvalue(L, 1); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF) + { + Eluna::GetEluna(L)->eventMgr->globalProcessor->AddEvent(functionRef, min, max, repeats); + Eluna::Push(L, functionRef); + } + return 1; + } + + /** + * Removes a global timed event specified by ID. + * + * @param int eventId : event Id to remove + * @param bool all_Events = false : remove from all events, not just global + */ + int RemoveEventById(lua_State* L) + { + int eventId = Eluna::CHECKVAL(L, 1); + bool all_Events = Eluna::CHECKVAL(L, 1, false); + + // not thread safe + if (all_Events) + Eluna::GetEluna(L)->eventMgr->SetState(eventId, LUAEVENT_STATE_ABORT); + else + Eluna::GetEluna(L)->eventMgr->globalProcessor->SetState(eventId, LUAEVENT_STATE_ABORT); + return 0; + } + + /** + * Removes all global timed events. + * + * @param bool all_Events = false : remove all events, not just global + */ + int RemoveEvents(lua_State* L) + { + bool all_Events = Eluna::CHECKVAL(L, 1, false); + + // not thread safe + if (all_Events) + Eluna::GetEluna(L)->eventMgr->SetStates(LUAEVENT_STATE_ABORT); + else + Eluna::GetEluna(L)->eventMgr->globalProcessor->SetStates(LUAEVENT_STATE_ABORT); + return 0; + } + + /** + * Performs an in-game spawn and returns the [Creature] or [GameObject] spawned. + * + * @param int32 spawnType : type of object to spawn, 1 = [Creature], 2 = [GameObject] + * @param uint32 entry : entry ID of the [Creature] or [GameObject] + * @param uint32 mapId : map ID to spawn the [Creature] or [GameObject] in + * @param uint32 instanceId : instance ID to put the [Creature] or [GameObject] in. Non instance is 0 + * @param float x : x coordinate of the [Creature] or [GameObject] + * @param float y : y coordinate of the [Creature] or [GameObject] + * @param float z : z coordinate of the [Creature] or [GameObject] + * @param float o : o facing/orientation of the [Creature] or [GameObject] + * @param bool save = false : optional to save the [Creature] or [GameObject] to the database + * @param uint32 durorresptime = 0 : despawn time of the [Creature] if it's not saved or respawn time of [GameObject] + * @param uint32 phase = 1 : phase to put the [Creature] or [GameObject] in + * @return [WorldObject] worldObject : returns [Creature] or [GameObject] + */ + int PerformIngameSpawn(lua_State* L) + { + int spawntype = Eluna::CHECKVAL(L, 1); + uint32 entry = Eluna::CHECKVAL(L, 2); + uint32 mapID = Eluna::CHECKVAL(L, 3); + uint32 instanceID = Eluna::CHECKVAL(L, 4); + float x = Eluna::CHECKVAL(L, 5); + float y = Eluna::CHECKVAL(L, 6); + float z = Eluna::CHECKVAL(L, 7); + float o = Eluna::CHECKVAL(L, 8); + bool save = Eluna::CHECKVAL(L, 9, false); + uint32 durorresptime = Eluna::CHECKVAL(L, 10, 0); + uint32 phase = Eluna::CHECKVAL(L, 11, PHASEMASK_NORMAL); + + if (!phase) + { + Eluna::Push(L); + return 1; + } + + Map* map = eMapMgr->FindMap(mapID, instanceID); + if (!map) + { + Eluna::Push(L); + return 1; + } + + Position pos = { x, y, z, o }; + + if (spawntype == 1) // spawn creature + { + if (save) + { + Creature* creature = new Creature(); +#ifdef CATA + if (!creature->Create(map->GenerateLowGuid(), map, entry, pos)) +#else + if (!creature->Create(map->GenerateLowGuid(), map, phase, entry, pos)) +#endif + { + delete creature; + Eluna::Push(L); + return 1; + } + +#ifdef CATA + creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); +#else + creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), phase); +#endif + + uint32 db_guid = creature->GetSpawnId(); + + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells() + // current "creature" variable is deleted and created fresh new, otherwise old values might trigger asserts or cause undefined behavior + creature->CleanupsBeforeDelete(); + delete creature; + creature = new Creature(); + + if (!creature->LoadFromDB(db_guid, map, true, true)) + { + delete creature; + Eluna::Push(L); + return 1; + } + + eObjectMgr->AddCreatureToGrid(db_guid, eObjectMgr->GetCreatureData(db_guid)); + Eluna::Push(L, creature); + } + else + { +#ifdef CATA + SummonCreatureExtraArgs extraArgs; + extraArgs.SummonDuration = durorresptime; + TempSummon* creature = map->SummonCreature(entry, pos, extraArgs); +#else + TempSummon* creature = map->SummonCreature(entry, pos, NULL, durorresptime); +#endif + if (!creature) + { + Eluna::Push(L); + return 1; + } + + if (durorresptime) + creature->SetTempSummonType(TEMPSUMMON_TIMED_OR_DEAD_DESPAWN); + else + creature->SetTempSummonType(TEMPSUMMON_MANUAL_DESPAWN); + + Eluna::Push(L, creature); + } + + return 1; + } + + if (spawntype == 2) // Spawn object + { + const GameObjectTemplate* objectInfo = eObjectMgr->GetGameObjectTemplate(entry); + if (!objectInfo) + { + Eluna::Push(L); + return 1; + } + + if (objectInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(objectInfo->displayId)) + { + Eluna::Push(L); + return 1; + } + + GameObject* object = new GameObject; + uint32 guidLow = map->GenerateLowGuid(); + QuaternionData rot = QuaternionData::fromEulerAnglesZYX(o, 0.f, 0.f); +#ifdef CATA + if (!object->Create(guidLow, objectInfo->entry, map, Position(x, y, z, o), rot, 0, GO_STATE_READY)) +#else + if (!object->Create(guidLow, objectInfo->entry, map, phase, Position(x, y, z, o), rot, 0, GO_STATE_READY)) +#endif + { + delete object; + Eluna::Push(L); + return 1; + } + + if (durorresptime) + object->SetRespawnTime(durorresptime); + + if (save) + { + // fill the gameobject data and save to the db +#ifdef CATA + object->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); +#else + object->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), phase); +#endif + guidLow = object->GetSpawnId(); + + // delete the old object and do a clean load from DB with a fresh new GameObject instance. + // this is required to avoid weird behavior and memory leaks + delete object; + + object = new GameObject(); + // this will generate a new lowguid if the object is in an instance + if (!object->LoadFromDB(guidLow, map, true)) + { + delete object; + Eluna::Push(L); + return 1; + } + eObjectMgr->AddGameobjectToGrid(guidLow, eObjectMgr->GetGameObjectData(guidLow)); + } + else + map->AddToMap(object); + Eluna::Push(L, object); + return 1; + } + + Eluna::Push(L); + return 1; + } + + /** + * Creates a [WorldPacket]. + * + * @param [Opcodes] opcode : the opcode of the packet + * @param uint32 size : the size of the packet + * @return [WorldPacket] packet + */ + int CreatePacket(lua_State* L) + { + uint32 opcode = Eluna::CHECKVAL(L, 1); + size_t size = Eluna::CHECKVAL(L, 2); + if (opcode >= NUM_MSG_TYPES) + return luaL_argerror(L, 1, "valid opcode expected"); + + Eluna::Push(L, new WorldPacket((OpcodesList)opcode, size)); + return 1; + } + + /** + * Adds an [Item] to a vendor and updates the world database. + * + * @param uint32 entry : [Creature] entry Id + * @param uint32 item : [Item] entry Id + * @param int32 maxcount : max [Item] stack count + * @param uint32 incrtime : combined with maxcount, incrtime tells how often (in seconds) the vendor list is refreshed and the limited [Item] copies are restocked + * @param uint32 extendedcost : unique cost of an [Item], such as conquest points for example + */ + int AddVendorItem(lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 item = Eluna::CHECKVAL(L, 2); + int maxcount = Eluna::CHECKVAL(L, 3); + uint32 incrtime = Eluna::CHECKVAL(L, 4); + uint32 extendedcost = Eluna::CHECKVAL(L, 5); + +#ifdef CATA + VendorItem vItem; + vItem.item = item; + vItem.maxcount = maxcount; + vItem.incrtime = incrtime; + vItem.ExtendedCost = extendedcost; + + if (!eObjectMgr->IsVendorItemValid(entry, vItem)) + return 0; + eObjectMgr->AddVendorItem(entry, vItem); +#else + if (!eObjectMgr->IsVendorItemValid(entry, item, maxcount, incrtime, extendedcost)) + return 0; + + eObjectMgr->AddVendorItem(entry, item, maxcount, incrtime, extendedcost); +#endif + return 0; + } + + /** + * Removes an [Item] from a vendor and updates the database. + * + * @param uint32 entry : [Creature] entry Id + * @param uint32 item : [Item] entry Id + */ + int VendorRemoveItem(lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 item = Eluna::CHECKVAL(L, 2); + if (!eObjectMgr->GetCreatureTemplate(entry)) + return luaL_argerror(L, 1, "valid CreatureEntry expected"); + +#ifdef CATA + eObjectMgr->RemoveVendorItem(entry, item, 1); +#else + eObjectMgr->RemoveVendorItem(entry, item); +#endif + + return 0; + } + + /** + * Removes all [Item]s from a vendor and updates the database. + * + * @param uint32 entry : [Creature] entry Id + */ + int VendorRemoveAllItems(lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + VendorItemData const* items = eObjectMgr->GetNpcVendorItemList(entry); + if (!items || items->Empty()) + return 0; + + auto const itemlist = items->m_items; + for (auto itr = itemlist.begin(); itr != itemlist.end(); ++itr) +#ifdef CATA + eObjectMgr->RemoveVendorItem(entry, itr->item, 1); +#else + eObjectMgr->RemoveVendorItem(entry, itr->item); + +#endif + return 0; + } + + /** + * Kicks a [Player] from the server. + * + * @param [Player] player : [Player] to kick + */ + int Kick(lua_State* L) + { + Player* player = Eluna::CHECKOBJ(L, 1); + +#ifndef CATA + player->GetSession()->KickPlayer("GlobalMethods::Kick Kick the player"); +#else + player->GetSession()->KickPlayer(); +#endif + return 0; + } + + /** + * Ban's a [Player]'s account, character or IP + * + * enum BanMode + * { + * BAN_ACCOUNT = 0, + * BAN_CHARACTER = 1, + * BAN_IP = 2 + * }; + * + * @param [BanMode] banMode : method of ban, refer to BanMode above + * @param string nameOrIP : If BanMode is 0 then accountname, if 1 then charactername if 2 then ip + * @param uint32 duration : duration (in seconds) of the ban + * @param string reason = "" : ban reason, this is optional + * @param string whoBanned = "" : the [Player]'s name that banned the account, character or IP, this is optional + * @return int result : status of the ban. 0 if success, 1 if syntax error, 2 if target not found, 3 if a longer ban already exists, nil if unknown result + */ + int Ban(lua_State* L) + { + int banMode = Eluna::CHECKVAL(L, 1); + std::string nameOrIP = Eluna::CHECKVAL(L, 2); + uint32 duration = Eluna::CHECKVAL(L, 3); + const char* reason = Eluna::CHECKVAL(L, 4, ""); + const char* whoBanned = Eluna::CHECKVAL(L, 5, ""); + + const int BAN_ACCOUNT = 0; + const int BAN_CHARACTER = 1; + const int BAN_IP = 2; + + BanMode mode = BanMode::BAN_ACCOUNT; + + switch (banMode) + { + case BAN_ACCOUNT: + if (!Utf8ToUpperOnlyLatin(nameOrIP)) + return luaL_argerror(L, 2, "invalid account name"); + mode = BanMode::BAN_ACCOUNT; + break; + case BAN_CHARACTER: + if (!normalizePlayerName(nameOrIP)) + return luaL_argerror(L, 2, "invalid character name"); + mode = BanMode::BAN_CHARACTER; + break; + case BAN_IP: + if (!IsIPAddress(nameOrIP.c_str())) + return luaL_argerror(L, 2, "invalid ip"); + mode = BanMode::BAN_IP; + break; + default: + return luaL_argerror(L, 1, "unknown banmode"); + } + + BanReturn result; + result = eWorld->BanAccount(mode, nameOrIP, duration, reason, whoBanned); + switch (result) + { + case BanReturn::BAN_SUCCESS: + Eluna::Push(L, 0); + break; + case BanReturn::BAN_SYNTAX_ERROR: + Eluna::Push(L, 1); + break; + case BanReturn::BAN_NOTFOUND: + Eluna::Push(L, 2); + break; + case BanReturn::BAN_EXISTS: + Eluna::Push(L, 3); + break; + } + return 1; + } + + /** + * Saves all [Player]s. + */ + int SaveAllPlayers(lua_State* /*L*/) + { + eObjectAccessor()SaveAllPlayers(); + return 0; + } + + /** + * Sends mail to a [Player]. + * + * There can be several item entry-amount pairs at the end of the function. + * There can be maximum of 12 different items. + * + * enum MailStationery + * { + * MAIL_STATIONERY_TEST = 1, + * MAIL_STATIONERY_DEFAULT = 41, + * MAIL_STATIONERY_GM = 61, + * MAIL_STATIONERY_AUCTION = 62, + * MAIL_STATIONERY_VAL = 64, // Valentine + * MAIL_STATIONERY_CHR = 65, // Christmas + * MAIL_STATIONERY_ORP = 67 // Orphan + * }; + * + * @param string subject : title (subject) of the mail + * @param string text : contents of the mail + * @param uint32 receiverGUIDLow : low GUID of the receiver + * @param uint32 senderGUIDLow = 0 : low GUID of the sender + * @param [MailStationery] stationary = MAIL_STATIONERY_DEFAULT : type of mail that is being sent as, refer to MailStationery above + * @param uint32 delay = 0 : mail send delay in milliseconds + * @param uint32 money = 0 : money to send + * @param uint32 cod = 0 : cod money amount + * @param uint32 entry = 0 : entry of an [Item] to send with mail + * @param uint32 amount = 0 : amount of the [Item] to send with mail + * @return uint32 itemGUIDlow : low GUID of the item. Up to 12 values returned, returns nil if no further items are sent + */ + int SendMail(lua_State* L) + { + int i = 0; + std::string subject = Eluna::CHECKVAL(L, ++i); + std::string text = Eluna::CHECKVAL(L, ++i); + uint32 receiverGUIDLow = Eluna::CHECKVAL(L, ++i); + uint32 senderGUIDLow = Eluna::CHECKVAL(L, ++i, 0); + uint32 stationary = Eluna::CHECKVAL(L, ++i, MAIL_STATIONERY_DEFAULT); + uint32 delay = Eluna::CHECKVAL(L, ++i, 0); + uint32 money = Eluna::CHECKVAL(L, ++i, 0); + uint32 cod = Eluna::CHECKVAL(L, ++i, 0); + int argAmount = lua_gettop(L); + + MailSender sender(MAIL_NORMAL, senderGUIDLow, (MailStationery)stationary); + MailDraft draft(subject, text); + + if (cod) + draft.AddCOD(cod); + if (money) + draft.AddMoney(money); + + CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); + uint8 addedItems = 0; + while (addedItems <= MAX_MAIL_ITEMS && i + 2 <= argAmount) + { + uint32 entry = Eluna::CHECKVAL(L, ++i); + uint32 amount = Eluna::CHECKVAL(L, ++i); + + ItemTemplate const* item_proto = eObjectMgr->GetItemTemplate(entry); + if (!item_proto) + { + luaL_error(L, "Item entry %d does not exist", entry); + continue; + } +#ifdef CATA + if (amount < 1 || (item_proto->ExtendedData->MaxCount > 0 && amount > uint32(item_proto->ExtendedData->MaxCount))) +#else + if (amount < 1 || (item_proto->MaxCount > 0 && amount > uint32(item_proto->MaxCount))) +#endif + { + luaL_error(L, "Item entry %d has invalid amount %d", entry, amount); + continue; + } + if (Item* item = Item::CreateItem(entry, amount)) + { + item->SaveToDB(trans); + draft.AddItem(item); + Eluna::Push(L, item->GetGUID().GetCounter()); + ++addedItems; + } + } + + Player* receiverPlayer = eObjectAccessor()FindPlayer(MAKE_NEW_GUID(receiverGUIDLow, 0, HIGHGUID_PLAYER)); + draft.SendMailTo(trans, MailReceiver(receiverPlayer, receiverGUIDLow), sender, MAIL_CHECK_MASK_NONE, delay); + CharacterDatabase.CommitTransaction(trans); + + return addedItems; + } + + /** + * Performs a bitwise AND (a & b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_and(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a & b); + return 1; + } + + /** + * Performs a bitwise OR (a | b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_or(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a | b); + return 1; + } + + /** + * Performs a bitwise left-shift (a << b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_lshift(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a << b); + return 1; + } + + /** + * Performs a bitwise right-shift (a >> b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_rshift(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a >> b); + return 1; + } + + /** + * Performs a bitwise XOR (a ^ b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_xor(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a ^ b); + return 1; + } + + /** + * Performs a bitwise NOT (~a). + * + * @param uint32 a + * @return uint32 result + */ + int bit_not(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, ~a); + return 1; + } + + /** + * Adds a taxi path to a specified map, returns the used pathId. + * + * Note that the first taxi point needs to be near the player when he starts the taxi path. + * The function should also be used only **once** per path added so use it on server startup for example. + * + * Related function: [Player:StartTaxi] + * + * -- Execute on startup + * local pathTable = {{mapid, x, y, z}, {mapid, x, y, z}} + * local path = AddTaxiPath(pathTable, 28135, 28135) + * + * -- Execute when the player should fly + * player:StartTaxi(path) + * + * @param table waypoints : table containing waypoints: {map, x, y, z[, actionFlag, delay]} + * @param uint32 mountA : alliance [Creature] entry + * @param uint32 mountH : horde [Creature] entry + * @param uint32 price = 0 : price of the taxi path + * @param uint32 pathId = 0 : path Id of the taxi path + * @return uint32 actualPathId + */ + int AddTaxiPath(lua_State* L) + { + luaL_checktype(L, 1, LUA_TTABLE); + uint32 mountA = Eluna::CHECKVAL(L, 2); + uint32 mountH = Eluna::CHECKVAL(L, 3); + uint32 price = Eluna::CHECKVAL(L, 4, 0); + uint32 pathId = Eluna::CHECKVAL(L, 5, 0); + lua_pushvalue(L, 1); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes} + + std::list nodes; + + int start = lua_gettop(L); + int end = start; + + Eluna::Push(L); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, nil + while (lua_next(L, -2) != 0) + { + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key, value + luaL_checktype(L, -1, LUA_TTABLE); + Eluna::Push(L); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key, value, nil + while (lua_next(L, -2) != 0) + { + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key, value, key2, value2 + lua_insert(L, end++); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, value2, key, value, key2 + } + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, value2, key, value + if (start == end) + continue; + if (end - start < 4) // no mandatory args, dont add + return luaL_argerror(L, 1, "all waypoints do not have mandatory arguments"); + + while (end - start < 8) // fill optional args with 0 + { + Eluna::Push(L, 0); + lua_insert(L, end++); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, node, key, value + } + TaxiPathNodeEntry entry; + + // mandatory + entry.ContinentID = Eluna::CHECKVAL(L, start); + entry.Loc.X = Eluna::CHECKVAL(L, start + 1); + entry.Loc.Y = Eluna::CHECKVAL(L, start + 2); + entry.Loc.Z = Eluna::CHECKVAL(L, start + 3); + // optional + entry.Flags = Eluna::CHECKVAL(L, start + 4, 0); + entry.Delay = Eluna::CHECKVAL(L, start + 5, 0); + + nodes.push_back(entry); + + while (end != start) // remove args + if (!lua_isnone(L, --end)) + lua_remove(L, end); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key, value + + lua_pop(L, 1); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key + } + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes} + lua_pop(L, 1); + // Stack: {nodes}, mountA, mountH, price, pathid + + if (nodes.size() < 2) + return 1; + if (!pathId) + pathId = sTaxiPathNodesByPath.size(); + if (sTaxiPathNodesByPath.size() <= pathId) + sTaxiPathNodesByPath.resize(pathId + 1); + sTaxiPathNodesByPath[pathId].clear(); + sTaxiPathNodesByPath[pathId].resize(nodes.size()); + static uint32 nodeId = 500; + uint32 startNode = nodeId; + uint32 index = 0; + for (std::list::iterator it = nodes.begin(); it != nodes.end(); ++it) + { + TaxiPathNodeEntry& entry = *it; + TaxiNodesEntry* nodeEntry = new TaxiNodesEntry(); + + entry.PathID = pathId; + entry.NodeIndex = nodeId; + nodeEntry->ID = index; + nodeEntry->ContinentID = entry.ContinentID; + nodeEntry->Pos.X = entry.Loc.X; + nodeEntry->Pos.Y = entry.Loc.Y; + nodeEntry->Pos.Z = entry.Loc.Z; + nodeEntry->MountCreatureID[0] = mountH; + nodeEntry->MountCreatureID[1] = mountA; + sTaxiNodesStore.SetEntry(nodeId++, nodeEntry); + sTaxiPathNodesByPath[pathId][index++] = new TaxiPathNodeEntry(entry); + } + if (startNode >= nodeId) + return 1; + sTaxiPathSetBySource[startNode][nodeId - 1] = TaxiPathBySourceAndDestination(pathId, price); + TaxiPathEntry* pathEntry = new TaxiPathEntry(); + + pathEntry->FromTaxiNode = startNode; + pathEntry->ToTaxiNode = nodeId - 1; + pathEntry->Cost = price; + pathEntry->ID = pathId; + + sTaxiPathStore.SetEntry(pathId, pathEntry); + + Eluna::Push(L, pathId); + return 1; + } + + /** + * Returns `true` if the bag and slot is a valid inventory position, otherwise `false`. + * + * Some commonly used combinations: + * + * *Bag 255 (common character inventory)* + * + * - Slots 0-18: equipment + * - Slots 19-22: bag slots + * - Slots 23-38: backpack + * - Slots 39-66: bank main slots + * - Slots 67-74: bank bag slots + * - Slots 86-117: keyring + * + * *Bags 19-22 (equipped bags)* + * + * - Slots 0-35 + * + * *Bags 67-74 (bank bags)* + * + * - Slots 0-35 + * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return bool isInventoryPos + */ + int IsInventoryPos(lua_State* L) + { + uint8 bag = Eluna::CHECKVAL(L, 1); + uint8 slot = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, Player::IsInventoryPos(bag, slot)); + return 1; + } + + /** + * Returns `true` if the bag and slot is a valid equipment position, otherwise `false`. + * + * See [Global:IsInventoryPos] for bag/slot combination examples. + * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return bool isEquipmentPosition + */ + int IsEquipmentPos(lua_State* L) + { + uint8 bag = Eluna::CHECKVAL(L, 1); + uint8 slot = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, Player::IsEquipmentPos(bag, slot)); + return 1; + } + + /** + * Returns `true` if the bag and slot is a valid bank position, otherwise `false`. + * + * See [Global:IsInventoryPos] for bag/slot combination examples. + * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return bool isBankPosition + */ + int IsBankPos(lua_State* L) + { + uint8 bag = Eluna::CHECKVAL(L, 1); + uint8 slot = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, Player::IsBankPos(bag, slot)); + return 1; + } + + /** + * Returns `true` if the bag and slot is a valid bag position, otherwise `false`. + * + * See [Global:IsInventoryPos] for bag/slot combination examples. + * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return bool isBagPosition + */ + int IsBagPos(lua_State* L) + { + uint8 bag = Eluna::CHECKVAL(L, 1); + uint8 slot = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, Player::IsBagPos((bag << 8) + slot)); + return 1; + } + + /** + * Returns `true` if the event is currently active, otherwise `false`. + * + * @param uint16 eventId : the event id to check. + * @return bool isActive + */ + int IsGameEventActive(lua_State* L) + { + uint16 eventId = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, eGameEventMgr->IsActiveEvent(eventId)); + return 1; + } + + /** + * Returns the server's current time. + * + * @return uint32 currTime : the current time, in milliseconds + */ + int GetCurrTime(lua_State* L) + { + Eluna::Push(L, ElunaUtil::GetCurrTime()); + return 1; + } + + /** + * Returns the difference between an old timestamp and the current time. + * + * @param uint32 oldTime : an old timestamp, in milliseconds + * @return uint32 timeDiff : the difference, in milliseconds + */ + int GetTimeDiff(lua_State* L) + { + uint32 oldtimems = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, ElunaUtil::GetTimeDiff(oldtimems)); + return 1; + } + + static std::string GetStackAsString(lua_State* L) + { + std::ostringstream oss; + int top = lua_gettop(L); + for (int i = 1; i <= top; ++i) + { + oss << luaL_tolstring(L, i, NULL); + lua_pop(L, 1); + } + return oss.str(); + } + + /** + * Prints given parameters to the info log. + * + * @param ... + */ + int PrintInfo(lua_State* L) + { + ELUNA_LOG_INFO("%s", GetStackAsString(L).c_str()); + return 0; + } + + /** + * Prints given parameters to the error log. + * + * @param ... + */ + int PrintError(lua_State* L) + { + ELUNA_LOG_ERROR("%s", GetStackAsString(L).c_str()); + return 0; + } + + /** + * Prints given parameters to the debug log. + * + * @param ... + */ + int PrintDebug(lua_State* L) + { + ELUNA_LOG_DEBUG("%s", GetStackAsString(L).c_str()); + return 0; + } + + /** + * Starts the event by eventId, if force is set, the event will force start regardless of previous event state. + * + * @param uint16 eventId : the event id to start. + * @param bool force = false : set `true` to force start the event. + */ + int StartGameEvent(lua_State* L) + { + uint16 eventId = Eluna::CHECKVAL(L, 1); + bool force = Eluna::CHECKVAL(L, 2, false); + + eGameEventMgr->StartEvent(eventId, force); + return 0; + } + + /** + * Stops the event by eventId, if force is set, the event will force stop regardless of previous event state. + * + * @param uint16 eventId : the event id to stop. + * @param bool force = false : set `true` to force stop the event. + */ + int StopGameEvent(lua_State* L) + { + uint16 eventId = Eluna::CHECKVAL(L, 1); + bool force = Eluna::CHECKVAL(L, 2, false); + + eGameEventMgr->StopEvent(eventId, force); + return 0; + } + + /** + * Returns an object representing a `long long` (64-bit) value. + * + * The value by default is 0, but can be initialized to a value by passing a number or long long as a string. + * + * @proto value = () + * @proto value = (n) + * @proto value = (n_ll) + * @proto value = (n_str) + * @param int32 n + * @param int64 n_ll + * @param string n_str + * @return int64 value + */ + int CreateLongLong(lua_State* L) + { + long long init = 0; + if (lua_isstring(L, 1)) + { + std::string str = Eluna::CHECKVAL(L, 1); + std::istringstream iss(str); + iss >> init; + if (iss.bad()) + return luaL_argerror(L, 1, "long long (as string) could not be converted"); + } + else if (!lua_isnoneornil(L, 1)) + init = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, init); + return 1; + } + + /** + * Returns an object representing an `unsigned long long` (64-bit) value. + * + * The value by default is 0, but can be initialized to a value by passing a number or unsigned long long as a string. + * + * @proto value = () + * @proto value = (n) + * @proto value = (n_ull) + * @proto value = (n_str) + * @param uint32 n + * @param uint64 n_ull + * @param string n_str + * @return uint64 value + */ + int CreateULongLong(lua_State* L) + { + unsigned long long init = 0; + if (lua_isstring(L, 1)) + { + std::string str = Eluna::CHECKVAL(L, 1); + std::istringstream iss(str); + iss >> init; + if (iss.bad()) + return luaL_argerror(L, 1, "unsigned long long (as string) could not be converted"); + } + else if (!lua_isnoneornil(L, 1)) + init = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, init); + return 1; + } + + /** + * Unbinds event handlers for either all [BattleGround] events, or one type of event. + * + * If `event_type` is `nil`, all [BattleGround] event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterBGEvent] + */ + int ClearBattleGroundEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->BGEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->BGEventBindings->Clear(Key((Hooks::BGEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [Creature]'s events, or one type of event. + * + * If `event_type` is `nil`, all the [Creature]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [Creature], not just one. + * To bind and unbind events to a single [Creature], see [Global:RegisterUniqueCreatureEvent] and [Global:ClearUniqueCreatureEvents]. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of one or more [Creature]s whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterCreatureEvent] + */ + int ClearCreatureEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::CREATURE_EVENT_COUNT; ++i) + E->CreatureEventBindings->Clear(Key((Hooks::CreatureEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->CreatureEventBindings->Clear(Key((Hooks::CreatureEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [Creature]'s events, or one type of event. + * + * If `event_type` is `nil`, all the [Creature]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect only a single [Creature]. + * To bind and unbind events to all instances of a [Creature], see [Global:RegisterCreatureEvent] and [Global:ClearCreatureEvent]. + * + * @proto (entry) + * @proto (entry, event_type) + * @param ObjectGuid guid : the GUID of a single [Creature] whose handlers will be cleared + * @param uint32 instance_id : the instance ID of a single [Creature] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterCreatureEvent] + */ + int ClearUniqueCreatureEvents(lua_State* L) + { + typedef UniqueObjectKey Key; + + if (lua_isnoneornil(L, 3)) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + uint32 instanceId = Eluna::CHECKVAL(L, 2); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::CREATURE_EVENT_COUNT; ++i) + E->CreatureUniqueBindings->Clear(Key((Hooks::CreatureEvents)i, guid, instanceId)); + } + else + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + uint32 instanceId = Eluna::CHECKVAL(L, 2); + uint32 event_type = Eluna::CHECKVAL(L, 3); + Eluna::GetEluna(L)->CreatureUniqueBindings->Clear(Key((Hooks::CreatureEvents)event_type, guid, instanceId)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [Creature]'s gossip events, or one type of event. + * + * If `event_type` is `nil`, all the [Creature]'s gossip event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [Creature], not just one. + * To bind and unbind gossip events to a single [Creature], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of a [Creature] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterCreatureGossipEvent] + */ + int ClearCreatureGossipEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i) + E->CreatureGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->CreatureGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [GameObject]'s events, or one type of event. + * + * If `event_type` is `nil`, all the [GameObject]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [GameObject], not just one. + * To bind and unbind events to a single [GameObject], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of a [GameObject] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGameObjectEvent] + */ + int ClearGameObjectEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GAMEOBJECT_EVENT_COUNT; ++i) + E->GameObjectEventBindings->Clear(Key((Hooks::GameObjectEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->GameObjectEventBindings->Clear(Key((Hooks::GameObjectEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [GameObject]'s gossip events, or one type of event. + * + * If `event_type` is `nil`, all the [GameObject]'s gossip event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [GameObject], not just one. + * To bind and unbind gossip events to a single [GameObject], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of a [GameObject] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGameObjectGossipEvent] + */ + int ClearGameObjectGossipEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i) + E->GameObjectGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->GameObjectGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all [Group] events, or one type of [Group] event. + * + * If `event_type` is `nil`, all [Group] event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGroupEvent] + */ + int ClearGroupEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->GroupEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->GroupEventBindings->Clear(Key((Hooks::GroupEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all [Guild] events, or one type of [Guild] event. + * + * If `event_type` is `nil`, all [Guild] event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGuildEvent] + */ + int ClearGuildEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->GuildEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->GuildEventBindings->Clear(Key((Hooks::GuildEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of an [Item]'s events, or one type of event. + * + * If `event_type` is `nil`, all the [Item]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [Item], not just one. + * To bind and unbind events to a single [Item], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of an [Item] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterItemEvent] + */ + int ClearItemEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::ITEM_EVENT_COUNT; ++i) + E->ItemEventBindings->Clear(Key((Hooks::ItemEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->ItemEventBindings->Clear(Key((Hooks::ItemEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of an [Item]'s gossip events, or one type of event. + * + * If `event_type` is `nil`, all the [Item]'s gossip event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [Item], not just one. + * To bind and unbind gossip events to a single [Item], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of an [Item] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterItemGossipEvent] + */ + int ClearItemGossipEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i) + E->ItemGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->ItemGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [WorldPacket] opcode's events, or one type of event. + * + * If `event_type` is `nil`, all the [WorldPacket] opcode's event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto (opcode) + * @proto (opcode, event_type) + * @param uint32 opcode : the type of [WorldPacket] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPacketEvent] + */ + int ClearPacketEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::PACKET_EVENT_COUNT; ++i) + E->PacketEventBindings->Clear(Key((Hooks::PacketEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->PacketEventBindings->Clear(Key((Hooks::PacketEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all [Player] events, or one type of [Player] event. + * + * If `event_type` is `nil`, all [Player] event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPlayerEvent] + */ + int ClearPlayerEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->PlayerEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->PlayerEventBindings->Clear(Key((Hooks::PlayerEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [Player]'s gossip events, or one type of event. + * + * If `event_type` is `nil`, all the [Player]'s gossip event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the low GUID of a [Player] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPlayerGossipEvent] + */ + int ClearPlayerGossipEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i) + E->PlayerGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->PlayerGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all server events, or one type of event. + * + * If `event_type` is `nil`, all server event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterServerEvent] + */ + int ClearServerEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->ServerEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->ServerEventBindings->Clear(Key((Hooks::ServerEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a non-instanced [Map]'s events, or one type of event. + * + * If `event_type` is `nil`, all the non-instanced [Map]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto (map_id) + * @proto (map_id, event_type) + * @param uint32 map_id : the ID of a [Map] + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPlayerGossipEvent] + */ + int ClearMapEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::INSTANCE_EVENT_COUNT; ++i) + E->MapEventBindings->Clear(Key((Hooks::InstanceEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->MapEventBindings->Clear(Key((Hooks::InstanceEvents)event_type, entry)); + } + + return 0; + } + + /** + * Unbinds event handlers for either all of an instanced [Map]'s events, or one type of event. + * + * If `event_type` is `nil`, all the instanced [Map]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto (instance_id) + * @proto (instance_id, event_type) + * @param uint32 entry : the ID of an instance of a [Map] + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterInstanceEvent] + */ + int ClearInstanceEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::INSTANCE_EVENT_COUNT; ++i) + E->InstanceEventBindings->Clear(Key((Hooks::InstanceEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->InstanceEventBindings->Clear(Key((Hooks::InstanceEvents)event_type, entry)); + } + + return 0; + } + + luaL_Reg GlobalMethods[] = + { + // Hooks + { "RegisterPacketEvent", &LuaGlobalFunctions::RegisterPacketEvent }, + { "RegisterServerEvent", &LuaGlobalFunctions::RegisterServerEvent }, + { "RegisterPlayerEvent", &LuaGlobalFunctions::RegisterPlayerEvent }, + { "RegisterGuildEvent", &LuaGlobalFunctions::RegisterGuildEvent }, + { "RegisterGroupEvent", &LuaGlobalFunctions::RegisterGroupEvent }, + { "RegisterCreatureEvent", &LuaGlobalFunctions::RegisterCreatureEvent }, + { "RegisterUniqueCreatureEvent", &LuaGlobalFunctions::RegisterUniqueCreatureEvent }, + { "RegisterCreatureGossipEvent", &LuaGlobalFunctions::RegisterCreatureGossipEvent }, + { "RegisterGameObjectEvent", &LuaGlobalFunctions::RegisterGameObjectEvent }, + { "RegisterGameObjectGossipEvent", &LuaGlobalFunctions::RegisterGameObjectGossipEvent }, + { "RegisterItemEvent", &LuaGlobalFunctions::RegisterItemEvent }, + { "RegisterItemGossipEvent", &LuaGlobalFunctions::RegisterItemGossipEvent }, + { "RegisterPlayerGossipEvent", &LuaGlobalFunctions::RegisterPlayerGossipEvent }, + { "RegisterBGEvent", &LuaGlobalFunctions::RegisterBGEvent }, + { "RegisterMapEvent", &LuaGlobalFunctions::RegisterMapEvent }, + { "RegisterInstanceEvent", &LuaGlobalFunctions::RegisterInstanceEvent }, + + { "ClearBattleGroundEvents", &LuaGlobalFunctions::ClearBattleGroundEvents }, + { "ClearCreatureEvents", &LuaGlobalFunctions::ClearCreatureEvents }, + { "ClearUniqueCreatureEvents", &LuaGlobalFunctions::ClearUniqueCreatureEvents }, + { "ClearCreatureGossipEvents", &LuaGlobalFunctions::ClearCreatureGossipEvents }, + { "ClearGameObjectEvents", &LuaGlobalFunctions::ClearGameObjectEvents }, + { "ClearGameObjectGossipEvents", &LuaGlobalFunctions::ClearGameObjectGossipEvents }, + { "ClearGroupEvents", &LuaGlobalFunctions::ClearGroupEvents }, + { "ClearGuildEvents", &LuaGlobalFunctions::ClearGuildEvents }, + { "ClearItemEvents", &LuaGlobalFunctions::ClearItemEvents }, + { "ClearItemGossipEvents", &LuaGlobalFunctions::ClearItemGossipEvents }, + { "ClearPacketEvents", &LuaGlobalFunctions::ClearPacketEvents }, + { "ClearPlayerEvents", &LuaGlobalFunctions::ClearPlayerEvents }, + { "ClearPlayerGossipEvents", &LuaGlobalFunctions::ClearPlayerGossipEvents }, + { "ClearServerEvents", &LuaGlobalFunctions::ClearServerEvents }, + { "ClearMapEvents", &LuaGlobalFunctions::ClearMapEvents }, + { "ClearInstanceEvents", &LuaGlobalFunctions::ClearInstanceEvents }, + + // Getters + { "GetLuaEngine", &LuaGlobalFunctions::GetLuaEngine }, + { "GetCoreName", &LuaGlobalFunctions::GetCoreName }, + { "GetRealmID", &LuaGlobalFunctions::GetRealmID }, + { "GetCoreVersion", &LuaGlobalFunctions::GetCoreVersion }, + { "GetCoreExpansion", &LuaGlobalFunctions::GetCoreExpansion }, + { "GetQuest", &LuaGlobalFunctions::GetQuest }, + { "GetPlayerByGUID", &LuaGlobalFunctions::GetPlayerByGUID }, + { "GetPlayerByName", &LuaGlobalFunctions::GetPlayerByName }, + { "GetGameTime", &LuaGlobalFunctions::GetGameTime }, + { "GetPlayersInWorld", &LuaGlobalFunctions::GetPlayersInWorld }, + { "GetGuildByName", &LuaGlobalFunctions::GetGuildByName }, + { "GetGuildByLeaderGUID", &LuaGlobalFunctions::GetGuildByLeaderGUID }, + { "GetPlayerCount", &LuaGlobalFunctions::GetPlayerCount }, + { "GetPlayerGUID", &LuaGlobalFunctions::GetPlayerGUID }, + { "GetItemGUID", &LuaGlobalFunctions::GetItemGUID }, + { "GetObjectGUID", &LuaGlobalFunctions::GetObjectGUID }, + { "GetUnitGUID", &LuaGlobalFunctions::GetUnitGUID }, + { "GetGUIDLow", &LuaGlobalFunctions::GetGUIDLow }, + { "GetGUIDType", &LuaGlobalFunctions::GetGUIDType }, + { "GetGUIDEntry", &LuaGlobalFunctions::GetGUIDEntry }, + { "GetAreaName", &LuaGlobalFunctions::GetAreaName }, + { "bit_not", &LuaGlobalFunctions::bit_not }, + { "bit_xor", &LuaGlobalFunctions::bit_xor }, + { "bit_rshift", &LuaGlobalFunctions::bit_rshift }, + { "bit_lshift", &LuaGlobalFunctions::bit_lshift }, + { "bit_or", &LuaGlobalFunctions::bit_or }, + { "bit_and", &LuaGlobalFunctions::bit_and }, + { "GetItemLink", &LuaGlobalFunctions::GetItemLink }, + { "GetMapById", &LuaGlobalFunctions::GetMapById }, + { "GetCurrTime", &LuaGlobalFunctions::GetCurrTime }, + { "GetTimeDiff", &LuaGlobalFunctions::GetTimeDiff }, + { "PrintInfo", &LuaGlobalFunctions::PrintInfo }, + { "PrintError", &LuaGlobalFunctions::PrintError }, + { "PrintDebug", &LuaGlobalFunctions::PrintDebug }, + { "GetActiveGameEvents", &LuaGlobalFunctions::GetActiveGameEvents }, + + // Boolean + { "IsInventoryPos", &LuaGlobalFunctions::IsInventoryPos }, + { "IsEquipmentPos", &LuaGlobalFunctions::IsEquipmentPos }, + { "IsBankPos", &LuaGlobalFunctions::IsBankPos }, + { "IsBagPos", &LuaGlobalFunctions::IsBagPos }, + { "IsGameEventActive", &LuaGlobalFunctions::IsGameEventActive }, + + // Other + { "ReloadEluna", &LuaGlobalFunctions::ReloadEluna }, + { "RunCommand", &LuaGlobalFunctions::RunCommand }, + { "SendWorldMessage", &LuaGlobalFunctions::SendWorldMessage }, + { "WorldDBQuery", &LuaGlobalFunctions::WorldDBQuery }, + { "WorldDBExecute", &LuaGlobalFunctions::WorldDBExecute }, + { "CharDBQuery", &LuaGlobalFunctions::CharDBQuery }, + { "CharDBExecute", &LuaGlobalFunctions::CharDBExecute }, + { "AuthDBQuery", &LuaGlobalFunctions::AuthDBQuery }, + { "AuthDBExecute", &LuaGlobalFunctions::AuthDBExecute }, + { "CreateLuaEvent", &LuaGlobalFunctions::CreateLuaEvent }, + { "RemoveEventById", &LuaGlobalFunctions::RemoveEventById }, + { "RemoveEvents", &LuaGlobalFunctions::RemoveEvents }, + { "PerformIngameSpawn", &LuaGlobalFunctions::PerformIngameSpawn }, + { "CreatePacket", &LuaGlobalFunctions::CreatePacket }, + { "AddVendorItem", &LuaGlobalFunctions::AddVendorItem }, + { "VendorRemoveItem", &LuaGlobalFunctions::VendorRemoveItem }, + { "VendorRemoveAllItems", &LuaGlobalFunctions::VendorRemoveAllItems }, + { "Kick", &LuaGlobalFunctions::Kick }, + { "Ban", &LuaGlobalFunctions::Ban }, + { "SaveAllPlayers", &LuaGlobalFunctions::SaveAllPlayers }, + { "SendMail", &LuaGlobalFunctions::SendMail }, + { "AddTaxiPath", &LuaGlobalFunctions::AddTaxiPath }, + { "CreateInt64", &LuaGlobalFunctions::CreateLongLong }, + { "CreateUint64", &LuaGlobalFunctions::CreateULongLong }, + { "StartGameEvent", &LuaGlobalFunctions::StartGameEvent }, + { "StopGameEvent", &LuaGlobalFunctions::StopGameEvent }, + + { NULL, NULL } + }; +} +#endif diff --git a/src/modules/Eluna/TrinityCore/GroupMethods.h b/src/modules/Eluna/TrinityCore/GroupMethods.h new file mode 100644 index 0000000000..33f4a08dd6 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/GroupMethods.h @@ -0,0 +1,477 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef GROUPMETHODS_H +#define GROUPMETHODS_H + +/*** + * Inherits all methods from: none + */ +namespace LuaGroup +{ + /** + * Returns 'true' if the [Player] is the [Group] leader + * + * @param ObjectGuid guid : guid of a possible leader + * @return bool isLeader + */ + int IsLeader(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->IsLeader(guid)); + return 1; + } + + /** + * Returns 'true' if the [Group] is full + * + * @return bool isFull + */ + int IsFull(lua_State* L, Group* group) + { + Eluna::Push(L, group->IsFull()); + return 1; + } + + /** + * Returns 'true' if the [Group] is a LFG group + * + * @return bool isLFGGroup + */ + int IsLFGGroup(lua_State* L, Group* group) + { + Eluna::Push(L, group->isLFGGroup()); + return 1; + } + + /** + * Returns 'true' if the [Group] is a raid [Group] + * + * @return bool isRaid + */ + int IsRaidGroup(lua_State* L, Group* group) + { + Eluna::Push(L, group->isRaidGroup()); + return 1; + } + + /** + * Returns 'true' if the [Group] is a battleground [Group] + * + * @return bool isBG + */ + int IsBGGroup(lua_State* L, Group* group) + { + Eluna::Push(L, group->isBGGroup()); + return 1; + } + + /** + * Returns 'true' if the [Player] is a member of this [Group] + * + * @param ObjectGuid guid : guid of a player + * @return bool isMember + */ + int IsMember(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->IsMember(guid)); + return 1; + } + + /** + * Returns 'true' if the [Player] is an assistant of this [Group] + * + * @param ObjectGuid guid : guid of a player + * @return bool isAssistant + */ + int IsAssistant(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->IsAssistant(guid)); + return 1; + } + + /** + * Returns 'true' if the [Player]s are in the same subgroup in this [Group] + * + * @param [Player] player1 : first [Player] to check + * @param [Player] player2 : second [Player] to check + * @return bool sameSubGroup + */ + int SameSubGroup(lua_State* L, Group* group) + { + Player* player1 = Eluna::CHECKOBJ(L, 2); + Player* player2 = Eluna::CHECKOBJ(L, 3); + Eluna::Push(L, group->SameSubGroup(player1, player2)); + return 1; + } + + /** + * Returns 'true' if the subgroup has free slots in this [Group] + * + * @param uint8 subGroup : subGroup ID to check + * @return bool hasFreeSlot + */ + int HasFreeSlotSubGroup(lua_State* L, Group* group) + { + uint8 subGroup = Eluna::CHECKVAL(L, 2); + + if (subGroup >= MAX_RAID_SUBGROUPS) + { + luaL_argerror(L, 2, "valid subGroup ID expected"); + return 0; + } + + Eluna::Push(L, group->HasFreeSlotSubGroup(subGroup)); + return 1; + } + + /** + * Adds a new member to the [Group] + * + * @param [Player] player : [Player] to add to the group + * @return bool added : true if member was added + */ + int AddMember(lua_State* L, Group* group) + { + Player* player = Eluna::CHECKOBJ(L, 2); + + if (player->GetGroup() || !group->IsCreated() || group->IsFull()) + { + Eluna::Push(L, false); + return 1; + } + + if (player->GetGroupInvite()) + player->UninviteFromGroup(); + + bool success = group->AddMember(player); + if (success) + group->BroadcastGroupUpdate(); + + Eluna::Push(L, success); + return 1; + } + + int IsBFGroup(lua_State* L, Group* group) + { + Eluna::Push(L, group->isBFGroup()); + return 1; + } + + /** + * Returns a table with the [Player]s in this [Group] + * + * @return table groupPlayers : table of [Player]s + */ + int GetMembers(lua_State* L, Group* group) + { + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (GroupReference* itr = group->GetFirstMember(); itr; itr = itr->next()) + { + Player* member = itr->GetSource(); + if (!member || !member->GetSession()) + continue; + + Eluna::Push(L, member); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); // push table to top of stack + return 1; + } + + /** + * Returns [Group] leader GUID + * + * @return ObjectGuid leaderGUID + */ + int GetLeaderGUID(lua_State* L, Group* group) + { + Eluna::Push(L, group->GetLeaderGUID()); + return 1; + } + + /** + * Returns the [Group]'s GUID + * + * @return ObjectGuid groupGUID + */ + int GetGUID(lua_State* L, Group* group) + { + Eluna::Push(L, group->GET_GUID()); + return 1; + } + + /** + * Returns a [Group] member's GUID by their name + * + * @param string name : the [Player]'s name + * @return ObjectGuid memberGUID + */ + int GetMemberGUID(lua_State* L, Group* group) + { + const char* name = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->GetMemberGUID(name)); + return 1; + } + + /** + * Returns the member count of this [Group] + * + * @return uint32 memberCount + */ + int GetMembersCount(lua_State* L, Group* group) + { + Eluna::Push(L, group->GetMembersCount()); + return 1; + } + + /** + * Returns the [Player]'s subgroup ID of this [Group] + * + * @param ObjectGuid guid : guid of the player + * @return uint8 subGroupID : a valid subgroup ID or MAX_RAID_SUBGROUPS+1 + */ + int GetMemberGroup(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->GetMemberGroup(guid)); + return 1; + } + + /** + * Returns the [Group] members' flags + * + *
+     * enum GroupMemberFlags
+     * {
+     *     MEMBER_FLAG_ASSISTANT   = 1,
+     *     MEMBER_FLAG_MAINTANK    = 2,
+     *     MEMBER_FLAG_MAINASSIST  = 4
+     * };
+     * 
+ * + * @param ObjectGuid guid : guid of the player + * @return uint8 flags + */ +#ifndef CATA + int GetMemberFlags(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->GetMemberFlags(guid)); + return 1; + } +#endif + + /** + * Sets the leader of this [Group] + * + * @param ObjectGuid guid : guid of the new leader + */ + int SetLeader(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + group->ChangeLeader(guid); + group->SendUpdate(); + return 0; + } + + /** + * Sends a specified [WorldPacket] to this [Group] + * + * @param [WorldPacket] packet : the [WorldPacket] to send + * @param bool ignorePlayersInBg : ignores [Player]s in a battleground + * @param ObjectGuid ignore : ignore a [Player] by their GUID + */ + int SendPacket(lua_State* L, Group* group) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + bool ignorePlayersInBg = Eluna::CHECKVAL(L, 3); + ObjectGuid ignore = Eluna::CHECKVAL(L, 4); + + group->BroadcastPacket(data, ignorePlayersInBg, -1, ignore); + return 0; + } + + /** + * Removes a [Player] from this [Group] and returns 'true' if successful + * + *
+     * enum RemoveMethod
+     * {
+     *     GROUP_REMOVEMETHOD_DEFAULT  = 0,
+     *     GROUP_REMOVEMETHOD_KICK     = 1,
+     *     GROUP_REMOVEMETHOD_LEAVE    = 2,
+     *     GROUP_REMOVEMETHOD_KICK_LFG = 3
+     * };
+     * 
+ * + * @param ObjectGuid guid : guid of the player to remove + * @param [RemoveMethod] method : method used to remove the player + * @return bool removed + */ + int RemoveMember(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + uint32 method = Eluna::CHECKVAL(L, 3, 0); + + Eluna::Push(L, group->RemoveMember(guid, (RemoveMethod)method)); + return 1; + } + + /** + * Disbands this [Group] + * + */ + int Disband(lua_State* /*L*/, Group* group) + { + group->Disband(); + return 0; + } + + /** + * Converts this [Group] to a raid [Group] + * + */ + int ConvertToRaid(lua_State* /*L*/, Group* group) + { + group->ConvertToRaid(); + return 0; + } + + /** + * Sets the member's subGroup + * + * @param ObjectGuid guid : guid of the player to move + * @param uint8 groupID : the subGroup's ID + */ + int SetMembersGroup(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + uint8 subGroup = Eluna::CHECKVAL(L, 3); + + if (subGroup >= MAX_RAID_SUBGROUPS) + { + luaL_argerror(L, 3, "valid subGroup ID expected"); + return 0; + } + + if (!group->HasFreeSlotSubGroup(subGroup)) + return 0; + + group->ChangeMembersGroup(guid, subGroup); + return 0; + } + + /** + * Sets the target icon of an object for the [Group] + * + * @param uint8 icon : the icon (Skull, Square, etc) + * @param ObjectGuid target : GUID of the icon target, 0 is to clear the icon + * @param ObjectGuid setter : GUID of the icon setter + */ + int SetTargetIcon(lua_State* L, Group* group) + { + uint8 icon = Eluna::CHECKVAL(L, 2); + ObjectGuid target = Eluna::CHECKVAL(L, 3); + ObjectGuid setter = Eluna::CHECKVAL(L, 4, ObjectGuid()); + + if (icon >= TARGET_ICONS_COUNT) + return luaL_argerror(L, 2, "valid target icon expected"); + + group->SetTargetIcon(icon, setter, target); + return 0; + } + + int ConvertToLFG(lua_State* /*L*/, Group* group) + { + group->ConvertToLFG(); + return 0; + } + + /** + * Sets or removes a flag for a [Group] member + * + *
+     * enum GroupMemberFlags
+     * {
+     *     MEMBER_FLAG_ASSISTANT   = 1,
+     *     MEMBER_FLAG_MAINTANK    = 2,
+     *     MEMBER_FLAG_MAINASSIST  = 4
+     * };
+     * 
+ * + * @param ObjectGuid target : GUID of the target + * @param bool apply : add the `flag` if `true`, remove the `flag` otherwise + * @param [GroupMemberFlags] flag : the flag to set or unset + */ +#ifndef CATA + int SetMemberFlag(lua_State* L, Group* group) + { + ObjectGuid target = Eluna::CHECKVAL(L, 2); + bool apply = Eluna::CHECKVAL(L, 3); + GroupMemberFlags flag = static_cast(Eluna::CHECKVAL(L, 4)); + + group->SetGroupMemberFlag(target, apply, flag); + return 0; + } +#endif + + ElunaRegister GroupMethods[] = + { + // Getters + { "GetMembers", &LuaGroup::GetMembers }, + { "GetLeaderGUID", &LuaGroup::GetLeaderGUID }, + { "GetGUID", &LuaGroup::GetGUID }, + { "GetMemberGroup", &LuaGroup::GetMemberGroup }, + { "GetMemberGUID", &LuaGroup::GetMemberGUID }, + { "GetMembersCount", &LuaGroup::GetMembersCount }, +#ifndef CATA + { "GetMemberFlags", &LuaGroup::GetMemberFlags }, +#else + { "GetMemberFlags", nullptr }, +#endif + + // Setters + { "SetLeader", &LuaGroup::SetLeader }, + { "SetMembersGroup", &LuaGroup::SetMembersGroup }, + { "SetTargetIcon", &LuaGroup::SetTargetIcon }, +#ifndef CATA + { "SetMemberFlag", &LuaGroup::SetMemberFlag }, +#else + { "SetMemberFlag", nullptr }, +#endif + + // Boolean + { "IsLeader", &LuaGroup::IsLeader }, + { "AddMember", &LuaGroup::AddMember }, + { "RemoveMember", &LuaGroup::RemoveMember }, + { "Disband", &LuaGroup::Disband }, + { "IsFull", &LuaGroup::IsFull }, + { "IsLFGGroup", &LuaGroup::IsLFGGroup }, + { "IsRaidGroup", &LuaGroup::IsRaidGroup }, + { "IsBGGroup", &LuaGroup::IsBGGroup }, + { "IsBFGroup", &LuaGroup::IsBFGroup }, + { "IsMember", &LuaGroup::IsMember }, + { "IsAssistant", &LuaGroup::IsAssistant }, + { "SameSubGroup", &LuaGroup::SameSubGroup }, + { "HasFreeSlotSubGroup", &LuaGroup::HasFreeSlotSubGroup }, + + // Other + { "SendPacket", &LuaGroup::SendPacket }, + { "ConvertToLFG", &LuaGroup::ConvertToLFG }, + { "ConvertToRaid", &LuaGroup::ConvertToRaid }, + + { NULL, NULL } + }; +}; + +#endif diff --git a/src/modules/Eluna/TrinityCore/GuildMethods.h b/src/modules/Eluna/TrinityCore/GuildMethods.h new file mode 100644 index 0000000000..63dd15bdf3 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/GuildMethods.h @@ -0,0 +1,276 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef GUILDMETHODS_H +#define GUILDMETHODS_H + +/*** + * Inherits all methods from: none + */ +namespace LuaGuild +{ + /** + * Returns a table with the [Player]s in this [Guild] + * + * Only the players that are online and on some map. + * + * @return table guildPlayers : table of [Player]s + */ + int GetMembers(lua_State* L, Guild* guild) + { + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 i = 0; + + std::shared_lock lock(*HashMapHolder::GetLock()); + const HashMapHolder::MapType& m = eObjectAccessor()GetPlayers(); + for (HashMapHolder::MapType::const_iterator it = m.begin(); it != m.end(); ++it) + { + if (Player* player = it->second) + { + if (player->IsInWorld() && player->GetGuildId() == guild->GetId()) + { + Eluna::Push(L, player); + lua_rawseti(L, tbl, ++i); + } + } + } + + lua_settop(L, tbl); // push table to top of stack + return 1; + } + + /** + * Returns the member count of this [Guild] + * + * @return uint32 memberCount + */ + int GetMemberCount(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetMemberCount()); + return 1; + } + + /** + * Finds and returns the [Guild] leader by their GUID if logged in + * + * @return [Player] leader + */ + int GetLeader(lua_State* L, Guild* guild) + { + Eluna::Push(L, eObjectAccessor()FindPlayer(guild->GetLeaderGUID())); + return 1; + } + + /** + * Returns [Guild] leader GUID + * + * @return ObjectGuid leaderGUID + */ + int GetLeaderGUID(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetLeaderGUID()); + return 1; + } + + /** + * Returns the [Guild]s entry ID + * + * @return uint32 entryId + */ + int GetId(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetId()); + return 1; + } + + /** + * Returns the [Guild]s name + * + * @return string guildName + */ + int GetName(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetName()); + return 1; + } + + /** + * Returns the [Guild]s current Message Of The Day + * + * @return string guildMOTD + */ + int GetMOTD(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetMOTD()); + return 1; + } + + /** + * Returns the [Guild]s current info + * + * @return string guildInfo + */ + int GetInfo(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetInfo()); + return 1; + } + +#ifndef CATA + /** + * Sets the leader of this [Guild] + * + * @param [Player] leader : the [Player] leader to change + */ + int SetLeader(lua_State* L, Guild* guild) + { + Player* player = Eluna::CHECKOBJ(L, 2); + + guild->HandleSetLeader(player->GetSession(), player->GetName()); + return 0; + } +#endif + + /** + * Sets the information of the bank tab specified + * + * @param uint8 tabId : the ID of the tab specified + * @param string info : the information to be set to the bank tab + */ + int SetBankTabText(lua_State* L, Guild* guild) + { + uint8 tabId = Eluna::CHECKVAL(L, 2); + const char* text = Eluna::CHECKVAL(L, 3); + + guild->SetBankTabText(tabId, text); + return 0; + } + + // SendPacketToGuild(packet) + /** + * Sends a [WorldPacket] to all the [Player]s in the [Guild] + * + * @param [WorldPacket] packet : the [WorldPacket] to be sent to the [Player]s + */ + int SendPacket(lua_State* L, Guild* guild) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + + guild->BroadcastPacket(data); + return 0; + } + + // SendPacketToRankedInGuild(packet, rankId) + /** + * Sends a [WorldPacket] to all the [Player]s at the specified rank in the [Guild] + * + * @param [WorldPacket] packet : the [WorldPacket] to be sent to the [Player]s + * @param uint8 rankId : the rank ID + */ + int SendPacketToRanked(lua_State* L, Guild* guild) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + uint8 ranked = Eluna::CHECKVAL(L, 3); + + guild->BroadcastPacketToRank(data, ranked); + return 0; + } + + /** + * Disbands the [Guild] + */ + int Disband(lua_State* /*L*/, Guild* guild) + { + guild->Disband(); + return 0; + } + + /** + * Adds the specified [Player] to the [Guild] at the specified rank. + * + * If no rank is specified, defaults to none. + * + * @param [Player] player : the [Player] to be added to the guild + * @param uint8 rankId : the rank ID + */ + int AddMember(lua_State* L, Guild* guild) + { + Player* player = Eluna::CHECKOBJ(L, 2); + uint8 rankId = Eluna::CHECKVAL(L, 3, GUILD_RANK_NONE); + + CharacterDatabaseTransaction trans(nullptr); + + guild->AddMember(trans, player->GET_GUID(), rankId); + return 0; + } + + /** + * Removes the specified [Player] from the [Guild]. + * + * @param [Player] player : the [Player] to be removed from the guild + * @param bool isDisbanding : default 'false', should only be set to 'true' if the guild is triggered to disband + */ + int DeleteMember(lua_State* L, Guild* guild) + { + Player* player = Eluna::CHECKOBJ(L, 2); + bool isDisbanding = Eluna::CHECKVAL(L, 3, false); + + CharacterDatabaseTransaction trans(nullptr); + + guild->DeleteMember(trans, player->GET_GUID(), isDisbanding); + return 0; + } + + /** + * Promotes/demotes the [Player] to the specified rank. + * + * @param [Player] player : the [Player] to be promoted/demoted + * @param uint8 rankId : the rank ID + */ + int SetMemberRank(lua_State* L, Guild* guild) + { + Player* player = Eluna::CHECKOBJ(L, 2); + uint8 newRank = Eluna::CHECKVAL(L, 3); + + CharacterDatabaseTransaction trans(nullptr); + + guild->ChangeMemberRank(trans, player->GET_GUID(), newRank); + return 0; + } + + ElunaRegister GuildMethods[] = + { + // Getters + { "GetMembers", &LuaGuild::GetMembers }, + { "GetLeader", &LuaGuild::GetLeader }, + { "GetLeaderGUID", &LuaGuild::GetLeaderGUID }, + { "GetId", &LuaGuild::GetId }, + { "GetName", &LuaGuild::GetName }, + { "GetMOTD", &LuaGuild::GetMOTD }, + { "GetInfo", &LuaGuild::GetInfo }, + { "GetMemberCount", &LuaGuild::GetMemberCount }, + + // Setters + { "SetBankTabText", &LuaGuild::SetBankTabText }, + { "SetMemberRank", &LuaGuild::SetMemberRank }, +#ifndef CATA + { "SetLeader", &LuaGuild::SetLeader }, +#else + { "SetLeader", nullptr }, +#endif + + // Other + { "SendPacket", &LuaGuild::SendPacket }, + { "SendPacketToRanked", &LuaGuild::SendPacketToRanked }, + { "Disband", &LuaGuild::Disband }, + { "AddMember", &LuaGuild::AddMember }, + { "DeleteMember", &LuaGuild::DeleteMember }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/ItemMethods.h b/src/modules/Eluna/TrinityCore/ItemMethods.h new file mode 100644 index 0000000000..46b0a2982b --- /dev/null +++ b/src/modules/Eluna/TrinityCore/ItemMethods.h @@ -0,0 +1,885 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef ITEMMETHODS_H +#define ITEMMETHODS_H + +/*** + * Inherits all methods from: [Object] + */ +namespace LuaItem +{ + /** + * Returns 'true' if the [Item] is soulbound, 'false' otherwise + * + * @return bool isSoulBound + */ + int IsSoulBound(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsSoulBound()); + return 1; + } + + /** + * Returns 'true' if the [Item] is account bound, 'false' otherwise + * + * @return bool isAccountBound + */ + int IsBoundAccountWide(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsBoundAccountWide()); + return 1; + } + + /** + * Returns 'true' if the [Item] is bound to a [Player] by an enchant, 'false' otehrwise + * + * @return bool isBoundByEnchant + */ + int IsBoundByEnchant(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsBoundByEnchant()); + return 1; + } + + /** + * Returns 'true' if the [Item] is not bound to the [Player] specified, 'false' otherwise + * + * @param [Player] player : the [Player] object to check the item against + * @return bool isNotBound + */ + int IsNotBoundToPlayer(lua_State* L, Item* item) + { + Player* player = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, item->IsBindedNotWith(player)); + return 1; + } + + /** + * Returns 'true' if the [Item] is locked, 'false' otherwise + * + * @return bool isLocked + */ + int IsLocked(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsLocked()); + return 1; + } + + /** + * Returns 'true' if the [Item] is a bag, 'false' otherwise + * + * @return bool isBag + */ + int IsBag(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsBag()); + return 1; + } + + /** + * Returns 'true' if the [Item] is a currency token, 'false' otherwise + * + * @return bool isCurrencyToken + */ + int IsCurrencyToken(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsCurrencyToken()); + return 1; + } + + /** + * Returns 'true' if the [Item] is a not an empty bag, 'false' otherwise + * + * @return bool isNotEmptyBag + */ + int IsNotEmptyBag(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsNotEmptyBag()); + return 1; + } + + /** + * Returns 'true' if the [Item] is broken, 'false' otherwise + * + * @return bool isBroken + */ + int IsBroken(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsBroken()); + return 1; + } + + /** + * Returns 'true' if the [Item] can be traded, 'false' otherwise + * + * @return bool isTradeable + */ + int CanBeTraded(lua_State* L, Item* item) + { + bool mail = Eluna::CHECKVAL(L, 2, false); + + Eluna::Push(L, item->CanBeTraded(mail)); + return 1; + } + + /** + * Returns 'true' if the [Item] is currently in a trade window, 'false' otherwise + * + * @return bool isInTrade + */ + int IsInTrade(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsInTrade()); + return 1; + } + + /** + * Returns 'true' if the [Item] is currently in a bag, 'false' otherwise + * + * @return bool isInBag + */ + int IsInBag(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsInBag()); + return 1; + } + + /** + * Returns 'true' if the [Item] is currently equipped, 'false' otherwise + * + * @return bool isEquipped + */ + int IsEquipped(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsEquipped()); + return 1; + } + + /** + * Returns 'true' if the [Item] has the [Quest] specified tied to it, 'false' otherwise + * + * @param uint32 questId : the [Quest] id to be checked + * @return bool hasQuest + */ + int HasQuest(lua_State* L, Item* item) + { + uint32 quest = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, item->hasQuest(quest)); + return 1; + } + + /** + * Returns 'true' if the [Item] is a potion, 'false' otherwise + * + * @return bool isPotion + */ + int IsPotion(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsPotion()); + return 1; + } + +#if defined(WOTLK) + /** + * Returns 'true' if the [Item] is a weapon vellum, 'false' otherwise + * + * @return bool isWeaponVellum + */ + int IsWeaponVellum(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsWeaponVellum()); + return 1; + } + + /** + * Returns 'true' if the [Item] is an armor vellum, 'false' otherwise + * + * @return bool isArmorVellum + */ + int IsArmorVellum(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsArmorVellum()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Item] is a conjured consumable, 'false' otherwise + * + * @return bool isConjuredConsumable + */ + int IsConjuredConsumable(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsConjuredConsumable()); + return 1; + } + +#ifndef CATA + int IsRefundExpired(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsRefundExpired()); + return 1; + } +#endif + + /** + * Returns the chat link of the [Item] + * + *
+     * enum LocaleConstant
+     * {
+     *     LOCALE_enUS = 0,
+     *     LOCALE_koKR = 1,
+     *     LOCALE_frFR = 2,
+     *     LOCALE_deDE = 3,
+     *     LOCALE_zhCN = 4,
+     *     LOCALE_zhTW = 5,
+     *     LOCALE_esES = 6,
+     *     LOCALE_esMX = 7,
+     *     LOCALE_ruRU = 8
+     * };
+     * 
+ * + * @param [LocaleConstant] locale = DEFAULT_LOCALE : locale to return the [Item]'s name in + * @return string itemLink + */ + int GetItemLink(lua_State* L, Item* item) + { + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const ItemTemplate* temp = item->GetTemplate(); +#ifdef CATA + std::string name = temp->ExtendedData->Display1->Str[locale]; + if (ItemLocale const* il = eObjectMgr->GetItemLocale(temp->BasicData->ID)) +#else + std::string name = temp->Name1; + if (ItemLocale const* il = eObjectMgr->GetItemLocale(temp->ItemId)) +#endif + ObjectMgr::GetLocaleString(il->Name, static_cast(locale), name); + + if (int32 itemRandPropId = item->GetItemRandomPropertyId()) + { +#ifndef CATA + std::array const* suffix = NULL; +#else + char* const* suffix = NULL; +#endif + if (itemRandPropId < 0) + { + const ItemRandomSuffixEntry* itemRandEntry = sItemRandomSuffixStore.LookupEntry(-item->GetItemRandomPropertyId()); + if (itemRandEntry) + suffix = &itemRandEntry->Name; + } + else + { + const ItemRandomPropertiesEntry* itemRandEntry = sItemRandomPropertiesStore.LookupEntry(item->GetItemRandomPropertyId()); + if (itemRandEntry) + suffix = &itemRandEntry->Name; + } + if (suffix) + { + name += ' '; +#ifndef CATA + name += (*suffix)[(name != temp->Name1) ? locale : uint8(DEFAULT_LOCALE)]; +#else + name += (*suffix)[(name != temp->ExtendedData->Display->Str[locale]) ? locale : uint8(DEFAULT_LOCALE)]; +#endif + } + } + + std::ostringstream oss; +#ifdef CATA + oss << "|c" << std::hex << ItemQualityColors[temp->ExtendedData->Quality] << std::dec << + "|Hitem:" << temp->BasicData->ID << ":" << +#else + oss << "|c" << std::hex << ItemQualityColors[temp->Quality] << std::dec << + "|Hitem:" << temp->ItemId << ":" << +#endif + item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT) << ":" << + item->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT) << ":" << + item->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_2) << ":" << + item->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_3) << ":" << + item->GetEnchantmentId(BONUS_ENCHANTMENT_SLOT) << ":" << + item->GetItemRandomPropertyId() << ":" << item->GetItemSuffixFactor() << ":" << + (uint32)item->GetOwner()->GetLevel() << "|h[" << name << "]|h|r"; + + Eluna::Push(L, oss.str()); + return 1; + } + + int GetOwnerGUID(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetOwnerGUID()); + return 1; + } + + /** + * Returns the [Player] who currently owns the [Item] + * + * @return [Player] player : the [Player] who owns the [Item] + */ + int GetOwner(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetOwner()); + return 1; + } + + /** + * Returns the [Item]s stack count + * + * @return uint32 count + */ + int GetCount(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetCount()); + return 1; + } + + /** + * Returns the [Item]s max stack count + * + * @return uint32 maxCount + */ + int GetMaxStackCount(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetMaxStackCount()); + return 1; + } + + /** + * Returns the [Item]s current slot + * + * @return uint8 slot + */ + int GetSlot(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetSlot()); + return 1; + } + + /** + * Returns the [Item]s current bag slot + * + * @return uint8 bagSlot + */ + int GetBagSlot(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetBagSlot()); + return 1; + } + + /** + * Returns the [Item]s enchantment ID by enchant slot specified + * + * @param [EnchantmentSlot] enchantSlot : the enchant slot specified + * @return uint32 enchantId : the id of the enchant slot specified + */ + int GetEnchantmentId(lua_State* L, Item* item) + { + uint32 enchant_slot = Eluna::CHECKVAL(L, 2); + + if (enchant_slot >= MAX_INSPECTED_ENCHANTMENT_SLOT) + return luaL_argerror(L, 2, "valid EnchantmentSlot expected"); + + Eluna::Push(L, item->GetEnchantmentId(EnchantmentSlot(enchant_slot))); + return 1; + } + + /** + * Returns the spell ID tied to the [Item] by spell index + * + * @param uint32 spellIndex : the spell index specified + * @return uint32 spellId : the id of the spell + */ + int GetSpellId(lua_State* L, Item* item) + { + uint32 index = Eluna::CHECKVAL(L, 2); + if (index >= MAX_ITEM_PROTO_SPELLS) + return luaL_argerror(L, 2, "valid SpellIndex expected"); + +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->ExtendedData->SpellID[index]); +#else + Eluna::Push(L, item->GetTemplate()->Spells[index].SpellId); +#endif + return 1; + } + + /** + * Returns the spell trigger tied to the [Item] by spell index + * + * @param uint32 spellIndex : the spell index specified + * @return uint32 spellTrigger : the spell trigger of the specified index + */ + int GetSpellTrigger(lua_State* L, Item* item) + { + uint32 index = Eluna::CHECKVAL(L, 2); + if (index >= MAX_ITEM_PROTO_SPELLS) + return luaL_argerror(L, 2, "valid SpellIndex expected"); + +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->ExtendedData->SpellTrigger[index]); +#else + Eluna::Push(L, item->GetTemplate()->Spells[index].SpellTrigger); +#endif + return 1; + } + + /** + * Returns class of the [Item] + * + * @return uint32 class + */ + int GetClass(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetClass()); +#else + Eluna::Push(L, item->GetTemplate()->Class); +#endif + return 1; + } + + /** + * Returns subclass of the [Item] + * + * @return uint32 subClass + */ + int GetSubClass(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetSubClass()); +#else + Eluna::Push(L, item->GetTemplate()->SubClass); +#endif + return 1; + } + + /** + * Returns the name of the [Item] + * + * @return string name + */ + int GetName(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetDefaultLocaleName()); +#else + Eluna::Push(L, item->GetTemplate()->Name1); +#endif + return 1; + } + + /** + * Returns the display ID of the [Item] + * + * @return uint32 displayId + */ + int GetDisplayId(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetDisplayID()); +#else + Eluna::Push(L, item->GetTemplate()->DisplayInfoID); +#endif + return 1; + } + + /** + * Returns the quality of the [Item] + * + * @return uint32 quality + */ + int GetQuality(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetQuality()); +#else + Eluna::Push(L, item->GetTemplate()->Quality); +#endif + return 1; + } + + /** + * Returns the default purchase count of the [Item] + * + * @return uint32 count + */ + int GetBuyCount(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetBuyCount()); +#else + Eluna::Push(L, item->GetTemplate()->BuyCount); +#endif + return 1; + } + + /** + * Returns the purchase price of the [Item] + * + * @return uint32 price + */ + int GetBuyPrice(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetBuyPrice()); +#else + Eluna::Push(L, item->GetTemplate()->BuyPrice); +#endif + return 1; + } + + /** + * Returns the sell price of the [Item] + * + * @return uint32 price + */ + int GetSellPrice(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetSellPrice()); +#else + Eluna::Push(L, item->GetTemplate()->SellPrice); +#endif + return 1; + } + + /** + * Returns the inventory type of the [Item] + * + * @return uint32 inventoryType + */ + int GetInventoryType(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetInventoryType()); +#else + Eluna::Push(L, item->GetTemplate()->InventoryType); +#endif + return 1; + } + + /** + * Returns the [Player] classes allowed to use this [Item] + * + * @return uint32 allowableClass + */ + int GetAllowableClass(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetAllowableClass()); +#else + Eluna::Push(L, item->GetTemplate()->AllowableClass); +#endif + return 1; + } + + /** + * Returns the [Player] races allowed to use this [Item] + * + * @return uint32 allowableRace + */ + int GetAllowableRace(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetAllowableRace()); +#else + Eluna::Push(L, item->GetTemplate()->AllowableRace); +#endif + return 1; + } + + /** + * Returns the [Item]s level + * + * @return uint32 itemLevel + */ + int GetItemLevel(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetBaseItemLevel()); +#else + Eluna::Push(L, item->GetTemplate()->ItemLevel); +#endif + return 1; + } + + /** + * Returns the minimum level required to use this [Item] + * + * @return uint32 requiredLevel + */ + int GetRequiredLevel(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetRequiredLevel()); +#else + Eluna::Push(L, item->GetTemplate()->RequiredLevel); +#endif + return 1; + } + +#ifdef WOTLK + int GetStatsCount(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->StatsCount); + return 1; + } +#endif + + /** + * Returns the random property ID of this [Item] + * + * @return uint32 randomPropertyId + */ + int GetRandomProperty(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetRandomProperty()); +#else + Eluna::Push(L, item->GetTemplate()->RandomProperty); +#endif + return 1; + } + + int GetRandomSuffix(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetRandomSuffix()); +#else + Eluna::Push(L, item->GetTemplate()->RandomSuffix); +#endif + return 1; + } + + /** + * Returns the item set ID of this [Item] + * + * @return uint32 itemSetId + */ + int GetItemSet(lua_State* L, Item* item) + { +#ifdef CATA + Eluna::Push(L, item->GetTemplate()->GetItemSet()); +#else + Eluna::Push(L, item->GetTemplate()->ItemSet); +#endif + return 1; + } + + /** + * Returns the bag size of this [Item], 0 if [Item] is not a bag + * + * @return uint32 bagSize + */ + int GetBagSize(lua_State* L, Item* item) + { + if (Bag* bag = item->ToBag()) + Eluna::Push(L, bag->GetBagSize()); + else + Eluna::Push(L, 0); + return 1; + } + + /** + * Sets the [Player] specified as the owner of the [Item] + * + * @param [Player] player : the [Player] specified + */ + int SetOwner(lua_State* L, Item* item) + { + Player* player = Eluna::CHECKOBJ(L, 2); + + item->SetOwnerGUID(player->GET_GUID()); + return 0; + } + + /** + * Sets the binding of the [Item] to 'true' or 'false' + * + * @param bool setBinding + */ + int SetBinding(lua_State* L, Item* item) + { + bool soulbound = Eluna::CHECKVAL(L, 2); + + item->SetBinding(soulbound); + item->SetState(ITEM_CHANGED, item->GetOwner()); + + return 0; + } + + /** + * Sets the stack count of the [Item] + * + * @param uint32 count + */ + int SetCount(lua_State* L, Item* item) + { + uint32 count = Eluna::CHECKVAL(L, 2); + item->SetCount(count); + return 0; + } + + /** + * Sets the specified enchantment of the [Item] to the specified slot + * + * @param uint32 enchantId : the ID of the enchant to be applied + * @param uint32 enchantSlot : the slot for the enchant to be applied to + * @return bool enchantmentSuccess : if enchantment is successfully set to specified slot, returns 'true', otherwise 'false' + */ + int SetEnchantment(lua_State* L, Item* item) + { + Player* owner = item->GetOwner(); + if (!owner) + { + Eluna::Push(L, false); + return 1; + } + + uint32 enchant = Eluna::CHECKVAL(L, 2); + if (!sSpellItemEnchantmentStore.LookupEntry(enchant)) + { + Eluna::Push(L, false); + return 1; + } + + EnchantmentSlot slot = (EnchantmentSlot)Eluna::CHECKVAL(L, 3); + if (slot >= MAX_INSPECTED_ENCHANTMENT_SLOT) + return luaL_argerror(L, 2, "valid EnchantmentSlot expected"); + + owner->ApplyEnchantment(item, slot, false); + item->SetEnchantment(slot, enchant, 0, 0); + owner->ApplyEnchantment(item, slot, true); + Eluna::Push(L, true); + return 1; + } + + /* OTHER */ + /** + * Removes an enchant from the [Item] by the specified slot + * + * @param uint32 enchantSlot : the slot for the enchant to be removed from + * @return bool enchantmentRemoved : if enchantment is successfully removed from specified slot, returns 'true', otherwise 'false' + */ + int ClearEnchantment(lua_State* L, Item* item) + { + Player* owner = item->GetOwner(); + if (!owner) + { + Eluna::Push(L, false); + return 1; + } + + EnchantmentSlot slot = (EnchantmentSlot)Eluna::CHECKVAL(L, 2); + if (slot >= MAX_INSPECTED_ENCHANTMENT_SLOT) + return luaL_argerror(L, 2, "valid EnchantmentSlot expected"); + + if (!item->GetEnchantmentId(slot)) + { + Eluna::Push(L, false); + return 1; + } + + owner->ApplyEnchantment(item, slot, false); + item->ClearEnchantment(slot); + Eluna::Push(L, true); + return 1; + } + + /** + * Saves the [Item] to the database + */ + int SaveToDB(lua_State* /*L*/, Item* item) + { + CharacterDatabaseTransaction trans = CharacterDatabaseTransaction(nullptr); + item->SaveToDB(trans); + return 0; + } + + ElunaRegister ItemMethods[] = + { + // Getters + { "GetOwnerGUID", &LuaItem::GetOwnerGUID }, + { "GetOwner", &LuaItem::GetOwner }, + { "GetCount", &LuaItem::GetCount }, + { "GetMaxStackCount", &LuaItem::GetMaxStackCount }, + { "GetSlot", &LuaItem::GetSlot }, + { "GetBagSlot", &LuaItem::GetBagSlot }, + { "GetEnchantmentId", &LuaItem::GetEnchantmentId }, + { "GetSpellId", &LuaItem::GetSpellId }, + { "GetSpellTrigger", &LuaItem::GetSpellTrigger }, + { "GetItemLink", &LuaItem::GetItemLink }, + { "GetClass", &LuaItem::GetClass }, + { "GetSubClass", &LuaItem::GetSubClass }, + { "GetName", &LuaItem::GetName }, + { "GetDisplayId", &LuaItem::GetDisplayId }, + { "GetQuality", &LuaItem::GetQuality }, + { "GetBuyCount", &LuaItem::GetBuyCount }, + { "GetBuyPrice", &LuaItem::GetBuyPrice }, + { "GetSellPrice", &LuaItem::GetSellPrice }, + { "GetInventoryType", &LuaItem::GetInventoryType }, + { "GetAllowableClass", &LuaItem::GetAllowableClass }, + { "GetAllowableRace", &LuaItem::GetAllowableRace }, + { "GetItemLevel", &LuaItem::GetItemLevel }, + { "GetRequiredLevel", &LuaItem::GetRequiredLevel }, +#ifndef CATA + { "GetStatsCount", &LuaItem::GetStatsCount }, +#else + { "GetStatsCount", nullptr }, +#endif + { "GetRandomProperty", &LuaItem::GetRandomProperty }, + { "GetRandomSuffix", &LuaItem::GetRandomSuffix }, + { "GetItemSet", &LuaItem::GetItemSet }, + { "GetBagSize", &LuaItem::GetBagSize }, + + // Setters + { "SetOwner", &LuaItem::SetOwner }, + { "SetBinding", &LuaItem::SetBinding }, + { "SetCount", &LuaItem::SetCount }, + + // Boolean + { "IsSoulBound", &LuaItem::IsSoulBound }, + { "IsBoundAccountWide", &LuaItem::IsBoundAccountWide }, + { "IsBoundByEnchant", &LuaItem::IsBoundByEnchant }, + { "IsNotBoundToPlayer", &LuaItem::IsNotBoundToPlayer }, + { "IsLocked", &LuaItem::IsLocked }, + { "IsBag", &LuaItem::IsBag }, + { "IsCurrencyToken", &LuaItem::IsCurrencyToken }, + { "IsNotEmptyBag", &LuaItem::IsNotEmptyBag }, + { "IsBroken", &LuaItem::IsBroken }, + { "CanBeTraded", &LuaItem::CanBeTraded }, + { "IsInTrade", &LuaItem::IsInTrade }, + { "IsInBag", &LuaItem::IsInBag }, + { "IsEquipped", &LuaItem::IsEquipped }, + { "HasQuest", &LuaItem::HasQuest }, + { "IsPotion", &LuaItem::IsPotion }, +#ifndef CATA + { "IsWeaponVellum", &LuaItem::IsWeaponVellum }, + { "IsArmorVellum", &LuaItem::IsArmorVellum }, + { "IsRefundExpired", &LuaItem::IsRefundExpired }, +#else + { "IsWeaponVellum", nullptr }, + { "IsArmorVellum", nullptr }, + { "IsRefundExpired", nullptr }, +#endif + { "IsConjuredConsumable", &LuaItem::IsConjuredConsumable }, + { "SetEnchantment", &LuaItem::SetEnchantment }, + { "ClearEnchantment", &LuaItem::ClearEnchantment }, + + // Other + { "SaveToDB", &LuaItem::SaveToDB }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/MapMethods.h b/src/modules/Eluna/TrinityCore/MapMethods.h new file mode 100644 index 0000000000..4384cce751 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/MapMethods.h @@ -0,0 +1,370 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef MAPMETHODS_H +#define MAPMETHODS_H + +#include "ElunaInstanceAI.h" + +/*** + * A game map, e.g. Azeroth, Eastern Kingdoms, the Molten Core, etc. + * + * Inherits all methods from: none + */ +namespace LuaMap +{ + + /** + * Returns `true` if the [Map] is an arena [BattleGround], `false` otherwise. + * + * @return bool isArena + */ + int IsArena(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsBattleArena()); + return 1; + } + + /** + * Returns `true` if the [Map] is a non-arena [BattleGround], `false` otherwise. + * + * @return bool isBattleGround + */ + int IsBattleground(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsBattleground()); + return 1; + } + + /** + * Returns `true` if the [Map] is a dungeon, `false` otherwise. + * + * @return bool isDungeon + */ + int IsDungeon(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsDungeon()); + return 1; + } + + /** + * Returns `true` if the [Map] has no [Player]s, `false` otherwise. + * + * @return bool isEmpty + */ + int IsEmpty(lua_State* L, Map* map) + { + Eluna::Push(L, map->isEmpty()); + return 1; + } + + /** + * Returns `true` if the [Map] is a heroic, `false` otherwise. + * + * @return bool isHeroic + */ + int IsHeroic(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsHeroic()); + return 1; + } + + /** + * Returns `true` if the [Map] is a raid, `false` otherwise. + * + * @return bool isRaid + */ + int IsRaid(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsRaid()); + return 1; + } + + /** + * Returns the name of the [Map]. + * + * @return string mapName + */ + int GetName(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetMapName()); + return 1; + } + + /** + * Returns the height of the [Map] at the given X and Y coordinates. + * + * In case of no height found nil is returned + * + * @param float x + * @param float y + * @return float z + */ + int GetHeight(lua_State* L, Map* map) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); +#ifdef CATA + PhaseShift phase; + float z = map->GetHeight(phase, x, y, MAX_HEIGHT); +#else + uint32 phasemask = Eluna::CHECKVAL(L, 4, 1); + + float z = map->GetHeight(phasemask, x, y, MAX_HEIGHT); +#endif + if (z != INVALID_HEIGHT) + Eluna::Push(L, z); + return 1; + } + + /** + * Returns the difficulty of the [Map]. + * + * Always returns 0 if the expansion is pre-TBC. + * + * @return int32 difficulty + */ + int GetDifficulty(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetDifficulty()); + return 1; + } + + /** + * Returns the instance ID of the [Map]. + * + * @return uint32 instanceId + */ + int GetInstanceId(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetInstanceId()); + return 1; + } + + /** + * Returns the player count currently on the [Map] (excluding GMs). + * + * @return uint32 playerCount + */ + int GetPlayerCount(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetPlayersCountExceptGMs()); + return 1; + } + + /** + * Returns the ID of the [Map]. + * + * @return uint32 mapId + */ + int GetMapId(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetId()); + return 1; + } + + /** + * Returns the area ID of the [Map] at the specified X, Y, and Z coordinates. + * + * @param float x + * @param float y + * @param float z + * @param uint32 phasemask = PHASEMASK_NORMAL + * @return uint32 areaId + */ + int GetAreaId(lua_State* L, Map* map) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); +#ifdef CATA + PhaseShift phase; + Eluna::Push(L, map->GetAreaId(phase, x, y, z)); +#else + float phasemask = Eluna::CHECKVAL(L, 5, PHASEMASK_NORMAL); + + Eluna::Push(L, map->GetAreaId(phasemask, x, y, z)); +#endif + return 1; + } + + /** + * Returns a [WorldObject] by its GUID from the map if it is spawned. + * + * @param ObjectGuid guid + * @return [WorldObject] object + */ + int GetWorldObject(lua_State* L, Map* map) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + + switch (guid.GetHigh()) + { + case HIGHGUID_PLAYER: + Eluna::Push(L, eObjectAccessor()GetPlayer(map, guid)); + break; + case HIGHGUID_TRANSPORT: + case HIGHGUID_MO_TRANSPORT: + case HIGHGUID_GAMEOBJECT: + Eluna::Push(L, map->GetGameObject(guid)); + break; + case HIGHGUID_VEHICLE: + case HIGHGUID_UNIT: + Eluna::Push(L, map->GetCreature(guid)); + break; + case HIGHGUID_PET: + Eluna::Push(L, map->GetPet(guid)); + break; + case HIGHGUID_DYNAMICOBJECT: + Eluna::Push(L, map->GetDynamicObject(guid)); + break; + case HIGHGUID_CORPSE: + Eluna::Push(L, map->GetCorpse(guid)); + break; + default: + break; + } + + return 1; + } + + /** + * Sets the [Weather] type based on [WeatherType] and grade supplied. + * + * enum WeatherType + * { + * WEATHER_TYPE_FINE = 0, + * WEATHER_TYPE_RAIN = 1, + * WEATHER_TYPE_SNOW = 2, + * WEATHER_TYPE_STORM = 3, + * WEATHER_TYPE_THUNDERS = 86, + * WEATHER_TYPE_BLACKRAIN = 90 + * }; + * + * @param uint32 zone : id of the zone to set the weather for + * @param [WeatherType] type : the [WeatherType], see above available weather types + * @param float grade : the intensity/grade of the [Weather], ranges from 0 to 1 + */ + int SetWeather(lua_State* L, Map* map) + { + (void)map; // ensure that the variable is referenced in order to pass compiler checks + uint32 zoneId = Eluna::CHECKVAL(L, 2); + uint32 weatherType = Eluna::CHECKVAL(L, 3); + float grade = Eluna::CHECKVAL(L, 4); + + if (Weather * weather = map->GetOrGenerateZoneDefaultWeather(zoneId)) + weather->SetWeather((WeatherType)weatherType, grade); + return 0; + } + + /** + * Gets the instance data table for the [Map], if it exists. + * + * The instance must be scripted using Eluna for this to succeed. + * If the instance is scripted in C++ this will return `nil`. + * + * @return table instance_data : instance data table, or `nil` + */ + int GetInstanceData(lua_State* L, Map* map) + { + ElunaInstanceAI* iAI = NULL; + if (InstanceMap* inst = map->ToInstanceMap()) + iAI = dynamic_cast(inst->GetInstanceScript()); + + if (iAI) + Eluna::GetEluna(L)->PushInstanceData(L, iAI, false); + else + Eluna::Push(L); // nil + + return 1; + } + + /** + * Saves the [Map]'s instance data to the database. + */ + int SaveInstanceData(lua_State* /*L*/, Map* map) + { + ElunaInstanceAI* iAI = NULL; + if (InstanceMap* inst = map->ToInstanceMap()) + iAI = dynamic_cast(inst->GetInstanceScript()); + + if (iAI) + iAI->SaveToDB(); + + return 0; + } + + /** + * Returns a table with all the current [Player]s in the map + * + * enum TeamId + * { + * TEAM_ALLIANCE = 0, + * TEAM_HORDE = 1, + * TEAM_NEUTRAL = 2 + * }; + * + * @param [TeamId] team : optional check team of the [Player], Alliance, Horde or Neutral (All) + * @return table mapPlayers + */ + int GetPlayers(lua_State* L, Map* map) + { + uint32 team = Eluna::CHECKVAL(L, 2, TEAM_NEUTRAL); + + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 i = 0; + + Map::PlayerList const& players = map->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* player = itr->GetSource(); + if (!player) + continue; + + if (player->GetSession() && (team >= TEAM_NEUTRAL || player->GetTeamId() == team)) + { + Eluna::Push(L, player); + lua_rawseti(L, tbl, ++i); + } + } + + lua_settop(L, tbl); + return 1; + } + + ElunaRegister MapMethods[] = + { + // Getters + { "GetName", &LuaMap::GetName }, + { "GetDifficulty", &LuaMap::GetDifficulty }, + { "GetInstanceId", &LuaMap::GetInstanceId }, + { "GetInstanceData", &LuaMap::GetInstanceData }, + { "GetPlayerCount", &LuaMap::GetPlayerCount }, + { "GetPlayers", &LuaMap::GetPlayers }, + { "GetMapId", &LuaMap::GetMapId }, + { "GetAreaId", &LuaMap::GetAreaId }, + { "GetHeight", &LuaMap::GetHeight }, + { "GetWorldObject", &LuaMap::GetWorldObject }, + + // Setters + { "SetWeather", &LuaMap::SetWeather }, + + // Boolean + { "IsArena", &LuaMap::IsArena }, + { "IsBattleground", &LuaMap::IsBattleground }, + { "IsDungeon", &LuaMap::IsDungeon }, + { "IsEmpty", &LuaMap::IsEmpty }, + { "IsHeroic", &LuaMap::IsHeroic }, + { "IsRaid", &LuaMap::IsRaid }, + + // Other + { "SaveInstanceData", &LuaMap::SaveInstanceData }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/ObjectMethods.h b/src/modules/Eluna/TrinityCore/ObjectMethods.h new file mode 100644 index 0000000000..91ef891e3e --- /dev/null +++ b/src/modules/Eluna/TrinityCore/ObjectMethods.h @@ -0,0 +1,498 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef OBJECTMETHODS_H +#define OBJECTMETHODS_H + +/*** + * A basic game object (either an [Item] or a [WorldObject]). + * + * Objects in MaNGOS/Trinity are stored an a giant block of "values". + * Subclasses of Object, like [WorldObject], extend the block with more data specific to that subclass. + * Further subclasses, like [Player], extend it even further. + * + * A detailed map of all the fields in this data block can be found in the UpdateFields.h file of your emulator + * (it varies depending on the expansion supported). + * + * The GetValue methods in this class (e.g. [Object:GetInt32Value]) provide low-level access to the data block. + * Other methods, like [Object:HasFlag] and [Object:GetScale], merely wrap the GetValue methods and provide a simpler interface. + * + * Inherits all methods from: none + */ +namespace LuaObject +{ + /** + * Returns `true` if the specified flag is set, otherwise `false`. + * + * @param uint16 index : the index of the flags data in the [Object] + * @param uint32 flag : the flag to check for in the flags data + * @return bool hasFlag + */ + int HasFlag(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 flag = Eluna::CHECKVAL(L, 3); + + Eluna::Push(L, obj->HasFlag(index, flag)); + return 1; + } + + /** + * Returns `true` if the [Object] has been added to its [Map], otherwise `false`. + * + * @return bool inWorld + */ + int IsInWorld(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->IsInWorld()); + return 1; + } + + /** + * Returns the data at the specified index, casted to a signed 32-bit integer. + * + * @param uint16 index + * @return int32 value + */ + int GetInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, obj->GetInt32Value(index)); + return 1; + } + + /** + * Returns the data at the specified index, casted to a unsigned 32-bit integer. + * + * @param uint16 index + * @return uint32 value + */ + int GetUInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, obj->GetUInt32Value(index)); + return 1; + } + + /** + * Returns the data at the specified index, casted to a single-precision floating point value. + * + * @param uint16 index + * @return float value + */ + int GetFloatValue(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, obj->GetFloatValue(index)); + return 1; + } + + /** + * Returns the data at the specified index and offset, casted to an unsigned 8-bit integer. + * + * E.g. if you want the second byte at index 10, you would pass in 1 as the offset. + * + * @param uint16 index + * @param uint8 offset : should be 0, 1, 2, or 3 + * @return uint8 value + */ + int GetByteValue(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetByteValue(index, offset)); + return 1; + } + + /** + * Returns the data at the specified index and offset, casted to a signed 16-bit integer. + * + * E.g. if you want the second half-word at index 10, you would pass in 1 as the offset. + * + * @param uint16 index + * @param uint8 offset : should be 0 or 1 + * @return uint16 value + */ + int GetUInt16Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetUInt16Value(index, offset)); + return 1; + } + + /** + * Returns the scale/size of the [Object]. + * + * This affects the size of a [WorldObject] in-game, but [Item]s don't have a "scale". + * + * @return float scale + */ + int GetScale(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GetObjectScale()); + return 1; + } + + /** + * Returns the entry of the [Object]. + * + * [Player]s do not have an "entry". + * + * @return uint32 entry + */ + int GetEntry(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GetEntry()); + return 1; + } + + /** + * Returns the GUID of the [Object]. + * + * GUID is an unique identifier for the object. + * + * However on MaNGOS and cMangos creatures and gameobjects inside different maps can share + * the same GUID but not on the same map. + * + * On TrinityCore this value is unique across all maps + * + * @return ObjectGuid guid + */ + int GetGUID(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GET_GUID()); + return 1; + } + + /** + * Returns the low-part of the [Object]'s GUID. + * + * On TrinityCore all low GUIDs are different for all objects of the same type. + * For example creatures in instances are assigned new GUIDs when the Map is created. + * + * On MaNGOS and cMaNGOS low GUIDs are unique only on the same map. + * For example creatures in instances use the same low GUID assigned for that spawn in the database. + * This is why to identify a creature you have to know the instanceId and low GUID. See [Map:GetIntstanceId] + * + * @return uint32 guidLow + */ + int GetGUIDLow(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GetGUID().GetCounter()); + return 1; + } + + /** + * Returns the TypeId of the [Object]. + * + * enum TypeID + * { + * TYPEID_OBJECT = 0, + * TYPEID_ITEM = 1, + * TYPEID_CONTAINER = 2, + * TYPEID_UNIT = 3, + * TYPEID_PLAYER = 4, + * TYPEID_GAMEOBJECT = 5, + * TYPEID_DYNAMICOBJECT = 6, + * TYPEID_CORPSE = 7 + * }; + * + * @return uint8 typeID + */ + int GetTypeId(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GetTypeId()); + return 1; + } + + /** + * Returns the data at the specified index, casted to an unsigned 64-bit integer. + * + * @param uint16 index + * @return uint64 value + */ + int GetUInt64Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, obj->GetUInt64Value(index)); + return 1; + } + + /** + * Sets the specified flag in the data value at the specified index. + * + * If the flag was already set, it remains set. + * + * To remove a flag, use [Object:RemoveFlag]. + * + * @param uint16 index + * @param uint32 value + */ + int SetFlag(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 flag = Eluna::CHECKVAL(L, 3); + + obj->SetFlag(index, flag); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to a signed 32-bit integer. + * + * @param uint16 index + * @param int32 value + */ + int SetInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + int32 value = Eluna::CHECKVAL(L, 3); + obj->SetInt32Value(index, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to an unsigned 32-bit integer. + * + * @param uint16 index + * @param uint32 value + */ + int SetUInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 value = Eluna::CHECKVAL(L, 3); + obj->SetUInt32Value(index, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to an unsigned 32-bit integer. + * + * @param uint16 index + * @param uint32 value + */ + int UpdateUInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 value = Eluna::CHECKVAL(L, 3); + obj->UpdateUInt32Value(index, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to a single-precision floating point value. + * + * @param uint16 index + * @param float value + */ + int SetFloatValue(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + float value = Eluna::CHECKVAL(L, 3); + + obj->SetFloatValue(index, value); + return 0; + } + + /** + * Sets the data at the specified index and offset to the given value, converted to an unsigned 8-bit integer. + * + * @param uint16 index + * @param uint8 offset : should be 0, 1, 2, or 3 + * @param uint8 value + */ + int SetByteValue(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + uint8 value = Eluna::CHECKVAL(L, 4); + obj->SetByteValue(index, offset, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to an unsigned 16-bit integer. + * + * @param uint16 index + * @param uint8 offset : should be 0 or 1 + * @param uint16 value + */ + int SetUInt16Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + uint16 value = Eluna::CHECKVAL(L, 4); + obj->SetUInt16Value(index, offset, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to a signed 16-bit integer. + * + * @param uint16 index + * @param uint8 offset : should be 0 or 1 + * @param int16 value + */ + int SetInt16Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + int16 value = Eluna::CHECKVAL(L, 4); + obj->SetInt16Value(index, offset, value); + return 0; + } + + /** + * Sets the [Object]'s scale/size to the given value. + * + * @param float scale + */ + int SetScale(lua_State* L, Object* obj) + { + float size = Eluna::CHECKVAL(L, 2); + + obj->SetObjectScale(size); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to an unsigned 64-bit integer. + * + * @param uint16 index + * @param uint64 value + */ + int SetUInt64Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint64 value = Eluna::CHECKVAL(L, 3); + obj->SetUInt64Value(index, value); + return 0; + } + + /** + * Removes a flag from the value at the specified index. + * + * @param uint16 index + * @param uint32 flag + */ + int RemoveFlag(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 flag = Eluna::CHECKVAL(L, 3); + + obj->RemoveFlag(index, flag); + return 0; + } + + /** + * Attempts to convert the [Object] to a [Corpse]. + * + * If the [Object] is not a [Corpse], returns `nil`. + * + * @return [Corpse] corpse : the [Object] as a [Corpse], or `nil` + */ + int ToCorpse(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToCorpse()); + return 1; + } + + /** + * Attempts to convert the [Object] to a [GameObject]. + * + * If the [Object] is not a [GameObject], returns `nil`. + * + * @return [GameObject] gameObject : the [Object] as a [GameObject], or `nil` + */ + int ToGameObject(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToGameObject()); + return 1; + } + + /** + * Attempts to convert the [Object] to a [Unit]. + * + * If the [Object] is not a [Unit], returns `nil`. + * + * @return [Unit] unit : the [Object] as a [Unit], or `nil` + */ + int ToUnit(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToUnit()); + return 1; + } + + /** + * Attempts to convert the [Object] to a [Creature]. + * + * If the [Object] is not a [Creature], returns `nil`. + * + * @return [Creature] creature : the [Object] as a [Creature], or `nil` + */ + int ToCreature(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToCreature()); + return 1; + } + + /** + * Attempts to convert the [Object] to a [Player]. + * + * If the [Object] is not a [Player], returns `nil`. + * + * @return [Player] player : the [Object] as a [Player], or `nil` + */ + int ToPlayer(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToPlayer()); + return 1; + } + + ElunaRegister ObjectMethods[] = + { + // Getters + { "GetEntry", &LuaObject::GetEntry }, + { "GetGUID", &LuaObject::GetGUID }, + { "GetGUIDLow", &LuaObject::GetGUIDLow }, + { "GetInt32Value", &LuaObject::GetInt32Value }, + { "GetUInt32Value", &LuaObject::GetUInt32Value }, + { "GetFloatValue", &LuaObject::GetFloatValue }, + { "GetByteValue", &LuaObject::GetByteValue }, + { "GetUInt16Value", &LuaObject::GetUInt16Value }, + { "GetUInt64Value", &LuaObject::GetUInt64Value }, + { "GetScale", &LuaObject::GetScale }, + { "GetTypeId", &LuaObject::GetTypeId }, + + // Setters + { "SetInt32Value", &LuaObject::SetInt32Value }, + { "SetUInt32Value", &LuaObject::SetUInt32Value }, + { "UpdateUInt32Value", &LuaObject::UpdateUInt32Value }, + { "SetFloatValue", &LuaObject::SetFloatValue }, + { "SetByteValue", &LuaObject::SetByteValue }, + { "SetUInt16Value", &LuaObject::SetUInt16Value }, + { "SetInt16Value", &LuaObject::SetInt16Value }, + { "SetUInt64Value", &LuaObject::SetUInt64Value }, + { "SetScale", &LuaObject::SetScale }, + { "SetFlag", &LuaObject::SetFlag }, + + // Boolean + { "IsInWorld", &LuaObject::IsInWorld }, + { "HasFlag", &LuaObject::HasFlag }, + + // Other + { "ToGameObject", &LuaObject::ToGameObject }, + { "ToUnit", &LuaObject::ToUnit }, + { "ToCreature", &LuaObject::ToCreature }, + { "ToPlayer", &LuaObject::ToPlayer }, + { "ToCorpse", &LuaObject::ToCorpse }, + { "RemoveFlag", &LuaObject::RemoveFlag }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/PlayerMethods.h b/src/modules/Eluna/TrinityCore/PlayerMethods.h new file mode 100644 index 0000000000..b1d1f8e866 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/PlayerMethods.h @@ -0,0 +1,4133 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef PLAYERMETHODS_H +#define PLAYERMETHODS_H + +/*** + * Inherits all methods from: [Object], [WorldObject], [Unit] + */ +namespace LuaPlayer +{ + /** + * Returns 'true' if the [Player] can Titan Grip, 'false' otherwise. + * + * @return bool canTitanGrip + */ + int CanTitanGrip(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanTitanGrip()); + return 1; + } + + /** + * Returns 'true' if the [Player] has a talent by ID in specified spec, 'false' otherwise. + * + * @param uint32 spellId : talent spellId to check + * @param uint8 spec : specified spec. 0 for primary, 1 for secondary. + * @return bool hasTalent + */ + int HasTalent(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + uint8 maxSpecs = MAX_TALENT_SPECS; + uint8 spec = Eluna::CHECKVAL(L, 3); + + if (spec >= maxSpecs) + return 1; + + Eluna::Push(L, player->HasTalent(spellId, spec)); + return 1; + } + + /** + * Returns 'true' if the [Player] has completed the specified achievement, 'false' otherwise. + * + * @param uint32 achievementId + * @return bool hasAchieved + */ + int HasAchieved(lua_State* L, Player* player) + { + uint32 achievementId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasAchieved(achievementId)); + return 1; + } + + /** + * Returns 'true' if the [Player] has an active [Quest] by specific ID, 'false' otherwise. + * + * @param uint32 questId + * @return bool hasQuest + */ + int HasQuest(lua_State* L, Player* player) + { + uint32 quest = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->IsActiveQuest(quest)); + return 1; + } + + /** + * Returns 'true' if the [Player] has a skill by specific ID, 'false' otherwise. + * + * @param uint32 skill + * @return bool hasSkill + */ + int HasSkill(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasSkill(skill)); + return 1; + } + + /** + * Returns 'true' if the [Player] has a [Spell] by specific ID, 'false' otherwise. + * + * @param uint32 spellId + * @return bool hasSpell + */ + int HasSpell(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasSpell(id)); + return 1; + } + + /** + * Returns true if [Player] has specified login flag + * + * @param uint32 flag + * @return bool hasLoginFlag + */ + int HasAtLoginFlag(lua_State* L, Player* player) + { + uint32 flag = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasAtLoginFlag((AtLoginFlags)flag)); + return 1; + } + + /** + * Returns true if [Player] has [Quest] for [GameObject] + * + * @param int32 entry : entry of a [GameObject] + * @return bool hasQuest + */ + int HasQuestForGO(lua_State* L, Player* player) + { + int32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasQuestForGO(entry)); + return 1; + } + + /** + * Returns 'true' if the [Player] has a title by specific ID, 'false' otherwise. + * + * @param uint32 titleId + * @return bool hasTitle + */ + int HasTitle(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); + if (titleInfo) + Eluna::Push(L, player->HasTitle(titleInfo)); + return 1; + } + + /** + * Returns 'true' if the [Player] has the given amount of item entry specified, 'false' otherwise. + * + * @param uint32 itemId : entry of the item + * @param uint32 count = 1 : amount of items the player needs should have + * @param bool check_bank = false : determines if the item can be in player bank + * @return bool hasItem + */ + int HasItem(lua_State* L, Player* player) + { + uint32 itemId = Eluna::CHECKVAL(L, 2); + uint32 count = Eluna::CHECKVAL(L, 3, 1); + bool check_bank = Eluna::CHECKVAL(L, 4, false); + Eluna::Push(L, player->HasItemCount(itemId, count, check_bank)); + return 1; + } + + /** + * Returns 'true' if the [Player] has a quest for the item entry specified, 'false' otherwise. + * + * @param uint32 entry : entry of the item + * @return bool hasQuest + */ + int HasQuestForItem(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasQuestForItem(entry)); + return 1; + } + + /** + * Returns 'true' if the [Player] can use the item or item entry specified, 'false' otherwise. + * + * @proto canUse = (item) + * @proto canUse = (entry) + * @param [Item] item : an instance of an item + * @param uint32 entry : entry of the item + * @return bool canUse + */ + int CanUseItem(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2, false); + if (item) + Eluna::Push(L, player->CanUseItem(item) == EQUIP_ERR_OK); + else + { + uint32 entry = Eluna::CHECKVAL(L, 2); + const ItemTemplate* temp = eObjectMgr->GetItemTemplate(entry); + if (temp) + Eluna::Push(L, player->CanUseItem(temp) == EQUIP_ERR_OK); + else + Eluna::Push(L, false); + } + return 1; + } + + /** + * Returns 'true' if the [Spell] specified by ID is currently on cooldown for the [Player], 'false' otherwise. + * + * @param uint32 spellId + * @return bool hasSpellCooldown + */ + int HasSpellCooldown(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetSpellHistory()->HasCooldown(spellId)); + return 1; + } + + /** + * Returns 'true' if the [Player] can share [Quest] specified by ID, 'false' otherwise. + * + * @param uint32 entryId + * @return bool hasSpellCooldown + */ + int CanShareQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->CanShareQuest(entry)); + return 1; + } + + /** + * Returns 'true' if the [Player] can currently communicate through chat, 'false' otherwise. + * + * @return bool canSpeak + */ + int CanSpeak(lua_State* L, Player* player) + { +#ifndef CATA + Eluna::Push(L, player->GetSession()->CanSpeak()); +#else + Eluna::Push(L, player->CanSpeak()); +#endif + return 1; + } + + /** + * Returns 'true' if the [Player] has permission to uninvite others from the current group, 'false' otherwise. + * + * @return bool canUninviteFromGroup + */ + int CanUninviteFromGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanUninviteFromGroup() == ERR_PARTY_RESULT_OK); + return 1; + } + + /** + * Returns 'true' if the [Player] can fly, 'false' otherwise. + * + * @return bool canFly + */ + int CanFly(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanFly()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently in water, 'false' otherwise. + * + * @return bool isInWater + */ + int IsInWater(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsInWater()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently moving, 'false' otherwise. + * + * @return bool isMoving + */ + int IsMoving(lua_State* L, Player* player) // enable for unit when mangos support it + { + Eluna::Push(L, player->isMoving()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently flying, 'false' otherwise. + * + * @return bool isFlying + */ + int IsFlying(lua_State* L, Player* player) // enable for unit when mangos support it + { + Eluna::Push(L, player->IsFlying()); + return 1; + } + + /** + * Returns 'true' if the [Player] is in a [Group], 'false' otherwise. + * + * @return bool isInGroup + */ + int IsInGroup(lua_State* L, Player* player) + { + Eluna::Push(L, (player->GetGroup() != NULL)); + return 1; + } + + /** + * Returns 'true' if the [Player] is in a [Guild], 'false' otherwise. + * + * @return bool isInGuild + */ + int IsInGuild(lua_State* L, Player* player) + { + Eluna::Push(L, (player->GetGuildId() != 0)); + return 1; + } + + /** + * Returns 'true' if the [Player] is a Game Master, 'false' otherwise. + * + * Note: This is only true when GM tag is activated! For alternative see [Player:GetGMRank] + * + * @return bool isGM + */ + int IsGM(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsGameMaster()); + return 1; + } + + /** + * Returns 'true' if the [Player] is in an arena team specified by type, 'false' otherwise. + * + * @param uint32 type + * @return bool isInArenaTeam + */ + int IsInArenaTeam(lua_State* L, Player* player) + { + uint32 type = Eluna::CHECKVAL(L, 2); + if (type < MAX_ARENA_SLOT && player->GetArenaTeamId(type)) + Eluna::Push(L, true); + else + Eluna::Push(L, false); + return 1; + } + + /** + * Returns 'true' if the [Player] is immune to everything. + * + * @return bool isImmune + */ + int IsImmuneToDamage(lua_State* L, Player* player) + { + Eluna::Push(L, player->isTotalImmune()); + return 1; + } + + /** + * Returns 'true' if the [Player] satisfies all requirements to complete the quest entry. + * + * @param uint32 entry + * @return bool canComplete + */ + int CanCompleteQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->CanCompleteQuest(entry)); + return 1; + } + +#ifndef CATA + /** + * Returns 'true' if the [Player] satisfies all requirements to complete the repeatable quest entry. + * + * @param uint32 entry + * @return bool canComplete + */ + int CanCompleteRepeatableQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* qInfo = sObjectMgr->GetQuestTemplate(entry); + if (qInfo) + Eluna::Push(L, player->CanCompleteRepeatableQuest(qInfo)); + else + Eluna::Push(L, false); + + return 1; + } + + /** + * Returns 'true' if the [Player] satisfies all requirements to turn in the quest. + * + * @param uint32 entry + * @return bool canReward + */ + int CanRewardQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* qInfo = sObjectMgr->GetQuestTemplate(entry); + if (qInfo) + Eluna::Push(L, player->CanRewardQuest(qInfo, true)); + else + Eluna::Push(L, false); + + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] is a part of the Horde faction, 'false' otherwise. + * + * @return bool isHorde + */ + int IsHorde(lua_State* L, Player* player) + { + Eluna::Push(L, (player->GetTeam() == HORDE)); + return 1; + } + + /** + * Returns 'true' if the [Player] is a part of the Alliance faction, 'false' otherwise. + * + * @return bool isAlliance + */ + int IsAlliance(lua_State* L, Player* player) + { + Eluna::Push(L, (player->GetTeam() == ALLIANCE)); + return 1; + } + + /** + * Returns 'true' if the [Player] is 'Do Not Disturb' flagged, 'false' otherwise. + * + * @return bool isDND + */ + int IsDND(lua_State* L, Player* player) + { + Eluna::Push(L, player->isDND()); + return 1; + } + + /** + * Returns 'true' if the [Player] is 'Away From Keyboard' flagged, 'false' otherwise. + * + * @return bool isAFK + */ + int IsAFK(lua_State* L, Player* player) + { + Eluna::Push(L, player->isAFK()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently falling, 'false' otherwise. + * + * @return bool isFalling + */ + int IsFalling(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsFalling()); + return 1; + } + + int IsGroupVisibleFor(lua_State* L, Player* player) + { + Player* target = Eluna::CHECKOBJ(L, 2); + Eluna::Push(L, player->IsGroupVisibleFor(target)); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently in the same raid as another [Player] by object, 'false' otherwise. + * + * @param [Player] player + * @return bool isInSameRaidWith + */ + int IsInSameRaidWith(lua_State* L, Player* player) + { + Player* target = Eluna::CHECKOBJ(L, 2); + Eluna::Push(L, player->IsInSameRaidWith(target)); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently in the same [Group] as another [Player] by object, 'false' otherwise. + * + * @param [Player] player + * @return bool isInSameGroupWith + */ + int IsInSameGroupWith(lua_State* L, Player* player) + { + Player* target = Eluna::CHECKOBJ(L, 2); + Eluna::Push(L, player->IsInSameGroupWith(target)); + return 1; + } + + /** + * Returns 'true' if the [Player] is eligible for Honor or XP gain by [Unit] specified, 'false' otherwise. + * + * @param [Unit] unit + * @return bool isHonorOrXPTarget + */ + int IsHonorOrXPTarget(lua_State* L, Player* player) + { + Unit* victim = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, player->isHonorOrXPTarget(victim)); + return 1; + } + + /** + * Returns 'true' if the [Player] can see anoter [Player] specified by object, 'false' otherwise. + * + * @param [Player] player + * @return bool isVisibleForPlayer + */ + int IsVisibleForPlayer(lua_State* L, Player* player) + { + Player* target = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, player->IsVisibleGloballyFor(target)); + return 1; + } + + int IsGMVisible(lua_State* L, Player* player) + { + Eluna::Push(L, player->isGMVisible()); + return 1; + } + + /** + * Returns 'true' if the [Player] has taxi cheat activated, 'false' otherwise. + * + * @return bool isTaxiCheater + */ + int IsTaxiCheater(lua_State* L, Player* player) + { + Eluna::Push(L, player->isTaxiCheater()); + return 1; + } + + int IsGMChat(lua_State* L, Player* player) + { + Eluna::Push(L, player->isGMChat()); + return 1; + } + + /** + * Returns 'true' if the [Player] is accepting whispers, 'false' otherwise. + * + * @return bool isAcceptingWhispers + */ + int IsAcceptingWhispers(lua_State* L, Player* player) + { + Eluna::Push(L, player->isAcceptWhispers()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently rested, 'false' otherwise. + * + * @return bool isRested + */ + int IsRested(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetRestBonus() > 0.0f); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently in a [BattleGround] queue, 'false' otherwise. + * + * @return bool inBattlegroundQueue + */ + int InBattlegroundQueue(lua_State* L, Player* player) + { + Eluna::Push(L, player->InBattlegroundQueue()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently in an arena, 'false' otherwise. + * + * @return bool inArena + */ + int InArena(lua_State* L, Player* player) + { + Eluna::Push(L, player->InArena()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently in a [BattleGround], 'false' otherwise. + * + * @return bool inBattleGround + */ + int InBattleground(lua_State* L, Player* player) + { + Eluna::Push(L, player->InBattleground()); + return 1; + } + + /** + * Returns 'true' if the [Player] can block incomming attacks, 'false' otherwise. + * + * @return bool canBlock + */ + int CanBlock(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanBlock()); + return 1; + } + + /** + * Returns 'true' if the [Player] can parry incomming attacks, 'false' otherwise. + * + * @return bool canParry + */ + int CanParry(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanParry()); + return 1; + } + + int HasReceivedQuestReward(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->IsQuestRewarded(entry)); + return 1; + } + + int IsOutdoorPvPActive(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsOutdoorPvPActive()); + return 1; + } + + int IsImmuneToEnvironmentalDamage(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsImmuneToEnvironmentalDamage()); + return 1; + } + + int InRandomLfgDungeon(lua_State* L, Player* player) + { + Eluna::Push(L, player->inRandomLfgDungeon()); + return 1; + } + + int IsUsingLfg(lua_State* L, Player* player) + { + Eluna::Push(L, player->isUsingLfg()); + return 1; + } + + int IsNeverVisible(lua_State* L, Player* player) + { + // Possibly add a bool var here +#ifdef CATA + Eluna::Push(L, player->IsNeverVisible()); +#else + Eluna::Push(L, player->IsNeverVisible(true)); +#endif + return 1; + } + + /*int CanFlyInZone(lua_State* L, Player* player) + { + uint32 mapid = Eluna::CHECKVAL(L, 2); + uint32 zone = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->IsKnowHowFlyIn(mapid, zone)); + return 1; + }*/ + + int HasPendingBind(lua_State* L, Player* player) + { + Eluna::Push(L, player->HasPendingBind()); + return 1; + } + + int IsARecruiter(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->IsARecruiter() || (player->GetSession()->GetRecruiterId() != 0)); + return 1; + } + + /** + * Returns the amount of available specs the [Player] currently has + * + * @return uint8 specCount + */ + int GetSpecsCount(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSpecsCount()); + return 1; + } + + /** + * Returns the [Player]s active spec ID + * + * @return uint32 specId + */ + int GetActiveSpec(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetActiveSpec()); + return 1; + } + +#ifndef CATA + /** + * Returns the normal phase of the player instead of the actual phase possibly containing GM phase + * + * @return uint32 phasemask + */ + int GetPhaseMaskForSpawn(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetPhaseMaskForSpawn()); + return 1; + } + + /** + * Returns the [Player]s current amount of Arena Points + * + * @return uint32 arenaPoints + */ + int GetArenaPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetArenaPoints()); + return 1; + } + + /** + * Returns the [Player]s current amount of Honor Points + * + * @return uint32 honorPoints + */ + int GetHonorPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetHonorPoints()); + return 1; + } + + /** + * Returns the [Player]s current shield block value + * + * @return uint32 blockValue + */ + int GetShieldBlockValue(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetShieldBlockValue()); + return 1; + } +#endif + + /** + * Returns the [Player]s cooldown delay by specified [Spell] ID + * + * @param uint32 spellId + * @return uint32 spellCooldownDelay + */ + int GetSpellCooldownDelay(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId)) + Eluna::Push(L, player->GetSpellHistory()->GetRemainingCooldown(spellInfo)); + else + Eluna::Push(L, 0); + + return 1; + } + + /** + * Returns the [Player]s current latency in MS + * + * @return uint32 latency + */ + int GetLatency(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetLatency()); + return 1; + } + + /** + * Returns the faction ID the [Player] is currently flagged as champion for + * + * @return uint32 championingFaction + */ + int GetChampioningFaction(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetChampioningFaction()); + return 1; + } + + /** + * Returns [Player]s original sub group + * + * @return uint8 subGroup + */ + int GetOriginalSubGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetOriginalSubGroup()); + return 1; + } + + /** + * Returns [Player]s original [Group] object + * + * @return [Group] group + */ + int GetOriginalGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetOriginalGroup()); + return 1; + } + + /** + * Returns a random Raid Member [Player] object within radius specified of [Player] + * + * @param float radius + * @return [Player] player + */ + int GetNextRandomRaidMember(lua_State* L, Player* player) + { + float radius = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetNextRandomRaidMember(radius)); + return 1; + } + + /** + * Returns [Player]s current sub group + * + * @return uint8 subGroup + */ + int GetSubGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSubGroup()); + return 1; + } + + /** + * Returns [Group] invitation + * + * @return [Group] group + */ + int GetGroupInvite(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetGroupInvite()); + return 1; + } + + /** + * Returns rested experience bonus + * + * @param uint32 xp + * @return uint32 xpBonus + */ + int GetXPRestBonus(lua_State* L, Player* player) + { + uint32 xp = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetXPRestBonus(xp)); + return 1; + } + + /** + * Returns the [Player]s current [BattleGround] type ID + * + * @return [BattleGroundTypeId] typeId + */ + int GetBattlegroundTypeId(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetBattlegroundTypeId()); + return 1; + } + + /** + * Returns the [Player]s current [BattleGround] ID + * + * @return uint32 battleGroundId + */ + int GetBattlegroundId(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetBattlegroundId()); + return 1; + } + + /** + * Returns the [Player]s reputation rank of faction specified + * + * @param uint32 faction + * @return [ReputationRank] rank + */ + int GetReputationRank(lua_State* L, Player* player) + { + uint32 faction = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetReputationRank(faction)); + return 1; + } + + /** + * Returns the [Player]s current level of intoxication + * + * @return uint16 drunkValue + */ + int GetDrunkValue(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetDrunkValue()); + return 1; + } + + /** + * Returns skill temporary bonus value + * + * @param uint32 skill + * @param int16 bonusVal + */ + int GetSkillTempBonusValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetSkillTempBonusValue(skill)); + return 1; + } + + /** + * Returns skill permanent bonus value + * + * @param uint32 skill + * @param int16 bonusVal + */ + int GetSkillPermBonusValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetSkillPermBonusValue(skill)); + return 1; + } + + /** + * Returns skill value without bonus' + * + * @param uint32 skill + * @return uint16 pureVal + */ + int GetPureSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetPureSkillValue(skill)); + return 1; + } + + /** + * Returns base skill value + * + * @param uint32 skill + * @return uint16 baseVal + */ + int GetBaseSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetBaseSkillValue(skill)); + return 1; + } + + /** + * Returns skill value + * + * @param uint32 skill + * @return uint16 val + */ + int GetSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetSkillValue(skill)); + return 1; + } + + /** + * Returns max value of specified skill without bonus' + * + * @param uint32 skill + * @return uint16 pureVal + */ + int GetPureMaxSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetPureMaxSkillValue(skill)); + return 1; + } + + /** + * Returns max value of specified skill + * + * @param uint32 skill + * @return uint16 val + */ + int GetMaxSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetMaxSkillValue(skill)); + return 1; + } + + /** + * Returns mana bonus from amount of intellect + * + * @return float bonus + */ + int GetManaBonusFromIntellect(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetManaBonusFromIntellect()); + return 1; + } + + /** + * Returns health bonus from amount of stamina + * + * @return float bonus + */ + int GetHealthBonusFromStamina(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetHealthBonusFromStamina()); + return 1; + } + + /** + * Returns raid or dungeon difficulty + * + * @param bool isRaid = true : argument is TrinityCore only + * @return int32 difficulty + */ + int GetDifficulty(lua_State* L, Player* player) + { + bool isRaid = Eluna::CHECKVAL(L, 2, true); + + Eluna::Push(L, player->GetDifficulty(isRaid)); + return 1; + } + + /** + * Returns the [Player]s current guild rank + * + * @return uint32 guildRank + */ + int GetGuildRank(lua_State* L, Player* player) // TODO: Move to Guild Methods + { +#ifdef CATA + Eluna::Push(L, player->GetGuildRank()); +#else + Eluna::Push(L, player->GetRank()); +#endif + return 1; + } + + /** + * Returns the [Player]s free talent point amount + * + * @return uint32 freeTalentPointAmt + */ + int GetFreeTalentPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetFreeTalentPoints()); + return 1; + } + + /** + * Returns the name of the [Player]s current [Guild] + * + * @return string guildName + */ + int GetGuildName(lua_State* L, Player* player) + { + if (!player->GetGuildId()) + return 1; + Eluna::Push(L, eGuildMgr->GetGuildNameById(player->GetGuildId())); + return 1; + } + + /** + * Returns the amount of reputation the [Player] has with the faction specified + * + * @param uint32 faction + * @return int32 reputationAmt + */ + int GetReputation(lua_State* L, Player* player) + { + uint32 faction = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetReputationMgr().GetReputation(faction)); + return 1; + } + + /** + * Returns [Unit] target combo points are on + * + * @return [Unit] target + */ + int GetComboTarget(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetComboTarget()); + return 1; + } + + /** + * Returns [Player]'s combo points + * + * @return uint8 comboPoints + */ + int GetComboPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetComboPoints()); + return 1; + } + + /** + * Returns the amount of time the [Player] has spent ingame + * + * @return uint32 inGameTime + */ + int GetInGameTime(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetInGameTime()); + return 1; + } + + /** + * Returns the status of the [Player]s [Quest] specified by entry ID + * + * @param uint32 questId + * @return [QuestStatus] questStatus + */ + int GetQuestStatus(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetQuestStatus(entry)); + return 1; + } + + /** + * Returns 'true' if the [Player]s [Quest] specified by entry ID has been rewarded, 'false' otherwise. + * + * @param uint32 questId + * @return bool questRewardStatus + */ + int GetQuestRewardStatus(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetQuestRewardStatus(questId)); + return 1; + } + + /** + * Returns [Quest] required [Creature] or [GameObject] count + * + * @param uint32 quest : entry of a quest + * @param int32 entry : entry of required [Creature] + * @return uint16 count + */ + int GetReqKillOrCastCurrentCount(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + int32 entry = Eluna::CHECKVAL(L, 3); + + Eluna::Push(L, player->GetReqKillOrCastCurrentCount(questId, entry)); + return 1; + } + + /** + * Returns the quest level of the [Player]s [Quest] specified by object + * + * @param uint32 questId + * @return [QuestStatus] questRewardStatus + */ + int GetQuestLevel(lua_State* L, Player* player) + { + Quest* quest = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, player->GetQuestLevel(quest)); + return 1; + } + + /** + * Returns a [Player]s [Item] object by gear slot specified + * + * @param uint8 slot + * @return [Item] item + */ + int GetEquippedItemBySlot(lua_State* L, Player* player) + { + uint8 slot = Eluna::CHECKVAL(L, 2); + if (slot >= EQUIPMENT_SLOT_END) + return 1; + + Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); + Eluna::Push(L, item); + return 1; + } + + /** + * Returns the [Player]s current resting bonus + * + * @return float restBonus + */ + int GetRestBonus(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetRestBonus()); + return 1; + } + + /** + * Returns active GM chat tag + * + * @return uint8 tag + */ + int GetChatTag(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetChatTag()); + return 1; + } + + /** + * Returns an item in given bag on given slot. + * + *
+     * Possible and most commonly used combinations:
+     *
+     * bag = 255
+     * slots 0-18 equipment
+     * slots 19-22 equipped bag slots
+     * slots 23-38 backpack
+     * slots 39-66 bank main slots
+     * slots 67-74 bank bag slots
+     * slots 86-117 keyring
+     *
+     * bag = 19-22
+     * slots 0-35 for equipped bags
+     *
+     * bag = 67-74
+     * slots 0-35 for bank bags
+     * 
+ * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return [Item] item : [Item] or nil + */ + int GetItemByPos(lua_State* L, Player* player) + { + uint8 bag = Eluna::CHECKVAL(L, 2); + uint8 slot = Eluna::CHECKVAL(L, 3); + + Eluna::Push(L, player->GetItemByPos(bag, slot)); + return 1; + } + + /** + * Returns an [Item] from the player by guid. + * + * The item can be equipped, in bags or in bank. + * + * @param ObjectGuid guid : an item guid + * @return [Item] item + */ + int GetItemByGUID(lua_State* L, Player* player) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetItemByGuid(guid)); + return 1; + } + + /** + * Returns a mailed [Item] by guid. + * + * @param ObjectGuid guid : an item guid + * @return [Item] item + */ + int GetMailItem(lua_State* L, Player* player) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetMItem(guid.GetCounter())); + return 1; + } + + /** + * Returns an [Item] from the player by entry. + * + * The item can be equipped, in bags or in bank. + * + * @param uint32 entryId + * @return [Item] item + */ + int GetItemByEntry(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetItemByEntry(entry)); + return 1; + } + + /** + * Returns the database textID of the [WorldObject]'s gossip header text for the [Player] + * + * @param [WorldObject] object + * @return uint32 textId : key to npc_text database table + */ + int GetGossipTextId(lua_State* L, Player* player) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + Eluna::Push(L, player->GetGossipTextId(obj)); + return 1; + } + + /** + * Returns the [Player]s currently selected [Unit] object + * + * @return [Unit] unit + */ + int GetSelection(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSelectedUnit()); + return 1; + } + + /** + * Returns the [Player]s GM Rank + * + * @return [AccountTypes] gmRank + */ + int GetGMRank(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetSecurity()); + return 1; + } + + /** + * Returns the [Player]s amount of money in copper + * + * @return uint32 coinage + */ + int GetCoinage(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetMoney()); + return 1; + } + + /** + * Returns the [Player]s current [Guild] ID + * + * @return uint32 guildId + */ + int GetGuildId(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetGuildId()); + return 1; + } + + /** + * Returns the [Player]s [TeamId] + * + * @return [TeamId] teamId + */ + int GetTeam(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetTeamId()); + return 1; + } + + /** + * Returns amount of the specified [Item] the [Player] has. + * + * @param uint32 entry : entry of the item + * @param bool checkinBank = false : also counts the items in player's bank if true + * @return uint32 itemamount + */ + int GetItemCount(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + bool checkinBank = Eluna::CHECKVAL(L, 3, false); + Eluna::Push(L, player->GetItemCount(entry, checkinBank)); + return 1; + } + + /** + * Returns the [Player]s lifetime Honorable Kills + * + * @return uint32 lifeTimeKils + */ + int GetLifetimeKills(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS)); + return 1; + } + + /** + * Returns the [Player]s IP address + * + * @return string ip + */ + int GetPlayerIP(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetRemoteAddress()); + return 1; + } + + /** + * Returns the [Player]s time played at current level + * + * @return uint32 currLevelPlayTime + */ + int GetLevelPlayedTime(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetLevelPlayedTime()); + return 1; + } + + /** + * Returns the [Player]s total time played + * + * @return uint32 totalPlayTime + */ + int GetTotalPlayedTime(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetTotalPlayedTime()); + return 1; + } + + /** + * Returns the [Player]s [Guild] object + * + * @return [Guild] guild + */ + int GetGuild(lua_State* L, Player* player) + { + Eluna::Push(L, eGuildMgr->GetGuildById(player->GetGuildId())); + return 1; + } + + /** + * Returns the [Player]s [Group] object + * + * @return [Group] group + */ + int GetGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetGroup()); + return 1; + } + + /** + * Returns the [Player]s account ID + * + * @return uint32 accountId + */ + int GetAccountId(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetAccountId()); + return 1; + } + + /** + * Returns the [Player]s account name + * + * @return string accountName + */ + int GetAccountName(lua_State* L, Player* player) + { + std::string accName; + if (eAccountMgr->GetName(player->GetSession()->GetAccountId(), accName)) + Eluna::Push(L, accName); + + return 1; + } + + /** + * Returns the [Player]s [Corpse] object + * + * @return [Corpse] corpse + */ + int GetCorpse(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetCorpse()); + return 1; + } + + /** + * Returns the [Player]s database locale index + * + * @return int localeIndex + */ + int GetDbLocaleIndex(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetSessionDbLocaleIndex()); + return 1; + } + + /** + * Returns the [Player]s game client locale + * + * @return [LocaleConstant] locale + */ + int GetDbcLocale(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetSessionDbcLocale()); + return 1; + } + + int GetRecruiterId(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetRecruiterId()); + return 1; + } + + int GetSelectedPlayer(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSelectedPlayer()); + return 1; + } + + int GetSelectedUnit(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSelectedUnit()); + return 1; + } + + int GetNearbyGameObject(lua_State* L, Player* player) + { + Eluna::Push(L, ChatHandler(player->GetSession()).GetNearbyGameObject()); + return 1; + } + +#ifndef CATA + /** + * Returns the amount of mails in the [Player]s mailbox + * + * @return uint32 count + */ + int GetMailCount(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetMailSize()); + return 1; + } + + /** + * Returns the [Player]s current experience points + * + * @return uint32 xp + */ + int GetXP(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetXP()); + return 1; + } + + /** + * Returns the [Player]s required experience points for next level + * + * @return uint32 xp + */ + int GetXPForNextLevel(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetXPForNextLevel()); + return 1; + } +#endif + + /** + * Locks the player controls and disallows all movement and casting. + * + * @param bool apply = true : lock if true and unlock if false + */ + int SetPlayerLock(lua_State* L, Player* player) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + if (apply) + { + player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED | UNIT_FLAG_SILENCED); + player->SetClientControl(player, 0); + } + else + { + player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED | UNIT_FLAG_SILENCED); + player->SetClientControl(player, 1); + } + return 0; + } + + /** + * Sets the [Player]s login flag to the flag specified + * + * @param uint32 flag + */ + int SetAtLoginFlag(lua_State* L, Player* player) + { + uint32 flag = Eluna::CHECKVAL(L, 2); + + player->SetAtLoginFlag((AtLoginFlags)flag); + return 0; + } + + /** + * Sets the [Player]s sheathe state to the state specified + * + * @param uint32 sheatheState + */ + int SetSheath(lua_State* L, Player* player) + { + uint32 sheathed = Eluna::CHECKVAL(L, 2); + if (sheathed >= MAX_SHEATH_STATE) + return 0; + + player->SetSheath((SheathState)sheathed); + return 0; + } + + /** + * Sets the [Player]s intoxication level to the level specified + * + * @param uint8 drunkValue + */ + int SetDrunkValue(lua_State* L, Player* player) + { + uint8 newDrunkValue = Eluna::CHECKVAL(L, 2); + + player->SetDrunkValue(newDrunkValue); + return 0; + } + + /** + * Sets the [Player]s faction standing to that of the race specified + * + * @param uint8 raceId + */ + int SetFactionForRace(lua_State* L, Player* player) + { + uint8 race = Eluna::CHECKVAL(L, 2); + + player->SetFactionForRace(race); + return 0; + } + + /** + * Sets (increases) skill of the [Player] + * + * @param uint16 id + * @param uint16 step + * @param uint16 currVal + * @param uint16 maxVal + */ + int SetSkill(lua_State* L, Player* player) + { + uint16 id = Eluna::CHECKVAL(L, 2); + uint16 step = Eluna::CHECKVAL(L, 3); + uint16 currVal = Eluna::CHECKVAL(L, 4); + uint16 maxVal = Eluna::CHECKVAL(L, 5); + + player->SetSkill(id, step, currVal, maxVal); + return 0; + } + + /** + * Sets the [Player]s guild rank to the rank specified + * + * @param uint8 rank + */ + int SetGuildRank(lua_State* L, Player* player) // TODO: Move to Guild Methods + { + uint8 rank = Eluna::CHECKVAL(L, 2); + + if (!player->GetGuildId()) + return 0; + +#ifdef CATA + player->SetGuildRank(rank); +#else + player->SetRank(rank); +#endif + return 0; + } + + /** + * Sets the [Player]s free talent points to the amount specified for the current spec + * + * @param uint32 talentPointAmt + */ + int SetFreeTalentPoints(lua_State* L, Player* player) + { + uint32 points = Eluna::CHECKVAL(L, 2); + + player->SetFreeTalentPoints(points); + player->SendTalentsInfoData(false); + return 0; + } + + /** + * Sets the [Player]s reputation amount for the faction specified + * + * @param uint32 factionId + * @param int32 reputationValue + */ + int SetReputation(lua_State* L, Player* player) + { + uint32 faction = Eluna::CHECKVAL(L, 2); + int32 value = Eluna::CHECKVAL(L, 3); + FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction); + + player->GetReputationMgr().SetReputation(factionEntry, value); + return 0; + } + + /** + * Sets [Quest] state + * + * @param uint32 entry : entry of a quest + * @param uint32 status + */ + int SetQuestStatus(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + uint32 status = Eluna::CHECKVAL(L, 3); + if (status >= MAX_QUEST_STATUS) + return 0; + + player->SetQuestStatus(entry, (QuestStatus)status); + return 0; + } + + /** + * Sets the [Player]s rest bonus to the amount specified + * + * @param float restBonus + */ + int SetRestBonus(lua_State* L, Player* player) + { + float bonus = Eluna::CHECKVAL(L, 2); + + player->SetRestBonus(bonus); + return 0; + } + + /** + * Toggles whether the [Player] accepts whispers or not + * + * @param bool acceptWhispers = true + */ + int SetAcceptWhispers(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetAcceptWhispers(on); + return 0; + } + + /** + * Toggles PvP Death + * + * @param bool on = true + */ + int SetPvPDeath(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetPvPDeath(on); + return 0; + } + + /** + * Toggles whether the [Player] has GM visibility on or off + * + * @param bool gmVisible = true + */ + int SetGMVisible(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetGMVisible(on); + return 0; + } + + /** + * Toggles whether the [Player] has taxi cheat enabled or not + * + * @param bool taxiCheat = true + */ + int SetTaxiCheat(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetTaxiCheater(on); + return 0; + } + + /** + * Toggle Blizz (GM) tag + * + * @param bool on = true + */ + int SetGMChat(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetGMChat(on); + return 0; + } + + /** + * Toggles the [Player]s GM mode on or off + * + * @param bool setGmMode = true + */ + int SetGameMaster(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetGameMaster(on); + return 0; + } + + /** + * Sets the [Player]s gender to gender specified + * + * - GENDER_MALE = 0 + * - GENDER_FEMALE = 1 + * + * @param [Gender] gender + */ + int SetGender(lua_State* L, Player* player) + { + uint32 _gender = Eluna::CHECKVAL(L, 2); + + Gender gender; + switch (_gender) + { + case 0: + gender = GENDER_MALE; + break; + case 1: + gender = GENDER_FEMALE; + break; + default: + return luaL_argerror(L, 2, "valid Gender expected"); + } + + player->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender); + player->SetByteValue(PLAYER_BYTES_3, 0, gender); + player->InitDisplayIds(); + return 0; + } + +#ifndef CATA + /** + * Sets the [Player]s Arena Points to the amount specified + * + * @param uint32 arenaPoints + */ + int SetArenaPoints(lua_State* L, Player* player) + { + uint32 arenaP = Eluna::CHECKVAL(L, 2); + player->SetArenaPoints(arenaP); + return 0; + } + + /** + * Sets the [Player]s Honor Points to the amount specified + * + * @param uint32 honorPoints + */ + int SetHonorPoints(lua_State* L, Player* player) + { + uint32 honorP = Eluna::CHECKVAL(L, 2); + player->SetHonorPoints(honorP); + return 0; + } +#endif + + /** + * Sets the [Player]s amount of Lifetime Honorable Kills to the value specified + * + * @param uint32 honorableKills + */ + int SetLifetimeKills(lua_State* L, Player* player) + { + uint32 val = Eluna::CHECKVAL(L, 2); + player->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, val); + return 0; + } + + /** + * Sets the [Player]s amount of money to copper specified + * + * @param uint32 copperAmt + */ + int SetCoinage(lua_State* L, Player* player) + { + uint32 amt = Eluna::CHECKVAL(L, 2); + player->SetMoney(amt); + return 0; + } + + /** + * Sets the [Player]s home location to the location specified + * + * @param float x : X Coordinate + * @param float y : Y Coordinate + * @param float z : Z Coordinate + * @param uint32 mapId : Map ID + * @param uint32 areaId : Area ID + */ + int SetBindPoint(lua_State* L, Player* player) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + uint32 mapId = Eluna::CHECKVAL(L, 5); + uint32 areaId = Eluna::CHECKVAL(L, 6); + + WorldLocation loc(mapId, x, y, z); + + player->SetHomebind(loc, areaId); + return 0; + } + + + /** + * Adds the specified title to the [Player]s list of known titles + * + * @param uint32 titleId + */ + int SetKnownTitle(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + CharTitlesEntry const* t = sCharTitlesStore.LookupEntry(id); + if (t) + player->SetTitle(t, false); + return 0; + } + + /** + * Adds the specified achievement to the [Player]s + * + * @param uint32 achievementid + */ + int SetAchievement(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + AchievementEntry const* t = sAchievementStore.LookupEntry(id); + if (t) + player->CompletedAchievement(t); + return 0; + } + + /** + * Toggle the [Player]s FFA flag + * + * @param bool applyFFA = true + */ + int SetFFA(lua_State* L, Player* player) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + if(apply) +#ifdef CATA + player->SetByteFlag(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PVP_FLAG, UNIT_BYTE2_FLAG_FFA_PVP); + else + player->RemoveByteFlag(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PVP_FLAG, UNIT_BYTE2_FLAG_FFA_PVP); +#else + player->SetPvpFlag(UNIT_BYTE2_FLAG_FFA_PVP); + else + player->RemovePvpFlag(UNIT_BYTE2_FLAG_FFA_PVP); +#endif + return 0; + } + + +#ifndef CATA + int SetMovement(lua_State* L, Player* player) + { + int32 pType = Eluna::CHECKVAL(L, 2); + + player->SetMovement((PlayerMovementType)pType); + return 0; + } +#endif + + /** + * Resets the [Player]s pets talent points + */ + int ResetPetTalents(lua_State* /*L*/, Player* player) + { + player->ResetPetTalents(); + player->SendTalentsInfoData(true); + return 0; + } + + /** + * Reset the [Player]s completed achievements + */ + int ResetAchievements(lua_State* /*L*/, Player* player) + { + player->ResetAchievements(); + return 0; + } + + /** + * Shows the mailbox window to the player from specified guid. + * + * @param ObjectGuid guid = playerguid : guid of the mailbox window sender + */ + int SendShowMailBox(lua_State* L, Player* player) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2, player->GET_GUID()); + + player->GetSession()->SendShowMailBox(guid); + return 0; + } + +#ifndef CATA + /** + * Adds or detracts from the [Player]s current Arena Points + * + * @param int32 amount + */ + int ModifyArenaPoints(lua_State* L, Player* player) + { + int32 amount = Eluna::CHECKVAL(L, 2); + + player->ModifyArenaPoints(amount); + return 0; + } + + /** + * Adds or detracts from the [Player]s current Honor Points + * + * @param int32 amount + */ + int ModifyHonorPoints(lua_State* L, Player* player) + { + int32 amount = Eluna::CHECKVAL(L, 2); + + player->ModifyHonorPoints(amount); + return 0; + } +#endif + + /** + * Saves the [Player] to the database + */ + int SaveToDB(lua_State* /*L*/, Player* player) + { + player->SaveToDB(); + return 0; + } + + /** + * Sends a summon request to the player from the given summoner + * + * @param [Unit] summoner + */ + int SummonPlayer(lua_State* L, Player* player) + { + Unit* summoner = Eluna::CHECKOBJ(L, 2); + + player->SendSummonRequestFrom(summoner); + return 0; + } + + /** + * Mutes the [Player] for the amount of seconds specified + * + * @param uint32 muteTime + */ + int Mute(lua_State* L, Player* player) + { + uint32 muteseconds = Eluna::CHECKVAL(L, 2); + /*const char* reason = luaL_checkstring(E, 2);*/ // Mangos does not have a reason field in database. + + time_t muteTime = time(NULL) + muteseconds; + player->GetSession()->m_muteTime = muteTime; +#ifdef WOTLK + LoginDatabase.PExecute("UPDATE account SET mutetime = {} WHERE id = {}", muteTime, player->GetSession()->GetAccountId()); +#else + std::ostringstream oss; + oss << "UPDATE account SET mutetime = " << muteTime << " WHERE id = " << player->GetSession()->GetAccountId(); + LoginDatabase.PExecute("%s", oss.str().c_str()); +#endif + return 0; + } + + /** + * Rewards the given quest entry for the [Player] if he has completed it. + * + * @param uint32 entry : quest entry + */ + int RewardQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* quest = eObjectMgr->GetQuestTemplate(entry); + + // If player doesn't have the quest + if (!quest || player->GetQuestStatus(entry) != QUEST_STATUS_COMPLETE) + return 0; + + player->RewardQuest(quest, 0, player); + return 0; + } + + /** + * Sends an auction house window to the [Player] from the [Unit] specified + * + * @param [Unit] sender + */ + int SendAuctionMenu(lua_State* L, Player* player) + { + Unit* unit = Eluna::CHECKOBJ(L, 2); + + AuctionHouseEntry const* ahEntry = AuctionHouseMgr::GetAuctionHouseEntry(unit->GetFaction()); + if (!ahEntry) + return 0; + + WorldPacket data(MSG_AUCTION_HELLO, 12); + data << unit->GET_GUID(); + data << uint32(ahEntry->ID); + data << uint8(1); + + player->GetSession()->SendPacket(&data); + return 0; + } + + /** + * Sends a flightmaster window to the [Player] from the [Creature] specified + * + * @param [Creature] sender + */ + int SendTaxiMenu(lua_State* L, Player* player) + { + Creature* creature = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendTaxiMenu(creature); + return 0; + } + + /** + * Sends a spirit resurrection request to the [Player] + */ + int SendSpiritResurrect(lua_State* /*L*/, Player* player) + { + player->GetSession()->SendSpiritResurrect(); + return 0; + } + + /** + * Sends a tabard vendor window to the [Player] from the [WorldObject] specified + * + * @param [WorldObject] sender + */ + int SendTabardVendorActivate(lua_State* L, Player* player) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendTabardVendorActivate(obj->GET_GUID()); + return 0; + } + + /** + * Sends a bank window to the [Player] from the [WorldObject] specified. + * + * @param [WorldObject] sender + */ + int SendShowBank(lua_State* L, Player* player) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendShowBank(obj->GET_GUID()); + return 0; + } + + /** + * Sends a vendor window to the [Player] from the [WorldObject] specified. + * + * @param [WorldObject] sender + */ + int SendListInventory(lua_State* L, Player* player) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendListInventory(obj->GET_GUID()); + return 0; + } + + /** + * Sends a trainer window to the [Player] from the [Creature] specified + * + * @param [Creature] sender + */ + int SendTrainerList(lua_State* L, Player* player) + { + Creature* obj = Eluna::CHECKOBJ(L, 2); + +#ifdef CATA + player->GetSession()->SendTrainerList(obj, NULL); +#else + player->GetSession()->SendTrainerList(obj); +#endif + return 0; + } + + /** + * Sends a guild invitation from the [Player]s [Guild] to the [Player] object specified + * + * @param [Player] invitee + */ + int SendGuildInvite(lua_State* L, Player* player) + { + Player* plr = Eluna::CHECKOBJ(L, 2); + + if (Guild* guild = player->GetGuild()) + guild->HandleInviteMember(player->GetSession(), plr->GetName()); + + return 0; + } + + /** + * Sends an update for the world state to the [Player] + * + * @param uint32 field + * @param uint32 value + */ + int SendUpdateWorldState(lua_State* L, Player* player) + { + uint32 field = Eluna::CHECKVAL(L, 2); + uint32 value = Eluna::CHECKVAL(L, 3); + + player->SendUpdateWorldState(field, value); + return 0; + } + + /** + * Forces the [Player] to log out + * + * @param bool saveToDb = true + */ + int LogoutPlayer(lua_State* L, Player* player) + { + bool save = Eluna::CHECKVAL(L, 2, true); + + player->GetSession()->LogoutPlayer(save); + return 0; + } + + /** + * Forcefully removes the [Player] from a [BattleGround] raid group + */ + int RemoveFromBattlegroundRaid(lua_State* /*L*/, Player* player) + { + player->RemoveFromBattlegroundOrBattlefieldRaid(); + return 0; + } + + /** + * Unbinds the [Player] from his instances except the one he currently is in. + * + * Difficulty is not used on classic. + * + * @param uint32 map = true + * @param uint32 difficulty = 0 + */ + int UnbindInstance(lua_State* L, Player* player) + { + uint32 map = Eluna::CHECKVAL(L, 2); + uint32 difficulty = Eluna::CHECKVAL(L, 3, 0); + + if (difficulty < MAX_DIFFICULTY) + player->UnbindInstance(map, (Difficulty)difficulty); + + return 0; + } + + /** + * Unbinds the [Player] from his instances except the one he currently is in. + */ + int UnbindAllInstances(lua_State* /*L*/, Player* player) + { + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Player::BoundInstancesMap& binds = player->GetBoundInstances(Difficulty(i)); + for (Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) + { + if (itr->first != player->GetMapId()) + player->UnbindInstance(itr, Difficulty(i)); + else + ++itr; + } + } + return 0; + } + + /** + * Forces the [Player] to leave a [BattleGround] + * + * @param bool teleToEntry = true + */ + int LeaveBattleground(lua_State* L, Player* player) + { + (void)L; // ensure that the variable is referenced in order to pass compiler checks + bool teleToEntryPoint = Eluna::CHECKVAL(L, 2, true); + + player->LeaveBattleground(teleToEntryPoint); + return 0; + } + + /** + * Repairs [Item] at specified position. + * + * @param uint16 position + * @param bool cost = true + * @param float discountMod = 1.0 + */ + int DurabilityRepair(lua_State* L, Player* player) + { + uint16 position = Eluna::CHECKVAL(L, 2); + bool takeCost = Eluna::CHECKVAL(L, 3, true); + float discountMod = Eluna::CHECKVAL(L, 4, 1.0f); + + player->DurabilityRepair(position, takeCost, discountMod); + return 0; + } + + /** + * Repairs all [Item]s. + * + * @param bool takeCost = true + * @param float discountMod = 1.0 + * @param bool guidBank = false + */ + int DurabilityRepairAll(lua_State* L, Player* player) + { + bool takeCost = Eluna::CHECKVAL(L, 2, true); + float discountMod = Eluna::CHECKVAL(L, 3, 1.0f); + bool guildBank = Eluna::CHECKVAL(L, 4, false); + + player->DurabilityRepairAll(takeCost, discountMod, guildBank); + return 0; + } + + /** + * Sets durability loss for an [Item] in the specified slot + * + * @param int32 slot + */ + int DurabilityPointLossForEquipSlot(lua_State* L, Player* player) + { + int32 slot = Eluna::CHECKVAL(L, 2); + + if (slot >= EQUIPMENT_SLOT_START && slot < EQUIPMENT_SLOT_END) + player->DurabilityPointLossForEquipSlot((EquipmentSlots)slot); + return 0; + } + + /** + * Sets durability loss on all [Item]s equipped + * + * If inventory is true, sets durability loss for [Item]s in bags + * + * @param int32 points + * @param bool inventory = true + */ + int DurabilityPointsLossAll(lua_State* L, Player* player) + { + int32 points = Eluna::CHECKVAL(L, 2); + bool inventory = Eluna::CHECKVAL(L, 3, true); + + player->DurabilityPointsLossAll(points, inventory); + return 0; + } + + /** + * Sets durability loss for the specified [Item] + * + * @param [Item] item + * @param int32 points + */ + int DurabilityPointsLoss(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2); + int32 points = Eluna::CHECKVAL(L, 3); + + player->DurabilityPointsLoss(item, points); + return 0; + } + + /** + * Damages specified [Item] + * + * @param [Item] item + * @param double percent + */ + int DurabilityLoss(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2); + double percent = Eluna::CHECKVAL(L, 3); + + player->DurabilityLoss(item, percent); + return 0; + } + + /** + * Damages all [Item]s equipped. If inventory is true, damages [Item]s in bags + * + * @param double percent + * @param bool inventory = true + */ + int DurabilityLossAll(lua_State* L, Player* player) + { + double percent = Eluna::CHECKVAL(L, 2); + bool inventory = Eluna::CHECKVAL(L, 3, true); + + player->DurabilityLossAll(percent, inventory); + return 0; + } + + /** + * Kills the [Player] + */ + int KillPlayer(lua_State* /*L*/, Player* player) + { + player->KillPlayer(); + return 0; + } + + /** + * Forces the [Player] to leave a [Group] + */ + int RemoveFromGroup(lua_State* /*L*/, Player* player) + { + if (!player->GetGroup()) + return 0; + + player->RemoveFromGroup(); + return 0; + } + + /** + * Returns the [Player]s accumulated talent reset cost + * + * @return uint32 resetCost + */ + int ResetTalentsCost(lua_State* L, Player* player) + { +#ifdef CATA + Eluna::Push(L, player->GetNextResetTalentsCost()); +#else + Eluna::Push(L, player->ResetTalentsCost()); +#endif + return 1; + } + + /** + * Resets the [Player]s talents + * + * @param bool noCost = true + */ + int ResetTalents(lua_State* L, Player* player) + { + bool no_cost = Eluna::CHECKVAL(L, 2, true); + + player->ResetTalents(no_cost); + player->SendTalentsInfoData(false); + return 0; + } + + /** + * Removes the [Spell] from the [Player] + * + * @param uint32 entry : entry of a [Spell] + */ + int RemoveSpell(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->RemoveSpell(entry); + return 0; + } + + /** + * Clears the [Player]s combo points + */ + int ClearComboPoints(lua_State* /*L*/, Player* player) + { + player->ClearComboPoints(); + return 0; + } + + /** + * Adds combo points to the [Player] + * + * @param [Unit] target + * @param int8 count + */ + int AddComboPoints(lua_State* L, Player* player) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + int8 count = Eluna::CHECKVAL(L, 3); + + player->AddComboPoints(target, count); + return 0; + } + + /** + * Gives [Quest] monster talked to credit + * + * @param uint32 entry : entry of a [Creature] + * @param [Creature] creature + */ + int TalkedToCreature(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + Creature* creature = Eluna::CHECKOBJ(L, 3); + + player->TalkedToCreature(entry, creature->GET_GUID()); + return 0; + } + + /** + * Gives [Quest] monster killed credit + * + * @param uint32 entry : entry of a [Creature] + */ + int KilledMonsterCredit(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->KilledMonsterCredit(entry, player->GET_GUID()); + return 0; + } + + /** + * Completes a [Quest] if in a [Group] + * + * @param uint32 quest : entry of a quest + * @param [WorldObject] obj + */ + int GroupEventHappens(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + WorldObject* obj = Eluna::CHECKOBJ(L, 3); + + player->GroupEventHappens(questId, obj); + return 0; + } + + /** + * Completes the [Quest] if a [Quest] area is explored, or completes the [Quest] + * + * @param uint32 quest : entry of a [Quest] + */ + int AreaExploredOrEventHappens(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + + player->AreaExploredOrEventHappens(questId); + return 0; + } + + /** + * Sets the given [Quest] entry failed for the [Player]. + * + * @param uint32 entry : entry of a [Quest] + */ + int FailQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->FailQuest(entry); + return 0; + } + + /** + * Sets the given quest entry incomplete for the [Player]. + * + * @param uint32 entry : quest entry + */ + int IncompleteQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->IncompleteQuest(entry); + return 0; + } + + /** + * Completes the given quest entry for the [Player] and tries to satisfy all quest requirements. + * + * The player should have the quest to complete it. + * + * @param uint32 entry : quest entry + */ + int CompleteQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* quest = eObjectMgr->GetQuestTemplate(entry); + + // If player doesn't have the quest + if (!quest || player->GetQuestStatus(entry) == QUEST_STATUS_NONE) + return 0; + + // Add quest items for quests that require items + for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x) + { + uint32 id = quest->RequiredItemId[x]; + uint32 count = quest->RequiredItemCount[x]; + + if (!id || !count) + continue; + + uint32 curItemCount = player->GetItemCount(id, true); + + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count - curItemCount); + if (msg == EQUIP_ERR_OK) + { + Item* item = player->StoreNewItem(dest, id, true); + player->SendNewItem(item, count - curItemCount, true, false); + } + } + + // All creature/GO slain/cast (not required, but otherwise it will display "Creature slain 0/10") + for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) + { + int32 creature = quest->RequiredNpcOrGo[i]; + uint32 creatureCount = quest->RequiredNpcOrGoCount[i]; + + if (creature > 0) + { + if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creature)) + for (uint16 z = 0; z < creatureCount; ++z) + player->KilledMonster(creatureInfo, ObjectGuid::Empty); + } + else if (creature < 0) + for (uint16 z = 0; z < creatureCount; ++z) + player->KillCreditGO(creature); + } + + + // If the quest requires reputation to complete + if (uint32 repFaction = quest->GetRepObjectiveFaction()) + { + uint32 repValue = quest->GetRepObjectiveValue(); + uint32 curRep = player->GetReputationMgr().GetReputation(repFaction); + if (curRep < repValue) + if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(repFaction)) + player->GetReputationMgr().SetReputation(factionEntry, repValue); + } + + // If the quest requires a SECOND reputation to complete + if (uint32 repFaction = quest->GetRepObjectiveFaction2()) + { + uint32 repValue2 = quest->GetRepObjectiveValue2(); + uint32 curRep = player->GetReputationMgr().GetReputation(repFaction); + if (curRep < repValue2) + if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(repFaction)) + player->GetReputationMgr().SetReputation(factionEntry, repValue2); + } + + // If the quest requires money + int32 ReqOrRewMoney = quest->GetRewOrReqMoney(); + if (ReqOrRewMoney < 0) + player->ModifyMoney(-ReqOrRewMoney); + + if (sWorld->getBoolConfig(CONFIG_QUEST_ENABLE_QUEST_TRACKER)) // check if Quest Tracker is enabled + { + // prepare Quest Tracker datas + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_QUEST_TRACK_GM_COMPLETE); + stmt->setUInt32(0, quest->GetQuestId()); + stmt->setUInt32(1, player->GetGUID().GetCounter()); + + // add to Quest Tracker + CharacterDatabase.Execute(stmt); + } + + player->CompleteQuest(entry); + return 0; + } + + /** + * Tries to add the given quest entry for the [Player]. + * + * @param uint32 entry : quest entry + */ + int AddQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* quest = eObjectMgr->GetQuestTemplate(entry); + + if (!quest) + return 0; + + // check item starting quest (it can work incorrectly if added without item in inventory) +#ifndef CATA + ItemTemplateContainer const& itc = sObjectMgr->GetItemTemplateStore(); + auto itr = std::find_if(std::begin(itc), std::end(itc), [quest](ItemTemplateContainer::value_type const& value) + { + return value.second.StartQuest == quest->GetQuestId(); + }); + + if (itr != std::end(itc)) + return 0; + +#elif CATA + ItemTemplateContainer const* itc = sObjectMgr->GetItemTemplateStore(); + ItemTemplateContainer::const_iterator result = std::find_if(itc->begin(), itc->end(), [quest](ItemTemplateContainer::value_type const& value) + { + return value.second.ExtendedData->StartQuest == quest->GetQuestId(); + }); +#endif + // ok, normal (creature/GO starting) quest + if (player->CanAddQuest(quest, true)) + player->AddQuestAndCheckCompletion(quest, NULL); + + return 0; + } + + /** + * Removes the given quest entry from the [Player]. + * + * @param uint32 entry : quest entry + */ + int RemoveQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* quest = eObjectMgr->GetQuestTemplate(entry); + + if (!quest) + return 0; + + // remove all quest entries for 'entry' from quest log + for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot) + { + uint32 logQuest = player->GetQuestSlotQuestId(slot); + if (logQuest == entry) + { + player->SetQuestSlot(slot, 0); + + // we ignore unequippable quest items in this case, its' still be equipped + player->TakeQuestSourceItem(logQuest, false); + + if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP)) + { + player->pvpInfo.IsHostile = player->pvpInfo.IsInHostileArea || player->HasPvPForcingQuest(); + player->UpdatePvPState(); + } + } + } + + player->RemoveActiveQuest(entry, false); + player->RemoveRewardedQuest(entry); + return 0; + } + + /** + * Sends whisper text from the [Player] + * + * @param string text + * @param uint32 lang : language the [Player] will speak + * @param [Player] receiver : is the [Player] that will receive the whisper, if TrinityCore + * @param ObjectGuid guid : is the GUID of a [Player] that will receive the whisper, not TrinityCore + */ + int Whisper(lua_State* L, Player* player) + { + std::string text = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); + Player* receiver = Eluna::CHECKOBJ(L, 4); + + player->Whisper(text, (Language)lang, receiver); + return 0; + } + + /** + * Sends a text emote from the [Player] + * + * @param string emoteText + */ + int TextEmote(lua_State* L, Player* player) + { + std::string text = Eluna::CHECKVAL(L, 2); + + player->TextEmote(text); + return 0; + } + + /** + * Sends yell text from the [Player] + * + * @param string text : text for the [Player] to yells + * @param uint32 lang : language the [Player] will speak + */ + int Yell(lua_State* L, Player* player) + { + std::string text = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); + + player->Yell(text, (Language)lang); + return 0; + } + + /** + * Sends say text from the [Player] + * + * @param string text : text for the [Player] to say + * @param uint32 lang : language the [Player] will speak + */ + int Say(lua_State* L, Player* player) + { + std::string text = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); + + player->Say(text, (Language)lang); + return 0; + } + + /** + * Gives the [Player] experience + * + * @param uint32 xp : experience to give + * @param [Unit] victim = nil + */ + int GiveXP(lua_State* L, Player* player) + { + uint32 xp = Eluna::CHECKVAL(L, 2); + Unit* victim = Eluna::CHECKOBJ(L, 3, false); + + player->GiveXP(xp, victim); + return 0; + } + + /** + * Toggle the [Player]s 'Do Not Disturb' flag + */ + int ToggleDND(lua_State* /*L*/, Player* player) + { + player->ToggleDND(); + return 0; + } + + /** + * Toggle the [Player]s 'Away From Keyboard' flag + */ + int ToggleAFK(lua_State* /*L*/, Player* player) + { + player->ToggleAFK(); + return 0; + } + + /** + * Equips the given item or item entry to the given slot. Returns the equipped item or nil. + * + * enum EquipmentSlots // 19 slots + * { + * EQUIPMENT_SLOT_START = 0, + * EQUIPMENT_SLOT_HEAD = 0, + * EQUIPMENT_SLOT_NECK = 1, + * EQUIPMENT_SLOT_SHOULDERS = 2, + * EQUIPMENT_SLOT_BODY = 3, + * EQUIPMENT_SLOT_CHEST = 4, + * EQUIPMENT_SLOT_WAIST = 5, + * EQUIPMENT_SLOT_LEGS = 6, + * EQUIPMENT_SLOT_FEET = 7, + * EQUIPMENT_SLOT_WRISTS = 8, + * EQUIPMENT_SLOT_HANDS = 9, + * EQUIPMENT_SLOT_FINGER1 = 10, + * EQUIPMENT_SLOT_FINGER2 = 11, + * EQUIPMENT_SLOT_TRINKET1 = 12, + * EQUIPMENT_SLOT_TRINKET2 = 13, + * EQUIPMENT_SLOT_BACK = 14, + * EQUIPMENT_SLOT_MAINHAND = 15, + * EQUIPMENT_SLOT_OFFHAND = 16, + * EQUIPMENT_SLOT_RANGED = 17, + * EQUIPMENT_SLOT_TABARD = 18, + * EQUIPMENT_SLOT_END = 19 + * }; + * + * enum InventorySlots // 4 slots + * { + * INVENTORY_SLOT_BAG_START = 19, + * INVENTORY_SLOT_BAG_END = 23 + * }; + * + * @proto equippedItem = (item, slot) + * @proto equippedItem = (entry, slot) + * @param [Item] item : item to equip + * @param uint32 entry : entry of the item to equip + * @param uint32 slot : equipment slot to equip the item to The slot can be [EquipmentSlots] or [InventorySlots] + * @return [Item] equippedItem : item or nil if equipping failed + */ + int EquipItem(lua_State* L, Player* player) + { + uint16 dest = 0; + Item* item = Eluna::CHECKOBJ(L, 2, false); + uint32 slot = Eluna::CHECKVAL(L, 3); + + if (slot >= INVENTORY_SLOT_BAG_END) + return 1; + + if (!item) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + item = Item::CreateItem(entry, 1, player); + if (!item) + return 1; + + InventoryResult result = player->CanEquipItem(slot, dest, item, false); + if (result != EQUIP_ERR_OK) + { + delete item; + return 1; + } + player->ItemAddedQuestCheck(entry, 1); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, entry, 1); + } + else + { + InventoryResult result = player->CanEquipItem(slot, dest, item, false); + if (result != EQUIP_ERR_OK) + return 1; + player->RemoveItem(item->GetBagSlot(), item->GetSlot(), true); + } + + Eluna::Push(L, player->EquipItem(dest, item, true)); + player->AutoUnequipOffhandIfNeed(); + return 1; + } + + /** + * Returns true if the player can equip the given [Item] or item entry to the given slot, false otherwise. + * + * @proto canEquip = (item, slot) + * @proto canEquip = (entry, slot) + * @param [Item] item : item to equip + * @param uint32 entry : entry of the item to equip + * @param uint32 slot : equipment slot to test + * @return bool canEquip + */ + int CanEquipItem(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2, false); + uint32 slot = Eluna::CHECKVAL(L, 3); + if (slot >= EQUIPMENT_SLOT_END) + { + Eluna::Push(L, false); + return 1; + } + + if (!item) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + uint16 dest; + InventoryResult msg = player->CanEquipNewItem(slot, dest, entry, false); + if (msg != EQUIP_ERR_OK) + { + Eluna::Push(L, false); + return 1; + } + } + else + { + uint16 dest; + InventoryResult msg = player->CanEquipItem(slot, dest, item, false); + if (msg != EQUIP_ERR_OK) + { + Eluna::Push(L, false); + return 1; + } + } + Eluna::Push(L, true); + return 1; + } + + /** + * Removes a title by ID from the [Player]s list of known titles + * + * @param uint32 titleId + */ + int UnsetKnownTitle(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + CharTitlesEntry const* t = sCharTitlesStore.LookupEntry(id); + if (t) + player->SetTitle(t, true); + return 0; + } + +#ifndef CATA + /** + * Advances all of the [Player]s weapon skills to the maximum amount available + */ + int AdvanceSkillsToMax(lua_State* /*L*/, Player* player) + { + player->UpdateWeaponsSkillsToMaxSkillsForLevel(); + return 0; + } +#endif + + /** + * Advances all of the [Player]s skills to the amount specified + * + * @param uint32 skillStep + */ + int AdvanceAllSkills(lua_State* L, Player* player) + { + uint32 step = Eluna::CHECKVAL(L, 2); + + if (!step) + return 0; + + for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i) + { + if (SkillLineEntry const* entry = sSkillLineStore.LookupEntry(i)) + { + if (entry->CategoryID == SKILL_CATEGORY_LANGUAGES || entry->CategoryID == SKILL_CATEGORY_GENERIC) + continue; + + if (player->HasSkill(entry->ID)) + player->UpdateSkill(entry->ID, step); + } + } + + return 0; + } + + /** + * Advances a [Player]s specific skill to the amount specified + * + * @param uint32 skillId + * @param uint32 skillStep + */ + int AdvanceSkill(lua_State* L, Player* player) + { + uint32 _skillId = Eluna::CHECKVAL(L, 2); + uint32 _step = Eluna::CHECKVAL(L, 3); + if (_skillId && _step) + { + if (player->HasSkill(_skillId)) + player->UpdateSkill(_skillId, _step); + } + return 0; + } + + /** + * Teleports a [Player] to the location specified + * + * @param uint32 mappId + * @param float xCoord + * @param float yCoord + * @param float zCoord + * @param float orientation + */ + int Teleport(lua_State* L, Player* player) + { + uint32 mapId = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + +#ifdef CATA + if (player->IsInFlight()) + { + player->GetMotionMaster()->MovementExpired(); + player->m_taxi.ClearTaxiDestinations(); + } + else + player->SaveRecallPosition(); +#else + if (player->IsInFlight()) + player->FinishTaxiFlight(); + else + player->SaveRecallPosition(); + +#endif + Eluna::Push(L, player->TeleportTo(mapId, x, y, z, o)); + return 1; + } + + int AddLifetimeKills(lua_State* L, Player* player) + { + uint32 val = Eluna::CHECKVAL(L, 2); + uint32 currentKills = player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS); + player->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, currentKills + val); + return 0; + } + + /** + * Adds the given amount of the specified item entry to the player. + * + * @param uint32 entry : entry of the item to add + * @param uint32 itemCount = 1 : amount of the item to add + * @return [Item] item : the item that was added or nil + */ + int AddItem(lua_State* L, Player* player) + { + uint32 itemId = Eluna::CHECKVAL(L, 2); + uint32 itemCount = Eluna::CHECKVAL(L, 3, 1); + + uint32 noSpaceForCount = 0; + ItemPosCountVec dest; + InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, itemCount, &noSpaceForCount); + if (msg != EQUIP_ERR_OK) + itemCount -= noSpaceForCount; + + if (itemCount == 0 || dest.empty()) + return 1; + + Item* item = player->StoreNewItem(dest, itemId, true, GenerateItemRandomPropertyId(itemId)); + + if (item) + player->SendNewItem(item, itemCount, true, false); + + Eluna::Push(L, item); + return 1; + } + + /** + * Removes the given amount of the specified [Item] from the player. + * + * @proto (item, itemCount) + * @proto (entry, itemCount) + * @param [Item] item : item to remove + * @param uint32 entry : entry of the item to remove + * @param uint32 itemCount = 1 : amount of the item to remove + */ + int RemoveItem(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2, false); + uint32 itemCount = Eluna::CHECKVAL(L, 3); + if (!item) + { + uint32 itemId = Eluna::CHECKVAL(L, 2); + player->DestroyItemCount(itemId, itemCount, true); + } + else + { + bool all = itemCount >= item->GetCount(); + player->DestroyItemCount(item, itemCount, true); + if (all) + Eluna::CHECKOBJ(L, 2)->Invalidate(); + } + return 0; + } + + /** + * Removes specified amount of lifetime kills + * + * @param uint32 val : kills to remove + */ + int RemoveLifetimeKills(lua_State* L, Player* player) + { + uint32 val = Eluna::CHECKVAL(L, 2); + uint32 currentKills = player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS); + if (val > currentKills) + val = currentKills; + player->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, currentKills - val); + return 0; + } + + /** + * Resets cooldown of the specified spell + * + * @param uint32 spellId + * @param bool update = true + */ + int ResetSpellCooldown(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + bool update = Eluna::CHECKVAL(L, 3, true); + + player->GetSpellHistory()->ResetCooldown(spellId, update); + return 0; + } + + /** + * Resets cooldown of the specified category + * + * @param uint32 category + * @param bool update = true + */ + int ResetTypeCooldowns(lua_State* L, Player* player) + { + uint32 category = Eluna::CHECKVAL(L, 2); + bool update = Eluna::CHECKVAL(L, 3, true); + (void)update; // ensure that the variable is referenced in order to pass compiler checks + + player->GetSpellHistory()->ResetCooldowns([category](SpellHistory::CooldownStorageType::iterator itr) -> bool + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); + return spellInfo && spellInfo->GetCategory() == category; + }, update); + + return 0; + } + + /** + * Resets all of the [Player]'s cooldowns + */ + int ResetAllCooldowns(lua_State* /*L*/, Player* player) + { + player->GetSpellHistory()->ResetAllCooldowns(); + return 0; + } + + /** + * Sends a Broadcast Message to the [Player] + * + * @param string message + */ + int SendBroadcastMessage(lua_State* L, Player* player) + { + const char* message = Eluna::CHECKVAL(L, 2); + if (std::string(message).length() > 0) + ChatHandler(player->GetSession()).SendSysMessage(message); + return 0; + } + + /** + * Sends an Area Trigger Message to the [Player] + * + * @param string message + */ + int SendAreaTriggerMessage(lua_State* L, Player* player) + { + std::string msg = Eluna::CHECKVAL(L, 2); + if (msg.length() > 0) + player->GetSession()->SendAreaTriggerMessage("%s", msg.c_str()); + return 0; + } + + /** + * Sends a Notification to the [Player] + * + * @param string message + */ + int SendNotification(lua_State* L, Player* player) + { + std::string msg = Eluna::CHECKVAL(L, 2); + if (msg.length() > 0) + player->GetSession()->SendNotification("%s", msg.c_str()); + return 0; + } + + /** + * Sends a [WorldPacket] to the [Player] + * + * @param [WorldPacket] packet + * @param bool selfOnly = true + */ + int SendPacket(lua_State* L, Player* player) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + bool selfOnly = Eluna::CHECKVAL(L, 3, true); + + if (selfOnly) + player->GetSession()->SendPacket(data); + else + player->SendMessageToSet(data, true); + + return 0; + } + + /** + * Sends addon message to the [Player] receiver + * + * @param string prefix + * @param string message + * @param [ChatMsg] channel + * @param [Player] receiver + * + */ + int SendAddonMessage(lua_State* L, Player* player) + { + std::string prefix = Eluna::CHECKVAL(L, 2); + std::string message = Eluna::CHECKVAL(L, 3); + uint8 channel = Eluna::CHECKVAL(L, 4); + Player* receiver = Eluna::CHECKOBJ(L, 5); + + std::string fullmsg = prefix + "\t" + message; + + WorldPacket data(SMSG_MESSAGECHAT, 100); + data << uint8(channel); + data << int32(LANG_ADDON); + data << player->GET_GUID(); + data << uint32(0); + data << receiver->GET_GUID(); + data << uint32(fullmsg.length() + 1); + data << fullmsg; + data << uint8(0); + + receiver->GetSession()->SendPacket(&data); + return 0; + } + + /** + * Kicks the [Player] from the server + */ + int KickPlayer(lua_State* /*L*/, Player* player) + { +#ifndef CATA + player->GetSession()->KickPlayer("PlayerMethods::KickPlayer Kick the player"); +#else + player->GetSession()->KickPlayer(); +#endif + return 0; + } + + /** + * Adds or subtracts from the [Player]s money in copper + * + * @param int32 copperAmt : negative to remove, positive to add + */ + int ModifyMoney(lua_State* L, Player* player) + { + int32 amt = Eluna::CHECKVAL(L, 2); + + player->ModifyMoney(amt); + return 1; + } + + /** + * Teaches the [Player] the [Spell] specified by entry ID + * + * @param uint32 spellId + */ + int LearnSpell(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + + player->LearnSpell(id, false); + return 0; + } + + /** + * Learn the [Player] the talent specified by talent_id and talentRank + * + * @param uint32 talent_id + * @param uint32 talentRank + */ + int LearnTalent(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + uint32 rank = Eluna::CHECKVAL(L, 3); + + player->LearnTalent(id, rank); + player->SendTalentsInfoData(false); + return 0; + } + + /** + * Remove cooldowns on spells that have less than 10 minutes of cooldown from the [Player], similarly to when you enter an arena. + */ + int RemoveArenaSpellCooldowns(lua_State* /*L*/, Player* player) + { + player->RemoveArenaSpellCooldowns(); + return 0; + } + + /** + * Resurrects the [Player]. + * + * @param float healthPercent = 100.0f + * @param bool ressSickness = false + */ + int ResurrectPlayer(lua_State* L, Player* player) + { + float percent = Eluna::CHECKVAL(L, 2, 100.0f); + bool sickness = Eluna::CHECKVAL(L, 3, false); + player->ResurrectPlayer(percent, sickness); + player->SpawnCorpseBones(); + return 0; + } + + /** + * Adds a new item to the gossip menu shown to the [Player] on next call to [Player:GossipSendMenu]. + * + * sender and intid are numbers which are passed directly to the gossip selection handler. Internally they are partly used for the database gossip handling. + * code specifies whether to show a box to insert text to. The player inserted text is passed to the gossip selection handler. + * money specifies an amount of money the player needs to have to click the option. An error message is shown if the player doesn't have enough money. + * Note that the money amount is only checked client side and is not removed from the player either. You will need to check again in your code before taking action. + * + * See also: [Player:GossipSendMenu], [Player:GossipAddQuests], [Player:GossipComplete], [Player:GossipClearMenu] + * + * @param uint32 icon : number that specifies used icon + * @param string msg : label on the gossip item + * @param uint32 sender : number passed to gossip handlers + * @param uint32 intid : number passed to gossip handlers + * @param bool code = false : show text input on click if true + * @param string popup = nil : if non empty string, a popup with given text shown on click + * @param uint32 money = 0 : required money in copper + */ + int GossipMenuAddItem(lua_State* L, Player* player) + { + uint32 _icon = Eluna::CHECKVAL(L, 2); + const char* msg = Eluna::CHECKVAL(L, 3); + uint32 _sender = Eluna::CHECKVAL(L, 4); + uint32 _intid = Eluna::CHECKVAL(L, 5); + bool _code = Eluna::CHECKVAL(L, 6, false); + const char* _promptMsg = Eluna::CHECKVAL(L, 7, ""); + uint32 _money = Eluna::CHECKVAL(L, 8, 0); + + player->PlayerTalkClass->GetGossipMenu().AddMenuItem(-1, GossipOptionIcon(_icon), msg, _sender, _intid, _promptMsg, _money, _code); + return 0; + } + + /** + * Closes the [Player]s currently open Gossip Menu. + * + * See also: [Player:GossipMenuAddItem], [Player:GossipAddQuests], [Player:GossipSendMenu], [Player:GossipClearMenu] + */ + int GossipComplete(lua_State* /*L*/, Player* player) + { + player->PlayerTalkClass->SendCloseGossip(); + return 0; + } + + /** + * Sends the current gossip items of the player to him as a gossip menu with header text from the given textId. + * + * If sender is a [Player] then menu_id is mandatory, otherwise it is not used for anything. + * menu_id is the ID used to trigger the OnGossipSelect registered for players. See [Global:RegisterPlayerGossipEvent] + * + * See also: [Player:GossipMenuAddItem], [Player:GossipAddQuests], [Player:GossipComplete], [Player:GossipClearMenu] + * + * @proto (npc_text, sender) + * @proto (npc_text, sender, menu_id) + * @param uint32 npc_text : entry ID of a header text in npc_text database table, common default is 100 + * @param [Object] sender : object acting as the source of the sent gossip menu + * @param uint32 menu_id : if sender is a [Player] then menu_id is mandatory + */ + int GossipSendMenu(lua_State* L, Player* player) + { + uint32 npc_text = Eluna::CHECKVAL(L, 2); + Object* sender = Eluna::CHECKOBJ(L, 3); + if (sender->GetTypeId() == TYPEID_PLAYER) + { + uint32 menu_id = Eluna::CHECKVAL(L, 4); + player->PlayerTalkClass->GetGossipMenu().SetMenuId(menu_id); + } + + player->PlayerTalkClass->SendGossipMenu(npc_text, sender->GET_GUID()); + return 0; + } + + /** + * Clears the [Player]s current gossip item list. + * + * See also: [Player:GossipMenuAddItem], [Player:GossipSendMenu], [Player:GossipAddQuests], [Player:GossipComplete] + * + * Note: This is needed when you show a gossip menu without using gossip hello or select hooks which do this automatically. + * Usually this is needed when using [Player] is the sender of a Gossip Menu. + */ + int GossipClearMenu(lua_State* /*L*/, Player* player) + { + player->PlayerTalkClass->ClearMenus(); + return 0; + } + + /** + * Attempts to start the taxi/flying to the given pathID + * + * @param uint32 pathId : pathId from DBC or [Global:AddTaxiPath] + */ + int StartTaxi(lua_State* L, Player* player) + { + uint32 pathId = Eluna::CHECKVAL(L, 2); + + player->ActivateTaxiPathTo(pathId); + return 0; + } + + /** + * Sends POI to the location on your map + * + * @param float x + * @param float y + * @param uint32 icon : map icon to show + * @param uint32 flags + * @param uint32 data + * @param string iconText + */ + int GossipSendPOI(lua_State* L, Player* player) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + uint32 icon = Eluna::CHECKVAL(L, 4); + uint32 flags = Eluna::CHECKVAL(L, 5); + uint32 data = Eluna::CHECKVAL(L, 6); + std::string iconText = Eluna::CHECKVAL(L, 7); + + WorldPacket packet(SMSG_GOSSIP_POI, 4 + 4 + 4 + 4 + 4 + 10); + packet << flags; + packet << x; + packet << y; + packet << icon; + packet << data; + packet << iconText; + + player->GetSession()->SendPacket(&packet); + return 0; + } + + /** + * Adds the gossip items to the [Player]'s gossip for the quests the given [WorldObject] can offer to the player. + * + * @param [WorldObject] source : a questgiver with quests + */ + int GossipAddQuests(lua_State* L, Player* player) + { + WorldObject* source = Eluna::CHECKOBJ(L, 2); + + if (source->GetTypeId() == TYPEID_UNIT) + { + if (source->GetUInt32Value(UNIT_NPC_FLAGS) & UNIT_NPC_FLAG_QUESTGIVER) + player->PrepareQuestMenu(source->GET_GUID()); + } + else if (source->GetTypeId() == TYPEID_GAMEOBJECT) + { + if (source->ToGameObject()->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + player->PrepareQuestMenu(source->GET_GUID()); + } + return 0; + } + + /** + * Shows a quest accepting window to the [Player] for the given quest. + * + * @param uint32 questId : entry of a quest + * @param bool activateAccept = true : auto finish the quest + */ + int SendQuestTemplate(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + bool activateAccept = Eluna::CHECKVAL(L, 3, true); + + Quest const* quest = eObjectMgr->GetQuestTemplate(questId); + if (!quest) + return 0; + +#ifdef CATA + player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, player->GET_GUID(), activateAccept, true); +#else + player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, player->GET_GUID(), activateAccept); + +#endif + return 0; + } + + /** + * Converts [Player]'s corpse to bones + */ + int SpawnBones(lua_State* /*L*/, Player* player) + { + player->SpawnCorpseBones(); + return 0; + } + + /** + * Loots [Player]'s bones for insignia + * + * @param [Player] looter + */ + int RemovedInsignia(lua_State* L, Player* player) + { + Player* looter = Eluna::CHECKOBJ(L, 2); + player->RemovedInsignia(looter); + return 0; + } + + /** + * Makes the [Player] invite another player to a group. + * + * @param [Player] invited : player to invite to group + * @return bool success : true if the player was invited to a group + */ + int GroupInvite(lua_State* L, Player* player) + { + Player* invited = Eluna::CHECKOBJ(L, 2); + + if (invited->GetGroup() || invited->GetGroupInvite()) + { + Eluna::Push(L, false); + return 1; + } + + // Get correct existing group if any + Group* group = player->GetGroup(); + + if (group && group->isBGGroup()) + group = player->GetOriginalGroup(); + + bool success = false; + + // Try invite if group found + if (group) + success = !group->IsFull() && group->AddInvite(invited); + else + { + // Create new group if one not found + group = new Group; + success = group->AddLeaderInvite(player) && group->AddInvite(invited); + if (!success) + delete group; + } + + if (success) + { +#ifdef CATA + WorldPacket data(SMSG_PARTY_INVITE, 10); // guess size +#else + WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size +#endif + data << uint8(1); // invited/already in group flag + data << player->GetName(); // max len 48 + data << uint32(0); // unk + data << uint8(0); // count + data << uint32(0); // unk + + invited->GetSession()->SendPacket(&data); + } + + Eluna::Push(L, success); + return 1; + } + + /** + * Creates a new [Group] with the creator [Player] as leader. + * + * @param [Player] invited : player to add to group + * @return [Group] createdGroup : the created group or nil + */ + int GroupCreate(lua_State* L, Player* player) + { + Player* invited = Eluna::CHECKOBJ(L, 2); + + if (player->GetGroup() || invited->GetGroup()) + return 0; + + if (player->GetGroupInvite()) + player->UninviteFromGroup(); + if (invited->GetGroupInvite()) + invited->UninviteFromGroup(); + + // Try create new group + Group* group = new Group; + if (!group->AddLeaderInvite(player)) + { + delete group; + return 0; + } + + // Forming a new group, create it + if (!group->IsCreated()) + { + group->RemoveInvite(player); + group->Create(player); + sGroupMgr->AddGroup(group); + } + + if (!group->AddMember(invited)) + return 0; + + group->BroadcastGroupUpdate(); + + Eluna::Push(L, group); + return 1; + } + + /** + * Starts a cinematic for the [Player] + * + * @param uint32 CinematicSequenceId : entry of a cinematic + */ + int SendCinematicStart(lua_State* L, Player* player) + { + uint32 CinematicSequenceId = Eluna::CHECKVAL(L, 2); + + player->SendCinematicStart(CinematicSequenceId); + return 0; + } + + /** + * Starts a movie for the [Player] + * + * @param uint32 MovieId : entry of a movie + */ + int SendMovieStart(lua_State* L, Player* player) + { + uint32 MovieId = Eluna::CHECKVAL(L, 2); + + player->SendMovieStart(MovieId); + return 0; + } + + int BindToInstance(lua_State* /*L*/, Player* player) + { + player->BindToInstance(); + return 0; + } + + int AddTalent(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + uint8 spec = Eluna::CHECKVAL(L, 3); + bool learning = Eluna::CHECKVAL(L, 4, true); + + if (spec >= MAX_TALENT_SPECS) + Eluna::Push(L, false); + else + Eluna::Push(L, player->AddTalent(spellId, spec, learning)); + + return 1; + } + + /*int GainSpellComboPoints(lua_State* L, Player* player) + { + int8 count = Eluna::CHECKVAL(L, 2); + + player->GainSpellComboPoints(count); + return 0; + }*/ + + int KillGOCredit(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + ObjectGuid guid = Eluna::CHECKVAL(L, 3); + + player->KillCreditGO(entry, guid); + return 0; + } + + int KilledPlayerCredit(lua_State* /*L*/, Player* player) + { + player->KilledPlayerCredit(); + return 0; + } + + int RemoveRewardedQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->RemoveRewardedQuest(entry); + return 0; + } + + int RemoveActiveQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->RemoveActiveQuest(entry); + return 0; + } + + int SummonPet(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + uint32 petType = Eluna::CHECKVAL(L, 7); + uint32 despwtime = Eluna::CHECKVAL(L, 8); + + if (petType >= MAX_PET_TYPE) + return 0; + + player->SummonPet(entry, x, y, z, o, (PetType)petType, despwtime); + return 0; + } + + int RemovePet(lua_State* L, Player* player) + { + int mode = Eluna::CHECKVAL(L, 2, PET_SAVE_AS_DELETED); + bool returnreagent = Eluna::CHECKVAL(L, 2, false); + + if (!player->GetPet()) + return 0; + + player->RemovePet(player->GetPet(), (PetSaveMode)mode, returnreagent); + return 0; + } + + ElunaRegister PlayerMethods[] = + { + // Getters + { "GetSelection", &LuaPlayer::GetSelection }, + { "GetGMRank", &LuaPlayer::GetGMRank }, + { "GetGuildId", &LuaPlayer::GetGuildId }, + { "GetCoinage", &LuaPlayer::GetCoinage }, + { "GetTeam", &LuaPlayer::GetTeam }, + { "GetItemCount", &LuaPlayer::GetItemCount }, + { "GetGroup", &LuaPlayer::GetGroup }, + { "GetGuild", &LuaPlayer::GetGuild }, + { "GetAccountId", &LuaPlayer::GetAccountId }, + { "GetAccountName", &LuaPlayer::GetAccountName }, +#ifndef CATA + { "GetArenaPoints", &LuaPlayer::GetArenaPoints }, + { "GetHonorPoints", &LuaPlayer::GetHonorPoints }, +#else + { "GetArenaPoints", nullptr }, + { "GetHonorPoints", nullptr }, +#endif + { "GetLifetimeKills", &LuaPlayer::GetLifetimeKills }, + { "GetPlayerIP", &LuaPlayer::GetPlayerIP }, + { "GetLevelPlayedTime", &LuaPlayer::GetLevelPlayedTime }, + { "GetTotalPlayedTime", &LuaPlayer::GetTotalPlayedTime }, + { "GetItemByPos", &LuaPlayer::GetItemByPos }, + { "GetItemByEntry", &LuaPlayer::GetItemByEntry }, + { "GetItemByGUID", &LuaPlayer::GetItemByGUID }, + { "GetMailItem", &LuaPlayer::GetMailItem }, + { "GetReputation", &LuaPlayer::GetReputation }, + { "GetEquippedItemBySlot", &LuaPlayer::GetEquippedItemBySlot }, + { "GetQuestLevel", &LuaPlayer::GetQuestLevel }, + { "GetChatTag", &LuaPlayer::GetChatTag }, + { "GetRestBonus", &LuaPlayer::GetRestBonus }, +#ifndef CATA + { "GetPhaseMaskForSpawn", &LuaPlayer::GetPhaseMaskForSpawn }, +#else + { "GetPhaseMaskForSpawn", nullptr }, +#endif + { "GetReqKillOrCastCurrentCount", &LuaPlayer::GetReqKillOrCastCurrentCount }, + { "GetQuestStatus", &LuaPlayer::GetQuestStatus }, + { "GetInGameTime", &LuaPlayer::GetInGameTime }, + { "GetComboPoints", &LuaPlayer::GetComboPoints }, + { "GetComboTarget", &LuaPlayer::GetComboTarget }, + { "GetGuildName", &LuaPlayer::GetGuildName }, + { "GetFreeTalentPoints", &LuaPlayer::GetFreeTalentPoints }, + { "GetActiveSpec", &LuaPlayer::GetActiveSpec }, + { "GetSpecsCount", &LuaPlayer::GetSpecsCount }, + { "GetSpellCooldownDelay", &LuaPlayer::GetSpellCooldownDelay }, + { "GetGuildRank", &LuaPlayer::GetGuildRank }, + { "GetDifficulty", &LuaPlayer::GetDifficulty }, + { "GetHealthBonusFromStamina", &LuaPlayer::GetHealthBonusFromStamina }, + { "GetManaBonusFromIntellect", &LuaPlayer::GetManaBonusFromIntellect }, + { "GetMaxSkillValue", &LuaPlayer::GetMaxSkillValue }, + { "GetPureMaxSkillValue", &LuaPlayer::GetPureMaxSkillValue }, + { "GetSkillValue", &LuaPlayer::GetSkillValue }, + { "GetBaseSkillValue", &LuaPlayer::GetBaseSkillValue }, + { "GetPureSkillValue", &LuaPlayer::GetPureSkillValue }, + { "GetSkillPermBonusValue", &LuaPlayer::GetSkillPermBonusValue }, + { "GetSkillTempBonusValue", &LuaPlayer::GetSkillTempBonusValue }, + { "GetReputationRank", &LuaPlayer::GetReputationRank }, + { "GetDrunkValue", &LuaPlayer::GetDrunkValue }, + { "GetBattlegroundId", &LuaPlayer::GetBattlegroundId }, + { "GetBattlegroundTypeId", &LuaPlayer::GetBattlegroundTypeId }, + { "GetXPRestBonus", &LuaPlayer::GetXPRestBonus }, + { "GetGroupInvite", &LuaPlayer::GetGroupInvite }, + { "GetSubGroup", &LuaPlayer::GetSubGroup }, + { "GetNextRandomRaidMember", &LuaPlayer::GetNextRandomRaidMember }, + { "GetOriginalGroup", &LuaPlayer::GetOriginalGroup }, + { "GetOriginalSubGroup", &LuaPlayer::GetOriginalSubGroup }, + { "GetChampioningFaction", &LuaPlayer::GetChampioningFaction }, + { "GetLatency", &LuaPlayer::GetLatency }, + { "GetRecruiterId", &LuaPlayer::GetRecruiterId }, + { "GetDbLocaleIndex", &LuaPlayer::GetDbLocaleIndex }, + { "GetDbcLocale", &LuaPlayer::GetDbcLocale }, + { "GetCorpse", &LuaPlayer::GetCorpse }, + { "GetGossipTextId", &LuaPlayer::GetGossipTextId }, + { "GetQuestRewardStatus", &LuaPlayer::GetQuestRewardStatus }, +#ifndef CATA + { "GetShieldBlockValue", &LuaPlayer::GetShieldBlockValue }, + { "GetMailCount", &LuaPlayer::GetMailCount }, + { "GetXP", &LuaPlayer::GetXP }, + { "GetXPForNextLevel", &LuaPlayer::GetXPForNextLevel }, +#else + { "GetShieldBlockValue", nullptr }, + { "GetMailCount", nullptr }, + { "GetXP", nullptr }, + { "GetXPForNextLevel", nullptr }, +#endif + + // Setters +#ifndef CATA + { "AdvanceSkillsToMax", &LuaPlayer::AdvanceSkillsToMax }, +#else + { "AdvanceSkillsToMax", nullptr }, +#endif + { "AdvanceSkill", &LuaPlayer::AdvanceSkill }, + { "AdvanceAllSkills", &LuaPlayer::AdvanceAllSkills }, + { "AddLifetimeKills", &LuaPlayer::AddLifetimeKills }, + { "SetCoinage", &LuaPlayer::SetCoinage }, + { "SetKnownTitle", &LuaPlayer::SetKnownTitle }, + { "UnsetKnownTitle", &LuaPlayer::UnsetKnownTitle }, + { "SetBindPoint", &LuaPlayer::SetBindPoint }, +#ifndef CATA + { "SetArenaPoints", &LuaPlayer::SetArenaPoints }, + { "SetHonorPoints", &LuaPlayer::SetHonorPoints }, +#else + { "SetArenaPoints", nullptr }, + { "SetHonorPoints", nullptr }, +#endif + { "SetLifetimeKills", &LuaPlayer::SetLifetimeKills }, + { "SetGameMaster", &LuaPlayer::SetGameMaster }, + { "SetGMChat", &LuaPlayer::SetGMChat }, + { "SetTaxiCheat", &LuaPlayer::SetTaxiCheat }, + { "SetGMVisible", &LuaPlayer::SetGMVisible }, + { "SetPvPDeath", &LuaPlayer::SetPvPDeath }, + { "SetAcceptWhispers", &LuaPlayer::SetAcceptWhispers }, + { "SetRestBonus", &LuaPlayer::SetRestBonus }, + { "SetQuestStatus", &LuaPlayer::SetQuestStatus }, + { "SetReputation", &LuaPlayer::SetReputation }, + { "SetFreeTalentPoints", &LuaPlayer::SetFreeTalentPoints }, + { "SetGuildRank", &LuaPlayer::SetGuildRank }, +#ifndef CATA + { "SetMovement", &LuaPlayer::SetMovement }, +#else + { "SetMovement", nullptr }, +#endif + { "SetSkill", &LuaPlayer::SetSkill }, + { "SetFactionForRace", &LuaPlayer::SetFactionForRace }, + { "SetDrunkValue", &LuaPlayer::SetDrunkValue }, + { "SetAtLoginFlag", &LuaPlayer::SetAtLoginFlag }, + { "SetPlayerLock", &LuaPlayer::SetPlayerLock }, + { "SetGender", &LuaPlayer::SetGender }, + { "SetSheath", &LuaPlayer::SetSheath }, + { "SetFFA", &LuaPlayer::SetFFA }, + + // Boolean + { "IsInGroup", &LuaPlayer::IsInGroup }, + { "IsInGuild", &LuaPlayer::IsInGuild }, + { "IsGM", &LuaPlayer::IsGM }, + { "IsImmuneToDamage", &LuaPlayer::IsImmuneToDamage }, + { "IsAlliance", &LuaPlayer::IsAlliance }, + { "IsHorde", &LuaPlayer::IsHorde }, + { "HasTitle", &LuaPlayer::HasTitle }, + { "HasItem", &LuaPlayer::HasItem }, + { "Teleport", &LuaPlayer::Teleport }, + { "AddItem", &LuaPlayer::AddItem }, + { "IsInArenaTeam", &LuaPlayer::IsInArenaTeam }, + { "CanCompleteQuest", &LuaPlayer::CanCompleteQuest }, + { "CanEquipItem", &LuaPlayer::CanEquipItem }, + { "IsFalling", &LuaPlayer::IsFalling }, + { "ToggleAFK", &LuaPlayer::ToggleAFK }, + { "ToggleDND", &LuaPlayer::ToggleDND }, + { "IsAFK", &LuaPlayer::IsAFK }, + { "IsDND", &LuaPlayer::IsDND }, + { "IsAcceptingWhispers", &LuaPlayer::IsAcceptingWhispers }, + { "IsGMChat", &LuaPlayer::IsGMChat }, + { "IsTaxiCheater", &LuaPlayer::IsTaxiCheater }, + { "IsGMVisible", &LuaPlayer::IsGMVisible }, + { "HasQuest", &LuaPlayer::HasQuest }, + { "InBattlegroundQueue", &LuaPlayer::InBattlegroundQueue }, + { "IsImmuneToEnvironmentalDamage", &LuaPlayer::IsImmuneToEnvironmentalDamage }, + { "CanSpeak", &LuaPlayer::CanSpeak }, + { "HasAtLoginFlag", &LuaPlayer::HasAtLoginFlag }, + { "InRandomLfgDungeon", &LuaPlayer::InRandomLfgDungeon }, + { "HasPendingBind", &LuaPlayer::HasPendingBind }, + { "HasAchieved", &LuaPlayer::HasAchieved }, + { "SetAchievement", &LuaPlayer::SetAchievement }, + { "CanUninviteFromGroup", &LuaPlayer::CanUninviteFromGroup }, + { "IsRested", &LuaPlayer::IsRested }, + { "IsNeverVisible", &LuaPlayer::IsNeverVisible }, + { "IsVisibleForPlayer", &LuaPlayer::IsVisibleForPlayer }, + { "IsUsingLfg", &LuaPlayer::IsUsingLfg }, + { "HasQuestForItem", &LuaPlayer::HasQuestForItem }, + { "HasQuestForGO", &LuaPlayer::HasQuestForGO }, + { "CanShareQuest", &LuaPlayer::CanShareQuest }, + { "HasReceivedQuestReward", &LuaPlayer::HasReceivedQuestReward }, + { "HasTalent", &LuaPlayer::HasTalent }, + { "IsInSameGroupWith", &LuaPlayer::IsInSameGroupWith }, + { "IsInSameRaidWith", &LuaPlayer::IsInSameRaidWith }, + { "IsGroupVisibleFor", &LuaPlayer::IsGroupVisibleFor }, + { "HasSkill", &LuaPlayer::HasSkill }, + { "IsHonorOrXPTarget", &LuaPlayer::IsHonorOrXPTarget }, + { "CanParry", &LuaPlayer::CanParry }, + { "CanBlock", &LuaPlayer::CanBlock }, + { "CanTitanGrip", &LuaPlayer::CanTitanGrip }, + { "InBattleground", &LuaPlayer::InBattleground }, + { "InArena", &LuaPlayer::InArena }, + { "IsOutdoorPvPActive", &LuaPlayer::IsOutdoorPvPActive }, + { "IsARecruiter", &LuaPlayer::IsARecruiter }, + { "CanUseItem", &LuaPlayer::CanUseItem }, + { "HasSpell", &LuaPlayer::HasSpell }, + { "HasSpellCooldown", &LuaPlayer::HasSpellCooldown }, + { "IsInWater", &LuaPlayer::IsInWater }, + { "CanFly", &LuaPlayer::CanFly }, + { "IsMoving", &LuaPlayer::IsMoving }, + { "IsFlying", &LuaPlayer::IsFlying }, +#ifndef CATA + { "CanCompleteRepeatableQuest", &LuaPlayer::CanCompleteRepeatableQuest }, + { "CanRewardQuest", &LuaPlayer::CanRewardQuest }, +#else + { "CanCompleteRepeatableQuest", nullptr }, + { "CanRewardQuest", nullptr }, +#endif + + // Gossip + { "GossipMenuAddItem", &LuaPlayer::GossipMenuAddItem }, + { "GossipSendMenu", &LuaPlayer::GossipSendMenu }, + { "GossipComplete", &LuaPlayer::GossipComplete }, + { "GossipClearMenu", &LuaPlayer::GossipClearMenu }, + + // Other + { "SendBroadcastMessage", &LuaPlayer::SendBroadcastMessage }, + { "SendAreaTriggerMessage", &LuaPlayer::SendAreaTriggerMessage }, + { "SendNotification", &LuaPlayer::SendNotification }, + { "SendPacket", &LuaPlayer::SendPacket }, + { "SendAddonMessage", &LuaPlayer::SendAddonMessage }, + { "ModifyMoney", &LuaPlayer::ModifyMoney }, + { "LearnSpell", &LuaPlayer::LearnSpell }, + { "LearnTalent", &LuaPlayer::LearnTalent }, + { "RemoveArenaSpellCooldowns", &LuaPlayer::RemoveArenaSpellCooldowns }, + { "RemoveItem", &LuaPlayer::RemoveItem }, + { "RemoveLifetimeKills", &LuaPlayer::RemoveLifetimeKills }, + { "ResurrectPlayer", &LuaPlayer::ResurrectPlayer }, + { "EquipItem", &LuaPlayer::EquipItem }, + { "ResetSpellCooldown", &LuaPlayer::ResetSpellCooldown }, + { "ResetTypeCooldowns", &LuaPlayer::ResetTypeCooldowns }, + { "ResetAllCooldowns", &LuaPlayer::ResetAllCooldowns }, + { "GiveXP", &LuaPlayer::GiveXP }, + { "RemovePet", &LuaPlayer::RemovePet }, + { "SummonPet", &LuaPlayer::SummonPet }, + { "Say", &LuaPlayer::Say }, + { "Yell", &LuaPlayer::Yell }, + { "TextEmote", &LuaPlayer::TextEmote }, + { "Whisper", &LuaPlayer::Whisper }, + { "CompleteQuest", &LuaPlayer::CompleteQuest }, + { "IncompleteQuest", &LuaPlayer::IncompleteQuest }, + { "FailQuest", &LuaPlayer::FailQuest }, + { "AddQuest", &LuaPlayer::AddQuest }, + { "RemoveQuest", &LuaPlayer::RemoveQuest }, + { "RemoveActiveQuest", &LuaPlayer::RemoveActiveQuest }, + { "RemoveRewardedQuest", &LuaPlayer::RemoveRewardedQuest }, + { "AreaExploredOrEventHappens", &LuaPlayer::AreaExploredOrEventHappens }, + { "GroupEventHappens", &LuaPlayer::GroupEventHappens }, + { "KilledMonsterCredit", &LuaPlayer::KilledMonsterCredit }, + { "KilledPlayerCredit", &LuaPlayer::KilledPlayerCredit }, + { "KillGOCredit", &LuaPlayer::KillGOCredit }, + { "TalkedToCreature", &LuaPlayer::TalkedToCreature }, + { "ResetPetTalents", &LuaPlayer::ResetPetTalents }, + { "AddComboPoints", &LuaPlayer::AddComboPoints }, + { "ClearComboPoints", &LuaPlayer::ClearComboPoints }, + { "RemoveSpell", &LuaPlayer::RemoveSpell }, + { "ResetTalents", &LuaPlayer::ResetTalents }, + { "ResetTalentsCost", &LuaPlayer::ResetTalentsCost }, + { "AddTalent", &LuaPlayer::AddTalent }, + { "RemoveFromGroup", &LuaPlayer::RemoveFromGroup }, + { "KillPlayer", &LuaPlayer::KillPlayer }, + { "DurabilityLossAll", &LuaPlayer::DurabilityLossAll }, + { "DurabilityLoss", &LuaPlayer::DurabilityLoss }, + { "DurabilityPointsLoss", &LuaPlayer::DurabilityPointsLoss }, + { "DurabilityPointsLossAll", &LuaPlayer::DurabilityPointsLossAll }, + { "DurabilityPointLossForEquipSlot", &LuaPlayer::DurabilityPointLossForEquipSlot }, + { "DurabilityRepairAll", &LuaPlayer::DurabilityRepairAll }, + { "DurabilityRepair", &LuaPlayer::DurabilityRepair }, +#ifndef CATA + { "ModifyHonorPoints", &LuaPlayer::ModifyHonorPoints }, + { "ModifyArenaPoints", &LuaPlayer::ModifyArenaPoints }, +#else + { "ModifyHonorPoints", nullptr }, + { "ModifyArenaPoints", nullptr }, +#endif + { "LeaveBattleground", &LuaPlayer::LeaveBattleground }, + { "BindToInstance", &LuaPlayer::BindToInstance }, + { "UnbindInstance", &LuaPlayer::UnbindInstance }, + { "UnbindAllInstances", &LuaPlayer::UnbindAllInstances }, + { "RemoveFromBattlegroundRaid", &LuaPlayer::RemoveFromBattlegroundRaid }, + { "ResetAchievements", &LuaPlayer::ResetAchievements }, + { "KickPlayer", &LuaPlayer::KickPlayer }, + { "LogoutPlayer", &LuaPlayer::LogoutPlayer }, + { "SendTrainerList", &LuaPlayer::SendTrainerList }, + { "SendListInventory", &LuaPlayer::SendListInventory }, + { "SendShowBank", &LuaPlayer::SendShowBank }, + { "SendTabardVendorActivate", &LuaPlayer::SendTabardVendorActivate }, + { "SendSpiritResurrect", &LuaPlayer::SendSpiritResurrect }, + { "SendTaxiMenu", &LuaPlayer::SendTaxiMenu }, + { "SendUpdateWorldState", &LuaPlayer::SendUpdateWorldState }, + { "RewardQuest", &LuaPlayer::RewardQuest }, + { "SendAuctionMenu", &LuaPlayer::SendAuctionMenu }, + { "SendShowMailBox", &LuaPlayer::SendShowMailBox }, + { "StartTaxi", &LuaPlayer::StartTaxi }, + { "GossipSendPOI", &LuaPlayer::GossipSendPOI }, + { "GossipAddQuests", &LuaPlayer::GossipAddQuests }, + { "SendQuestTemplate", &LuaPlayer::SendQuestTemplate }, + { "SpawnBones", &LuaPlayer::SpawnBones }, + { "RemovedInsignia", &LuaPlayer::RemovedInsignia }, + { "SendGuildInvite", &LuaPlayer::SendGuildInvite }, + { "Mute", &LuaPlayer::Mute }, + { "SummonPlayer", &LuaPlayer::SummonPlayer }, + { "SaveToDB", &LuaPlayer::SaveToDB }, + { "GroupInvite", &LuaPlayer::GroupInvite }, + { "GroupCreate", &LuaPlayer::GroupCreate }, + { "SendCinematicStart", &LuaPlayer::SendCinematicStart }, + { "SendMovieStart", &LuaPlayer::SendMovieStart }, + + // Not implemented methods + { "GetHonorStoredKills", nullptr }, // classic only + { "GetRankPoints", nullptr }, // classic only + { "GetHonorLastWeekStandingPos", nullptr }, // classic only + + { "SetHonorStoredKills", nullptr }, // classic only + { "SetRankPoints", nullptr }, // classic only + { "SetHonorLastWeekStandingPos", nullptr }, // classic only + + { "CanFlyInZone", nullptr }, // not implemented + + { "UpdateHonor", nullptr }, // classic only + { "ResetHonor", nullptr }, // classic only + { "ClearHonorInfo", nullptr }, // classic only + { "GainSpellComboPoints", nullptr }, // not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/QuestMethods.h b/src/modules/Eluna/TrinityCore/QuestMethods.h new file mode 100644 index 0000000000..dc425cd097 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/QuestMethods.h @@ -0,0 +1,203 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef QUESTMETHODS_H +#define QUESTMETHODS_H + +/*** + * Inherits all methods from: none + */ +namespace LuaQuest +{ + /** + * Returns 'true' if the [Quest] has the specified flag, false otherwise. + * Below flags are based off of 3.3.5a. Subject to change. + * + *
+     * enum QuestFlags
+     * {
+     *     // Flags used at server and sent to client
+     *     QUEST_FLAGS_NONE                    = 0x0,
+     *     QUEST_FLAGS_STAY_ALIVE              = 0x1,       // Not used currently
+     *     QUEST_FLAGS_PARTY_ACCEPT            = 0x2,       // Not used currently. If player in party, all players that can accept this quest will receive confirmation box to accept quest CMSG_QUEST_CONFIRM_ACCEPT/SMSG_QUEST_CONFIRM_ACCEPT
+     *     QUEST_FLAGS_EXPLORATION             = 0x4,       // Not used currently
+     *     QUEST_FLAGS_SHARABLE                = 0x8,       // Can be shared: Player::CanShareQuest()
+     *     QUEST_FLAGS_HAS_CONDITION           = 0x10,      // Not used currently
+     *     QUEST_FLAGS_HIDE_REWARD_POI         = 0x20,      // Not used currently: Unsure of content
+     *     QUEST_FLAGS_RAID                    = 0x40,      // Not used currently
+     *     QUEST_FLAGS_TBC                     = 0x80,      // Not used currently: Available if TBC expansion enabled only
+     *     QUEST_FLAGS_NO_MONEY_FROM_XP        = 0x100,     // Not used currently: Experience is not converted to gold at max level
+     *     QUEST_FLAGS_HIDDEN_REWARDS          = 0x200,     // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE))
+     *     QUEST_FLAGS_TRACKING                = 0x400,     // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
+     *     QUEST_FLAGS_DEPRECATE_REPUTATION    = 0x800,     // Not used currently
+     *     QUEST_FLAGS_DAILY                   = 0x1000,    // Used to know quest is Daily one
+     *     QUEST_FLAGS_FLAGS_PVP               = 0x2000,    // Having this quest in log forces PvP flag
+     *     QUEST_FLAGS_UNAVAILABLE             = 0x4000,    // Used on quests that are not generically available
+     *     QUEST_FLAGS_WEEKLY                  = 0x8000,
+     *     QUEST_FLAGS_AUTOCOMPLETE            = 0x10000,   // auto complete
+     *     QUEST_FLAGS_DISPLAY_ITEM_IN_TRACKER = 0x20000,   // Displays usable item in quest tracker
+     *     QUEST_FLAGS_OBJ_TEXT                = 0x40000,   // use Objective text as Complete text
+     *     QUEST_FLAGS_AUTO_ACCEPT             = 0x80000,   // The client recognizes this flag as auto-accept. However, NONE of the current quests (3.3.5a) have this flag. Maybe blizz used to use it, or will use it in the future.
+     *
+     *     // ... 4.x added flags up to 0x80000000 - all unknown for now
+     * };
+     * 
+ * + * @param [QuestFlags] flag : all available flags can be seen above + * @return bool hasFlag + */ + int HasFlag(lua_State* L, Quest* quest) + { + uint32 flag = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, quest->HasFlag(flag)); + return 1; + } + + /** + * Returns 'true' if the [Quest] is a daily quest, false otherwise. + * + * @return bool isDaily + */ + int IsDaily(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->IsDaily()); + return 1; + } + + /** + * Returns 'true' if the [Quest] is repeatable, false otherwise. + * + * @return bool isRepeatable + */ + int IsRepeatable(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->IsRepeatable()); + return 1; + } + + /** + * Returns entry ID of the [Quest]. + * + * @return uint32 entryId + */ + int GetId(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetQuestId()); + return 1; + } + + /** + * Returns the [Quest]'s level. + * + * @return uint32 level + */ + int GetLevel(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetQuestLevel()); + return 1; + } + + /** + * Returns the minimum level required to pick up the [Quest]. + * + * @return uint32 minLevel + */ + int GetMinLevel(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetMinLevel()); + return 1; + } + + /** + * Returns the next [Quest] entry ID. + * + * @return int32 entryId + */ + int GetNextQuestId(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetNextQuestId()); + return 1; + } + + /** + * Returns the previous [Quest] entry ID. + * + * @return int32 entryId + */ + int GetPrevQuestId(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetPrevQuestId()); + return 1; + } + + /** + * Returns the next [Quest] entry ID in the specific [Quest] chain. + * + * @return int32 entryId + */ + int GetNextQuestInChain(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetNextQuestInChain()); + return 1; + } + + /** + * Returns the [Quest]'s flags. + * + * @return [QuestFlags] flags + */ + int GetFlags(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetFlags()); + return 1; + } + + /** + * Returns the [Quest]'s type. + * + * TODO: Document types available. + * + * @return uint32 type + */ + int GetType(lua_State* L, Quest* quest) + { +#ifdef CATA + Eluna::Push(L, quest->GetQuestType()); +#else + Eluna::Push(L, quest->GetType()); +#endif + return 1; + } + + int GetMaxLevel(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetMaxLevel()); + return 1; + } + + ElunaRegister QuestMethods[] = + { + // Getters + { "GetId", &LuaQuest::GetId }, + { "GetLevel", &LuaQuest::GetLevel }, + { "GetMaxLevel", &LuaQuest::GetMaxLevel }, + { "GetMinLevel", &LuaQuest::GetMinLevel }, + { "GetNextQuestId", &LuaQuest::GetNextQuestId }, + { "GetPrevQuestId", &LuaQuest::GetPrevQuestId }, + { "GetNextQuestInChain", &LuaQuest::GetNextQuestInChain }, + { "GetFlags", &LuaQuest::GetFlags }, + { "GetType", &LuaQuest::GetType }, + + // Boolean + { "HasFlag", &LuaQuest::HasFlag }, + { "IsDaily", &LuaQuest::IsDaily }, + { "IsRepeatable", &LuaQuest::IsRepeatable }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/SpellMethods.h b/src/modules/Eluna/TrinityCore/SpellMethods.h new file mode 100644 index 0000000000..c4389319e4 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/SpellMethods.h @@ -0,0 +1,198 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef SPELLMETHODS_H +#define SPELLMETHODS_H + +/*** + * An instance of a spell, created when the spell is cast by a [Unit]. + * + * Inherits all methods from: none + */ +namespace LuaSpell +{ + /** + * Returns `true` if the [Spell] is automatically repeating, `false` otherwise. + * + * @return bool isAutoRepeating + */ + int IsAutoRepeat(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->IsAutoRepeat()); + return 1; + } + + /** + * Returns the [Unit] that casted the [Spell]. + * + * @return [Unit] caster + */ + int GetCaster(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->GetCaster()); + return 1; + } + + /** + * Returns the cast time of the [Spell]. + * + * @return int32 castTime + */ + int GetCastTime(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->GetCastTime()); + return 1; + } + + /** + * Returns the entry ID of the [Spell]. + * + * @return uint32 entryId + */ + int GetEntry(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->m_spellInfo->Id); + return 1; + } + + /** + * Returns the power cost of the [Spell]. + * + * @return uint32 powerCost + */ + int GetPowerCost(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->GetPowerCost()); + return 1; + } + + /** + * Returns the spell duration of the [Spell]. + * + * @return int32 duration + */ + int GetDuration(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->GetSpellInfo()->GetDuration()); + return 1; + } + + /** + * Returns the target destination coordinates of the [Spell]. + * + * @return float x : x coordinate of the [Spell] + * @return float y : y coordinate of the [Spell] + * @return float z : z coordinate of the [Spell] + */ + int GetTargetDest(lua_State* L, Spell* spell) + { + if (!spell->m_targets.HasDst()) + return 3; + + float x, y, z; + spell->m_targets.GetDstPos()->GetPosition(x, y, z); + + Eluna::Push(L, x); + Eluna::Push(L, y); + Eluna::Push(L, z); + return 3; + } + + /** + * Returns the target [Object] of the [Spell]. + * + * The target can be any of the following [Object] types: + * - [Player] + * - [Creature] + * - [GameObject] + * - [Item] + * - [Corpse] + * + * @return [Object] target + */ + int GetTarget(lua_State* L, Spell* spell) + { + if (GameObject* target = spell->m_targets.GetGOTarget()) + Eluna::Push(L, target); + else if (Item* target = spell->m_targets.GetItemTarget()) + Eluna::Push(L, target); + else if (Corpse* target = spell->m_targets.GetCorpseTarget()) + Eluna::Push(L, target); + else if (Unit* target = spell->m_targets.GetUnitTarget()) + Eluna::Push(L, target); + else if (WorldObject* target = spell->m_targets.GetObjectTarget()) + Eluna::Push(L, target); + return 1; + } + + /** + * Sets the [Spell] to automatically repeat. + * + * @param bool repeat : set variable to 'true' for spell to automatically repeat + */ + int SetAutoRepeat(lua_State* L, Spell* spell) + { + bool repeat = Eluna::CHECKVAL(L, 2); + spell->SetAutoRepeat(repeat); + return 0; + } + + /** + * Casts the [Spell]. + * + * @param bool skipCheck = false : skips initial checks to see if the [Spell] can be casted or not, this is optional + */ + int Cast(lua_State* L, Spell* spell) + { + bool skipCheck = Eluna::CHECKVAL(L, 2, false); + spell->cast(skipCheck); + return 0; + } + + /** + * Cancels the [Spell]. + */ + int Cancel(lua_State* /*L*/, Spell* spell) + { + spell->cancel(); + return 0; + } + + /** + * Finishes the [Spell]. + */ + int Finish(lua_State* /*L*/, Spell* spell) + { + spell->finish(); + return 0; + } + + ElunaRegister SpellMethods[] = + { + // Getters + { "GetCaster", &LuaSpell::GetCaster }, + { "GetCastTime", &LuaSpell::GetCastTime }, + { "GetEntry", &LuaSpell::GetEntry }, + { "GetDuration", &LuaSpell::GetDuration }, + { "GetPowerCost", &LuaSpell::GetPowerCost }, + { "GetTargetDest", &LuaSpell::GetTargetDest }, + { "GetTarget", &LuaSpell::GetTarget }, + + // Setters + { "SetAutoRepeat", &LuaSpell::SetAutoRepeat }, + + // Boolean + { "IsAutoRepeat", &LuaSpell::IsAutoRepeat }, + + // Other + { "Cancel", &LuaSpell::Cancel }, + { "Cast", &LuaSpell::Cast }, + { "Finish", &LuaSpell::Finish }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/UnitMethods.h b/src/modules/Eluna/TrinityCore/UnitMethods.h new file mode 100644 index 0000000000..24183c81f7 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/UnitMethods.h @@ -0,0 +1,2711 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef UNITMETHODS_H +#define UNITMETHODS_H + +/*** + * Inherits all methods from: [Object], [WorldObject] + */ +namespace LuaUnit +{ + /** + * The [Unit] tries to attack a given target + * + * @param [Unit] who : [Unit] to attack + * @param bool meleeAttack = false: attack with melee or not + * @return didAttack : if the [Unit] did not attack + */ + int Attack(lua_State* L, Unit* unit) + { + Unit* who = Eluna::CHECKOBJ(L, 2); + bool meleeAttack = Eluna::CHECKVAL(L, 3, false); + + Eluna::Push(L, unit->Attack(who, meleeAttack)); + return 1; + } + + /** + * The [Unit] stops attacking its target + * + * @return bool isAttacking : if the [Unit] wasn't attacking already + */ + int AttackStop(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->AttackStop()); + return 1; + } + + /** + * Returns true if the [Unit] is standing. + * + * @return bool isStanding + */ + int IsStandState(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsStandState()); + return 1; + } + + /** + * Returns true if the [Unit] is mounted. + * + * @return bool isMounted + */ + int IsMounted(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsMounted()); + return 1; + } + + /** + * Returns true if the [Unit] is rooted. + * + * @return bool isRooted + */ + int IsRooted(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsRooted() || unit->HasUnitMovementFlag(MOVEMENTFLAG_ROOT)); + return 1; + } + + /** + * Returns true if the [Unit] has full health. + * + * @return bool hasFullHealth + */ + int IsFullHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsFullHealth()); + return 1; + } + + /** + * Returns true if the [Unit] is in an accessible place for the given [Creature]. + * + * @param [WorldObject] obj + * @param float radius + * @return bool isAccessible + */ + int IsInAccessiblePlaceFor(lua_State* L, Unit* unit) + { + Creature* creature = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, unit->isInAccessiblePlaceFor(creature)); + return 1; + } + + /** + * Returns true if the [Unit] an auctioneer. + * + * @return bool isAuctioneer + */ + int IsAuctioneer(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsAuctioner()); + return 1; + } + + /** + * Returns true if the [Unit] a guild master. + * + * @return bool isGuildMaster + */ + int IsGuildMaster(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsGuildMaster()); + return 1; + } + + /** + * Returns true if the [Unit] an innkeeper. + * + * @return bool isInnkeeper + */ + int IsInnkeeper(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsInnkeeper()); + return 1; + } + + /** + * Returns true if the [Unit] a trainer. + * + * @return bool isTrainer + */ + int IsTrainer(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsTrainer()); + return 1; + } + + /** + * Returns true if the [Unit] is able to show a gossip window. + * + * @return bool hasGossip + */ + int IsGossip(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsGossip()); + return 1; + } + + /** + * Returns true if the [Unit] is a taxi master. + * + * @return bool isTaxi + */ + int IsTaxi(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsTaxi()); + return 1; + } + + /** + * Returns true if the [Unit] is a spirit healer. + * + * @return bool isSpiritHealer + */ + int IsSpiritHealer(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsSpiritHealer()); + return 1; + } + + /** + * Returns true if the [Unit] is a spirit guide. + * + * @return bool isSpiritGuide + */ + int IsSpiritGuide(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsSpiritGuide()); + return 1; + } + + /** + * Returns true if the [Unit] is a tabard designer. + * + * @return bool isTabardDesigner + */ + int IsTabardDesigner(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsTabardDesigner()); + return 1; + } + + /** + * Returns true if the [Unit] provides services like vendor, training and auction. + * + * @return bool isTabardDesigner + */ + int IsServiceProvider(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsServiceProvider()); + return 1; + } + + /** + * Returns true if the [Unit] is a spirit guide or spirit healer. + * + * @return bool isSpiritService + */ + int IsSpiritService(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsSpiritService()); + return 1; + } + + /** + * Returns true if the [Unit] is alive. + * + * @return bool isAlive + */ + int IsAlive(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsAlive()); + return 1; + } + + /** + * Returns true if the [Unit] is dead. + * + * @return bool isDead + */ + int IsDead(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isDead()); + return 1; + } + + /** + * Returns true if the [Unit] is dying. + * + * @return bool isDying + */ + int IsDying(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isDying()); + return 1; + } + + /** + * Returns true if the [Unit] is a banker. + * + * @return bool isBanker + */ + int IsBanker(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsBanker()); + return 1; + } + + /** + * Returns true if the [Unit] is a vendor. + * + * @return bool isVendor + */ + int IsVendor(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsVendor()); + return 1; + } + + /** + * Returns true if the [Unit] is a battle master. + * + * @return bool isBattleMaster + */ + int IsBattleMaster(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsBattleMaster()); + return 1; + } + + /** + * Returns true if the [Unit] is a charmed. + * + * @return bool isCharmed + */ + int IsCharmed(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsCharmed()); + return 1; + } + + /** + * Returns true if the [Unit] is an armorer and can repair equipment. + * + * @return bool isArmorer + */ + int IsArmorer(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsArmorer()); + return 1; + } + + /** + * Returns true if the [Unit] is attacking a player. + * + * @return bool isAttackingPlayer + */ + int IsAttackingPlayer(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isAttackingPlayer()); + return 1; + } + + /** + * Returns true if the [Unit] flagged for PvP. + * + * @return bool isPvP + */ + int IsPvPFlagged(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsPvP()); + return 1; + } + + /** + * Returns true if the [Unit] is on a [Vehicle]. + * + * @return bool isOnVehicle + */ + int IsOnVehicle(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetVehicle()); + return 1; + } + + /** + * Returns true if the [Unit] is in combat. + * + * @return bool inCombat + */ + int IsInCombat(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsInCombat()); + return 1; + } + + /** + * Returns true if the [Unit] is under water. + * + * @return bool underWater + */ + int IsUnderWater(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsUnderWater()); + return 1; + } + + /** + * Returns true if the [Unit] is in water. + * + * @return bool inWater + */ + int IsInWater(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsInWater()); + return 1; + } + + /** + * Returns true if the [Unit] is not moving. + * + * @return bool notMoving + */ + int IsStopped(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsStopped()); + return 1; + } + + /** + * Returns true if the [Unit] is a quest giver. + * + * @return bool questGiver + */ + int IsQuestGiver(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsQuestGiver()); + return 1; + } + + /** + * Returns true if the [Unit]'s health is below the given percentage. + * + * @param int32 healthpct : percentage in integer from + * @return bool isBelow + */ + int HealthBelowPct(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->HealthBelowPct(Eluna::CHECKVAL(L, 2))); + return 1; + } + + /** + * Returns true if the [Unit]'s health is above the given percentage. + * + * @param int32 healthpct : percentage in integer from + * @return bool isAbove + */ + int HealthAbovePct(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->HealthAbovePct(Eluna::CHECKVAL(L, 2))); + return 1; + } + + /** + * Returns true if the [Unit] has an aura from the given spell entry. + * + * @param uint32 spell : entry of the aura spell + * @return bool hasAura + */ + int HasAura(lua_State* L, Unit* unit) + { + uint32 spell = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, unit->HasAura(spell)); + return 1; + } + + /** + * Returns true if the [Unit] is casting a spell + * + * @return bool isCasting + */ + int IsCasting(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->HasUnitState(UNIT_STATE_CASTING)); + return 1; + } + + /** + * Returns true if the [Unit] has the given unit state. + * + * @param [UnitState] state : an unit state + * @return bool hasState + */ + int HasUnitState(lua_State* L, Unit* unit) + { + uint32 state = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, unit->HasUnitState(state)); + return 1; + } + + int IsVisible(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsVisible()); + return 1; + } + + int IsMoving(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isMoving()); + return 1; + } + + int IsFlying(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsFlying()); + return 1; + } + + /** + * Returns the [Unit]'s owner. + * + * @return [Unit] owner + */ + int GetOwner(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetOwner()); + return 1; + } + + /** + * Returns the [Unit]'s owner's GUID. + * + * @return ObjectGuid ownerGUID + */ + int GetOwnerGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetOwnerGUID()); + return 1; + } + + /** + * Returns the [Unit]'s mount's modelID. + * + * @return uint32 mountId : displayId of the mount + */ + int GetMountId(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetMountDisplayId()); + return 1; + } + + /** + * Returns the [Unit]'s creator's GUID. + * + * @return ObjectGuid creatorGUID + */ + int GetCreatorGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCreatorGUID()); + return 1; + } + + /** + * Returns the [Unit]'s charmer's GUID. + * + * @return ObjectGuid charmerGUID + */ + int GetCharmerGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCharmerGUID()); + return 1; + } + + /** + * Returns the GUID of the [Unit]'s charmed entity. + * + * @return ObjectGuid charmedGUID + */ + int GetCharmGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCharmedGUID()); + return 1; + } + + /** + * Returns the GUID of the [Unit]'s pet. + * + * @return ObjectGuid petGUID + */ + int GetPetGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetPetGUID()); + return 1; + } + + /** + * Returns the GUID of the [Unit]'s charmer or owner. + * + * @return ObjectGuid controllerGUID + */ + int GetControllerGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCharmerOrOwnerGUID()); + return 1; + } + + /** + * Returns the GUID of the [Unit]'s charmer or owner or its own GUID. + * + * @return ObjectGuid controllerGUID + */ + int GetControllerGUIDS(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCharmerOrOwnerOrOwnGUID()); + return 1; + } + + /** + * Returns [Unit]'s specified stat + * + * @param uint32 statType + * @return float stat + */ + int GetStat(lua_State* L, Unit* unit) + { + uint32 stat = Eluna::CHECKVAL(L, 2); + + if (stat >= MAX_STATS) + return 1; + + Eluna::Push(L, unit->GetStat((Stats)stat)); + return 1; + } + + /** + * Returns the [Unit]'s base spell power + * + * @param uint32 spellSchool + * @return uint32 spellPower + */ + int GetBaseSpellPower(lua_State* L, Unit* unit) + { + uint32 spellschool = Eluna::CHECKVAL(L, 2); + + if (spellschool >= MAX_SPELL_SCHOOL) + return 1; + + Eluna::Push(L, unit->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + spellschool)); + return 1; + } + + /** + * Returns the [Unit]'s current victim target or nil. + * + * @return [Unit] victim + */ + int GetVictim(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetVictim()); + return 1; + } + + /** + * Returns the currently casted [Spell] of given type or nil. + * + *
+     * enum CurrentSpellTypes
+     * {
+     *     CURRENT_MELEE_SPELL             = 0,
+     *     CURRENT_GENERIC_SPELL           = 1,
+     *     CURRENT_CHANNELED_SPELL         = 2,
+     *     CURRENT_AUTOREPEAT_SPELL        = 3
+     * };
+     * 
+ * + * @param [CurrentSpellTypes] spellType + * @return [Spell] castedSpell + */ + int GetCurrentSpell(lua_State* L, Unit* unit) + { + uint32 type = Eluna::CHECKVAL(L, 2); + if (type >= CURRENT_MAX_SPELL) + return luaL_argerror(L, 2, "valid CurrentSpellTypes expected"); + + Eluna::Push(L, unit->GetCurrentSpell(type)); + return 1; + } + + /** + * Returns the [Unit]'s current stand state. + * + * @return uint8 standState + */ + int GetStandState(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetStandState()); + return 1; + } + + /** + * Returns the [Unit]'s current display ID. + * + * @return uint32 displayId + */ + int GetDisplayId(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetDisplayId()); + return 1; + } + + /** + * Returns the [Unit]'s native/original display ID. + * + * @return uint32 displayId + */ + int GetNativeDisplayId(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetNativeDisplayId()); + return 1; + } + + /** + * Returns the [Unit]'s level. + * + * @return uint8 level + */ + int GetLevel(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetLevel()); + return 1; + } + + /** + * Returns the [Unit]'s health amount. + * + * @return uint32 healthAmount + */ + int GetHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetHealth()); + return 1; + } + + Powers PowerSelectorHelper(lua_State* L, Unit* unit, int powerType = -1) + { + if (powerType == -1) + return unit->GetPowerType(); + + if (powerType < 0 || powerType >= int(MAX_POWERS)) + luaL_argerror(L, 2, "valid Powers expected"); + + return (Powers)powerType; + } + + /** + * Returns the [Unit]'s power amount for given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + * @return uint32 powerAmount + */ + int GetPower(lua_State* L, Unit* unit) + { + int type = Eluna::CHECKVAL(L, 2, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + Eluna::Push(L, unit->GetPower(power)); + return 1; + } + + /** + * Returns the [Unit]'s max power amount for given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + * @return uint32 maxPowerAmount + */ + int GetMaxPower(lua_State* L, Unit* unit) + { + int type = Eluna::CHECKVAL(L, 2, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + Eluna::Push(L, unit->GetMaxPower(power)); + return 1; + } + + /** + * Returns the [Unit]'s power percent for given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + * @return float powerPct + */ + int GetPowerPct(lua_State* L, Unit* unit) + { + int type = Eluna::CHECKVAL(L, 2, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + float percent = ((float)unit->GetPower(power) / (float)unit->GetMaxPower(power)) * 100.0f; + + Eluna::Push(L, percent); + return 1; + } + + /** + * Returns the [Unit]'s current power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @return [Powers] powerType + */ + int GetPowerType(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetPowerType()); + return 1; + } + + /** + * Returns the [Unit]'s max health. + * + * @return uint32 maxHealth + */ + int GetMaxHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetMaxHealth()); + return 1; + } + + /** + * Returns the [Unit]'s health percent. + * + * @return float healthPct + */ + int GetHealthPct(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetHealthPct()); + return 1; + } + + /** + * Returns the [Unit]'s gender. + * + * @return uint8 gender : 0 for male, 1 for female and 2 for none + */ + int GetGender(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetGender()); + return 1; + } + + /** + * Returns the [Unit]'s race ID. + * + * @return [Races] race + */ + int GetRace(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetRace()); + return 1; + } + + /** + * Returns the [Unit]'s class ID. + * + * @return [Classes] class + */ + int GetClass(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetClass()); + return 1; + } + + /** + * Returns the race mask + * + * @return uint32 racemask + */ + int GetRaceMask(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetRaceMask()); + return 1; + } + + /** + * Returns the class mask + * + * @return uint32 classmask + */ + int GetClassMask(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetClassMask()); + return 1; + } + + /** + * Returns the [Unit]'s creature type ID (enumerated in CreatureType.dbc). + * + *
+     * enum CreatureType
+     * {
+     *     CREATURE_TYPE_BEAST            = 1,
+     *     CREATURE_TYPE_DRAGONKIN        = 2,
+     *     CREATURE_TYPE_DEMON            = 3,
+     *     CREATURE_TYPE_ELEMENTAL        = 4,
+     *     CREATURE_TYPE_GIANT            = 5,
+     *     CREATURE_TYPE_UNDEAD           = 6,
+     *     CREATURE_TYPE_HUMANOID         = 7,
+     *     CREATURE_TYPE_CRITTER          = 8,
+     *     CREATURE_TYPE_MECHANICAL       = 9,
+     *     CREATURE_TYPE_NOT_SPECIFIED    = 10,
+     *     CREATURE_TYPE_TOTEM            = 11,
+     *     CREATURE_TYPE_NON_COMBAT_PET   = 12,     // This and below is TBC+
+     *     CREATURE_TYPE_GAS_CLOUD        = 13
+     * };
+     * 
+ * + * @return [CreatureType] creatureType + */ + int GetCreatureType(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCreatureType()); + return 1; + } + + /** + * Returns the [Unit]'s class' name in given or default locale or nil. + * + *
+     * enum LocaleConstant
+     * {
+     *     LOCALE_enUS = 0,
+     *     LOCALE_koKR = 1,
+     *     LOCALE_frFR = 2,
+     *     LOCALE_deDE = 3,
+     *     LOCALE_zhCN = 4,
+     *     LOCALE_zhTW = 5,
+     *     LOCALE_esES = 6,
+     *     LOCALE_esMX = 7,
+     *     LOCALE_ruRU = 8
+     * };
+     * 
+ * + * @param [LocaleConstant] locale = DEFAULT_LOCALE + * @return string className : class name or nil + */ + int GetClassAsString(lua_State* L, Unit* unit) + { + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const ChrClassesEntry* entry = sChrClassesStore.LookupEntry(unit->GetClass()); + if (!entry) + return 1; + + Eluna::Push(L, entry->Name[locale]); + return 1; + } + + /** + * Returns the [Unit]'s race's name in given or default locale or nil. + * + *
+     * enum LocaleConstant
+     * {
+     *     LOCALE_enUS = 0,
+     *     LOCALE_koKR = 1,
+     *     LOCALE_frFR = 2,
+     *     LOCALE_deDE = 3,
+     *     LOCALE_zhCN = 4,
+     *     LOCALE_zhTW = 5,
+     *     LOCALE_esES = 6,
+     *     LOCALE_esMX = 7,
+     *     LOCALE_ruRU = 8
+     * };
+     * 
+ * + * @param [LocaleConstant] locale = DEFAULT_LOCALE : locale to return the race name in + * @return string raceName : race name or nil + */ + int GetRaceAsString(lua_State* L, Unit* unit) + { + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const ChrRacesEntry* entry = sChrRacesStore.LookupEntry(unit->GetRace()); + if (!entry) + return 1; + + Eluna::Push(L, entry->Name[locale]); + return 1; + } + + /** + * Returns the [Unit]'s faction ID. + * + * @return uint32 faction + */ + int GetFaction(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetFaction()); + return 1; + } + + /** + * Returns the [Aura] of the given spell entry on the [Unit] or nil. + * + * @param uint32 spellID : entry of the aura spell + * @return [Aura] aura : aura object or nil + */ + int GetAura(lua_State* L, Unit* unit) + { + uint32 spellID = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, unit->GetAura(spellID)); + return 1; + } + + /** + * Returns a table containing friendly [Unit]'s within given range of the [Unit]. + * + * @param float range = 533.333 : search radius + * @return table friendyUnits : table filled with friendly units + */ + int GetFriendlyUnitsInRange(lua_State* L, Unit* unit) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + + std::list list; + Trinity::AnyFriendlyUnitInObjectRangeCheck checker(unit, unit, range); + Trinity::UnitListSearcher searcher(unit, list, checker); + Cell::VisitAllObjects(unit, searcher, range); + + ElunaUtil::ObjectGUIDCheck guidCheck(unit->GET_GUID()); + list.remove_if(guidCheck); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns a table containing unfriendly [Unit]'s within given range of the [Unit]. + * + * @param float range = 533.333 : search radius + * @return table unfriendyUnits : table filled with unfriendly units + */ + int GetUnfriendlyUnitsInRange(lua_State* L, Unit* unit) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + + std::list list; + Trinity::AnyUnfriendlyUnitInObjectRangeCheck checker(unit, unit, range); + Trinity::UnitListSearcher searcher(unit, list, checker); + Cell::VisitAllObjects(unit, searcher, range); + + ElunaUtil::ObjectGUIDCheck guidCheck(unit->GET_GUID()); + list.remove_if(guidCheck); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns [Unit]'s [Vehicle] methods + * + * @return [Vehicle] vehicle + */ + int GetVehicleKit(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetVehicleKit()); + return 1; + } + + int GetVehicle(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetVehicle()); + return 1; + } + + /** + * Returns the Critter Guid + * + * @return ObjectGuid critterGuid + */ + int GetCritterGUID(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCritterGUID()); + return 1; + } + + /** + * Returns the [Unit]'s speed of given [UnitMoveType]. + * + *
+     * enum UnitMoveType
+     * {
+     *     MOVE_WALK           = 0,
+     *     MOVE_RUN            = 1,
+     *     MOVE_RUN_BACK       = 2,
+     *     MOVE_SWIM           = 3,
+     *     MOVE_SWIM_BACK      = 4,
+     *     MOVE_TURN_RATE      = 5,
+     *     MOVE_FLIGHT         = 6,
+     *     MOVE_FLIGHT_BACK    = 7,
+     *     MOVE_PITCH_RATE     = 8
+     * };
+     * 
+ * + * @param [UnitMoveType] type + * @return float speed + */ + int GetSpeed(lua_State* L, Unit* unit) + { + uint32 type = Eluna::CHECKVAL(L, 2); + if (type >= MAX_MOVE_TYPE) + return luaL_argerror(L, 2, "valid UnitMoveType expected"); + + Eluna::Push(L, unit->GetSpeed((UnitMoveType)type)); + return 1; + } + + /** + * Returns the current movement type for this [Unit]. + * + *
+     * enum MovementGeneratorType
+     * {
+     *     IDLE_MOTION_TYPE                = 0,
+     *     RANDOM_MOTION_TYPE              = 1,
+     *     WAYPOINT_MOTION_TYPE            = 2,
+     *     MAX_DB_MOTION_TYPE              = 3,
+     *     ANIMAL_RANDOM_MOTION_TYPE       = 3, // TC
+     *
+     *     CONFUSED_MOTION_TYPE            = 4,
+     *     CHASE_MOTION_TYPE               = 5,
+     *     HOME_MOTION_TYPE                = 6,
+     *     FLIGHT_MOTION_TYPE              = 7,
+     *     POINT_MOTION_TYPE               = 8,
+     *     FLEEING_MOTION_TYPE             = 9,
+     *     DISTRACT_MOTION_TYPE            = 10,
+     *     ASSISTANCE_MOTION_TYPE          = 11,
+     *     ASSISTANCE_DISTRACT_MOTION_TYPE = 12,
+     *     TIMED_FLEEING_MOTION_TYPE       = 13,
+     *     FOLLOW_MOTION_TYPE              = 14,
+     *     EFFECT_MOTION_TYPE              = 15, // mangos
+     *     ROTATE_MOTION_TYPE              = 15, // TC
+     *     EFFECT_MOTION_TYPE              = 16, // TC
+     *     NULL_MOTION_TYPE                = 17, // TC
+     * };
+     * 
+ * + * @return [MovementGeneratorType] movementType + */ + int GetMovementType(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetMotionMaster()->GetCurrentMovementGeneratorType()); + return 1; + } + + /** + * Sets the [Unit]'s owner GUID to given GUID. + * + * @param ObjectGuid guid : new owner guid + */ + int SetOwnerGUID(lua_State* L, Unit* unit) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + + unit->SetOwnerGUID(guid); + return 0; + } + + /** + * Sets the [Unit]'s PvP on or off. + * + * @param bool apply = true : true if set on, false if off + */ + int SetPvP(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + unit->SetPvP(apply); + return 0; + } + + /** + * Sets the [Unit]'s sheath state. + * + * enum SheathState + * { + * SHEATH_STATE_UNARMED = 0, // non prepared weapon + * SHEATH_STATE_MELEE = 1, // prepared melee weapon + * SHEATH_STATE_RANGED = 2 // prepared ranged weapon + * }; + * + * @param [SheathState] sheathState : valid SheathState + */ + int SetSheath(lua_State* L, Unit* unit) + { + uint32 sheathed = Eluna::CHECKVAL(L, 2); + if (sheathed >= MAX_SHEATH_STATE) + return luaL_argerror(L, 2, "valid SheathState expected"); + + unit->SetSheath((SheathState)sheathed); + return 0; + } + + /** + * Sets the [Unit]'s name internally. + * + * @param string name : new name + */ + int SetName(lua_State* L, Unit* unit) + { + const char* name = Eluna::CHECKVAL(L, 2); + if (std::string(name).length() > 0) + unit->SetName(name); + return 0; + } + + /** + * Sets the [Unit]'s speed of given [UnitMoveType] to given rate. + * If forced, packets sent to clients forcing the visual change. + * + *
+     * enum UnitMoveType
+     * {
+     *     MOVE_WALK           = 0,
+     *     MOVE_RUN            = 1,
+     *     MOVE_RUN_BACK       = 2,
+     *     MOVE_SWIM           = 3,
+     *     MOVE_SWIM_BACK      = 4,
+     *     MOVE_TURN_RATE      = 5,
+     *     MOVE_FLIGHT         = 6,
+     *     MOVE_FLIGHT_BACK    = 7,
+     *     MOVE_PITCH_RATE     = 8
+     * };
+     * 
+ * + * @param [UnitMoveType] type + * @param float rate + * @param bool forced = false + */ + int SetSpeed(lua_State* L, Unit* unit) + { + uint32 type = Eluna::CHECKVAL(L, 2); + float rate = Eluna::CHECKVAL(L, 3); + bool forced = Eluna::CHECKVAL(L, 4, false); + (void)forced; // ensure that the variable is referenced in order to pass compiler checks + if (type >= MAX_MOVE_TYPE) + return luaL_argerror(L, 2, "valid UnitMoveType expected"); + + unit->SetSpeedRate((UnitMoveType)type, rate); + return 0; + } + + /** + * Sets the [Unit]'s faction. + * + * @param uint32 faction : new faction ID + */ + int SetFaction(lua_State* L, Unit* unit) + { + uint32 factionId = Eluna::CHECKVAL(L, 2); + + unit->SetFaction(factionId); + return 0; + } + + /** + * Sets the [Unit]'s level. + * + * @param uint8 level : new level + */ + int SetLevel(lua_State* L, Unit* unit) + { + uint8 newlevel = Eluna::CHECKVAL(L, 2); + + if (newlevel < 1) + return luaL_argerror(L, 2, "level cannot be below 1"); + + if (Player* player = unit->ToPlayer()) + { + player->GiveLevel(newlevel); + player->InitTalentForLevel(); + player->SetUInt32Value(PLAYER_XP, 0); + } + else + unit->SetLevel(newlevel); + + return 0; + } + + /** + * Sets the [Unit]'s health. + * + * @param uint32 health : new health + */ + int SetHealth(lua_State* L, Unit* unit) + { + uint32 amt = Eluna::CHECKVAL(L, 2); + unit->SetHealth(amt); + return 0; + } + + /** + * Sets the [Unit]'s max health. + * + * @param uint32 maxHealth : new max health + */ + int SetMaxHealth(lua_State* L, Unit* unit) + { + uint32 amt = Eluna::CHECKVAL(L, 2); + unit->SetMaxHealth(amt); + return 0; + } + + /** + * Sets the [Unit]'s power amount for the given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param uint32 amount : new power amount + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + */ + int SetPower(lua_State* L, Unit* unit) + { + uint32 amt = Eluna::CHECKVAL(L, 2); + int type = Eluna::CHECKVAL(L, 3, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + unit->SetPower(power, amt); + return 0; + } + + /** + * modifies the [Unit]'s power amount for the given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int32 amount : amount to modify + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + */ + int ModifyPower(lua_State* L, Unit* unit) + { + int32 amt = Eluna::CHECKVAL(L, 2); + int type = Eluna::CHECKVAL(L, 3, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + unit->ModifyPower(power, amt); + return 0; + } + + /** + * Sets the [Unit]'s max power amount for the given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + * @param uint32 maxPower : new max power amount + */ + int SetMaxPower(lua_State* L, Unit* unit) + { + int type = Eluna::CHECKVAL(L, 2, -1); + uint32 amt = Eluna::CHECKVAL(L, 3); + Powers power = PowerSelectorHelper(L, unit, type); + + unit->SetMaxPower(power, amt); + return 0; + } + + /** + * Sets the [Unit]'s power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param [Powers] type : a valid power type + */ + int SetPowerType(lua_State* L, Unit* unit) + { + uint32 type = Eluna::CHECKVAL(L, 2); + if (type >= int(MAX_POWERS)) + return luaL_argerror(L, 2, "valid Powers expected"); + + unit->SetPowerType((Powers)type); + return 0; + } + + /** + * Sets the [Unit]'s modelID. + * + * @param uint32 displayId + */ + int SetDisplayId(lua_State* L, Unit* unit) + { + uint32 model = Eluna::CHECKVAL(L, 2); + unit->SetDisplayId(model); + return 0; + } + + /** + * Sets the [Unit]'s native/default modelID. + * + * @param uint32 displayId + */ + int SetNativeDisplayId(lua_State* L, Unit* unit) + { + uint32 model = Eluna::CHECKVAL(L, 2); +#ifndef CATA + unit->SetNativeDisplayId(model); +#else + unit->SetDisplayId(model, true); +#endif + return 0; + } + + /** + * Sets the [Unit]'s facing/orientation. + * + * @param uint32 orientation + */ + int SetFacing(lua_State* L, Unit* unit) + { + float o = Eluna::CHECKVAL(L, 2); + unit->SetFacingTo(o); + return 0; + } + + /** + * Sets the [Unit] to face the given [WorldObject]'s direction. + * + * @param [WorldObject] target + */ + int SetFacingToObject(lua_State* L, Unit* unit) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + unit->SetFacingToObject(obj); + return 0; + } + + /** + * Sets creator GUID + * + * @param ObjectGuid guid + */ + int SetCreatorGUID(lua_State* L, Unit* unit) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + + unit->SetCreatorGUID(guid); + return 0; + } + + /** + * Sets pet GUID + * + * @param ObjectGuid guid + */ + int SetPetGUID(lua_State* L, Unit* unit) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + + unit->SetPetGUID(guid); + return 0; + } + + /** + * Toggles (Sets) [Unit]'s water walking + * + * @param bool enable = true + */ + int SetWaterWalk(lua_State* L, Unit* unit) + { + bool enable = Eluna::CHECKVAL(L, 2, true); + + unit->SetWaterWalking(enable); + return 0; + } + + /** + * Sets the [Unit]'s stand state + * + * @param uint8 state : stand state + */ + int SetStandState(lua_State* L, Unit* unit) + { + uint8 state = Eluna::CHECKVAL(L, 2); + + unit->SetStandState(UnitStandStateType(state)); + return 0; + } + + /** + * Sets the [Unit] in combat with the `enemy` [Unit]. + * + * @param [Unit] enemy : the [Unit] to start combat with + */ + int SetInCombatWith(lua_State* L, Unit* unit) + { + Unit* enemy = Eluna::CHECKOBJ(L, 2); + unit->SetInCombatWith(enemy); + return 0; + } + + /** + * Sets the [Unit]'s FFA flag on or off. + * + * @param bool apply = true + */ + int SetFFA(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + if (apply) + { + unit->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + for (Unit::ControlList::iterator itr = unit->m_Controlled.begin(); itr != unit->m_Controlled.end(); ++itr) + (*itr)->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + } + else + { + unit->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + for (Unit::ControlList::iterator itr = unit->m_Controlled.begin(); itr != unit->m_Controlled.end(); ++itr) + (*itr)->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + } + + return 0; + } + + /** + * Sets the [Unit]'s sanctuary flag on or off. + * + * @param bool apply = true + */ + int SetSanctuary(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + if (apply) + { + unit->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY); + unit->CombatStop(); + unit->CombatStopWithPets(); + } + else + unit->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY); + + return 0; + } + + int SetCritterGUID(lua_State* L, Unit* unit) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + unit->SetCritterGUID(guid); + return 0; + } + + + int SetStunned(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + unit->SetControlled(apply, UNIT_STATE_STUNNED); + return 0; + } + + /** + * Roots the [Unit] to the ground, if 'false' specified, unroots the [Unit]. + * + * @param bool apply = true + */ + int SetRooted(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + unit->SetControlled(apply, UNIT_STATE_ROOT); + return 0; + } + + /** + * Confuses the [Unit], if 'false' specified, the [Unit] is no longer confused. + * + * @param bool apply = true + */ + int SetConfused(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + unit->SetControlled(apply, UNIT_STATE_CONFUSED); + return 0; + } + + /** + * Fears the [Unit], if 'false' specified, the [Unit] is no longer feared. + * + * @param bool apply = true + */ + int SetFeared(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + unit->SetControlled(apply, UNIT_STATE_FLEEING); + return 0; + } + + int SetCanFly(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + unit->SetCanFly(apply); + return 0; + } + + int SetVisible(lua_State* L, Unit* unit) + { + bool x = Eluna::CHECKVAL(L, 2, true); + + unit->SetVisible(x); + return 0; + } + + /** + * Clears the [Unit]'s threat list. + */ + int ClearThreatList(lua_State* /*L*/, Unit* unit) + { + unit->GetThreatManager().ClearAllThreat(); + return 0; + } + + /** + * Mounts the [Unit] on the given displayID/modelID. + * + * @param uint32 displayId + */ + int Mount(lua_State* L, Unit* unit) + { + uint32 displayId = Eluna::CHECKVAL(L, 2); + + unit->Mount(displayId); + return 0; + } + + /** + * Dismounts the [Unit]. + */ + int Dismount(lua_State* /*L*/, Unit* unit) + { + if (unit->IsMounted()) + { + unit->Dismount(); + unit->RemoveAurasByType(SPELL_AURA_MOUNTED); + } + + return 0; + } + + /** + * Makes the [Unit] perform the given emote. + * + * @param uint32 emoteId + */ + int PerformEmote(lua_State* L, Unit* unit) + { + Emote emote = static_cast(Eluna::CHECKVAL(L, 2)); + unit->HandleEmoteCommand(emote); + return 0; + } + + /** + * Makes the [Unit] perform the given emote continuously. + * + * @param uint32 emoteId + */ + int EmoteState(lua_State* L, Unit* unit) + { + uint32 emoteId = Eluna::CHECKVAL(L, 2); + + unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, emoteId); + return 0; + } + + /** + * Returns calculated percentage from Health + * + * @return int32 percentage + */ + int CountPctFromCurHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->CountPctFromCurHealth(Eluna::CHECKVAL(L, 2))); + return 1; + } + + /** + * Returns calculated percentage from Max Health + * + * @return int32 percentage + */ + int CountPctFromMaxHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->CountPctFromMaxHealth(Eluna::CHECKVAL(L, 2))); + return 1; + } + + /** + * Sends chat message to [Player] + * + * @param uint8 type : chat, whisper, etc + * @param uint32 lang : language to speak + * @param string msg + * @param [Player] target + */ + int SendChatMessageToPlayer(lua_State* L, Unit* unit) + { + uint8 type = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); + std::string msg = Eluna::CHECKVAL(L, 4); + Player* target = Eluna::CHECKOBJ(L, 5); + + if (type >= MAX_CHAT_MSG_TYPE) + return luaL_argerror(L, 2, "valid ChatMsg expected"); + if (lang >= LANGUAGES_COUNT) + return luaL_argerror(L, 3, "valid Language expected"); + + WorldPacket data; + ChatHandler::BuildChatPacket(data, ChatMsg(type), Language(lang), unit, target, msg); + + target->GetSession()->SendPacket(&data); + return 0; + } + + /** + * Stops the [Unit]'s movement + */ + int MoveStop(lua_State* /*L*/, Unit* unit) + { + unit->StopMoving(); + return 0; + } + + /** + * The [Unit]'s movement expires and clears movement + * + * @param bool reset = true : cleans movement + */ + int MoveExpire(lua_State* L, Unit* unit) + { + (void) L; // ensure that the variable is referenced in order to pass compiler checks + unit->GetMotionMaster()->Clear(); + return 0; + } + + /** + * Clears the [Unit]'s movement + * + * @param bool reset = true : clean movement + */ + int MoveClear(lua_State* L, Unit* unit) + { + (void) L; // ensure that the variable is referenced in order to pass compiler checks + unit->GetMotionMaster()->Clear(); + return 0; + } + + /** + * The [Unit] will be idle + */ + int MoveIdle(lua_State* /*L*/, Unit* unit) + { + unit->GetMotionMaster()->MoveIdle(); + return 0; + } + + /** + * The [Unit] will move at random + * + * @param float radius : limit on how far the [Unit] will move at random + */ + int MoveRandom(lua_State* L, Unit* unit) + { + float radius = Eluna::CHECKVAL(L, 2); + float x, y, z; + unit->GetPosition(x, y, z); + unit->GetMotionMaster()->MoveRandom(radius); + return 0; + } + + /** + * The [Unit] will move to its set home location + */ + int MoveHome(lua_State* /*L*/, Unit* unit) + { + unit->GetMotionMaster()->MoveTargetedHome(); + return 0; + } + + /** + * The [Unit] will follow the target + * + * @param [Unit] target : target to follow + * @param float dist = 0 : distance to start following + * @param float angle = 0 + */ + int MoveFollow(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + float dist = Eluna::CHECKVAL(L, 3, 0.0f); + float angle = Eluna::CHECKVAL(L, 4, 0.0f); + unit->GetMotionMaster()->MoveFollow(target, dist, angle); + return 0; + } + + /** + * The [Unit] will chase the target + * + * @param [Unit] target : target to chase + * @param float dist = 0 : distance start chasing + * @param float angle = 0 + */ + int MoveChase(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + float dist = Eluna::CHECKVAL(L, 3, 0.0f); + float angle = Eluna::CHECKVAL(L, 4, 0.0f); + unit->GetMotionMaster()->MoveChase(target, dist, angle); + return 0; + } + + /** + * The [Unit] will move confused + */ + int MoveConfused(lua_State* /*L*/, Unit* unit) + { + unit->GetMotionMaster()->MoveConfused(); + return 0; + } + + /** + * The [Unit] will flee + * + * @param [Unit] target + * @param uint32 time = 0 : flee delay + */ + int MoveFleeing(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + uint32 time = Eluna::CHECKVAL(L, 3, 0); + unit->GetMotionMaster()->MoveFleeing(target, time); + return 0; + } + + /** + * The [Unit] will move to the coordinates + * + * @param uint32 id : unique waypoint Id + * @param float x + * @param float y + * @param float z + * @param bool genPath = true : if true, generates path + */ + int MoveTo(lua_State* L, Unit* unit) + { + uint32 id = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + bool genPath = Eluna::CHECKVAL(L, 6, true); + + unit->GetMotionMaster()->MovePoint(id, x, y, z, genPath); + return 0; + } + + /** + * Makes the [Unit] jump to the coordinates + * + * @param float x + * @param float y + * @param float z + * @param float zSpeed : start velocity + * @param float maxHeight : maximum height + * @param uint32 id = 0 : unique movement Id + */ + int MoveJump(lua_State* L, Unit* unit) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float zSpeed = Eluna::CHECKVAL(L, 5); + float maxHeight = Eluna::CHECKVAL(L, 6); + uint32 id = Eluna::CHECKVAL(L, 7, 0); + + Position pos(x, y, z); + + unit->GetMotionMaster()->MoveJump(pos, zSpeed, maxHeight, id); + return 0; + } + + /** + * The [Unit] will whisper the message to a [Player] + * + * @param string msg : message for the [Unit] to emote + * @param uint32 lang : language for the [Unit] to speak + * @param [Player] receiver : specific [Unit] to receive the message + * @param bool bossWhisper = false : is a boss whisper + */ + int SendUnitWhisper(lua_State* L, Unit* unit) + { + const char* msg = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); + (void)lang; // ensure that the variable is referenced in order to pass compiler checks + Player* receiver = Eluna::CHECKOBJ(L, 4); + bool bossWhisper = Eluna::CHECKVAL(L, 5, false); + + if (std::string(msg).length() > 0) + unit->Whisper(msg, (Language)lang, receiver, bossWhisper); + + return 0; + } + + /** + * The [Unit] will emote the message + * + * @param string msg : message for the [Unit] to emote + * @param [Unit] receiver = nil : specific [Unit] to receive the message + * @param bool bossEmote = false : is a boss emote + */ + int SendUnitEmote(lua_State* L, Unit* unit) + { + const char* msg = Eluna::CHECKVAL(L, 2); + Unit* receiver = Eluna::CHECKOBJ(L, 3, false); + bool bossEmote = Eluna::CHECKVAL(L, 4, false); + + if (std::string(msg).length() > 0) + unit->TextEmote(msg, receiver, bossEmote); + + return 0; + } + + /** + * The [Unit] will say the message + * + * @param string msg : message for the [Unit] to say + * @param uint32 language : language for the [Unit] to speak + */ + int SendUnitSay(lua_State* L, Unit* unit) + { + const char* msg = Eluna::CHECKVAL(L, 2); + uint32 language = Eluna::CHECKVAL(L, 3); + + if (std::string(msg).length() > 0) + unit->Say(msg, (Language)language, unit); + + return 0; + } + + /** + * The [Unit] will yell the message + * + * @param string msg : message for the [Unit] to yell + * @param uint32 language : language for the [Unit] to speak + */ + int SendUnitYell(lua_State* L, Unit* unit) + { + const char* msg = Eluna::CHECKVAL(L, 2); + uint32 language = Eluna::CHECKVAL(L, 3); + + if (std::string(msg).length() > 0) + unit->Yell(msg, (Language)language, unit); + + return 0; + } + + /** + * Unmorphs the [Unit] setting it's display ID back to the native display ID. + */ + int DeMorph(lua_State* /*L*/, Unit* unit) + { + unit->DeMorph(); + return 0; + } + + /** + * Makes the [Unit] cast the spell on the target. + * + * @param [Unit] target = nil : can be self or another unit + * @param uint32 spell : entry of a spell + * @param bool triggered = false : if true the spell is instant and has no cost + */ + int CastSpell(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2, false); + uint32 spell = Eluna::CHECKVAL(L, 3); + bool triggered = Eluna::CHECKVAL(L, 4, false); + + SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spell); + if (!spellEntry) + return 0; + + unit->CastSpell(target, spell, triggered); + return 0; + } + + /** + * Casts the [Spell] at target [Unit] with custom basepoints or casters. + * See also [Unit:CastSpell]. + * + * @param [Unit] target = nil + * @param uint32 spell + * @param bool triggered = false + * @param int32 bp0 = nil : custom basepoints for [Spell] effect 1. If nil, no change is made + * @param int32 bp1 = nil : custom basepoints for [Spell] effect 2. If nil, no change is made + * @param int32 bp2 = nil : custom basepoints for [Spell] effect 3. If nil, no change is made + * @param [Item] castItem = nil + * @param ObjectGuid originalCaster = ObjectGuid() + */ + int CastCustomSpell(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2, false); + uint32 spell = Eluna::CHECKVAL(L, 3); + bool triggered = Eluna::CHECKVAL(L, 4, false); + bool has_bp0 = !lua_isnoneornil(L, 5); + int32 bp0 = Eluna::CHECKVAL(L, 5, 0); + bool has_bp1 = !lua_isnoneornil(L, 6); + int32 bp1 = Eluna::CHECKVAL(L, 6, 0); + bool has_bp2 = !lua_isnoneornil(L, 7); + int32 bp2 = Eluna::CHECKVAL(L, 7, 0); + Item* castItem = Eluna::CHECKOBJ(L, 8, false); + ObjectGuid originalCaster = Eluna::CHECKVAL(L, 9, ObjectGuid()); + + CastSpellExtraArgs args; + if (has_bp0) + args.AddSpellMod(SPELLVALUE_BASE_POINT0, bp0); + if (has_bp1) + args.AddSpellMod(SPELLVALUE_BASE_POINT1, bp1); + if (has_bp2) + args.AddSpellMod(SPELLVALUE_BASE_POINT2, bp2); + if (triggered) + args.TriggerFlags = TRIGGERED_FULL_MASK; + if (castItem) + args.SetCastItem(castItem); + if (originalCaster) + args.SetOriginalCaster(originalCaster); + + unit->CastSpell(target, spell, args); + return 0; + } + + /** + * Makes the [Unit] cast the spell to the given coordinates, used for area effect spells. + * + * @param float x + * @param float y + * @param float z + * @param uint32 spell : entry of a spell + * @param bool triggered = true : if true the spell is instant and has no cost + */ + int CastSpellAoF(lua_State* L, Unit* unit) + { + float _x = Eluna::CHECKVAL(L, 2); + float _y = Eluna::CHECKVAL(L, 3); + float _z = Eluna::CHECKVAL(L, 4); + uint32 spell = Eluna::CHECKVAL(L, 5); + bool triggered = Eluna::CHECKVAL(L, 6, true); + + CastSpellExtraArgs args; + if (triggered) + args.TriggerFlags = TRIGGERED_FULL_MASK; + + unit->CastSpell(Position(_x, _y, _z), spell, args); + return 0; + } + + /** + * Clears the [Unit]'s combat + */ + int ClearInCombat(lua_State* /*L*/, Unit* unit) + { + unit->ClearInCombat(); + return 0; + } + + /** + * Stops the [Unit]'s current spell cast + * + * @param uint32 spell = 0 : entry of a spell + */ + int StopSpellCast(lua_State* L, Unit* unit) + { + uint32 spellId = Eluna::CHECKVAL(L, 2, 0); + unit->CastStop(spellId); + return 0; + } + + /** + * Interrupts [Unit]'s spell state, casting, etc. + * + * if spell is not interruptible, it will return + * + * @param int32 spellType : type of spell to interrupt + * @param bool delayed = true : skips if the spell is delayed + */ + int InterruptSpell(lua_State* L, Unit* unit) + { + int spellType = Eluna::CHECKVAL(L, 2); + bool delayed = Eluna::CHECKVAL(L, 3, true); + switch (spellType) + { + case 0: + spellType = CURRENT_MELEE_SPELL; + break; + case 1: + spellType = CURRENT_GENERIC_SPELL; + break; + case 2: + spellType = CURRENT_CHANNELED_SPELL; + break; + case 3: + spellType = CURRENT_AUTOREPEAT_SPELL; + break; + default: + return luaL_argerror(L, 2, "valid CurrentSpellTypes expected"); + } + + unit->InterruptSpell((CurrentSpellTypes)spellType, delayed); + return 0; + } + + /** + * Adds the [Aura] of the given spell entry on the given target from the [Unit]. + * + * @param uint32 spell : entry of a spell + * @param [Unit] target : aura will be applied on the target + * @return [Aura] aura + */ + int AddAura(lua_State* L, Unit* unit) + { + uint32 spell = Eluna::CHECKVAL(L, 2); + Unit* target = Eluna::CHECKOBJ(L, 3); + + SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spell); + if (!spellEntry) + return 1; + + Eluna::Push(L, unit->AddAura(spell, target)); + return 1; + } + + /** + * Removes [Aura] of the given spell entry from the [Unit]. + * + * @param uint32 spell : entry of a spell + */ + int RemoveAura(lua_State* L, Unit* unit) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + unit->RemoveAurasDueToSpell(spellId); + return 0; + } + + /** + * Removes all [Aura]'s from the [Unit]. + * + * Note: talents and racials are also auras, use with caution + */ + int RemoveAllAuras(lua_State* /*L*/, Unit* unit) + { + unit->RemoveAllAuras(); + return 0; + } + + /** + * Removes all positive visible [Aura]'s from the [Unit]. + */ + int RemoveArenaAuras(lua_State* /*L*/, Unit* unit) + { + unit->RemoveArenaAuras(); + return 0; + } + + /** + * Adds the given unit state for the [Unit]. + * + * @param [UnitState] state + */ + int AddUnitState(lua_State* L, Unit* unit) + { + uint32 state = Eluna::CHECKVAL(L, 2); + + unit->AddUnitState(state); + return 0; + } + + /** + * Removes the given unit state from the [Unit]. + * + * @param [UnitState] state + */ + int ClearUnitState(lua_State* L, Unit* unit) + { + uint32 state = Eluna::CHECKVAL(L, 2); + + unit->ClearUnitState(state); + return 0; + } + + /** + * Makes the [Unit] teleport to given coordinates within same map. + * + * @param float x + * @param float y + * @param float z + * @param float o : orientation + */ + int NearTeleport(lua_State* L, Unit* unit) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float o = Eluna::CHECKVAL(L, 5); + + unit->NearTeleportTo(x, y, z, o); + return 0; + } + + /** + * Makes the [Unit] damage the target [Unit] + * + *
+     * enum SpellSchools
+     * {
+     *     SPELL_SCHOOL_NORMAL  = 0,
+     *     SPELL_SCHOOL_HOLY    = 1,
+     *     SPELL_SCHOOL_FIRE    = 2,
+     *     SPELL_SCHOOL_NATURE  = 3,
+     *     SPELL_SCHOOL_FROST   = 4,
+     *     SPELL_SCHOOL_SHADOW  = 5,
+     *     SPELL_SCHOOL_ARCANE  = 6,
+     *     MAX_SPELL_SCHOOL     = 7
+     * };
+     * 
+ * + * @param [Unit] target : [Unit] to damage + * @param uint32 damage : amount to damage + * @param bool durabilityloss = true : if false, the damage does not do durability damage + * @param [SpellSchools] school = MAX_SPELL_SCHOOL : school the damage is done in or MAX_SPELL_SCHOOL for direct damage + * @param uint32 spell = 0 : spell that inflicts the damage + */ + int DealDamage(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + uint32 damage = Eluna::CHECKVAL(L, 3); + bool durabilityloss = Eluna::CHECKVAL(L, 4, true); + uint32 school = Eluna::CHECKVAL(L, 5, MAX_SPELL_SCHOOL); + uint32 spell = Eluna::CHECKVAL(L, 6, 0); + if (school > MAX_SPELL_SCHOOL) + return luaL_argerror(L, 6, "valid SpellSchool expected"); + + // flat melee damage without resistence/etc reduction + if (school == MAX_SPELL_SCHOOL) + { + Unit::DealDamage(unit, target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, durabilityloss); + unit->SendAttackStateUpdate(HITINFO_AFFECTS_VICTIM, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_HIT, 0); + return 0; + } + + SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); + + if (Unit::IsDamageReducedByArmor(schoolmask)) + damage = Unit::CalcArmorReducedDamage(unit, target, damage, NULL, BASE_ATTACK); + + // melee damage by specific school + if (!spell) + { + DamageInfo dmgInfo(unit, target, damage, nullptr, schoolmask, SPELL_DIRECT_DAMAGE, BASE_ATTACK); + unit->CalcAbsorbResist(dmgInfo); + + if (!dmgInfo.GetDamage()) + damage = 0; + else + damage = dmgInfo.GetDamage(); + + uint32 absorb = dmgInfo.GetAbsorb(); + uint32 resist = dmgInfo.GetResist(); + unit->DealDamageMods(target, damage, &absorb); + + Unit::DealDamage(unit, target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); + unit->SendAttackStateUpdate(HITINFO_AFFECTS_VICTIM, target, 0, schoolmask, damage, absorb, resist, VICTIMSTATE_HIT, 0); + return 0; + } + + if (!spell) + return 0; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell); + if (!spellInfo) + return 0; + + SpellNonMeleeDamage dmgInfo(unit, target, spell, spellInfo->GetSchoolMask()); + Unit::DealDamageMods(dmgInfo.target, dmgInfo.damage, &dmgInfo.absorb); + + unit->SendSpellNonMeleeDamageLog(&dmgInfo); + unit->DealSpellDamage(&dmgInfo, true); + return 0; + } + + /** + * Makes the [Unit] heal the target [Unit] with given spell + * + * @param [Unit] target : [Unit] to heal + * @param uint32 spell : spell that causes the healing + * @param uint32 amount : amount to heal + * @param bool critical = false : if true, heal is logged as critical + */ + int DealHeal(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + uint32 spell = Eluna::CHECKVAL(L, 3); + uint32 amount = Eluna::CHECKVAL(L, 4); + bool critical = Eluna::CHECKVAL(L, 5, false); + + if (const SpellInfo* info = sSpellMgr->GetSpellInfo(spell)) + { + HealInfo healInfo(unit, target, amount, info, info->GetSchoolMask()); + unit->HealBySpell(healInfo, critical); + } + + return 0; + } + + /** + * Makes the [Unit] kill the target [Unit] + * + * @param [Unit] target : [Unit] to kill + * @param bool durLoss = true : when true, the target's items suffer durability loss + */ + int Kill(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + bool durLoss = Eluna::CHECKVAL(L, 3, true); + + Unit::Kill(unit, target, durLoss); + return 0; + } + + /** + * Adds threat to the [Unit] from the victim. + * + *
+     * enum SpellSchoolMask
+     * {
+     *     SPELL_SCHOOL_MASK_NONE    = 0,
+     *     SPELL_SCHOOL_MASK_NORMAL  = 1,
+     *     SPELL_SCHOOL_MASK_HOLY    = 2,
+     *     SPELL_SCHOOL_MASK_FIRE    = 4,
+     *     SPELL_SCHOOL_MASK_NATURE  = 8,
+     *     SPELL_SCHOOL_MASK_FROST   = 16,
+     *     SPELL_SCHOOL_MASK_SHADOW  = 32,
+     *     SPELL_SCHOOL_MASK_ARCANE  = 64,
+     * }
+     * 
+ * + * @param [Unit] victim : [Unit] that caused the threat + * @param float threat : threat amount + * @param [SpellSchoolMask] schoolMask = 0 : [SpellSchoolMask] of the threat causer + * @param uint32 spell = 0 : spell entry used for threat + */ + int AddThreat(lua_State* L, Unit* unit) + { + Unit* victim = Eluna::CHECKOBJ(L, 2); + float threat = Eluna::CHECKVAL(L, 3, true); + uint32 spell = Eluna::CHECKVAL(L, 4, 0); + + unit->GetThreatManager().AddThreat(victim, threat, spell ? sSpellMgr->GetSpellInfo(spell) : NULL, true, true); + return 0; + } + + int RestoreDisplayId(lua_State* /*L*/, Unit* unit) + { + unit->RestoreDisplayId(); + return 0; + } + + int RestoreFaction(lua_State* /*L*/, Unit* unit) + { + unit->RestoreFaction(); + return 0; + } + + int RemoveBindSightAuras(lua_State* /*L*/, Unit* unit) + { + unit->RemoveBindSightAuras(); + return 0; + } + + int RemoveCharmAuras(lua_State* /*L*/, Unit* unit) + { + unit->RemoveCharmAuras(); + return 0; + } + + int DisableMelee(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + if (apply) + unit->AddUnitState(UNIT_STATE_CANNOT_AUTOATTACK); + else + unit->ClearUnitState(UNIT_STATE_CANNOT_AUTOATTACK); + + return 0; + } + + /*int SummonGuardian(lua_State* L, Unit* unit) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + uint32 desp = Eluna::CHECKVAL(L, 7, 0); + + SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(61); + if (!properties) + return 1; + Position pos; + pos.Relocate(x,y,z,o); + TempSummon* summon = unit->GetMap()->SummonCreature(entry, pos, properties, desp, unit); + + if (!summon) + return 1; + + if (summon->HasUnitTypeMask(UNIT_MASK_GUARDIAN)) + ((Guardian*)summon)->InitStatsForLevel(unit->getLevel()); + + if (properties && properties->Category == SUMMON_CATEGORY_ALLY) + summon->setFaction(unit->getFaction()); + if (summon->GetEntry() == 27893) + { + if (uint32 weapon = unit->GetUInt32Value(PLAYER_VISIBLE_ITEM_16_ENTRYID)) + { + summon->SetDisplayId(11686); + summon->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, weapon); + } + else + summon->SetDisplayId(1126); + } + summon->AI()->EnterEvadeMode(); + + Eluna::Push(L, summon); + return 1; + }*/ + + ElunaRegister UnitMethods[] = + { + // Getters + { "GetLevel", &LuaUnit::GetLevel }, + { "GetHealth", &LuaUnit::GetHealth }, + { "GetDisplayId", &LuaUnit::GetDisplayId }, + { "GetNativeDisplayId", &LuaUnit::GetNativeDisplayId }, + { "GetPower", &LuaUnit::GetPower }, + { "GetMaxPower", &LuaUnit::GetMaxPower }, + { "GetPowerType", &LuaUnit::GetPowerType }, + { "GetMaxHealth", &LuaUnit::GetMaxHealth }, + { "GetHealthPct", &LuaUnit::GetHealthPct }, + { "GetPowerPct", &LuaUnit::GetPowerPct }, + { "GetGender", &LuaUnit::GetGender }, + { "GetRace", &LuaUnit::GetRace }, + { "GetClass", &LuaUnit::GetClass }, + { "GetRaceMask", &LuaUnit::GetRaceMask }, + { "GetClassMask", &LuaUnit::GetClassMask }, + { "GetRaceAsString", &LuaUnit::GetRaceAsString }, + { "GetClassAsString", &LuaUnit::GetClassAsString }, + { "GetAura", &LuaUnit::GetAura }, + { "GetFaction", &LuaUnit::GetFaction }, + { "GetCurrentSpell", &LuaUnit::GetCurrentSpell }, + { "GetCreatureType", &LuaUnit::GetCreatureType }, + { "GetMountId", &LuaUnit::GetMountId }, + { "GetOwner", &LuaUnit::GetOwner }, + { "GetFriendlyUnitsInRange", &LuaUnit::GetFriendlyUnitsInRange }, + { "GetUnfriendlyUnitsInRange", &LuaUnit::GetUnfriendlyUnitsInRange }, + { "GetOwnerGUID", &LuaUnit::GetOwnerGUID }, + { "GetCreatorGUID", &LuaUnit::GetCreatorGUID }, + { "GetMinionGUID", &LuaUnit::GetPetGUID }, + { "GetCharmerGUID", &LuaUnit::GetCharmerGUID }, + { "GetCharmGUID", &LuaUnit::GetCharmGUID }, + { "GetPetGUID", &LuaUnit::GetPetGUID }, + { "GetCritterGUID", &LuaUnit::GetCritterGUID }, + { "GetControllerGUID", &LuaUnit::GetControllerGUID }, + { "GetControllerGUIDS", &LuaUnit::GetControllerGUIDS }, + { "GetStandState", &LuaUnit::GetStandState }, + { "GetVictim", &LuaUnit::GetVictim }, + { "GetSpeed", &LuaUnit::GetSpeed }, + { "GetStat", &LuaUnit::GetStat }, + { "GetBaseSpellPower", &LuaUnit::GetBaseSpellPower }, + { "GetVehicleKit", &LuaUnit::GetVehicleKit }, + { "GetVehicle", &LuaUnit::GetVehicle }, + { "GetMovementType", &LuaUnit::GetMovementType }, + + // Setters + { "SetFaction", &LuaUnit::SetFaction }, + { "SetLevel", &LuaUnit::SetLevel }, + { "SetHealth", &LuaUnit::SetHealth }, + { "SetMaxHealth", &LuaUnit::SetMaxHealth }, + { "SetPower", &LuaUnit::SetPower }, + { "SetMaxPower", &LuaUnit::SetMaxPower }, + { "SetPowerType", &LuaUnit::SetPowerType }, + { "SetDisplayId", &LuaUnit::SetDisplayId }, + { "SetNativeDisplayId", &LuaUnit::SetNativeDisplayId }, + { "SetFacing", &LuaUnit::SetFacing }, + { "SetFacingToObject", &LuaUnit::SetFacingToObject }, + { "SetSpeed", &LuaUnit::SetSpeed }, + { "SetStunned", &LuaUnit::SetStunned }, + { "SetRooted", &LuaUnit::SetRooted}, + { "SetConfused", &LuaUnit::SetConfused}, + { "SetFeared", &LuaUnit::SetFeared}, + { "SetPvP", &LuaUnit::SetPvP }, + { "SetFFA", &LuaUnit::SetFFA }, + { "SetSanctuary", &LuaUnit::SetSanctuary }, + { "SetCanFly", &LuaUnit::SetCanFly }, + { "SetVisible", &LuaUnit::SetVisible }, + { "SetOwnerGUID", &LuaUnit::SetOwnerGUID }, + { "SetName", &LuaUnit::SetName }, + { "SetSheath", &LuaUnit::SetSheath }, + { "SetCreatorGUID", &LuaUnit::SetCreatorGUID }, + { "SetMinionGUID", &LuaUnit::SetPetGUID }, + { "SetPetGUID", &LuaUnit::SetPetGUID }, + { "SetCritterGUID", &LuaUnit::SetCritterGUID }, + { "SetWaterWalk", &LuaUnit::SetWaterWalk }, + { "SetStandState", &LuaUnit::SetStandState }, + { "SetInCombatWith", &LuaUnit::SetInCombatWith }, + { "ModifyPower", &LuaUnit::ModifyPower }, + + // Boolean + { "IsAlive", &LuaUnit::IsAlive }, + { "IsDead", &LuaUnit::IsDead }, + { "IsDying", &LuaUnit::IsDying }, + { "IsPvPFlagged", &LuaUnit::IsPvPFlagged }, + { "IsInCombat", &LuaUnit::IsInCombat }, + { "IsBanker", &LuaUnit::IsBanker }, + { "IsBattleMaster", &LuaUnit::IsBattleMaster }, + { "IsCharmed", &LuaUnit::IsCharmed }, + { "IsArmorer", &LuaUnit::IsArmorer }, + { "IsAttackingPlayer", &LuaUnit::IsAttackingPlayer }, + { "IsInWater", &LuaUnit::IsInWater }, + { "IsUnderWater", &LuaUnit::IsUnderWater }, + { "IsAuctioneer", &LuaUnit::IsAuctioneer }, + { "IsGuildMaster", &LuaUnit::IsGuildMaster }, + { "IsInnkeeper", &LuaUnit::IsInnkeeper }, + { "IsTrainer", &LuaUnit::IsTrainer }, + { "IsGossip", &LuaUnit::IsGossip }, + { "IsTaxi", &LuaUnit::IsTaxi }, + { "IsSpiritHealer", &LuaUnit::IsSpiritHealer }, + { "IsSpiritGuide", &LuaUnit::IsSpiritGuide }, + { "IsTabardDesigner", &LuaUnit::IsTabardDesigner }, + { "IsServiceProvider", &LuaUnit::IsServiceProvider }, + { "IsSpiritService", &LuaUnit::IsSpiritService }, + { "HealthBelowPct", &LuaUnit::HealthBelowPct }, + { "HealthAbovePct", &LuaUnit::HealthAbovePct }, + { "IsMounted", &LuaUnit::IsMounted }, + { "AttackStop", &LuaUnit::AttackStop }, + { "Attack", &LuaUnit::Attack }, + { "IsVisible", &LuaUnit::IsVisible }, + { "IsMoving", &LuaUnit::IsMoving }, + { "IsFlying", &LuaUnit::IsFlying }, + { "IsStopped", &LuaUnit::IsStopped }, + { "HasUnitState", &LuaUnit::HasUnitState }, + { "IsQuestGiver", &LuaUnit::IsQuestGiver }, + { "IsInAccessiblePlaceFor", &LuaUnit::IsInAccessiblePlaceFor }, + { "IsVendor", &LuaUnit::IsVendor }, + { "IsRooted", &LuaUnit::IsRooted }, + { "IsFullHealth", &LuaUnit::IsFullHealth }, + { "HasAura", &LuaUnit::HasAura }, + { "IsCasting", &LuaUnit::IsCasting }, + { "IsStandState", &LuaUnit::IsStandState }, + { "IsOnVehicle", &LuaUnit::IsOnVehicle }, + + // Other + { "AddAura", &LuaUnit::AddAura }, + { "RemoveAura", &LuaUnit::RemoveAura }, + { "RemoveAllAuras", &LuaUnit::RemoveAllAuras }, + { "RemoveArenaAuras", &LuaUnit::RemoveArenaAuras }, + { "ClearInCombat", &LuaUnit::ClearInCombat }, + { "DeMorph", &LuaUnit::DeMorph }, + { "SendUnitWhisper", &LuaUnit::SendUnitWhisper }, + { "SendUnitEmote", &LuaUnit::SendUnitEmote }, + { "SendUnitSay", &LuaUnit::SendUnitSay }, + { "SendUnitYell", &LuaUnit::SendUnitYell }, + { "CastSpell", &LuaUnit::CastSpell }, + { "CastCustomSpell", &LuaUnit::CastCustomSpell }, + { "CastSpellAoF", &LuaUnit::CastSpellAoF }, + { "Kill", &LuaUnit::Kill }, + { "StopSpellCast", &LuaUnit::StopSpellCast }, + { "InterruptSpell", &LuaUnit::InterruptSpell }, + { "SendChatMessageToPlayer", &LuaUnit::SendChatMessageToPlayer }, + { "PerformEmote", &LuaUnit::PerformEmote }, + { "EmoteState", &LuaUnit::EmoteState }, + { "CountPctFromCurHealth", &LuaUnit::CountPctFromCurHealth }, + { "CountPctFromMaxHealth", &LuaUnit::CountPctFromMaxHealth }, + { "Dismount", &LuaUnit::Dismount }, + { "Mount", &LuaUnit::Mount }, + { "RestoreDisplayId", &LuaUnit::RestoreDisplayId }, + { "RestoreFaction", &LuaUnit::RestoreFaction }, + { "RemoveBindSightAuras", &LuaUnit::RemoveBindSightAuras }, + { "RemoveCharmAuras", &LuaUnit::RemoveCharmAuras }, + { "ClearThreatList", &LuaUnit::ClearThreatList }, + { "ClearUnitState", &LuaUnit::ClearUnitState }, + { "AddUnitState", &LuaUnit::AddUnitState }, + { "DisableMelee", &LuaUnit::DisableMelee }, + { "NearTeleport", &LuaUnit::NearTeleport }, + { "MoveIdle", &LuaUnit::MoveIdle }, + { "MoveRandom", &LuaUnit::MoveRandom }, + { "MoveHome", &LuaUnit::MoveHome }, + { "MoveFollow", &LuaUnit::MoveFollow }, + { "MoveChase", &LuaUnit::MoveChase }, + { "MoveConfused", &LuaUnit::MoveConfused }, + { "MoveFleeing", &LuaUnit::MoveFleeing }, + { "MoveTo", &LuaUnit::MoveTo }, + { "MoveJump", &LuaUnit::MoveJump }, + { "MoveStop", &LuaUnit::MoveStop }, + { "MoveExpire", &LuaUnit::MoveExpire }, + { "MoveClear", &LuaUnit::MoveClear }, + { "DealDamage", &LuaUnit::DealDamage }, + { "DealHeal", &LuaUnit::DealHeal }, + { "AddThreat", &LuaUnit::AddThreat }, + + // Not implemented methods + { "SummonGuardian", nullptr }, // not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/VehicleMethods.h b/src/modules/Eluna/TrinityCore/VehicleMethods.h new file mode 100644 index 0000000000..57f8372e69 --- /dev/null +++ b/src/modules/Eluna/TrinityCore/VehicleMethods.h @@ -0,0 +1,114 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef VEHICLEMETHODS_H +#define VEHICLEMETHODS_H + +/*** + * Inherits all methods from: none + */ +namespace LuaVehicle +{ + /** + * Returns true if the [Unit] passenger is on board + * + * @param [Unit] passenger + * @return bool isOnBoard + */ + int IsOnBoard(lua_State* L, Vehicle* vehicle) + { + Unit* passenger = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, passenger->IsOnVehicle(vehicle->GetBase())); + return 1; + } + + /** + * Returns the [Vehicle]'s owner + * + * @return [Unit] owner + */ + int GetOwner(lua_State* L, Vehicle* vehicle) + { + Eluna::Push(L, vehicle->GetBase()); + return 1; + } + + /** + * Returns the [Vehicle]'s entry + * + * @return uint32 entry + */ + int GetEntry(lua_State* L, Vehicle* vehicle) + { + Eluna::Push(L, vehicle->GetVehicleInfo()->ID); + return 1; + } + + /** + * Returns the [Vehicle]'s passenger in the specified seat + * + * @param int8 seat + * @return [Unit] passenger + */ + int GetPassenger(lua_State* L, Vehicle* vehicle) + { + int8 seatId = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, vehicle->GetPassenger(seatId)); + return 1; + } + + /** + * Adds [Unit] passenger to a specified seat in the [Vehicle] + * + * @param [Unit] passenger + * @param int8 seat + */ + int AddPassenger(lua_State* L, Vehicle* vehicle) + { + Unit* passenger = Eluna::CHECKOBJ(L, 2); + int8 seatId = Eluna::CHECKVAL(L, 3); + +#ifndef CATA + vehicle->AddPassenger(passenger, seatId); +#else + vehicle->AddVehiclePassenger(passenger, seatId); +#endif + return 0; + } + + /** + * Removes [Unit] passenger from the [Vehicle] + * + * @param [Unit] passenger + */ + int RemovePassenger(lua_State* L, Vehicle* vehicle) + { + Unit* passenger = Eluna::CHECKOBJ(L, 2); + + vehicle->RemovePassenger(passenger); + return 0; + } + + ElunaRegister VehicleMethods[] = + { + // Getters + { "GetOwner", &LuaVehicle::GetOwner }, + { "GetEntry", &LuaVehicle::GetEntry }, + { "GetPassenger", &LuaVehicle::GetPassenger }, + + // Boolean + { "IsOnBoard", &LuaVehicle::IsOnBoard }, + + // Other + { "AddPassenger", &LuaVehicle::AddPassenger }, + { "RemovePassenger", &LuaVehicle::RemovePassenger }, + + { NULL, NULL } + }; +} + +#endif // VEHICLEMETHODS_H diff --git a/src/modules/Eluna/TrinityCore/WorldObjectMethods.h b/src/modules/Eluna/TrinityCore/WorldObjectMethods.h new file mode 100644 index 0000000000..03d9aa396c --- /dev/null +++ b/src/modules/Eluna/TrinityCore/WorldObjectMethods.h @@ -0,0 +1,1183 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef WORLDOBJECTMETHODS_H +#define WORLDOBJECTMETHODS_H + +/*** + * Inherits all methods from: [Object] + */ +namespace LuaWorldObject +{ + /** + * Returns the name of the [WorldObject] + * + * @return string name + */ + int GetName(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetName()); + return 1; + } + + /** + * Returns the current [Map] object of the [WorldObject] + * + * @return [Map] mapObject + */ + int GetMap(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetMap()); + return 1; + } + + /** + * Returns the current phase of the [WorldObject] + * + * @return uint32 phase + */ + int GetPhaseMask(lua_State* L, WorldObject* obj) + { +#ifdef CATA + EventMap event; + Eluna::Push(L, event.GetPhaseMask()); +#else + Eluna::Push(L, obj->GetPhaseMask()); +#endif + return 1; + } + + /** + * Sets the [WorldObject]'s phase mask. + * + * @param uint32 phaseMask + * @param bool update = true : update visibility to nearby objects + */ + int SetPhaseMask(lua_State* L, WorldObject* obj) + { + uint32 phaseMask = Eluna::CHECKVAL(L, 2); +#ifdef CATA + EventMap event; + event.SetPhase(phaseMask); +#else + bool update = Eluna::CHECKVAL(L, 3, true); + obj->SetPhaseMask(phaseMask, update); +#endif + return 0; + } + + /** + * Returns the current instance ID of the [WorldObject] + * + * @return uint32 instanceId + */ + int GetInstanceId(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetInstanceId()); + return 1; + } + + /** + * Returns the current area ID of the [WorldObject] + * + * @return uint32 areaId + */ + int GetAreaId(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetAreaId()); + return 1; + } + + /** + * Returns the current zone ID of the [WorldObject] + * + * @return uint32 zoneId + */ + int GetZoneId(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetZoneId()); + return 1; + } + + /** + * Returns the current map ID of the [WorldObject] + * + * @return uint32 mapId + */ + int GetMapId(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetMapId()); + return 1; + } + + /** + * Returns the current X coordinate of the [WorldObject] + * + * @return float x + */ + int GetX(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPositionX()); + return 1; + } + + /** + * Returns the current Y coordinate of the [WorldObject] + * + * @return float y + */ + int GetY(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPositionY()); + return 1; + } + + /** + * Returns the current Z coordinate of the [WorldObject] + * + * @return float z + */ + int GetZ(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPositionZ()); + return 1; + } + + /** + * Returns the current orientation of the [WorldObject] + * + * @return float orientation / facing + */ + int GetO(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetOrientation()); + return 1; + } + + /** + * Returns the coordinates and orientation of the [WorldObject] + * + * @return float x : x coordinate of the [WorldObject] + * @return float y : y coordinate of the [WorldObject] + * @return float z : z coordinate (height) of the [WorldObject] + * @return float o : facing / orientation of the [WorldObject] + */ + int GetLocation(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPositionX()); + Eluna::Push(L, obj->GetPositionY()); + Eluna::Push(L, obj->GetPositionZ()); + Eluna::Push(L, obj->GetOrientation()); + return 4; + } + + /** + * Returns the nearest [Player] object in sight of the [WorldObject] or within the given range + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return [Player] nearestPlayer + */ + int GetNearestPlayer(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 hostile = Eluna::CHECKVAL(L, 3, 0); + uint32 dead = Eluna::CHECKVAL(L, 4, 1); + + Unit* target = NULL; + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_PLAYER, 0, hostile, dead); + Trinity::UnitLastSearcher searcher(obj, target, checker); + Cell::VisitAllObjects(obj, searcher, range); + + Eluna::Push(L, target); + return 1; + } + + /** + * Returns the nearest [GameObject] object in sight of the [WorldObject] or within the given range and/or with a specific entry ID + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 entryId = 0 : optionally set entry ID of game object to find + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * + * @return [GameObject] nearestGameObject + */ + int GetNearestGameObject(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 entry = Eluna::CHECKVAL(L, 3, 0); + uint32 hostile = Eluna::CHECKVAL(L, 4, 0); + + GameObject* target = NULL; + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_GAMEOBJECT, entry, hostile); + Trinity::GameObjectLastSearcher searcher(obj, target, checker); + Cell::VisitAllObjects(obj, searcher, range); + + Eluna::Push(L, target); + return 1; + } + + /** + * Returns the nearest [Creature] object in sight of the [WorldObject] or within the given range and/or with a specific entry ID + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 entryId = 0 : optionally set entry ID of creature to find + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return [Creature] nearestCreature + */ + int GetNearestCreature(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 entry = Eluna::CHECKVAL(L, 3, 0); + uint32 hostile = Eluna::CHECKVAL(L, 4, 0); + uint32 dead = Eluna::CHECKVAL(L, 5, 1); + + Creature* target = NULL; + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_UNIT, entry, hostile, dead); + Trinity::CreatureLastSearcher searcher(obj, target, checker); + Cell::VisitAllObjects(obj, searcher, range); + + Eluna::Push(L, target); + return 1; + } + + /** + * Returns a table of [Player] objects in sight of the [WorldObject] or within the given range + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return table playersInRange : table of [Player]s + */ + int GetPlayersInRange(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 hostile = Eluna::CHECKVAL(L, 3, 0); + uint32 dead = Eluna::CHECKVAL(L, 4, 1); + + std::list list; + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_PLAYER, 0, hostile, dead); + Trinity::PlayerListSearcher searcher(obj, list, checker); + Cell::VisitAllObjects(obj, searcher, range); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns a table of [Creature] objects in sight of the [WorldObject] or within the given range and/or with a specific entry ID + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 entryId = 0 : optionally set entry ID of creatures to find + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return table creaturesInRange : table of [Creature]s + */ + int GetCreaturesInRange(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 entry = Eluna::CHECKVAL(L, 3, 0); + uint32 hostile = Eluna::CHECKVAL(L, 4, 0); + uint32 dead = Eluna::CHECKVAL(L, 5, 1); + + std::list list; + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_UNIT, entry, hostile, dead); + Trinity::CreatureListSearcher searcher(obj, list, checker); + Cell::VisitAllObjects(obj, searcher, range); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns a table of [GameObject] objects in sight of the [WorldObject] or within the given range and/or with a specific entry ID + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 entryId = 0 : optionally set entry ID of game objects to find + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * + * @return table gameObjectsInRange : table of [GameObject]s + */ + int GetGameObjectsInRange(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 entry = Eluna::CHECKVAL(L, 3, 0); + uint32 hostile = Eluna::CHECKVAL(L, 4, 0); + + std::list list; + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_GAMEOBJECT, entry, hostile); + Trinity::GameObjectListSearcher searcher(obj, list, checker); + Cell::VisitAllObjects(obj, searcher, range); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns nearest [WorldObject] in sight of the [WorldObject]. + * The distance, type, entry and hostility requirements the [WorldObject] must match can be passed. + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param [TypeMask] type = 0 : the [TypeMask] that the [WorldObject] must be. This can contain multiple types. 0 will be ingored + * @param uint32 entry = 0 : the entry of the [WorldObject], 0 will be ingored + * @param uint32 hostile = 0 : specifies whether the [WorldObject] needs to be 1 hostile, 2 friendly or 0 either + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return [WorldObject] worldObject + */ + int GetNearObject(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint16 type = Eluna::CHECKVAL(L, 3, 0); // TypeMask + uint32 entry = Eluna::CHECKVAL(L, 4, 0); + uint32 hostile = Eluna::CHECKVAL(L, 5, 0); // 0 none, 1 hostile, 2 friendly + uint32 dead = Eluna::CHECKVAL(L, 6, 1); // 0 both, 1 alive, 2 dead + + float x, y, z; + obj->GetPosition(x, y, z); + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, type, entry, hostile, dead); + + WorldObject* target = NULL; + Trinity::WorldObjectLastSearcher searcher(obj, target, checker); + Cell::VisitAllObjects(obj, searcher, range); + + Eluna::Push(L, target); + return 1; + } + + /** + * Returns a table of [WorldObject]s in sight of the [WorldObject]. + * The distance, type, entry and hostility requirements the [WorldObject] must match can be passed. + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param [TypeMask] type = 0 : the [TypeMask] that the [WorldObject] must be. This can contain multiple types. 0 will be ingored + * @param uint32 entry = 0 : the entry of the [WorldObject], 0 will be ingored + * @param uint32 hostile = 0 : specifies whether the [WorldObject] needs to be 1 hostile, 2 friendly or 0 either + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return table worldObjectList : table of [WorldObject]s + */ + int GetNearObjects(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint16 type = Eluna::CHECKVAL(L, 3, 0); // TypeMask + uint32 entry = Eluna::CHECKVAL(L, 4, 0); + uint32 hostile = Eluna::CHECKVAL(L, 5, 0); // 0 none, 1 hostile, 2 friendly + uint32 dead = Eluna::CHECKVAL(L, 6, 1); // 0 both, 1 alive, 2 dead + + float x, y, z; + obj->GetPosition(x, y, z); + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, type, entry, hostile, dead); + + std::list list; + Trinity::WorldObjectListSearcher searcher(obj, list, checker); + Cell::VisitAllObjects(obj, searcher, range); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns the distance from this [WorldObject] to another [WorldObject], or from this [WorldObject] to a point in 3d space. + * + * The function takes into account the given object sizes. See also [WorldObject:GetExactDistance], [WorldObject:GetDistance2d] + * + * @proto dist = (obj) + * @proto dist = (x, y, z) + * + * @param [WorldObject] obj + * @param float x : the X-coordinate of the point + * @param float y : the Y-coordinate of the point + * @param float z : the Z-coordinate of the point + * + * @return float dist : the distance in yards + */ + int GetDistance(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + Eluna::Push(L, obj->GetDistance(target)); + else + { + float X = Eluna::CHECKVAL(L, 2); + float Y = Eluna::CHECKVAL(L, 3); + float Z = Eluna::CHECKVAL(L, 4); + Eluna::Push(L, obj->GetDistance(X, Y, Z)); + } + return 1; + } + + /** + * Returns the distance from this [WorldObject] to another [WorldObject], or from this [WorldObject] to a point in 3d space. + * + * The function does not take into account the given object sizes, which means only the object coordinates are compared. See also [WorldObject:GetDistance], [WorldObject:GetDistance2d] + * + * @proto dist = (obj) + * @proto dist = (x, y, z) + * + * @param [WorldObject] obj + * @param float x : the X-coordinate of the point + * @param float y : the Y-coordinate of the point + * @param float z : the Z-coordinate of the point + * + * @return float dist : the distance in yards + */ + int GetExactDistance(lua_State* L, WorldObject* obj) + { + float x, y, z; + obj->GetPosition(x, y, z); + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + { + float x2, y2, z2; + target->GetPosition(x2, y2, z2); + x -= x2; + y -= y2; + z -= z2; + } + else + { + x -= Eluna::CHECKVAL(L, 2); + y -= Eluna::CHECKVAL(L, 3); + z -= Eluna::CHECKVAL(L, 4); + } + + Eluna::Push(L, std::sqrt(x*x + y*y + z*z)); + return 1; + } + + /** + * Returns the distance from this [WorldObject] to another [WorldObject], or from this [WorldObject] to a point in 2d space. + * + * The function takes into account the given object sizes. See also [WorldObject:GetDistance], [WorldObject:GetExactDistance2d] + * + * @proto dist = (obj) + * @proto dist = (x, y) + * + * @param [WorldObject] obj + * @param float x : the X-coordinate of the point + * @param float y : the Y-coordinate of the point + * + * @return float dist : the distance in yards + */ + int GetDistance2d(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + Eluna::Push(L, obj->GetDistance2d(target)); + else + { + float X = Eluna::CHECKVAL(L, 2); + float Y = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetDistance2d(X, Y)); + } + return 1; + } + + /** + * Returns the distance from this [WorldObject] to another [WorldObject], or from this [WorldObject] to a point in 2d space. + * + * The function does not take into account the given object sizes, which means only the object coordinates are compared. See also [WorldObject:GetDistance], [WorldObject:GetDistance2d] + * + * @proto dist = (obj) + * @proto dist = (x, y) + * + * @param [WorldObject] obj + * @param float x : the X-coordinate of the point + * @param float y : the Y-coordinate of the point + * + * @return float dist : the distance in yards + */ + int GetExactDistance2d(lua_State* L, WorldObject* obj) + { + float x, y, z; + obj->GetPosition(x, y, z); + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + { + float x2, y2, z2; + target->GetPosition(x2, y2, z2); + x -= x2; + y -= y2; + } + else + { + x -= Eluna::CHECKVAL(L, 2); + y -= Eluna::CHECKVAL(L, 3); + } + + Eluna::Push(L, std::sqrt(x*x + y*y)); + return 1; + } + + /** + * Returns the x, y and z of a point dist away from the [WorldObject]. + * + * @param float distance : specifies the distance of the point from the [WorldObject] in yards + * @param float angle : specifies the angle of the point relative to the orientation / facing of the [WorldObject] in radians + * + * @return float x + * @return float y + * @return float z + */ + int GetRelativePoint(lua_State* L, WorldObject* obj) + { + float dist = Eluna::CHECKVAL(L, 2); + float rad = Eluna::CHECKVAL(L, 3); + + float x, y, z; + obj->GetClosePoint(x, y, z, 0.0f, dist, rad); + + Eluna::Push(L, x); + Eluna::Push(L, y); + Eluna::Push(L, z); + return 3; + } + + /** + * Returns the angle between this [WorldObject] and another [WorldObject] or a point. + * + * The angle is the angle between two points and orientation will be ignored. + * + * @proto dist = (obj) + * @proto dist = (x, y) + * + * @param [WorldObject] object + * @param float x + * @param float y + * + * @return float angle : angle in radians in range 0..2*pi + */ + int GetAngle(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); +#ifndef CATA + if (target) + Eluna::Push(L, obj->GetAbsoluteAngle(target)); + else + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetAbsoluteAngle(x, y)); + } +#else + if (target) + Eluna::Push(L, obj->GetAngle(target)); + else + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetAngle(x, y)); + } +#endif + + return 1; + } + + /** + * Sends a [WorldPacket] to [Player]s in sight of the [WorldObject]. + * + * @param [WorldPacket] packet + */ + int SendPacket(lua_State* L, WorldObject* obj) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + + obj->SendMessageToSet(data, true); + return 0; + } + + /** + * Spawns a [GameObject] at specified location. + * + * @param uint32 entry : [GameObject] entry ID + * @param float x + * @param float y + * @param float z + * @param float o + * @param uint32 respawnDelay = 30 : respawn time in seconds + * @return [GameObject] gameObject + */ + int SummonGameObject(lua_State* L, WorldObject* obj) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + uint32 respawnDelay = Eluna::CHECKVAL(L, 7, 30); + +#ifndef CATA + QuaternionData rot = QuaternionData::fromEulerAnglesZYX(o, 0.f, 0.f); + + Eluna::Push(L, obj->SummonGameObject(entry, Position(x, y, z, o), rot, Seconds(respawnDelay))); +#else + QuaternionData rot = QuaternionData::fromEulerAnglesZYX(o, 0.f, 0.f); + Eluna::Push(L, obj->SummonGameObject(entry, x, y, z, o, rot, respawnDelay)); +#endif + return 1; + } + + /** + * Spawns the creature at specified location. + * + * enum TempSummonType + * { + * TEMPSUMMON_TIMED_OR_DEAD_DESPAWN = 1, // despawns after a specified time OR when the creature disappears + * TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN = 2, // despawns after a specified time OR when the creature dies + * TEMPSUMMON_TIMED_DESPAWN = 3, // despawns after a specified time + * TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT = 4, // despawns after a specified time after the creature is out of combat + * TEMPSUMMON_CORPSE_DESPAWN = 5, // despawns instantly after death + * TEMPSUMMON_CORPSE_TIMED_DESPAWN = 6, // despawns after a specified time after death + * TEMPSUMMON_DEAD_DESPAWN = 7, // despawns when the creature disappears + * TEMPSUMMON_MANUAL_DESPAWN = 8, // despawns when UnSummon() is called + * TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN = 9, // despawns after a specified time (OOC) OR when the creature dies + * TEMPSUMMON_TIMED_OOC_OR_DEAD_DESPAWN = 10 // despawns after a specified time (OOC) OR when the creature disappears + * }; + * + * @param uint32 entry : [Creature]'s entry ID + * @param float x + * @param float y + * @param float z + * @param float o + * @param [TempSummonType] spawnType = MANUAL_DESPAWN : defines how and when the creature despawns + * @param uint32 despawnTimer = 0 : despawn time in milliseconds + * @return [Creature] spawnedCreature + */ + int SpawnCreature(lua_State* L, WorldObject* obj) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + uint32 spawnType = Eluna::CHECKVAL(L, 7, 8); + uint32 despawnTimer = Eluna::CHECKVAL(L, 8, 0); + + TempSummonType type; + switch (spawnType) + { + case 1: + type = TEMPSUMMON_TIMED_OR_DEAD_DESPAWN; + break; + case 2: + type = TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN; + break; + case 3: + type = TEMPSUMMON_TIMED_DESPAWN; + break; + case 4: + type = TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT; + break; + case 5: + type = TEMPSUMMON_CORPSE_DESPAWN; + break; + case 6: + type = TEMPSUMMON_CORPSE_TIMED_DESPAWN; + break; + case 7: + type = TEMPSUMMON_DEAD_DESPAWN; + break; + case 8: + type = TEMPSUMMON_MANUAL_DESPAWN; + break; + default: + return luaL_argerror(L, 7, "valid SpawnType expected"); + } + +#ifndef CATA + Eluna::Push(L, obj->SummonCreature(entry, x, y, z, o, type, Milliseconds(despawnTimer))); +#else + Eluna::Push(L, obj->SummonCreature(entry, x, y, z, o, type, despawnTimer)); +#endif + return 1; + } + + /** + * Registers a timed event to the [WorldObject] + * When the passed function is called, the parameters `(eventId, delay, repeats, worldobject)` are passed to it. + * Repeats will decrease on each call if the event does not repeat indefinitely + * + * Note that for [Creature] and [GameObject] the timed event timer ticks only if the creature is in sight of someone + * For all [WorldObject]s the timed events are removed when the object is destoryed. This means that for example a [Player]'s events are removed on logout. + * + * local function Timed(eventid, delay, repeats, worldobject) + * print(worldobject:GetName()) + * end + * worldobject:RegisterEvent(Timed, 1000, 5) -- do it after 1 second 5 times + * worldobject:RegisterEvent(Timed, {1000, 10000}, 0) -- do it after 1 to 10 seconds forever + * + * @proto eventId = (function, delay) + * @proto eventId = (function, delaytable) + * @proto eventId = (function, delay, repeats) + * @proto eventId = (function, delaytable, repeats) + * + * @param function function : function to trigger when the time has passed + * @param uint32 delay : set time in milliseconds for the event to trigger + * @param table delaytable : a table `{min, max}` containing the minimum and maximum delay time + * @param uint32 repeats = 1 : how many times for the event to repeat, 0 is infinite + * @return int eventId : unique ID for the timed event used to cancel it or nil + */ + int RegisterEvent(lua_State* L, WorldObject* obj) + { + luaL_checktype(L, 2, LUA_TFUNCTION); + uint32 min, max; + if (lua_istable(L, 3)) + { + Eluna::Push(L, 1); + lua_gettable(L, 3); + min = Eluna::CHECKVAL(L, -1); + Eluna::Push(L, 2); + lua_gettable(L, 3); + max = Eluna::CHECKVAL(L, -1); + lua_pop(L, 2); + } + else + min = max = Eluna::CHECKVAL(L, 3); + uint32 repeats = Eluna::CHECKVAL(L, 4, 1); + + if (min > max) + return luaL_argerror(L, 3, "min is bigger than max delay"); + + lua_pushvalue(L, 2); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF) + { + obj->elunaEvents->AddEvent(functionRef, min, max, repeats); + Eluna::Push(L, functionRef); + } + return 1; + } + + /** + * Removes the timed event from a [WorldObject] by the specified event ID + * + * @param int eventId : event Id to remove + */ + int RemoveEventById(lua_State* L, WorldObject* obj) + { + int eventId = Eluna::CHECKVAL(L, 2); + obj->elunaEvents->SetState(eventId, LUAEVENT_STATE_ABORT); + return 0; + } + + /** + * Removes all timed events from a [WorldObject] + * + */ + int RemoveEvents(lua_State* /*L*/, WorldObject* obj) + { + obj->elunaEvents->SetStates(LUAEVENT_STATE_ABORT); + return 0; + } + + /** + * Returns true if the given [WorldObject] or coordinates are in the [WorldObject]'s line of sight + * + * @proto isInLoS = (worldobject) + * @proto isInLoS = (x, y, z) + * + * @param [WorldObject] worldobject + * @param float x + * @param float y + * @param float z + * @return bool isInLoS + */ + int IsWithinLoS(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + + if (target) + Eluna::Push(L, obj->IsWithinLOSInMap(target)); + else + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + Eluna::Push(L, obj->IsWithinLOS(x, y, z)); + } + + return 1; + } + + /** + * Returns true if the [WorldObject]s are on the same map + * + * @param [WorldObject] worldobject + * @return bool isInMap + */ + int IsInMap(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, true); + Eluna::Push(L, obj->IsInMap(target)); + return 1; + } + + /** + * Returns true if the point is in the given distance of the [WorldObject] + * + * Notice that the distance is measured from the edge of the [WorldObject]. + * + * @param float x + * @param float y + * @param float z + * @param float distance + * @return bool isInDistance + */ + int IsWithinDist3d(lua_State* L, WorldObject* obj) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float dist = Eluna::CHECKVAL(L, 5); + Eluna::Push(L, obj->IsWithinDist3d(x, y, z, dist)); + return 1; + } + + /** + * Returns true if the point is in the given distance of the [WorldObject] + * + * The distance is measured only in x,y coordinates. + * Notice that the distance is measured from the edge of the [WorldObject]. + * + * @param float x + * @param float y + * @param float distance + * @return bool isInDistance + */ + int IsWithinDist2d(lua_State* L, WorldObject* obj) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float dist = Eluna::CHECKVAL(L, 4); + Eluna::Push(L, obj->IsWithinDist2d(x, y, dist)); + return 1; + } + + /** + * Returns true if the target is in the given distance of the [WorldObject] + * + * Notice that the distance is measured from the edge of the [WorldObject]s. + * + * @param [WorldObject] target + * @param float distance + * @param bool is3D = true : if false, only x,y coordinates used for checking + * @return bool isInDistance + */ + int IsWithinDist(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, true); + float distance = Eluna::CHECKVAL(L, 3); + bool is3D = Eluna::CHECKVAL(L, 4, true); + Eluna::Push(L, obj->IsWithinDist(target, distance, is3D)); + return 1; + } + + /** + * Returns true if the [WorldObject] is on the same map and within given distance + * + * Notice that the distance is measured from the edge of the [WorldObject]s. + * + * @param [WorldObject] target + * @param float distance + * @param bool is3D = true : if false, only x,y coordinates used for checking + * @return bool isInDistance + */ + int IsWithinDistInMap(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2); + float distance = Eluna::CHECKVAL(L, 3); + bool is3D = Eluna::CHECKVAL(L, 4, true); + + Eluna::Push(L, obj->IsWithinDistInMap(target, distance, is3D)); + return 1; + } + + /** + * Returns true if the target is within given range + * + * Notice that the distance is measured from the edge of the [WorldObject]s. + * + * @param [WorldObject] target + * @param float minrange + * @param float maxrange + * @param bool is3D = true : if false, only x,y coordinates used for checking + * @return bool isInDistance + */ + int IsInRange(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2); + float minrange = Eluna::CHECKVAL(L, 3); + float maxrange = Eluna::CHECKVAL(L, 4); + bool is3D = Eluna::CHECKVAL(L, 5, true); + + Eluna::Push(L, obj->IsInRange(target, minrange, maxrange, is3D)); + return 1; + } + + /** + * Returns true if the point is within given range + * + * Notice that the distance is measured from the edge of the [WorldObject]. + * + * @param float x + * @param float y + * @param float minrange + * @param float maxrange + * @return bool isInDistance + */ + int IsInRange2d(lua_State* L, WorldObject* obj) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float minrange = Eluna::CHECKVAL(L, 4); + float maxrange = Eluna::CHECKVAL(L, 5); + + Eluna::Push(L, obj->IsInRange2d(x, y, minrange, maxrange)); + return 1; + } + + /** + * Returns true if the point is within given range + * + * Notice that the distance is measured from the edge of the [WorldObject]. + * + * @param float x + * @param float y + * @param float z + * @param float minrange + * @param float maxrange + * @return bool isInDistance + */ + int IsInRange3d(lua_State* L, WorldObject* obj) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float minrange = Eluna::CHECKVAL(L, 5); + float maxrange = Eluna::CHECKVAL(L, 6); + + Eluna::Push(L, obj->IsInRange3d(x, y, z, minrange, maxrange)); + return 1; + } + + /** + * Returns true if the target is in the given arc in front of the [WorldObject] + * + * @param [WorldObject] target + * @param float arc = pi + * @return bool isInFront + */ + int IsInFront(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2); + float arc = Eluna::CHECKVAL(L, 3, static_cast(M_PI)); + + Eluna::Push(L, obj->isInFront(target, arc)); + return 1; + } + + /** + * Returns true if the target is in the given arc behind the [WorldObject] + * + * @param [WorldObject] target + * @param float arc = pi + * @return bool isInBack + */ + int IsInBack(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2); + float arc = Eluna::CHECKVAL(L, 3, static_cast(M_PI)); + + Eluna::Push(L, obj->isInBack(target, arc)); + return 1; + } + + /** + * The [WorldObject] plays music to a [Player] + * + * If no [Player] provided it will play the music to everyone near. + * This method does not interrupt previously played music. + * + * See also [WorldObject:PlayDistanceSound], [WorldObject:PlayDirectSound] + * + * @param uint32 music : entry of a music + * @param [Player] player = nil : [Player] to play the music to + */ + int PlayMusic(lua_State* L, WorldObject* obj) + { + uint32 musicid = Eluna::CHECKVAL(L, 2); + Player* player = Eluna::CHECKOBJ(L, 3, false); + + WorldPacket data(SMSG_PLAY_MUSIC, 4); + data << uint32(musicid); + + if (player) + player->SendDirectMessage(&data); + else + obj->SendMessageToSet(&data, true); + + return 0; + } + + /** + * The [WorldObject] plays a sound to a [Player] + * + * If no [Player] provided it will play the sound to everyone near. + * This method will play sound and does not interrupt prvious sound. + * + * See also [WorldObject:PlayDistanceSound], [WorldObject:PlayMusic] + * + * @param uint32 sound : entry of a sound + * @param [Player] player = nil : [Player] to play the sound to + */ + int PlayDirectSound(lua_State* L, WorldObject* obj) + { + uint32 soundId = Eluna::CHECKVAL(L, 2); + Player* player = Eluna::CHECKOBJ(L, 3, false); + if (!sSoundEntriesStore.LookupEntry(soundId)) + return 0; + + if (player) + obj->PlayDirectSound(soundId, player); + else + obj->PlayDirectSound(soundId); + + return 0; + } + + /** + * The [WorldObject] plays a sound to a [Player] + * + * If no [Player] it will play the sound to everyone near. + * Sound will fade the further you are from the [WorldObject]. + * This method interrupts previously playing sound. + * + * See also [WorldObject:PlayDirectSound], [WorldObject:PlayMusic] + * + * @param uint32 sound : entry of a sound + * @param [Player] player = nil : [Player] to play the sound to + */ + int PlayDistanceSound(lua_State* L, WorldObject* obj) + { + uint32 soundId = Eluna::CHECKVAL(L, 2); + Player* player = Eluna::CHECKOBJ(L, 3, false); + if (!sSoundEntriesStore.LookupEntry(soundId)) + return 0; + + if (player) + obj->PlayDistanceSound(soundId, player); + else + obj->PlayDistanceSound(soundId); + + return 0; + } + + ElunaRegister WorldObjectMethods[] = + { + // Getters + { "GetName", &LuaWorldObject::GetName }, + { "GetMap", &LuaWorldObject::GetMap }, + { "GetPhaseMask", &LuaWorldObject::GetPhaseMask }, + { "SetPhaseMask", &LuaWorldObject::SetPhaseMask }, + { "GetInstanceId", &LuaWorldObject::GetInstanceId }, + { "GetAreaId", &LuaWorldObject::GetAreaId }, + { "GetZoneId", &LuaWorldObject::GetZoneId }, + { "GetMapId", &LuaWorldObject::GetMapId }, + { "GetX", &LuaWorldObject::GetX }, + { "GetY", &LuaWorldObject::GetY }, + { "GetZ", &LuaWorldObject::GetZ }, + { "GetO", &LuaWorldObject::GetO }, + { "GetLocation", &LuaWorldObject::GetLocation }, + { "GetPlayersInRange", &LuaWorldObject::GetPlayersInRange }, + { "GetCreaturesInRange", &LuaWorldObject::GetCreaturesInRange }, + { "GetGameObjectsInRange", &LuaWorldObject::GetGameObjectsInRange }, + { "GetNearestPlayer", &LuaWorldObject::GetNearestPlayer }, + { "GetNearestGameObject", &LuaWorldObject::GetNearestGameObject }, + { "GetNearestCreature", &LuaWorldObject::GetNearestCreature }, + { "GetNearObject", &LuaWorldObject::GetNearObject }, + { "GetNearObjects", &LuaWorldObject::GetNearObjects }, + { "GetDistance", &LuaWorldObject::GetDistance }, + { "GetExactDistance", &LuaWorldObject::GetExactDistance }, + { "GetDistance2d", &LuaWorldObject::GetDistance2d }, + { "GetExactDistance2d", &LuaWorldObject::GetExactDistance2d }, + { "GetRelativePoint", &LuaWorldObject::GetRelativePoint }, + { "GetAngle", &LuaWorldObject::GetAngle }, + + // Boolean + { "IsWithinLoS", &LuaWorldObject::IsWithinLoS }, + { "IsInMap", &LuaWorldObject::IsInMap }, + { "IsWithinDist3d", &LuaWorldObject::IsWithinDist3d }, + { "IsWithinDist2d", &LuaWorldObject::IsWithinDist2d }, + { "IsWithinDist", &LuaWorldObject::IsWithinDist }, + { "IsWithinDistInMap", &LuaWorldObject::IsWithinDistInMap }, + { "IsInRange", &LuaWorldObject::IsInRange }, + { "IsInRange2d", &LuaWorldObject::IsInRange2d }, + { "IsInRange3d", &LuaWorldObject::IsInRange3d }, + { "IsInFront", &LuaWorldObject::IsInFront }, + { "IsInBack", &LuaWorldObject::IsInBack }, + + // Other + { "SummonGameObject", &LuaWorldObject::SummonGameObject }, + { "SpawnCreature", &LuaWorldObject::SpawnCreature }, + { "SendPacket", &LuaWorldObject::SendPacket }, + { "RegisterEvent", &LuaWorldObject::RegisterEvent }, + { "RemoveEventById", &LuaWorldObject::RemoveEventById }, + { "RemoveEvents", &LuaWorldObject::RemoveEvents }, + { "PlayMusic", &LuaWorldObject::PlayMusic }, + { "PlayDirectSound", &LuaWorldObject::PlayDirectSound }, + { "PlayDistanceSound", &LuaWorldObject::PlayDistanceSound }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/TrinityCore/WorldPacketMethods.h b/src/modules/Eluna/TrinityCore/WorldPacketMethods.h new file mode 100644 index 0000000000..b1ea86b73c --- /dev/null +++ b/src/modules/Eluna/TrinityCore/WorldPacketMethods.h @@ -0,0 +1,347 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef WORLDPACKETMETHODS_H +#define WORLDPACKETMETHODS_H + +/*** + * A packet used to pass messages between the server and a client. + * + * Each packet has an opcode that determines the type of message being sent, + * e.g. if a CMSG_LOGOUT_REQUEST packet is sent to the server, + * the client has sent a message that its [Player] wants to logout. + * + * The packet can contain further data, the format of which depends on the opcode. + * + * Inherits all methods from: none + */ +namespace LuaPacket +{ + /** + * Returns the opcode of the [WorldPacket]. + * + * @return uint16 opcode + */ + int GetOpcode(lua_State* L, WorldPacket* packet) + { + Eluna::Push(L, packet->GetOpcode()); + return 1; + } + + /** + * Returns the size of the [WorldPacket]. + * + * @return uint32 size + */ + int GetSize(lua_State* L, WorldPacket* packet) + { + Eluna::Push(L, packet->size()); + return 1; + } + + /** + * Sets the opcode of the [WorldPacket] to the specified opcode. + * + * @param [Opcodes] opcode : see Opcodes.h for all known opcodes + */ + int SetOpcode(lua_State* L, WorldPacket* packet) + { + uint32 opcode = Eluna::CHECKVAL(L, 2); + if (opcode >= NUM_MSG_TYPES) + return luaL_argerror(L, 2, "valid opcode expected"); + + packet->SetOpcode((OpcodesList)opcode); + return 0; + } + + /** + * Reads and returns a signed 8-bit integer value from the [WorldPacket]. + * + * @return int8 value + */ + int ReadByte(lua_State* L, WorldPacket* packet) + { + int8 _byte; + (*packet) >> _byte; + Eluna::Push(L, _byte); + return 1; + } + + /** + * Reads and returns an unsigned 8-bit integer value from the [WorldPacket]. + * + * @return uint8 value + */ + int ReadUByte(lua_State* L, WorldPacket* packet) + { + uint8 _ubyte; + (*packet) >> _ubyte; + Eluna::Push(L, _ubyte); + return 1; + } + + /** + * Reads and returns a signed 16-bit integer value from the [WorldPacket]. + * + * @return int16 value + */ + int ReadShort(lua_State* L, WorldPacket* packet) + { + int16 _short; + (*packet) >> _short; + Eluna::Push(L, _short); + return 1; + } + + /** + * Reads and returns an unsigned 16-bit integer value from the [WorldPacket]. + * + * @return uint16 value + */ + int ReadUShort(lua_State* L, WorldPacket* packet) + { + uint16 _ushort; + (*packet) >> _ushort; + Eluna::Push(L, _ushort); + return 1; + } + + /** + * Reads and returns a signed 32-bit integer value from the [WorldPacket]. + * + * @return int32 value + */ + int ReadLong(lua_State* L, WorldPacket* packet) + { + int32 _long; + (*packet) >> _long; + Eluna::Push(L, _long); + return 1; + } + + /** + * Reads and returns an unsigned 32-bit integer value from the [WorldPacket]. + * + * @return uint32 value + */ + int ReadULong(lua_State* L, WorldPacket* packet) + { + uint32 _ulong; + (*packet) >> _ulong; + Eluna::Push(L, _ulong); + return 1; + } + + /** + * Reads and returns a single-precision floating-point value from the [WorldPacket]. + * + * @return float value + */ + int ReadFloat(lua_State* L, WorldPacket* packet) + { + float _val; + (*packet) >> _val; + Eluna::Push(L, _val); + return 1; + } + + /** + * Reads and returns a double-precision floating-point value from the [WorldPacket]. + * + * @return double value + */ + int ReadDouble(lua_State* L, WorldPacket* packet) + { + double _val; + (*packet) >> _val; + Eluna::Push(L, _val); + return 1; + } + + /** + * Reads and returns an unsigned 64-bit integer value from the [WorldPacket]. + * + * @return ObjectGuid value : value returned as string + */ + int ReadGUID(lua_State* L, WorldPacket* packet) + { + ObjectGuid guid; + (*packet) >> guid; + Eluna::Push(L, guid); + return 1; + } + + /** + * Reads and returns a string value from the [WorldPacket]. + * + * @return string value + */ + int ReadString(lua_State* L, WorldPacket* packet) + { + std::string _val; + (*packet) >> _val; + Eluna::Push(L, _val); + return 1; + } + + /** + * Writes an unsigned 64-bit integer value to the [WorldPacket]. + * + * @param ObjectGuid value : the value to be written to the [WorldPacket] + */ + int WriteGUID(lua_State* L, WorldPacket* packet) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + (*packet) << guid; + return 0; + } + + /** + * Writes a string to the [WorldPacket]. + * + * @param string value : the string to be written to the [WorldPacket] + */ + int WriteString(lua_State* L, WorldPacket* packet) + { + std::string _val = Eluna::CHECKVAL(L, 2); + (*packet) << _val; + return 0; + } + + /** + * Writes a signed 8-bit integer value to the [WorldPacket]. + * + * @param int8 value : the int8 value to be written to the [WorldPacket] + */ + int WriteByte(lua_State* L, WorldPacket* packet) + { + int8 byte = Eluna::CHECKVAL(L, 2); + (*packet) << byte; + return 0; + } + + /** + * Writes an unsigned 8-bit integer value to the [WorldPacket]. + * + * @param uint8 value : the uint8 value to be written to the [WorldPacket] + */ + int WriteUByte(lua_State* L, WorldPacket* packet) + { + uint8 byte = Eluna::CHECKVAL(L, 2); + (*packet) << byte; + return 0; + } + + /** + * Writes a signed 16-bit integer value to the [WorldPacket]. + * + * @param int16 value : the int16 value to be written to the [WorldPacket] + */ + int WriteShort(lua_State* L, WorldPacket* packet) + { + int16 _short = Eluna::CHECKVAL(L, 2); + (*packet) << _short; + return 0; + } + + /** + * Writes an unsigned 16-bit integer value to the [WorldPacket]. + * + * @param uint16 value : the uint16 value to be written to the [WorldPacket] + */ + int WriteUShort(lua_State* L, WorldPacket* packet) + { + uint16 _ushort = Eluna::CHECKVAL(L, 2); + (*packet) << _ushort; + return 0; + } + + /** + * Writes a signed 32-bit integer value to the [WorldPacket]. + * + * @param int32 value : the int32 value to be written to the [WorldPacket] + */ + int WriteLong(lua_State* L, WorldPacket* packet) + { + int32 _long = Eluna::CHECKVAL(L, 2); + (*packet) << _long; + return 0; + } + + /** + * Writes an unsigned 32-bit integer value to the [WorldPacket]. + * + * @param uint32 value : the uint32 value to be written to the [WorldPacket] + */ + int WriteULong(lua_State* L, WorldPacket* packet) + { + uint32 _ulong = Eluna::CHECKVAL(L, 2); + (*packet) << _ulong; + return 0; + } + + /** + * Writes a 32-bit floating-point value to the [WorldPacket]. + * + * @param float value : the float value to be written to the [WorldPacket] + */ + int WriteFloat(lua_State* L, WorldPacket* packet) + { + float _val = Eluna::CHECKVAL(L, 2); + (*packet) << _val; + return 0; + } + + /** + * Writes a 64-bit floating-point value to the [WorldPacket]. + * + * @param double value : the double value to be written to the [WorldPacket] + */ + int WriteDouble(lua_State* L, WorldPacket* packet) + { + double _val = Eluna::CHECKVAL(L, 2); + (*packet) << _val; + return 0; + } + + ElunaRegister PacketMethods[] = + { + // Getters + { "GetOpcode", &LuaPacket::GetOpcode }, + { "GetSize", &LuaPacket::GetSize }, + + // Setters + { "SetOpcode", &LuaPacket::SetOpcode }, + + // Readers + { "ReadByte", &LuaPacket::ReadByte }, + { "ReadUByte", &LuaPacket::ReadUByte }, + { "ReadShort", &LuaPacket::ReadShort }, + { "ReadUShort", &LuaPacket::ReadUShort }, + { "ReadLong", &LuaPacket::ReadLong }, + { "ReadULong", &LuaPacket::ReadULong }, + { "ReadGUID", &LuaPacket::ReadGUID }, + { "ReadString", &LuaPacket::ReadString }, + { "ReadFloat", &LuaPacket::ReadFloat }, + { "ReadDouble", &LuaPacket::ReadDouble }, + + // Writers + { "WriteByte", &LuaPacket::WriteByte }, + { "WriteUByte", &LuaPacket::WriteUByte }, + { "WriteShort", &LuaPacket::WriteShort }, + { "WriteUShort", &LuaPacket::WriteUShort }, + { "WriteLong", &LuaPacket::WriteLong }, + { "WriteULong", &LuaPacket::WriteULong }, + { "WriteGUID", &LuaPacket::WriteGUID }, + { "WriteString", &LuaPacket::WriteString }, + { "WriteFloat", &LuaPacket::WriteFloat }, + { "WriteDouble", &LuaPacket::WriteDouble }, + + { NULL, NULL } + }; +}; + +#endif diff --git a/src/modules/Eluna/VMangos/AuraMethods.h b/src/modules/Eluna/VMangos/AuraMethods.h new file mode 100644 index 0000000000..a590cf36d0 --- /dev/null +++ b/src/modules/Eluna/VMangos/AuraMethods.h @@ -0,0 +1,230 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef AURAMETHODS_H +#define AURAMETHODS_H + +/*** + * The persistent effect of a [Spell] that remains on a [Unit] after the [Spell] + * has been cast. + * + * As an example, if you cast a damage-over-time spell on a target, an [Aura] is + * put on the target that deals damage continuously. + * + * [Aura]s on your player are displayed in-game as a series of icons to the left + * of the mini-map. + * + * Inherits all methods from: none + */ +namespace LuaAura +{ + /** + * Returns the [Unit] that casted the [Spell] that caused this [Aura] to be applied. + * + * @return [Unit] caster + */ + int GetCaster(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetCaster()); + return 1; + } + + /** + * Returns the GUID of the [Unit] that casted the [Spell] that caused this [Aura] to be applied. + * + * @return string caster_guid : the GUID of the Unit as a decimal string + */ + int GetCasterGUID(lua_State* L, Aura* aura) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, aura->GetCasterGUID()); +#else + Eluna::Push(L, aura->GetCasterGuid()); +#endif + return 1; + } + + /** + * Returns the level of the [Unit] that casted the [Spell] that caused this [Aura] to be applied. + * + * @return uint32 caster_level + */ + int GetCasterLevel(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetCaster()->GetLevel()); + return 1; + } + + /** + * Returns the amount of time left until the [Aura] expires. + * + * @return int32 duration : amount of time left in milliseconds + */ + int GetDuration(lua_State* L, Aura* aura) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, aura->GetDuration()); +#else + Eluna::Push(L, aura->GetAuraDuration()); +#endif + return 1; + } + + /** + * Returns the ID of the [Spell] that caused this [Aura] to be applied. + * + * @return uint32 aura_id + */ + int GetAuraId(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetId()); + return 1; + } + + /** + * Returns the amount of time this [Aura] lasts when applied. + * + * To determine how much time has passed since this Aura was applied, + * subtract the result of [Aura]:GetDuration from the result of this method. + * + * @return int32 max_duration : the maximum duration of the Aura, in milliseconds + */ + int GetMaxDuration(lua_State* L, Aura* aura) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, aura->GetMaxDuration()); +#else + Eluna::Push(L, aura->GetAuraMaxDuration()); +#endif + return 1; + } + + /** + * Returns the number of times the [Aura] has "stacked". + * + * This is the same as the number displayed on the [Aura]'s icon in-game. + * + * @return uint32 stack_amount + */ + int GetStackAmount(lua_State* L, Aura* aura) + { + Eluna::Push(L, aura->GetStackAmount()); + return 1; + } + + /** + * Returns the [Unit] that the [Aura] has been applied to. + * + * @return [Unit] owner + */ + int GetOwner(lua_State* L, Aura* aura) + { +#if defined TRINITY || defined AZEROTHCORE + Eluna::Push(L, aura->GetOwner()); +#else + Eluna::Push(L, aura->GetTarget()); +#endif + return 1; + } + + /** + * Change the amount of time before the [Aura] expires. + * + * @param int32 duration : the new duration of the Aura, in milliseconds + */ + int SetDuration(lua_State* L, Aura* aura) + { + int32 duration = Eluna::CHECKVAL(L, 2); +#if defined TRINITY || defined AZEROTHCORE + aura->SetDuration(duration); +#else + aura->GetHolder()->SetAuraDuration(duration); +#if (defined(TBC) || defined(CLASSIC)) + aura->GetHolder()->UpdateAuraDuration(); +#else + aura->GetHolder()->SendAuraUpdate(false); +#endif +#endif + return 0; + } + + /** + * Change the maximum amount of time before the [Aura] expires. + * + * This does not affect the current duration of the [Aura], but if the [Aura] + * is reset to the maximum duration, it will instead change to `duration`. + * + * @param int32 duration : the new maximum duration of the Aura, in milliseconds + */ + int SetMaxDuration(lua_State* L, Aura* aura) + { + int32 duration = Eluna::CHECKVAL(L, 2); +#if defined TRINITY || defined AZEROTHCORE + aura->SetMaxDuration(duration); +#else + aura->GetHolder()->SetAuraMaxDuration(duration); +#if (defined(TBC) || defined(CLASSIC)) + aura->GetHolder()->UpdateAuraDuration(); +#else + aura->GetHolder()->SendAuraUpdate(false); +#endif +#endif + return 0; + } + + /** + * Change the amount of times the [Aura] has "stacked" on the [Unit]. + * + * If `amount` is greater than or equal to the current number of stacks, + * then the [Aura] has its duration reset to the maximum duration. + * + * @param uint32 amount + */ + int SetStackAmount(lua_State* L, Aura* aura) + { + uint8 amount = Eluna::CHECKVAL(L, 2); + aura->GetHolder()->SetStackAmount(amount); + return 0; + } + + /** + * Remove this [Aura] from the [Unit] it is applied to. + */ + int Remove(lua_State* L, Aura* aura) + { +#if defined TRINITY || defined AZEROTHCORE + aura->Remove(); +#else + aura->GetTarget()->RemoveSpellAuraHolder(aura->GetHolder(), AURA_REMOVE_BY_CANCEL); +#endif + Eluna::CHECKOBJ(L, 1)->Invalidate(); + return 0; + } + + ElunaRegister AuraMethods[] = + { + // Getters + { "GetCaster", &LuaAura::GetCaster }, + { "GetCasterGUID", &LuaAura::GetCasterGUID }, + { "GetCasterLevel", &LuaAura::GetCasterLevel }, + { "GetDuration", &LuaAura::GetDuration }, + { "GetMaxDuration", &LuaAura::GetMaxDuration }, + { "GetAuraId", &LuaAura::GetAuraId }, + { "GetStackAmount", &LuaAura::GetStackAmount }, + { "GetOwner", &LuaAura::GetOwner }, + + // Setters + { "SetDuration", &LuaAura::SetDuration }, + { "SetMaxDuration", &LuaAura::SetMaxDuration }, + { "SetStackAmount", &LuaAura::SetStackAmount }, + + // Other + { "Remove", &LuaAura::Remove }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/BattleGroundMethods.h b/src/modules/Eluna/VMangos/BattleGroundMethods.h similarity index 82% rename from src/modules/Eluna/BattleGroundMethods.h rename to src/modules/Eluna/VMangos/BattleGroundMethods.h index 54d5bdd7d2..21ddabb282 100644 --- a/src/modules/Eluna/BattleGroundMethods.h +++ b/src/modules/Eluna/VMangos/BattleGroundMethods.h @@ -121,11 +121,7 @@ namespace LuaBattleGround */ int GetInstanceId(lua_State* L, BattleGround* bg) { -#ifdef CMANGOS - Eluna::Push(L, bg->GetInstanceId()); -#else Eluna::Push(L, bg->GetInstanceID()); -#endif return 1; } @@ -147,13 +143,7 @@ namespace LuaBattleGround */ int GetTypeId(lua_State* L, BattleGround* bg) { -#ifdef CMANGOS - Eluna::Push(L, bg->GetTypeId()); -#elif !AZEROTHCORE Eluna::Push(L, bg->GetTypeID()); -#else - Eluna::Push(L, bg->GetBgTypeID()); -#endif return 1; } @@ -252,5 +242,30 @@ namespace LuaBattleGround Eluna::Push(L, bg->GetStatus()); return 1; } + + ElunaRegister BattleGroundMethods[] = + { + // Getters + { "GetName", &LuaBattleGround::GetName }, + { "GetAlivePlayersCountByTeam", &LuaBattleGround::GetAlivePlayersCountByTeam }, + { "GetMap", &LuaBattleGround::GetMap }, + { "GetBonusHonorFromKillCount", &LuaBattleGround::GetBonusHonorFromKillCount }, + { "GetBracketId", &LuaBattleGround::GetBracketId }, + { "GetEndTime", &LuaBattleGround::GetEndTime }, + { "GetFreeSlotsForTeam", &LuaBattleGround::GetFreeSlotsForTeam }, + { "GetInstanceId", &LuaBattleGround::GetInstanceId }, + { "GetMapId", &LuaBattleGround::GetMapId }, + { "GetTypeId", &LuaBattleGround::GetTypeId }, + { "GetMaxLevel", &LuaBattleGround::GetMaxLevel }, + { "GetMinLevel", &LuaBattleGround::GetMinLevel }, + { "GetMaxPlayers", &LuaBattleGround::GetMaxPlayers }, + { "GetMinPlayers", &LuaBattleGround::GetMinPlayers }, + { "GetMaxPlayersPerTeam", &LuaBattleGround::GetMaxPlayersPerTeam }, + { "GetMinPlayersPerTeam", &LuaBattleGround::GetMinPlayersPerTeam }, + { "GetWinner", &LuaBattleGround::GetWinner }, + { "GetStatus", &LuaBattleGround::GetStatus }, + + { NULL, NULL } + }; }; #endif diff --git a/src/modules/Eluna/VMangos/CorpseMethods.h b/src/modules/Eluna/VMangos/CorpseMethods.h new file mode 100644 index 0000000000..13188331fe --- /dev/null +++ b/src/modules/Eluna/VMangos/CorpseMethods.h @@ -0,0 +1,95 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef CORPSEMETHODS_H +#define CORPSEMETHODS_H + +/*** + * The remains of a [Player] that has died. + * + * Inherits all methods from: [Object], [WorldObject] + */ +namespace LuaCorpse +{ + /** + * Returns the GUID of the [Player] that left the [Corpse] behind. + * + * @return ObjectGuid ownerGUID + */ + int GetOwnerGUID(lua_State* L, Corpse* corpse) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, corpse->GetOwnerGUID()); +#else + Eluna::Push(L, corpse->GetOwnerGuid()); +#endif + return 1; + } + + /** + * Returns the time when the [Player] became a ghost and spawned this [Corpse]. + * + * @return uint32 ghostTime + */ + int GetGhostTime(lua_State* L, Corpse* corpse) + { + Eluna::Push(L, corpse->GetGhostTime()); + return 1; + } + + /** + * Returns the [CorpseType] of a [Corpse]. + * + * enum CorpseType + * { + * CORPSE_BONES = 0, + * CORPSE_RESURRECTABLE_PVE = 1, + * CORPSE_RESURRECTABLE_PVP = 2 + * }; + * + * @return [CorpseType] corpseType + */ + int GetType(lua_State* L, Corpse* corpse) + { + Eluna::Push(L, corpse->GetType()); + return 1; + } + + /** + * Sets the "ghost time" to the current time. + * + * See [Corpse:GetGhostTime]. + */ + int ResetGhostTime(lua_State* /*L*/, Corpse* corpse) + { + corpse->ResetGhostTime(); + return 0; + } + + /** + * Saves the [Corpse] to the database. + */ + int SaveToDB(lua_State* /*L*/, Corpse* corpse) + { + corpse->SaveToDB(); + return 0; + } + + ElunaRegister CorpseMethods[] = + { + // Getters + { "GetOwnerGUID", &LuaCorpse::GetOwnerGUID }, + { "GetGhostTime", &LuaCorpse::GetGhostTime }, + { "GetType", &LuaCorpse::GetType }, + + // Other + { "ResetGhostTime", &LuaCorpse::ResetGhostTime }, + { "SaveToDB", &LuaCorpse::SaveToDB }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/VMangos/CreatureMethods.h b/src/modules/Eluna/VMangos/CreatureMethods.h new file mode 100644 index 0000000000..3334fad928 --- /dev/null +++ b/src/modules/Eluna/VMangos/CreatureMethods.h @@ -0,0 +1,1517 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef CREATUREMETHODS_H +#define CREATUREMETHODS_H + +/*** + * Non-[Player] controlled [Unit]s (i.e. NPCs). + * + * Inherits all methods from: [Object], [WorldObject], [Unit] + */ +namespace LuaCreature +{ + /** + * Returns `true` if the [Creature] can regenerate health, + * and returns `false` otherwise. + * + * @return bool isRegenerating + */ + int IsRegeneratingHealth(lua_State* L, Creature* creature) + { +#if defined(AZEROTHCORE) + Eluna::Push(L, creature->isRegeneratingHealth()); +#elif defined(TRINITY) + Eluna::Push(L, creature->CanRegenerateHealth()); +#else + Eluna::Push(L, creature->IsRegeneratingHealth()); +#endif + return 1; + } + +#if defined(TRINITY) || defined(AZEROTHCORE) + /** + * Sets whether the [Creature] can regenerate health or not. + * + * @param bool enable = true : `true` to enable health regeneration, `false` to disable it + */ + int SetRegeneratingHealth(lua_State* L, Creature* creature) + { + bool enable = Eluna::CHECKVAL(L, 2, true); + +#if defined(AZEROTHCORE) + creature->SetRegeneratingHealth(enable); +#else + creature->SetRegenerateHealth(enable); +#endif + return 0; + } +#endif + + /** + * Returns `true` if the [Creature] is set to not give reputation when killed, + * and returns `false` otherwise. + * + * @return bool reputationDisabled + */ + int IsReputationGainDisabled(lua_State* L, Creature* creature) + { +#ifndef CMANGOS + Eluna::Push(L, creature->IsReputationGainDisabled()); +#else + Eluna::Push(L, creature->IsNoReputation()); +#endif + return 1; + } + + /** + * Returns `true` if the [Creature] completes the [Quest] with the ID `questID`, + * and returns `false` otherwise. + * + * @param uint32 questID : the ID of a [Quest] + * @return bool completesQuest + */ + int CanCompleteQuest(lua_State* L, Creature* creature) + { + uint32 quest_id = Eluna::CHECKVAL(L, 2); + +#if defined(TRINITY) || defined(AZEROTHCORE) + Eluna::Push(L, creature->hasInvolvedQuest(quest_id)); +#else + Eluna::Push(L, creature->HasInvolvedQuest(quest_id)); +#endif + return 1; + } + + /** + * Returns `true` if the [Creature] can be targeted for attack, + * and returns `false` otherwise. + * + * @param bool mustBeDead = false : if `true`, only returns `true` if the [Creature] is also dead. Otherwise, it must be alive. + * @return bool targetable + */ + int IsTargetableForAttack(lua_State* L, Creature* creature) + { + bool mustBeDead = Eluna::CHECKVAL(L, 2, false); + + Eluna::Push(L, creature->IsTargetableBy(NULL, false, mustBeDead)); + return 1; + } + + /** + * Returns `true` if the [Creature] can assist `friend` in combat against `enemy`, + * and returns `false` otherwise. + * + * @param [Unit] friend : the Unit we will be assisting + * @param [Unit] enemy : the Unit that we would attack if we assist `friend` + * @param bool checkFaction = true : if `true`, the [Creature] must be the same faction as `friend` to assist + * @return bool canAssist + */ + int CanAssistTo(lua_State* L, Creature* creature) + { + Unit* u = Eluna::CHECKOBJ(L, 2); + Unit* enemy = Eluna::CHECKOBJ(L, 3); + bool checkfaction = Eluna::CHECKVAL(L, 4, true); + + Eluna::Push(L, creature->CanAssistTo(u, enemy, checkfaction)); + return 1; + } + + /** + * Returns `true` if the [Creature] has searched for combat assistance already, + * and returns `false` otherwise. + * + * @return bool searchedForAssistance + */ + int HasSearchedAssistance(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->HasSearchedAssistance()); + return 1; + } + + /** + * Returns `true` if the [Creature] will give its loot to `player`, + * and returns `false` otherwise. + * + * @return bool tapped + */ + int IsTappedBy(lua_State* L, Creature* creature) + { + Player* player = Eluna::CHECKOBJ(L, 2); + +#if defined(TRINITY) || defined(AZEROTHCORE) + Eluna::Push(L, creature->isTappedBy(player)); +#else + Eluna::Push(L, creature->IsTappedBy(player)); +#endif + return 1; + } + + /** + * Returns `true` if the [Creature] will give its loot to a [Player] or [Group], + * and returns `false` otherwise. + * + * @return bool hasLootRecipient + */ + int HasLootRecipient(lua_State* L, Creature* creature) + { +#if defined(TRINITY) || defined(AZEROTHCORE) + Eluna::Push(L, creature->hasLootRecipient()); +#else + Eluna::Push(L, creature->HasLootRecipient()); +#endif + return 1; + } + + /** + * Returns `true` if the [Creature] can start attacking nearby hostile [Unit]s, + * and returns `false` otherwise. + * + * @return bool canAggro + */ + int CanAggro(lua_State* L, Creature* creature) + { + Eluna::Push(L, !creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)); + return 1; + } + + /** + * Returns `true` if the [Creature] can move through deep water, + * and returns `false` otherwise. + * + * @return bool canSwim + */ + int CanSwim(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->CanSwim()); + return 1; + } + + /** + * Returns `true` if the [Creature] can move on land, + * and returns `false` otherwise. + * + * @return bool canWalk + */ + int CanWalk(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->CanWalk()); + return 1; + } + + /** + * Returns `true` if the [Creature] is returning to its spawn position from combat, + * and returns `false` otherwise. + * + * @return bool inEvadeMode + */ + int IsInEvadeMode(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsInEvadeMode()); + return 1; + } + + /** + * Returns `true` if the [Creature]'s rank is Elite or Rare Elite, + * and returns `false` otherwise. + * + * @return bool isElite + */ + int IsElite(lua_State* L, Creature* creature) + { +#if defined(TRINITY) || defined(AZEROTHCORE) + Eluna::Push(L, creature->isElite()); +#else + Eluna::Push(L, creature->IsElite()); +#endif + return 1; + } + + /** + * Returns `true` if the [Creature] is a city guard, + * and returns `false` otherwise. + * + * @return bool isGuard + */ + int IsGuard(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsGuard()); + return 1; + } + + /** + * Returns `true` if the [Creature] is a civilian, + * and returns `false` otherwise. + * + * @return bool isCivilian + */ + int IsCivilian(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsCivilian()); + return 1; + } + + /** + * Returns `true` if the [Creature] is the leader of a player faction, + * and returns `false` otherwise. + * + * @return bool isLeader + */ + int IsRacialLeader(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsRacialLeader()); + return 1; + } + + /** + * Returns `true` if the [Creature]'s flags_extra includes Dungeon Boss (0x1000000), + * and returns `false` otherwise. + * + * @return bool isDungeonBoss + */ +#if defined(TRINITY) || defined(AZEROTHCORE) + int IsDungeonBoss(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsDungeonBoss()); + return 1; + } +#endif + + /** + * Returns `true` if the [Creature]'s rank is Boss, + * and returns `false` otherwise. + * + * @return bool isWorldBoss + */ + int IsWorldBoss(lua_State* L, Creature* creature) + { +#if defined(TRINITY) || defined(AZEROTHCORE) + Eluna::Push(L, creature->isWorldBoss()); +#else + Eluna::Push(L, creature->IsWorldBoss()); +#endif + return 1; + } + + /** + * Returns `true` if the [Creature] cannot cast `spellId` due to a category cooldown, + * and returns `false` otherwise. + * + * @param uint32 spellId : the ID of a [Spell] + * @return bool hasCooldown + */ + int HasCategoryCooldown(lua_State* L, Creature* creature) + { + uint32 spell = Eluna::CHECKVAL(L, 2); + + if (const SpellEntry* sp_info = sSpellMgr.GetSpellEntry(spell)) + { + Eluna::Push(L, creature->HasSpellCategoryCooldown(sp_info->Category)); + } + + return 1; + } + + /** + * Returns `true` if the [Creature] can cast `spellId` when mind-controlled, + * and returns `false` otherwise. + * + * @param uint32 spellId : the ID of a [Spell] + * @return bool hasSpell + */ + int HasSpell(lua_State* L, Creature* creature) + { + uint32 id = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->HasSpell(id)); + return 1; + } + + /** + * Returns `true` if the [Creature] starts the [Quest] `questId`, + * and returns `false` otherwise. + * + * @param uint32 questId : the ID of a [Quest] + * @return bool hasQuest + */ + int HasQuest(lua_State* L, Creature* creature) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + +#if defined(TRINITY) || defined(AZEROTHCORE) + Eluna::Push(L, creature->hasQuest(questId)); +#else + Eluna::Push(L, creature->HasQuest(questId)); +#endif + return 1; + } + + /** + * Returns `true` if the [Creature] has `spellId` on cooldown, + * and returns `false` otherwise. + * + * @param uint32 spellId : the ID of a [Spell] + * @return bool hasCooldown + */ + int HasSpellCooldown(lua_State* L, Creature* creature) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->IsSpellReady(spellId)); + return 1; + } + + /** + * Returns `true` if the [Creature] can fly, + * and returns `false` otherwise. + * + * @return bool canFly + */ + int CanFly(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->CanFly()); + return 1; + } + +#if defined(TRINITY) || defined(AZEROTHCORE) + /** + * Returns `true` if the [Creature] is an invisible trigger, + * and returns `false` otherwise. + * + * @return bool canFly + */ + int IsTrigger(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsTrigger()); + return 1; + } + + /** + * Returns true if the [Creature] is damaged enough for looting + * + * @return bool isDamagedEnough + */ + int IsDamageEnoughForLootingAndReward(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->IsDamageEnoughForLootingAndReward()); + return 1; + } + + /** + * Returns true if the [Creature] can start attacking specified target + * + * Does not work on most targets + * + * @param [Unit] target + * @param bool force = true : force [Creature] to attack + */ + int CanStartAttack(lua_State* L, Creature* creature) // TODO: Implement core side + { + Unit* target = Eluna::CHECKOBJ(L, 2); +#ifndef AZEROTHCORE + bool force = Eluna::CHECKVAL(L, 3, true); + Eluna::Push(L, creature->CanStartAttack(target, force)); +#else + Eluna::Push(L, creature->CanStartAttack(target)); +#endif + return 1; + } + + /** + * Returns true if [Creature] has the specified loot mode + * + * @param uint16 lootMode + * @return bool hasLootMode + */ + int HasLootMode(lua_State* L, Creature* creature) // TODO: Implement LootMode features + { + uint16 lootMode = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->HasLootMode(lootMode)); + return 1; + } +#endif + + /** + * Returns the time it takes for this [Creature] to respawn once killed. + * + * This value does not usually change over a [Creature]'s lifespan, + * but can be modified by [Creature:SetRespawnDelay]. + * + * @return uint32 respawnDelay : the respawn delay, in seconds + */ + int GetRespawnDelay(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetRespawnDelay()); + return 1; + } + + /** + * Returns the radius the [Creature] is permitted to wander from its + * respawn point. + * + * @return float wanderRadius + */ + int GetWanderRadius(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetWanderDistance()); + return 1; + } + +#if defined(TRINITY) || defined(AZEROTHCORE) + /** + * Returns the current waypoint path ID of the [Creature]. + * + * @return uint32 pathId + */ + int GetWaypointPath(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetWaypointPath()); + return 1; + } +#endif + + /** + * Returns the current waypoint ID of the [Creature]. + * + * @return uint32 wpId + */ + int GetCurrentWaypointId(lua_State* L, Creature* creature) + { +#if defined(TRINITY) + Eluna::Push(L, creature->GetCurrentWaypointInfo().first); +#elif defined(AZEROTHCORE) + Eluna::Push(L, creature->GetCurrentWaypointID()); +#else + Eluna::Push(L, creature->GetMotionMaster()->getLastReachedWaypoint()); +#endif + return 1; + } + + /** + * Returns the default movement type for this [Creature]. + * + * @return [MovementGeneratorType] defaultMovementType + */ + int GetDefaultMovementType(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetDefaultMovementType()); + return 1; + } + + /** + * Returns the aggro range of the [Creature] for `target`. + * + * @param [Unit] target + * @return float aggroRange + */ + int GetAggroRange(lua_State* L, Creature* creature) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + +#if defined(TRINITY) || defined(AZEROTHCORE) + Eluna::Push(L, creature->GetAggroRange(target)); +#else + float AttackDist = creature->GetAttackDistance(target); + float ThreatRadius = sWorld.getConfig(CONFIG_FLOAT_THREAT_RADIUS); + Eluna::Push(L, ThreatRadius > AttackDist ? ThreatRadius : AttackDist); +#endif + return 1; + } + +#ifndef AZEROTHCORE + /** + * Returns the effective aggro range of the [Creature] for `target`. + * + * If this is smaller than the minimum aggro range set in the config file, + * that is used as the aggro range instead. + * + * @param [Unit] target + * @return float attackDistance + */ + int GetAttackDistance(lua_State* L, Creature* creature) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, creature->GetAttackDistance(target)); + return 1; + } +#endif + + /** + * Returns the [Group] that can loot this [Creature]. + * + * @return [Group] lootRecipientGroup : the group or `nil` + */ + int GetLootRecipientGroup(lua_State* L, Creature* creature) + { +#if defined(TRINITY) || defined(AZEROTHCORE) + Eluna::Push(L, creature->GetLootRecipientGroup()); +#else + Eluna::Push(L, creature->GetGroupLootRecipient()); +#endif + return 1; + } + + /** + * Returns the [Player] that can loot this [Creature]. + * + * @return [Player] lootRecipient : the player or `nil` + */ + int GetLootRecipient(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetLootRecipient()); + return 1; + } + + /** + * Returns the [Creature]'s script name. + * + * This is used by the core to apply C++ scripts to the Creature. + * + * It is not used by Eluna. Eluna will override AI scripts. + * + * @return string scriptName + */ + int GetScriptName(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetScriptName()); + return 1; + } + + /** + * Returns the [Creature]'s AI name. + * + * This is used by the core to assign the Creature's default AI. + * + * If the Creature is scripted by Eluna, the AI is overriden. + * + * @return string AIName + */ + int GetAIName(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetAIName()); + return 1; + } + + /** + * Returns the [Creature]'s script ID. + * + * Every C++ script name is assigned a unique ID by the core. + * This returns the ID for this [Creature]'s script name. + * + * @return uint32 scriptID + */ + int GetScriptId(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetScriptId()); + return 1; + } + + /** + * Returns the [Creature]'s cooldown for `spellID`. + * + * @param uint32 spellID + * @return uint32 cooldown : the cooldown, in milliseconds + */ + int GetCreatureSpellCooldownDelay(lua_State* L, Creature* creature) + { + uint32 spell = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, creature->GetSpellCooldownDelay(spell)); + return 1; + } + + /** + * Returns the delay between when the [Creature] dies and when its body despawns. + * + * @return uint32 corpseDelay : the delay, in seconds + */ + int GetCorpseDelay(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetCorpseDelay()); + return 1; + } + + /** + * Returns position the [Creature] returns to when evading from combat + * or respawning. + * + * @return float x + * @return float y + * @return float z + * @return float o + */ + int GetHomePosition(lua_State* L, Creature* creature) + { + float x, y, z, o; +#if defined(TRINITY) || defined(AZEROTHCORE) + creature->GetHomePosition(x, y, z, o); +#else + creature->GetRespawnCoord(x, y, z, &o); +#endif + + Eluna::Push(L, x); + Eluna::Push(L, y); + Eluna::Push(L, z); + Eluna::Push(L, o); + return 4; + } + + /** + * Sets the position the [Creature] returns to when evading from combat + * or respawning. + * + * @param float x + * @param float y + * @param float z + * @param float o + */ + int SetHomePosition(lua_State* L, Creature* creature) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float o = Eluna::CHECKVAL(L, 5); + + creature->SetHomePosition(x, y, z, o); + + return 0; + } + + enum SelectAggroTarget + { + SELECT_TARGET_RANDOM = 0, // Just selects a random target + SELECT_TARGET_TOPAGGRO, // Selects targes from top aggro to bottom + SELECT_TARGET_BOTTOMAGGRO, // Selects targets from bottom aggro to top + SELECT_TARGET_NEAREST, + SELECT_TARGET_FARTHEST + }; + + /** + * Returns a target from the [Creature]'s threat list based on the + * supplied arguments. + * + * enum SelectAggroTarget + * { + * SELECT_TARGET_RANDOM = 0, //Just selects a random target + * SELECT_TARGET_TOPAGGRO, //Selects targets from top aggro to bottom + * SELECT_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top + * SELECT_TARGET_NEAREST, + * SELECT_TARGET_FARTHEST + * }; + * + * For example, if you wanted to select the third-farthest [Player] + * within 50 yards that has the [Aura] "Corrupted Blood" (ID 24328), + * you could use this function like so: + * + * target = creature:GetAITarget(4, true, 3, 50, 24328) + * + * @param [SelectAggroTarget] targetType : how the threat list should be sorted + * @param bool playerOnly = false : if `true`, skips targets that aren't [Player]s + * @param uint32 position = 0 : used as an offset into the threat list. If `targetType` is random, used as the number of players from top of aggro to choose from + * @param float distance = 0.0 : if positive, the maximum distance for the target. If negative, the minimum distance + * @param int32 aura = 0 : if positive, the target must have this [Aura]. If negative, the the target must not have this Aura + * @return [Unit] target : the target, or `nil` + */ + int GetAITarget(lua_State* L, Creature* creature) + { + uint32 targetType = Eluna::CHECKVAL(L, 2); + bool playerOnly = Eluna::CHECKVAL(L, 3, false); + uint32 position = Eluna::CHECKVAL(L, 4, 0); + float dist = Eluna::CHECKVAL(L, 5, 0.0f); + int32 aura = Eluna::CHECKVAL(L, 6, 0); + + ThreatList const& threatlist = creature->GetThreatManager().getThreatList(); + if (threatlist.empty()) + return 1; + if (position >= threatlist.size()) + return 1; + std::list targetList; + for (auto itr = threatlist.begin(); itr != threatlist.end(); ++itr) + { + Unit* target = (*itr)->getTarget(); + if (!target) + continue; + if (playerOnly && target->GetTypeId() != TYPEID_PLAYER) + continue; + if (aura > 0 && !target->HasAura(aura)) + continue; + else if (aura < 0 && target->HasAura(-aura)) + continue; + if (dist > 0.0f && !creature->IsWithinDist(target, dist)) + continue; + else if (dist < 0.0f && creature->IsWithinDist(target, -dist)) + continue; + targetList.push_back(target); + } + + if (targetList.empty()) + return 1; + if (position >= targetList.size()) + return 1; + + if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) + targetList.sort(ElunaUtil::ObjectDistanceOrderPred(creature)); + + switch (targetType) + { + case SELECT_TARGET_NEAREST: + case SELECT_TARGET_TOPAGGRO: + { + std::list::const_iterator itr = targetList.begin(); + if (position) + std::advance(itr, position); + Eluna::Push(L, *itr); + } + break; + case SELECT_TARGET_FARTHEST: + case SELECT_TARGET_BOTTOMAGGRO: + { + std::list::reverse_iterator ritr = targetList.rbegin(); + if (position) + std::advance(ritr, position); + Eluna::Push(L, *ritr); + } + break; + case SELECT_TARGET_RANDOM: + { + std::list::const_iterator itr = targetList.begin(); + if (position) + std::advance(itr, urand(0, position)); + else + std::advance(itr, urand(0, targetList.size() - 1)); + Eluna::Push(L, *itr); + } + break; + default: + luaL_argerror(L, 2, "SelectAggroTarget expected"); + break; + } + + return 1; + } + + /** + * Returns all [Unit]s in the [Creature]'s threat list. + * + * @return table targets + */ + int GetAITargets(lua_State* L, Creature* creature) + { +#if defined(TRINITY) + auto const& threatlist = creature->GetThreatManager().GetSortedThreatList(); +#elif defined(AZEROTHCORE) + auto const& threatlist = creature->getThreatMgr().getThreatList(); +#elif defined(CMANGOS) + auto const& threatlist = creature->getThreatManager().getThreatList(); +#else + ThreatList const& threatlist = creature->GetThreatManager().getThreatList(); +#endif + +#if defined(TRINITY) + lua_createtable(L, creature->GetThreatManager().GetThreatListSize(), 0); +#else + lua_createtable(L, threatlist.size(), 0); +#endif + int tbl = lua_gettop(L); + uint32 i = 0; +#if defined(TRINITY) + for (ThreatReference const* itr : threatlist) +#else + for (auto itr = threatlist.begin(); itr != threatlist.end(); ++itr) +#endif + { +#if defined(TRINITY) + Unit* target = itr->GetVictim(); +#else + Unit* target = (*itr)->getTarget(); +#endif + if (!target) + continue; + Eluna::Push(L, target); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns the number of [Unit]s in this [Creature]'s threat list. + * + * @return double targetsCount + */ + int GetAITargetsCount(lua_State* L, Creature* creature) + { +#if defined(TRINITY) + Eluna::Push(L, creature->GetThreatManager().GetThreatListSize()); +#elif defined(AZEROTHCORE) + Eluna::Push(L, creature->getThreatMgr().getThreatList().size()); +#elif defined(CMANGOS) + Eluna::Push(L, creature->getThreatManager().getThreatList().size()); +#else + Eluna::Push(L, (double)creature->GetThreatManager().getThreatList().size()); +#endif + return 1; + } + + /** + * Returns the [Creature]'s NPC flags. + * + * These are used to control whether the NPC is a vendor, can repair items, + * can give quests, etc. + * + * @return [NPCFlags] npcFlags + */ + int GetNPCFlags(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetUInt32Value(UNIT_NPC_FLAGS)); + return 1; + } + + /** + * Returns the [Creature]'s Extra flags. + * + * These are used to control whether the NPC is a civilian, uses pathfinding, + * if it's a guard, etc. + * + * @return [ExtraFlags] extraFlags + */ + int GetExtraFlags(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetCreatureInfo()->flags_extra); + return 1; + } + +#if defined(CLASSIC) || defined(TBC) || defined(WOTLK) + /** + * Returns the [Creature]'s shield block value. + * + * @return uint32 shieldBlockValue + */ + int GetShieldBlockValue(lua_State* L, Creature* creature) + { + Eluna::Push(L, creature->GetShieldBlockValue()); + return 1; + } +#endif + +#if defined(TRINITY) || defined(AZEROTHCORE) + int GetLootMode(lua_State* L, Creature* creature) // TODO: Implement LootMode features + { + Eluna::Push(L, creature->GetLootMode()); + return 1; + } +#endif + + /** + * Returns the guid of the [Creature] that is used as the ID in the database + * + * @return uint32 dbguid + */ + int GetDBTableGUIDLow(lua_State* L, Creature* creature) + { +#if defined(TRINITY) || defined(AZEROTHCORE) + Eluna::Push(L, creature->GetSpawnId()); +#else + // on mangos based this is same as lowguid + Eluna::Push(L, creature->GetGUIDLow()); +#endif + return 1; + } + + /** + * Sets the [Creature]'s NPC flags to `flags`. + * + * @param [NPCFlags] flags + */ + int SetNPCFlags(lua_State* L, Creature* creature) + { + uint32 flags = Eluna::CHECKVAL(L, 2); + + creature->SetUInt32Value(UNIT_NPC_FLAGS, flags); + return 0; + } + +#if defined(TRINITY) || defined(AZEROTHCORE) + /** + * Sets the [Creature]'s ReactState to `state`. + * + * @param [ReactState] state + */ + int SetReactState(lua_State* L, Creature* creature) + { + uint32 state = Eluna::CHECKVAL(L, 2); + + creature->SetReactState((ReactStates)state); + return 0; + } +#endif + + /** + * Makes the [Creature] able to fly if enabled. + * + * @param bool disable + */ + int SetDisableGravity(lua_State* L, Creature* creature) + { + bool disable = Eluna::CHECKVAL(L, 2); + +#if defined(TRINITY) || defined(AZEROTHCORE) + creature->SetDisableGravity(disable); +#else + creature->SetLevitate(disable); +#endif + return 0; + } + +#if defined(TRINITY) || defined(AZEROTHCORE) + int SetLootMode(lua_State* L, Creature* creature) // TODO: Implement LootMode features + { + uint16 lootMode = Eluna::CHECKVAL(L, 2); + + creature->SetLootMode(lootMode); + return 0; + } +#endif + + /** + * Sets the [Creature]'s death state to `deathState`. + * + * @param [DeathState] deathState + */ + int SetDeathState(lua_State* L, Creature* creature) + { + int32 state = Eluna::CHECKVAL(L, 2); + +#if defined(TRINITY) || defined(AZEROTHCORE) + creature->setDeathState((DeathState)state); +#else + creature->SetDeathState((DeathState)state); +#endif + return 0; + } + + /** + * Sets whether the [Creature] is currently walking or running. + * + * @param bool enable = true : `true` to enable walking, `false` for running + */ + int SetWalk(lua_State* L, Creature* creature) // TODO: Move same to Player ? + { + bool enable = Eluna::CHECKVAL(L, 2, true); + + creature->SetWalk(enable); + return 0; + } + + /** + * Equips given [Item]s to the [Unit]. Using 0 removes the equipped [Item] + * + * @param uint32 main_hand : main hand [Item]'s entry + * @param uint32 off_hand : off hand [Item]'s entry + * @param uint32 ranged : ranged [Item]'s entry + */ + int SetEquipmentSlots(lua_State* L, Creature* creature) + { + uint32 main_hand = Eluna::CHECKVAL(L, 2); + uint32 off_hand = Eluna::CHECKVAL(L, 3); + uint32 ranged = Eluna::CHECKVAL(L, 4); + +#if defined(TRINITY) || defined(AZEROTHCORE) + creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, main_hand); + creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, off_hand); + creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, ranged); +#else + creature->SetVirtualItem(VIRTUAL_ITEM_SLOT_0, main_hand); + creature->SetVirtualItem(VIRTUAL_ITEM_SLOT_1, off_hand); + creature->SetVirtualItem(VIRTUAL_ITEM_SLOT_2, ranged); +#endif + return 0; + } + + /** + * Sets whether the [Creature] can be aggroed. + * + * @param bool allow = true : `true` to allow aggro, `false` to disable aggro + */ + int SetAggroEnabled(lua_State* L, Creature* creature) + { + bool allow = Eluna::CHECKVAL(L, 2, true); + + if (allow) + creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC); + else + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC); + + return 0; + } + + /** + * Sets whether the [Creature] gives reputation or not. + * + * @param bool disable = true : `true` to disable reputation, `false` to enable + */ + int SetDisableReputationGain(lua_State* L, Creature* creature) + { + bool disable = Eluna::CHECKVAL(L, 2, true); +#ifndef CMANGOS + creature->SetDisableReputationGain(disable); +#else + creature->SetNoReputation(disable); +#endif + return 0; + } + + /** + * Sets the [Creature] as in combat with all [Player]s in the dungeon instance. + * + * This is used by raid bosses to prevent Players from using out-of-combat + * actions once the encounter has begun. + */ + int SetInCombatWithZone(lua_State* /*L*/, Creature* creature) + { +#if defined(AZEROTHCORE) + if (creature->IsAIEnabled) + creature->AI()->DoZoneInCombat(); +#elif defined(TRINITY) + if (creature->IsAIEnabled()) + creature->AI()->DoZoneInCombat(); +#else + creature->SetInCombatWithZone(); +#endif + return 0; + } + + /** + * Sets the distance the [Creature] can wander from it's spawn point. + * + * @param float distance + */ + int SetWanderRadius(lua_State* L, Creature* creature) + { + float dist = Eluna::CHECKVAL(L, 2); + + creature->SetWanderDistance(dist); + return 0; + } + + /** + * Sets the time it takes for the [Creature] to respawn when killed. + * + * @param uint32 delay : the delay, in seconds + */ + int SetRespawnDelay(lua_State* L, Creature* creature) + { + uint32 delay = Eluna::CHECKVAL(L, 2); + + creature->SetRespawnDelay(delay); + return 0; + } + + /** + * Sets the default movement type of the [Creature]. + * + * @param [MovementGeneratorType] type + */ + int SetDefaultMovementType(lua_State* L, Creature* creature) + { + int32 type = Eluna::CHECKVAL(L, 2); + + creature->SetDefaultMovementType((MovementGeneratorType)type); + return 0; + } + + /** + * Sets whether the [Creature] can search for assistance at low health or not. + * + * @param bool enable = true : `true` to disable searching, `false` to allow + */ + int SetNoSearchAssistance(lua_State* L, Creature* creature) + { + bool val = Eluna::CHECKVAL(L, 2, true); + + creature->SetNoSearchAssistance(val); + return 0; + } + + /** + * Sets whether the [Creature] can call nearby enemies for help in combat or not. + * + * @param bool enable = true : `true` to disable calling for help, `false` to enable + */ + int SetNoCallAssistance(lua_State* L, Creature* creature) + { + bool val = Eluna::CHECKVAL(L, 2, true); + + creature->SetNoCallAssistance(val); + return 0; + } + + /** + * Sets whether the creature is hovering / levitating or not. + * + * @param bool enable = true : `true` to enable hovering, `false` to disable + */ + int SetHover(lua_State* L, Creature* creature) + { + bool enable = Eluna::CHECKVAL(L, 2, true); + +#if defined(TRINITY) || defined(AZEROTHCORE) + creature->SetHover(enable); +#else + // Copy paste from Aura::HandleAuraHover + // TODO: implement core side properly + WorldPacket data; + if (enable) + data.Initialize(SMSG_MOVE_SET_HOVER, 8 + 4); + else + data.Initialize(SMSG_MOVE_UNSET_HOVER, 8 + 4); + data << creature->GetPackGUID(); + data << uint32(0); +#if defined(CMANGOS) + creature->SendMessageToSet(data, true); +#else + creature->SendMessageToSet(&data, true); +#endif +#endif + return 0; + } + + /** + * Despawn this [Creature]. + * + * @param uint32 delay = 0 : dely to despawn in milliseconds + */ + int DespawnOrUnsummon(lua_State* L, Creature* creature) + { + uint32 msTimeToDespawn = Eluna::CHECKVAL(L, 2, 0); + +#if defined(TRINITY) + creature->DespawnOrUnsummon(Milliseconds(msTimeToDespawn)); +#elif defined(AZEROTHCORE) + creature->DespawnOrUnsummon(msTimeToDespawn); +#else + creature->ForcedDespawn(msTimeToDespawn); +#endif + return 0; + } + + /** + * Respawn this [Creature]. + */ + int Respawn(lua_State* /*L*/, Creature* creature) + { + creature->Respawn(); + return 0; + } + + /** + * Remove this [Creature]'s corpse. + */ + int RemoveCorpse(lua_State* /*L*/, Creature* creature) + { + creature->RemoveCorpse(); + return 0; + } + + /** + * Make the [Creature] start following its waypoint path. + */ + int MoveWaypoint(lua_State* /*L*/, Creature* creature) + { +#if defined(TRINITY) || defined(AZEROTHCORE) + creature->GetMotionMaster()->MovePath(creature->GetWaypointPath(), true); +#else + creature->GetMotionMaster()->MoveWaypoint(); +#endif + return 0; + } + + /** + * Make the [Creature] call for assistance in combat from other nearby [Creature]s. + */ + int CallAssistance(lua_State* /*L*/, Creature* creature) + { + creature->CallAssistance(); + return 0; + } + + /** + * Make the [Creature] call for help in combat from friendly [Creature]s within `radius`. + * + * @param float radius + */ + int CallForHelp(lua_State* L, Creature* creature) + { + float radius = Eluna::CHECKVAL(L, 2); + + creature->CallForHelp(radius); + return 0; + } + + /** + * Make the [Creature] flee combat to get assistance from a nearby friendly [Creature]. + */ + int FleeToGetAssistance(lua_State* /*L*/, Creature* creature) + { + creature->DoFleeToGetAssistance(); + return 0; + } + + /** + * Make the [Creature] attack `target`. + * + * @param [Unit] target + */ + int AttackStart(lua_State* L, Creature* creature) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + + creature->AI()->AttackStart(target); + return 0; + } + + /** + * Save the [Creature] in the database. + */ + int SaveToDB(lua_State* /*L*/, Creature* creature) + { + creature->SaveToDB(); + return 0; + } + + /** + * Make the [Creature] try to find a new target. + * + * This should be called every update cycle for the Creature's AI. + */ + int SelectVictim(lua_State* L, Creature* creature) + { +#if defined(TRINITY) || defined(AZEROTHCORE) + Eluna::Push(L, creature->SelectVictim()); +#else + Eluna::Push(L, creature->SelectHostileTarget()); +#endif + return 1; + } + + /** + * Transform the [Creature] into another Creature. + * + * @param uint32 entry : the Creature ID to transform into + * @param uint32 dataGUIDLow = 0 : use this Creature's model and equipment instead of the defaults + */ + int UpdateEntry(lua_State* L, Creature* creature) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + uint32 dataGuidLow = Eluna::CHECKVAL(L, 3, 0); + + creature->UpdateEntry(entry, dataGuidLow ? eGameEventMgr->GetCreatureUpdateDataForActiveEvent(dataGuidLow) : NULL); + return 0; + } + +#if defined(TRINITY) || defined(AZEROTHCORE) + /** + * Resets [Creature]'s loot mode to default + */ + int ResetLootMode(lua_State* /*L*/, Creature* creature) // TODO: Implement LootMode features + { + creature->ResetLootMode(); + return 0; + } + + /** + * Removes specified loot mode from [Creature] + * + * @param uint16 lootMode + */ + int RemoveLootMode(lua_State* L, Creature* creature) // TODO: Implement LootMode features + { + uint16 lootMode = Eluna::CHECKVAL(L, 2); + + creature->RemoveLootMode(lootMode); + return 0; + } + + /** + * Adds a loot mode to the [Creature] + * + * @param uint16 lootMode + */ + int AddLootMode(lua_State* L, Creature* creature) // TODO: Implement LootMode features + { + uint16 lootMode = Eluna::CHECKVAL(L, 2); + + creature->AddLootMode(lootMode); + return 0; + } +#endif + + /** + * Returns the [Creature]'s creature family ID (enumerated in CreatureFamily.dbc). + * + *
+     * enum CreatureFamily
+     * {
+     *     CREATURE_FAMILY_NONE                = 0,    // TrinityCore only
+     *     CREATURE_FAMILY_WOLF                = 1,
+     *     CREATURE_FAMILY_CAT                 = 2,
+     *     CREATURE_FAMILY_SPIDER              = 3,
+     *     CREATURE_FAMILY_BEAR                = 4,
+     *     CREATURE_FAMILY_BOAR                = 5,
+     *     CREATURE_FAMILY_CROCOLISK           = 6,
+     *     CREATURE_FAMILY_CARRION_BIRD        = 7,
+     *     CREATURE_FAMILY_CRAB                = 8,
+     *     CREATURE_FAMILY_GORILLA             = 9,
+     *     CREATURE_FAMILY_HORSE_CUSTOM        = 10,   // Does not exist in DBC but used for horse like beasts in DB
+     *     CREATURE_FAMILY_RAPTOR              = 11,
+     *     CREATURE_FAMILY_TALLSTRIDER         = 12,
+     *     CREATURE_FAMILY_FELHUNTER           = 15,
+     *     CREATURE_FAMILY_VOIDWALKER          = 16,
+     *     CREATURE_FAMILY_SUCCUBUS            = 17,
+     *     CREATURE_FAMILY_DOOMGUARD           = 19,
+     *     CREATURE_FAMILY_SCORPID             = 20,
+     *     CREATURE_FAMILY_TURTLE              = 21,
+     *     CREATURE_FAMILY_IMP                 = 23,
+     *     CREATURE_FAMILY_BAT                 = 24,
+     *     CREATURE_FAMILY_HYENA               = 25,
+     *     CREATURE_FAMILY_BIRD_OF_PREY        = 26,   // Named CREATURE_FAMILY_OWL in Mangos
+     *     CREATURE_FAMILY_WIND_SERPENT        = 27,
+     *     CREATURE_FAMILY_REMOTE_CONTROL      = 28,
+     *     CREATURE_FAMILY_FELGUARD            = 29,   // This and below is TBC+
+     *     CREATURE_FAMILY_DRAGONHAWK          = 30,
+     *     CREATURE_FAMILY_RAVAGER             = 31,
+     *     CREATURE_FAMILY_WARP_STALKER        = 32,
+     *     CREATURE_FAMILY_SPOREBAT            = 33,
+     *     CREATURE_FAMILY_NETHER_RAY          = 34,
+     *     CREATURE_FAMILY_SERPENT             = 35,
+     *     CREATURE_FAMILY_SEA_LION            = 36,   // TBC only
+     *     CREATURE_FAMILY_MOTH                = 37,   // This and below is WotLK+
+     *     CREATURE_FAMILY_CHIMAERA            = 38,
+     *     CREATURE_FAMILY_DEVILSAUR           = 39,
+     *     CREATURE_FAMILY_GHOUL               = 40,
+     *     CREATURE_FAMILY_SILITHID            = 41,
+     *     CREATURE_FAMILY_WORM                = 42,
+     *     CREATURE_FAMILY_RHINO               = 43,
+     *     CREATURE_FAMILY_WASP                = 44,
+     *     CREATURE_FAMILY_CORE_HOUND          = 45,
+     *     CREATURE_FAMILY_SPIRIT_BEAST        = 46
+     * };
+     * 
+ * + * @return [CreatureFamily] creatureFamily + */ + int GetCreatureFamily(lua_State* L, Creature* creature) + { + uint32 entry = creature->GetEntry(); + + CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(entry); + if (cInfo) + Eluna::Push(L, cInfo->pet_family); + return 1; + } + + ElunaRegister CreatureMethods[] = + { + // Getters + { "GetAITarget", &LuaCreature::GetAITarget }, + { "GetAITargets", &LuaCreature::GetAITargets }, + { "GetAITargetsCount", &LuaCreature::GetAITargetsCount }, + { "GetHomePosition", &LuaCreature::GetHomePosition }, + { "GetCorpseDelay", &LuaCreature::GetCorpseDelay }, + { "GetCreatureSpellCooldownDelay", &LuaCreature::GetCreatureSpellCooldownDelay }, + { "GetScriptId", &LuaCreature::GetScriptId }, + { "GetAIName", &LuaCreature::GetAIName }, + { "GetScriptName", &LuaCreature::GetScriptName }, + { "GetAttackDistance", &LuaCreature::GetAttackDistance }, + { "GetAggroRange", &LuaCreature::GetAggroRange }, + { "GetDefaultMovementType", &LuaCreature::GetDefaultMovementType }, + { "GetRespawnDelay", &LuaCreature::GetRespawnDelay }, + { "GetWanderRadius", &LuaCreature::GetWanderRadius }, + { "GetCurrentWaypointId", &LuaCreature::GetCurrentWaypointId }, + { "GetLootRecipient", &LuaCreature::GetLootRecipient }, + { "GetLootRecipientGroup", &LuaCreature::GetLootRecipientGroup }, + { "GetNPCFlags", &LuaCreature::GetNPCFlags }, + { "GetExtraFlags", &LuaCreature::GetExtraFlags }, + { "GetShieldBlockValue", &LuaCreature::GetShieldBlockValue }, + { "GetDBTableGUIDLow", &LuaCreature::GetDBTableGUIDLow }, + { "GetCreatureFamily", &LuaCreature::GetCreatureFamily }, + + // Setters + { "SetHover", &LuaCreature::SetHover }, + { "SetDisableGravity", &LuaCreature::SetDisableGravity }, + { "SetAggroEnabled", &LuaCreature::SetAggroEnabled }, + { "SetNoCallAssistance", &LuaCreature::SetNoCallAssistance }, + { "SetNoSearchAssistance", &LuaCreature::SetNoSearchAssistance }, + { "SetDefaultMovementType", &LuaCreature::SetDefaultMovementType }, + { "SetRespawnDelay", &LuaCreature::SetRespawnDelay }, + { "SetWanderRadius", &LuaCreature::SetWanderRadius }, + { "SetInCombatWithZone", &LuaCreature::SetInCombatWithZone }, + { "SetDisableReputationGain", &LuaCreature::SetDisableReputationGain }, + { "SetNPCFlags", &LuaCreature::SetNPCFlags }, + { "SetDeathState", &LuaCreature::SetDeathState }, + { "SetWalk", &LuaCreature::SetWalk }, + { "SetHomePosition", &LuaCreature::SetHomePosition }, + { "SetEquipmentSlots", &LuaCreature::SetEquipmentSlots }, + + // Boolean + { "IsRegeneratingHealth", &LuaCreature::IsRegeneratingHealth }, + { "IsWorldBoss", &LuaCreature::IsWorldBoss }, + { "IsRacialLeader", &LuaCreature::IsRacialLeader }, + { "IsCivilian", &LuaCreature::IsCivilian }, + { "IsGuard", &LuaCreature::IsGuard }, + { "IsElite", &LuaCreature::IsElite }, + { "IsInEvadeMode", &LuaCreature::IsInEvadeMode }, + { "HasCategoryCooldown", &LuaCreature::HasCategoryCooldown }, + { "CanWalk", &LuaCreature::CanWalk }, + { "CanSwim", &LuaCreature::CanSwim }, + { "CanAggro", &LuaCreature::CanAggro }, + { "HasSearchedAssistance", &LuaCreature::HasSearchedAssistance }, + { "IsTappedBy", &LuaCreature::IsTappedBy }, + { "HasLootRecipient", &LuaCreature::HasLootRecipient }, + { "CanAssistTo", &LuaCreature::CanAssistTo }, + { "IsTargetableForAttack", &LuaCreature::IsTargetableForAttack }, + { "CanCompleteQuest", &LuaCreature::CanCompleteQuest }, + { "IsReputationGainDisabled", &LuaCreature::IsReputationGainDisabled }, + { "HasSpell", &LuaCreature::HasSpell }, + { "HasQuest", &LuaCreature::HasQuest }, + { "HasSpellCooldown", &LuaCreature::HasSpellCooldown }, + { "CanFly", &LuaCreature::CanFly }, + + // Other + { "FleeToGetAssistance", &LuaCreature::FleeToGetAssistance }, + { "CallForHelp", &LuaCreature::CallForHelp }, + { "CallAssistance", &LuaCreature::CallAssistance }, + { "RemoveCorpse", &LuaCreature::RemoveCorpse }, + { "DespawnOrUnsummon", &LuaCreature::DespawnOrUnsummon }, + { "Respawn", &LuaCreature::Respawn }, + { "AttackStart", &LuaCreature::AttackStart }, + { "SaveToDB", &LuaCreature::SaveToDB }, + { "SelectVictim", &LuaCreature::SelectVictim }, + { "MoveWaypoint", &LuaCreature::MoveWaypoint }, + { "UpdateEntry", &LuaCreature::UpdateEntry }, + + // Not implemented methods + { "GetWaypointPath", nullptr }, // not implemented + { "GetLootMode", nullptr }, // not implemented + { "SetRegeneratingHealth", nullptr }, // not implemented + { "SetLootMode", nullptr }, // not implemented + { "SetReactState", nullptr }, // not implemented + { "IsDungeonBoss", nullptr }, // not implemented + { "IsTrigger", nullptr }, // not implemented + { "CanStartAttack", nullptr }, // not implemented + { "IsDamageEnoughForLootingAndReward", nullptr }, // not implemented + { "HasLootMode", nullptr }, // not implemented + { "AddLootMode", nullptr }, // not implemented + { "ResetLootMode", nullptr }, // not implemented + { "RemoveLootMode", nullptr }, // not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/VMangos/ElunaQueryMethods.h b/src/modules/Eluna/VMangos/ElunaQueryMethods.h new file mode 100644 index 0000000000..ced7898947 --- /dev/null +++ b/src/modules/Eluna/VMangos/ElunaQueryMethods.h @@ -0,0 +1,399 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef QUERYMETHODS_H +#define QUERYMETHODS_H + +#if defined TRINITY || defined AZEROTHCORE +#define RESULT (*result) +#else +#define RESULT result +#endif + +/*** + * The result of a database query. + * + * E.g. the return value of [Global:WorldDBQuery]. + * + * Inherits all methods from: none + */ +namespace LuaQuery +{ + static void CheckFields(lua_State* L, ElunaQuery* result) + { + uint32 field = Eluna::CHECKVAL(L, 2); + uint32 count = RESULT->GetFieldCount(); + if (field >= count) + { + char arr[256]; + sprintf(arr, "trying to access invalid field index %u. There are %u fields available and the indexes start from 0", field, count); + luaL_argerror(L, 2, arr); + } + } + + /** + * Returns `true` if the specified column of the current row is `NULL`, otherwise `false`. + * + * @param uint32 column + * @return bool isNull + */ + int IsNull(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, RESULT->Fetch()[col].IsNull()); +#else + Eluna::Push(L, RESULT->Fetch()[col].IsNULL()); +#endif + return 1; + } + + /** + * Returns the number of columns in the result set. + * + * @return uint32 columnCount + */ + int GetColumnCount(lua_State* L, ElunaQuery* result) + { + Eluna::Push(L, RESULT->GetFieldCount()); + return 1; + } + + /** + * Returns the number of rows in the result set. + * + * @return uint32 rowCount + */ + int GetRowCount(lua_State* L, ElunaQuery* result) + { + if (RESULT->GetRowCount() > (uint32)-1) + Eluna::Push(L, (uint32)-1); + else + Eluna::Push(L, (uint32)(RESULT->GetRowCount())); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a boolean. + * + * @param uint32 column + * @return bool data + */ + int GetBool(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetBool()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to an unsigned 8-bit integer. + * + * @param uint32 column + * @return uint8 data + */ + int GetUInt8(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetUInt8()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to an unsigned 16-bit integer. + * + * @param uint32 column + * @return uint16 data + */ + int GetUInt16(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetUInt16()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to an unsigned 32-bit integer. + * + * @param uint32 column + * @return uint32 data + */ + int GetUInt32(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetUInt32()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to an unsigned 64-bit integer. + * + * @param uint32 column + * @return uint64 data + */ + int GetUInt64(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetUInt64()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a signed 8-bit integer. + * + * @param uint32 column + * @return int8 data + */ + int GetInt8(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetInt8()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a signed 16-bit integer. + * + * @param uint32 column + * @return int16 data + */ + int GetInt16(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetInt16()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a signed 32-bit integer. + * + * @param uint32 column + * @return int32 data + */ + int GetInt32(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetInt32()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a signed 64-bit integer. + * + * @param uint32 column + * @return int64 data + */ + int GetInt64(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetInt64()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a 32-bit floating point value. + * + * @param uint32 column + * @return float data + */ + int GetFloat(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetFloat()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a 64-bit floating point value. + * + * @param uint32 column + * @return double data + */ + int GetDouble(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + Eluna::Push(L, RESULT->Fetch()[col].GetDouble()); + return 1; + } + + /** + * Returns the data in the specified column of the current row, casted to a string. + * + * @param uint32 column + * @return string data + */ + int GetString(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + CheckFields(L, result); + +#ifndef TRINITY + Eluna::Push(L, RESULT->Fetch()[col].GetString()); +#else + Eluna::Push(L, RESULT->Fetch()[col].GetCString()); +#endif + return 1; + } + + /** + * Advances the [ElunaQuery] to the next row in the result set. + * + * *Do not* call this immediately after a query, or you'll skip the first row. + * + * Returns `false` if there was no new row, otherwise `true`. + * + * @return bool hadNextRow + */ + int NextRow(lua_State* L, ElunaQuery* result) + { + Eluna::Push(L, RESULT->NextRow()); + return 1; + } + + /** + * Returns a table from the current row where keys are field names and values are the row's values. + * + * All numerical values will be numbers and everything else is returned as a string. + * + * **For example,** the query: + * + * SELECT entry, name FROM creature_template + * + * would result in a table like: + * + * { entry = 123, name = "some creature name" } + * + * To move to next row use [ElunaQuery:NextRow]. + * + * @return table rowData : table filled with row columns and data where `T[column] = data` + */ + int GetRow(lua_State* L, ElunaQuery* result) + { + uint32 col = RESULT->GetFieldCount(); + Field* row = RESULT->Fetch(); + + lua_createtable(L, 0, col); + int tbl = lua_gettop(L); + +#if !defined TRINITY && !AZEROTHCORE + const QueryFieldNames& names = RESULT->GetFieldNames(); +#endif + + for (uint32 i = 0; i < col; ++i) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, RESULT->GetFieldName(i)); + + const char* str = row[i].GetCString(); + if (row[i].IsNull() || !str) + Eluna::Push(L); + else + { + // MYSQL_TYPE_LONGLONG Interpreted as string for lua + switch (row[i].GetType()) + { +#if defined TRINITY || AZEROTHCORE + case DatabaseFieldTypes::Int8: + case DatabaseFieldTypes::Int16: + case DatabaseFieldTypes::Int32: + case DatabaseFieldTypes::Int64: + case DatabaseFieldTypes::Float: + case DatabaseFieldTypes::Double: +#else + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: +#endif + Eluna::Push(L, strtod(str, NULL)); + break; + default: + Eluna::Push(L, str); + break; + } + } +#else + Eluna::Push(L, names[i]); + + const char* str = row[i].GetString(); + if (row[i].IsNULL() || !str) + Eluna::Push(L); + else + { + // MYSQL_TYPE_LONGLONG Interpreted as string for lua + switch (row[i].GetType()) + { + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + Eluna::Push(L, strtod(str, NULL)); + break; + default: + Eluna::Push(L, str); + break; + } + } +#endif + + lua_rawset(L, tbl); + } + + lua_settop(L, tbl); + return 1; + } + + ElunaRegister QueryMethods[] = + { + // Getters + { "GetColumnCount", &LuaQuery::GetColumnCount }, + { "GetRowCount", &LuaQuery::GetRowCount }, + { "GetRow", &LuaQuery::GetRow }, + { "GetBool", &LuaQuery::GetBool }, + { "GetUInt8", &LuaQuery::GetUInt8 }, + { "GetUInt16", &LuaQuery::GetUInt16 }, + { "GetUInt32", &LuaQuery::GetUInt32 }, + { "GetUInt64", &LuaQuery::GetUInt64 }, + { "GetInt8", &LuaQuery::GetInt8 }, + { "GetInt16", &LuaQuery::GetInt16 }, + { "GetInt32", &LuaQuery::GetInt32 }, + { "GetInt64", &LuaQuery::GetInt64 }, + { "GetFloat", &LuaQuery::GetFloat }, + { "GetDouble", &LuaQuery::GetDouble }, + { "GetString", &LuaQuery::GetString }, + + // Boolean + { "NextRow", &LuaQuery::NextRow }, + { "IsNull", &LuaQuery::IsNull }, + + { NULL, NULL } + }; +}; +#undef RESULT + +#endif diff --git a/src/modules/Eluna/VMangos/GameObjectMethods.h b/src/modules/Eluna/VMangos/GameObjectMethods.h new file mode 100644 index 0000000000..4e09d73883 --- /dev/null +++ b/src/modules/Eluna/VMangos/GameObjectMethods.h @@ -0,0 +1,355 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef GAMEOBJECTMETHODS_H +#define GAMEOBJECTMETHODS_H + +/*** + * Inherits all methods from: [Object], [WorldObject] + */ +namespace LuaGameObject +{ + /** + * Returns 'true' if the [GameObject] can give the specified [Quest] + * + * @param uint32 questId : quest entry Id to check + * @return bool hasQuest + */ + int HasQuest(lua_State* L, GameObject* go) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, go->hasQuest(questId)); +#else + Eluna::Push(L, go->HasQuest(questId)); +#endif + return 1; + } + + /** + * Returns 'true' if the [GameObject] is spawned + * + * @return bool isSpawned + */ + int IsSpawned(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->isSpawned()); + return 1; + } + + /** + * Returns 'true' if the [GameObject] is a transport + * + * @return bool isTransport + */ + int IsTransport(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->IsTransport()); + return 1; + } + + /** + * Returns 'true' if the [GameObject] is active + * + * @return bool isActive + */ + int IsActive(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->isActiveObject()); + return 1; + } + + /*int IsDestructible(lua_State* L, GameObject* go) // TODO: Implementation core side + { + Eluna::Push(L, go->IsDestructibleBuilding()); + return 1; + }*/ + + /** + * Returns display ID of the [GameObject] + * + * @return uint32 displayId + */ + int GetDisplayId(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetDisplayId()); + return 1; + } + + /** + * Returns the state of a [GameObject] + * Below are client side [GOState]s off of 3.3.5a + * + *
+     * enum GOState
+     * {
+     *     GO_STATE_ACTIVE             = 0,                        // show in world as used and not reset (closed door open)
+     *     GO_STATE_READY              = 1,                        // show in world as ready (closed door close)
+     *     GO_STATE_ACTIVE_ALTERNATIVE = 2                         // show in world as used in alt way and not reset (closed door open by cannon fire)
+     * };
+     * 
+ * + * @return [GOState] goState + */ + int GetGoState(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetGoState()); + return 1; + } + + /** + * Returns the [LootState] of a [GameObject] + * Below are [LootState]s off of 3.3.5a + * + *
+     * enum LootState
+     * {
+     *     GO_NOT_READY = 0,
+     *     GO_READY,                                               // can be ready but despawned, and then not possible activate until spawn
+     *     GO_ACTIVATED,
+     *     GO_JUST_DEACTIVATED
+     * };
+     * 
+ * + * @return [LootState] lootState + */ + int GetLootState(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->getLootState()); + return 1; + } + + /** + * Returns the [Player] that can loot the [GameObject] + * + * Not the original looter and may be nil. + * + * @return [Player] player + */ + int GetLootRecipient(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetLootRecipient()); + return 1; + } + + /** + * Returns the [Group] that can loot the [GameObject] + * + * Not the original looter and may be nil. + * + * @return [Group] group + */ + int GetLootRecipientGroup(lua_State* L, GameObject* go) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, go->GetLootRecipientGroup()); +#else + Eluna::Push(L, go->GetGroupLootRecipient()); +#endif + return 1; + } + + /** + * Returns the guid of the [GameObject] that is used as the ID in the database + * + * @return uint32 dbguid + */ + int GetDBTableGUIDLow(lua_State* L, GameObject* go) + { + Eluna::Push(L, go->GetGUIDLow()); + return 1; + } + + /** + * Sets the state of a [GameObject] + * + *
+     * enum GOState
+     * {
+     *     GO_STATE_ACTIVE             = 0,                        // show in world as used and not reset (closed door open)
+     *     GO_STATE_READY              = 1,                        // show in world as ready (closed door close)
+     *     GO_STATE_ACTIVE_ALTERNATIVE = 2                         // show in world as used in alt way and not reset (closed door open by cannon fire)
+     * };
+     * 
+ * + * @param [GOState] state : all available go states can be seen above + */ + int SetGoState(lua_State* L, GameObject* go) + { + uint32 state = Eluna::CHECKVAL(L, 2, 0); + + if (state == 0) + go->SetGoState(GO_STATE_ACTIVE); + else if (state == 1) + go->SetGoState(GO_STATE_READY); + else if (state == 2) + go->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + + return 0; + } + + /** + * Sets the [LootState] of a [GameObject] + * Below are [LootState]s off of 3.3.5a + * + *
+     * enum LootState
+     * {
+     *     GO_NOT_READY = 0,
+     *     GO_READY,                                               // can be ready but despawned, and then not possible activate until spawn
+     *     GO_ACTIVATED,
+     *     GO_JUST_DEACTIVATED
+     * };
+     * 
+ * + * @param [LootState] state : all available loot states can be seen above + */ + int SetLootState(lua_State* L, GameObject* go) + { + uint32 state = Eluna::CHECKVAL(L, 2, 0); + + if (state == 0) + go->SetLootState(GO_NOT_READY); + else if (state == 1) + go->SetLootState(GO_READY); + else if (state == 2) + go->SetLootState(GO_ACTIVATED); + else if (state == 3) + go->SetLootState(GO_JUST_DEACTIVATED); + + return 0; + } + + /** + * Saves [GameObject] to the database + * + */ + int SaveToDB(lua_State* /*L*/, GameObject* go) + { + go->SaveToDB(); + return 0; + } + + /** + * Removes [GameObject] from the world + * + * The object is no longer reachable after this and it is not respawned. + * + * @param bool deleteFromDB : if true, it will delete the [GameObject] from the database + */ + int RemoveFromWorld(lua_State* L, GameObject* go) + { + bool deldb = Eluna::CHECKVAL(L, 2, false); + + // cs_gobject.cpp copy paste +#if defined TRINITY || AZEROTHCORE + ObjectGuid ownerGuid = go->GetOwnerGUID(); +#else + ObjectGuid ownerGuid = go->GetOwnerGuid(); +#endif + if (ownerGuid) + { + Unit* owner = eObjectAccessor()GetUnit(*go, ownerGuid); + if (!owner || !ownerGuid.IsPlayer()) + return 0; + + owner->RemoveGameObject(go, false); + } + + if (deldb) + go->DeleteFromDB(); + + go->SetRespawnTime(0); + go->Delete(); + + Eluna::CHECKOBJ(L, 1)->Invalidate(); + return 0; + } + + /** + * Activates a door or a button/lever + * + * @param uint32 delay = 0 : cooldown time in seconds to restore the [GameObject] back to normal. 0 for infinite duration + */ + int UseDoorOrButton(lua_State* L, GameObject* go) + { + uint32 delay = Eluna::CHECKVAL(L, 2, 0); + + go->UseDoorOrButton(delay); + return 0; + } + + /** + * Despawns a [GameObject] + * + * The gameobject may be automatically respawned by the core + */ + int Despawn(lua_State* /*L*/, GameObject* go) + { + go->SetLootState(GO_JUST_DEACTIVATED); + return 0; + } + + /** + * Respawns a [GameObject] + */ + int Respawn(lua_State* /*L*/, GameObject* go) + { + go->Respawn(); + return 0; + } + + /** + * Sets the respawn or despawn time for the gameobject. + * + * Respawn time is also used as despawn time depending on gameobject settings + * + * @param int32 delay = 0 : cooldown time in seconds to respawn or despawn the object. 0 means never + */ + int SetRespawnTime(lua_State* L, GameObject* go) + { + int32 respawn = Eluna::CHECKVAL(L, 2); + + go->SetRespawnTime(respawn); + return 0; + } + + ElunaRegister GameObjectMethods[] = + { + // Getters + { "GetDisplayId", &LuaGameObject::GetDisplayId }, + { "GetGoState", &LuaGameObject::GetGoState }, + { "GetLootState", &LuaGameObject::GetLootState }, + { "GetLootRecipient", &LuaGameObject::GetLootRecipient }, + { "GetLootRecipientGroup", &LuaGameObject::GetLootRecipientGroup }, + { "GetDBTableGUIDLow", &LuaGameObject::GetDBTableGUIDLow }, + + // Setters + { "SetGoState", &LuaGameObject::SetGoState }, + { "SetLootState", &LuaGameObject::SetLootState }, + { "SetRespawnTime", &LuaGameObject::SetRespawnTime }, + + // Boolean + { "IsTransport", &LuaGameObject::IsTransport }, + { "IsActive", &LuaGameObject::IsActive }, + { "HasQuest", &LuaGameObject::HasQuest }, + { "IsSpawned", &LuaGameObject::IsSpawned }, + + // Other + { "RemoveFromWorld", &LuaGameObject::RemoveFromWorld }, + { "UseDoorOrButton", &LuaGameObject::UseDoorOrButton }, + { "Despawn", &LuaGameObject::Despawn }, + { "Respawn", &LuaGameObject::Respawn }, + { "SaveToDB", &LuaGameObject::SaveToDB }, + + // Not implemented methods + { "IsDestructible", nullptr }, // Not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/VMangos/GlobalMethods.h b/src/modules/Eluna/VMangos/GlobalMethods.h new file mode 100644 index 0000000000..221b21cc13 --- /dev/null +++ b/src/modules/Eluna/VMangos/GlobalMethods.h @@ -0,0 +1,2973 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef GLOBALMETHODS_H +#define GLOBALMETHODS_H + +#include "BindingMap.h" + +/*** + * These functions can be used anywhere at any time, including at start-up. + */ +namespace LuaGlobalFunctions +{ + /** + * Returns Lua engine's name. + * + * Always returns "ElunaEngine" on Eluna. + * + * @return string engineName + */ + int GetLuaEngine(lua_State* L) + { + Eluna::Push(L, "ElunaEngine"); + return 1; + } + + /** + * Returns emulator's name. + * + * The result will be either `MaNGOS`, `cMaNGOS`, or `TrinityCore`. + * + * @return string coreName + */ + int GetCoreName(lua_State* L) + { + Eluna::Push(L, CORE_NAME); + return 1; + } + + /** + * Returns emulator .conf RealmID + * + * - for MaNGOS returns the realmID as it is stored in the core. + * - for TrinityCore returns the realmID as it is in the conf file. + * @return uint32 realm ID + */ + + int GetRealmID(lua_State* L) + { + Eluna::Push(L, realmID); + return 1; + } + + /** + * Returns emulator version + * + * - For TrinityCore returns the date of the last revision, e.g. `2015-08-26 22:53:12 +0300` + * - For cMaNGOS returns the date and time of the last revision, e.g. `2015-09-06 13:18:50` + * - for MaNGOS returns the version number as string, e.g. `21000` + * + * @return string version + */ + int GetCoreVersion(lua_State* L) + { + Eluna::Push(L, CORE_VERSION); + return 1; + } + + /** + * Returns emulator's supported expansion. + * + * Expansion is 0 for pre-TBC, 1 for TBC, 2 for WotLK, and 3 for Cataclysm. + * + * @return int32 expansion + */ + int GetCoreExpansion(lua_State* L) + { +#ifdef CLASSIC + Eluna::Push(L, 0); +#elif defined(TBC) + Eluna::Push(L, 1); +#elif defined(WOTLK) + Eluna::Push(L, 2); +#elif defined(CATA) + Eluna::Push(L, 3); +#endif + return 1; + } + + /** + * Returns [Quest] template + * + * @param uint32 questId : [Quest] entry ID + * @return [Quest] quest + */ + int GetQuest(lua_State* L) + { + uint32 questId = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, eObjectMgr->GetQuestTemplate(questId)); + return 1; + } + + /** + * Finds and Returns [Player] by guid if found + * + * @param ObjectGuid guid : guid of the [Player], you can get it with [Object:GetGUID] + * @return [Player] player + */ + int GetPlayerByGUID(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, eObjectAccessor()FindPlayer(guid)); + return 1; + } + + /** + * Finds and Returns [Player] by name if found + * + * @param string name : name of the [Player] + * @return [Player] player + */ + int GetPlayerByName(lua_State* L) + { + const char* name = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, eObjectAccessor()FindPlayerByName(name)); + return 1; + } + + /** + * Returns game time in seconds + * + * @return uint32 time + */ + int GetGameTime(lua_State* L) + { + Eluna::Push(L, eWorld->GetGameTime()); + return 1; + } + + /** + * Returns a table with all the current [Player]s in the world + * + * Does not return players that may be teleporting or otherwise not on any map. + * + * enum TeamId + * { + * TEAM_ALLIANCE = 0, + * TEAM_HORDE = 1, + * TEAM_NEUTRAL = 2 + * }; + * + * @param [TeamId] team = TEAM_NEUTRAL : optional check team of the [Player], Alliance, Horde or Neutral (All) + * @param bool onlyGM = false : optional check if GM only + * @return table worldPlayers + */ + int GetPlayersInWorld(lua_State* L) + { + uint32 team = Eluna::CHECKVAL(L, 1, TEAM_NEUTRAL); + bool onlyGM = Eluna::CHECKVAL(L, 2, false); + + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 i = 0; + + { + HashMapHolder::ReadGuard g(HashMapHolder::GetLock()); + const HashMapHolder::MapType& m = eObjectAccessor()GetPlayers(); + for (HashMapHolder::MapType::const_iterator it = m.begin(); it != m.end(); ++it) + { + if (Player* player = it->second) + { + if (!player->IsInWorld()) + continue; + if ((team == TEAM_NEUTRAL || player->GetTeamId() == team) && (!onlyGM || player->IsGameMaster())) + + { + Eluna::Push(L, player); + lua_rawseti(L, tbl, ++i); + } + } + } + } + lua_settop(L, tbl); // push table to top of stack + return 1; + } + + /** + * Returns a [Guild] by name. + * + * @param string name + * @return [Guild] guild : the Guild, or `nil` if it doesn't exist + */ + int GetGuildByName(lua_State* L) + { + const char* name = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, eGuildMgr->GetGuildByName(name)); + return 1; + } + + /** + * Returns a [Map] by ID. + * + * @param uint32 mapId : see [Map.dbc](https://github.com/cmangos/issues/wiki/Map.dbc) + * @param uint32 instanceId = 0 : required if the map is an instance, otherwise don't pass anything + * @return [Map] map : the Map, or `nil` if it doesn't exist + */ + int GetMapById(lua_State* L) + { + uint32 mapid = Eluna::CHECKVAL(L, 1); + uint32 instance = Eluna::CHECKVAL(L, 2, 0); + + Eluna::Push(L, eMapMgr->FindMap(mapid, instance)); + return 1; + } + + /** + * Returns [Guild] by the leader's GUID + * + * @param ObjectGuid guid : the guid of a [Guild] leader + * @return [Guild] guild, or `nil` if it doesn't exist + */ + int GetGuildByLeaderGUID(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, eGuildMgr->GetGuildByLeader(guid)); + return 1; + } + + /** + * Returns the amount of [Player]s in the world. + * + * @return uint32 count + */ + int GetPlayerCount(lua_State* L) + { + Eluna::Push(L, eWorld->GetActiveSessionCount()); + return 1; + } + + /** + * Builds a [Player]'s GUID + * + * [Player] GUID consist of low GUID and type ID + * + * [Player] and [Creature] for example can have the same low GUID but not GUID. + * + * @param uint32 lowguid : low GUID of the [Player] + * @return ObjectGuid guid + */ + int GetPlayerGUID(lua_State* L) + { + uint32 lowguid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, MAKE_NEW_GUID(lowguid, 0, HIGHGUID_PLAYER)); + return 1; + } + + /** + * Builds an [Item]'s GUID. + * + * [Item] GUID consist of low GUID and type ID + * [Player] and [Item] for example can have the same low GUID but not GUID. + * + * @param uint32 lowguid : low GUID of the [Item] + * @return ObjectGuid guid + */ + int GetItemGUID(lua_State* L) + { + uint32 lowguid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, MAKE_NEW_GUID(lowguid, 0, HIGHGUID_ITEM)); + return 1; + } + + /** + * Builds a [GameObject]'s GUID. + * + * A GameObject's GUID consist of entry ID, low GUID and type ID + * + * A [Player] and GameObject for example can have the same low GUID but not GUID. + * + * @param uint32 lowguid : low GUID of the [GameObject] + * @param uint32 entry : entry ID of the [GameObject] + * @return ObjectGuid guid + */ + int GetObjectGUID(lua_State* L) + { + uint32 lowguid = Eluna::CHECKVAL(L, 1); + uint32 entry = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, MAKE_NEW_GUID(lowguid, entry, HIGHGUID_GAMEOBJECT)); + return 1; + } + + /** + * Builds a [Creature]'s GUID. + * + * [Creature] GUID consist of entry ID, low GUID and type ID + * + * [Player] and [Creature] for example can have the same low GUID but not GUID. + * + * @param uint32 lowguid : low GUID of the [Creature] + * @param uint32 entry : entry ID of the [Creature] + * @return ObjectGuid guid + */ + int GetUnitGUID(lua_State* L) + { + uint32 lowguid = Eluna::CHECKVAL(L, 1); + uint32 entry = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, MAKE_NEW_GUID(lowguid, entry, HIGHGUID_UNIT)); + return 1; + } + + /** + * Returns the low GUID from a GUID. + * + * A GUID consists of a low GUID, type ID, and possibly an entry ID depending on the type ID. + * + * Low GUID is an ID to distinct the objects of the same type. + * + * [Player] and [Creature] for example can have the same low GUID but not GUID. + * + * On TrinityCore all low GUIDs are different for all objects of the same type. + * For example creatures in instances are assigned new GUIDs when the Map is created. + * + * On MaNGOS and cMaNGOS low GUIDs are unique only on the same map. + * For example creatures in instances use the same low GUID assigned for that spawn in the database. + * This is why to identify a creature you have to know the instanceId and low GUID. See [Map:GetIntstanceId] + * + * @param ObjectGuid guid : GUID of an [Object] + * @return uint32 lowguid : low GUID of the [Object] + */ + int GetGUIDLow(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, guid.GetCounter()); + return 1; + } + + /** + * Returns an chat link for an [Item]. + * + * enum LocaleConstant + * { + * LOCALE_enUS = 0, + * LOCALE_koKR = 1, + * LOCALE_frFR = 2, + * LOCALE_deDE = 3, + * LOCALE_zhCN = 4, + * LOCALE_zhTW = 5, + * LOCALE_esES = 6, + * LOCALE_esMX = 7, + * LOCALE_ruRU = 8 + * }; + * + * @param uint32 entry : entry ID of an [Item] + * @param [LocaleConstant] locale = DEFAULT_LOCALE : locale to return the [Item] name in + * @return string itemLink + */ + int GetItemLink(lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const ItemTemplate* temp = eObjectMgr->GetItemTemplate(entry); + if (!temp) + return luaL_argerror(L, 1, "valid ItemEntry expected"); + + std::string name = temp->Name1; + if (ItemLocale const* il = eObjectMgr->GetItemLocale(entry)) + name = il->Name[locale]; + + std::ostringstream oss; + oss << "|c" << std::hex << ItemQualityColors[temp->Quality] << std::dec << + "|Hitem:" << entry << ":0:" << + "0:0:0:0|h[" << name << "]|h|r"; + + Eluna::Push(L, oss.str()); + return 1; + } + + /** + * Returns the type ID from a GUID. + * + * Type ID is different for each type ([Player], [Creature], [GameObject], etc.). + * + * GUID consist of entry ID, low GUID, and type ID. + * + * @param ObjectGuid guid : GUID of an [Object] + * @return int32 typeId : type ID of the [Object] + */ + int GetGUIDType(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, static_cast(guid.GetHigh())); + return 1; + } + + /** + * Returns the entry ID from a GUID. + * + * GUID consist of entry ID, low GUID, and type ID. + * + * @param ObjectGuid guid : GUID of an [Creature] or [GameObject] + * @return uint32 entry : entry ID, or `0` if `guid` is not a [Creature] or [GameObject] + */ + int GetGUIDEntry(lua_State* L) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, guid.GetEntry()); + return 1; + } + + /** + * Returns the area or zone's name. + * + * enum LocaleConstant + * { + * LOCALE_enUS = 0, + * LOCALE_koKR = 1, + * LOCALE_frFR = 2, + * LOCALE_deDE = 3, + * LOCALE_zhCN = 4, + * LOCALE_zhTW = 5, + * LOCALE_esES = 6, + * LOCALE_esMX = 7, + * LOCALE_ruRU = 8 + * }; + * + * @param uint32 areaOrZoneId : area ID or zone ID + * @param [LocaleConstant] locale = DEFAULT_LOCALE : locale to return the name in + * @return string areaOrZoneName + */ + int GetAreaName(lua_State* L) + { + uint32 areaOrZoneId = Eluna::CHECKVAL(L, 1); + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const auto* areaEntry = AreaEntry::GetById(areaOrZoneId); + if (!areaEntry) + return luaL_argerror(L, 1, "valid Area or Zone ID expected"); + + std::string areaOrZoneName = ""; + areaOrZoneName = areaEntry->Name; + sObjectMgr.GetAreaLocaleString(areaEntry->Id, locale, &areaOrZoneName); + Eluna::Push(L, areaOrZoneName); + + return 1; + } + + /** + * Returns the currently active game events. + * + * @return table activeEvents + */ + int GetActiveGameEvents(lua_State* L) + { + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 counter = 1; + GameEventMgr::ActiveEvents const& activeEvents = eGameEventMgr->GetActiveEventList(); + + for (GameEventMgr::ActiveEvents::const_iterator i = activeEvents.begin(); i != activeEvents.end(); ++i) + { + Eluna::Push(L, *i); + lua_rawseti(L, tbl, counter); + + counter++; + } + + lua_settop(L, tbl); + return 1; + } + + static int RegisterEntryHelper(lua_State* L, int regtype) + { + uint32 id = Eluna::CHECKVAL(L, 1); + uint32 ev = Eluna::CHECKVAL(L, 2); + luaL_checktype(L, 3, LUA_TFUNCTION); + uint32 shots = Eluna::CHECKVAL(L, 4, 0); + + lua_pushvalue(L, 3); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef >= 0) + return Eluna::GetEluna(L)->Register(L, regtype, id, ObjectGuid(), 0, ev, functionRef, shots); + else + luaL_argerror(L, 3, "unable to make a ref to function"); + return 0; + } + + static int RegisterEventHelper(lua_State* L, int regtype) + { + uint32 ev = Eluna::CHECKVAL(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + uint32 shots = Eluna::CHECKVAL(L, 3, 0); + + lua_pushvalue(L, 2); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef >= 0) + return Eluna::GetEluna(L)->Register(L, regtype, 0, ObjectGuid(), 0, ev, functionRef, shots); + else + luaL_argerror(L, 2, "unable to make a ref to function"); + return 0; + } + + static int RegisterUniqueHelper(lua_State* L, int regtype) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + uint32 instanceId = Eluna::CHECKVAL(L, 2); + uint32 ev = Eluna::CHECKVAL(L, 3); + luaL_checktype(L, 4, LUA_TFUNCTION); + uint32 shots = Eluna::CHECKVAL(L, 5, 0); + + lua_pushvalue(L, 4); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef >= 0) + return Eluna::GetEluna(L)->Register(L, regtype, 0, guid, instanceId, ev, functionRef, shots); + else + luaL_argerror(L, 4, "unable to make a ref to function"); + return 0; + } + + /** + * Registers a server event handler. + * + * enum ServerEvents + * { + * // Server + * SERVER_EVENT_ON_NETWORK_START = 1, // Not Implemented + * SERVER_EVENT_ON_NETWORK_STOP = 2, // Not Implemented + * SERVER_EVENT_ON_SOCKET_OPEN = 3, // Not Implemented + * SERVER_EVENT_ON_SOCKET_CLOSE = 4, // Not Implemented + * SERVER_EVENT_ON_PACKET_RECEIVE = 5, // (event, packet, player) - Player only if accessible. Can return false, newPacket + * SERVER_EVENT_ON_PACKET_RECEIVE_UNKNOWN = 6, // Not Implemented + * SERVER_EVENT_ON_PACKET_SEND = 7, // (event, packet, player) - Player only if accessible. Can return false + * + * // World + * WORLD_EVENT_ON_OPEN_STATE_CHANGE = 8, // (event, open) - Needs core support on Mangos + * WORLD_EVENT_ON_CONFIG_LOAD = 9, // (event, reload) + * // UNUSED = 10, + * WORLD_EVENT_ON_SHUTDOWN_INIT = 11, // (event, code, mask) + * WORLD_EVENT_ON_SHUTDOWN_CANCEL = 12, // (event) + * WORLD_EVENT_ON_UPDATE = 13, // (event, diff) + * WORLD_EVENT_ON_STARTUP = 14, // (event) + * WORLD_EVENT_ON_SHUTDOWN = 15, // (event) + * + * // Eluna + * ELUNA_EVENT_ON_LUA_STATE_CLOSE = 16, // (event) - triggers just before shutting down eluna (on shutdown and restart) + * + * // Map + * MAP_EVENT_ON_CREATE = 17, // (event, map) + * MAP_EVENT_ON_DESTROY = 18, // (event, map) + * MAP_EVENT_ON_GRID_LOAD = 19, // Not Implemented + * MAP_EVENT_ON_GRID_UNLOAD = 20, // Not Implemented + * MAP_EVENT_ON_PLAYER_ENTER = 21, // (event, map, player) + * MAP_EVENT_ON_PLAYER_LEAVE = 22, // (event, map, player) + * MAP_EVENT_ON_UPDATE = 23, // (event, map, diff) + * + * // Area trigger + * TRIGGER_EVENT_ON_TRIGGER = 24, // (event, player, triggerId) - Can return true + * + * // Weather + * WEATHER_EVENT_ON_CHANGE = 25, // (event, zoneId, state, grade) + * + * // Auction house + * AUCTION_EVENT_ON_ADD = 26, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) + * AUCTION_EVENT_ON_REMOVE = 27, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) + * AUCTION_EVENT_ON_SUCCESSFUL = 28, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) + * AUCTION_EVENT_ON_EXPIRE = 29, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) + * + * // AddOns + * ADDON_EVENT_ON_MESSAGE = 30, // (event, sender, type, prefix, msg, target) - target can be nil/whisper_target/guild/group/channel. Can return false + * + * WORLD_EVENT_ON_DELETE_CREATURE = 31, // (event, creature) + * WORLD_EVENT_ON_DELETE_GAMEOBJECT = 32, // (event, gameobject) + * + * // Eluna + * ELUNA_EVENT_ON_LUA_STATE_OPEN = 33, // (event) - triggers after all scripts are loaded + * + * GAME_EVENT_START = 34, // (event, gameeventid) + * GAME_EVENT_STOP = 35, // (event, gameeventid) + * }; + * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : server event ID, refer to ServerEvents above + * @param function function : function that will be called when the event occurs + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterServerEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_SERVER); + } + + /** + * Registers a [Player] event handler. + * + *
+     * enum PlayerEvents
+     * {
+     *     PLAYER_EVENT_ON_CHARACTER_CREATE        =     1,        // (event, player)
+     *     PLAYER_EVENT_ON_CHARACTER_DELETE        =     2,        // (event, guid)
+     *     PLAYER_EVENT_ON_LOGIN                   =     3,        // (event, player)
+     *     PLAYER_EVENT_ON_LOGOUT                  =     4,        // (event, player)
+     *     PLAYER_EVENT_ON_SPELL_CAST              =     5,        // (event, player, spell, skipCheck)
+     *     PLAYER_EVENT_ON_KILL_PLAYER             =     6,        // (event, killer, killed)
+     *     PLAYER_EVENT_ON_KILL_CREATURE           =     7,        // (event, killer, killed)
+     *     PLAYER_EVENT_ON_KILLED_BY_CREATURE      =     8,        // (event, killer, killed)
+     *     PLAYER_EVENT_ON_DUEL_REQUEST            =     9,        // (event, target, challenger)
+     *     PLAYER_EVENT_ON_DUEL_START              =     10,       // (event, player1, player2)
+     *     PLAYER_EVENT_ON_DUEL_END                =     11,       // (event, winner, loser, type)
+     *     PLAYER_EVENT_ON_GIVE_XP                 =     12,       // (event, player, amount, victim) - Can return new XP amount
+     *     PLAYER_EVENT_ON_LEVEL_CHANGE            =     13,       // (event, player, oldLevel)
+     *     PLAYER_EVENT_ON_MONEY_CHANGE            =     14,       // (event, player, amount) - Can return new money amount
+     *     PLAYER_EVENT_ON_REPUTATION_CHANGE       =     15,       // (event, player, factionId, standing, incremental) - Can return new standing
+     *     PLAYER_EVENT_ON_TALENTS_CHANGE          =     16,       // (event, player, points)
+     *     PLAYER_EVENT_ON_TALENTS_RESET           =     17,       // (event, player, noCost)
+     *     PLAYER_EVENT_ON_CHAT                    =     18,       // (event, player, msg, Type, lang) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_WHISPER                 =     19,       // (event, player, msg, Type, lang, receiver) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_GROUP_CHAT              =     20,       // (event, player, msg, Type, lang, group) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_GUILD_CHAT              =     21,       // (event, player, msg, Type, lang, guild) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_CHANNEL_CHAT            =     22,       // (event, player, msg, Type, lang, channel) - Can return false, newMessage
+     *     PLAYER_EVENT_ON_EMOTE                   =     23,       // (event, player, emote) - Not triggered on any known emote
+     *     PLAYER_EVENT_ON_TEXT_EMOTE              =     24,       // (event, player, textEmote, emoteNum, guid)
+     *     PLAYER_EVENT_ON_SAVE                    =     25,       // (event, player)
+     *     PLAYER_EVENT_ON_BIND_TO_INSTANCE        =     26,       // (event, player, difficulty, mapid, permanent)
+     *     PLAYER_EVENT_ON_UPDATE_ZONE             =     27,       // (event, player, newZone, newArea)
+     *     PLAYER_EVENT_ON_MAP_CHANGE              =     28,       // (event, player)
+     *
+     *     // Custom
+     *     PLAYER_EVENT_ON_EQUIP                   =     29,       // (event, player, item, bag, slot)
+     *     PLAYER_EVENT_ON_FIRST_LOGIN             =     30,       // (event, player)
+     *     PLAYER_EVENT_ON_CAN_USE_ITEM            =     31,       // (event, player, itemEntry) - Can return InventoryResult enum value
+     *     PLAYER_EVENT_ON_LOOT_ITEM               =     32,       // (event, player, item, count)
+     *     PLAYER_EVENT_ON_ENTER_COMBAT            =     33,       // (event, player, enemy)
+     *     PLAYER_EVENT_ON_LEAVE_COMBAT            =     34,       // (event, player)
+     *     PLAYER_EVENT_ON_REPOP                   =     35,       // (event, player)
+     *     PLAYER_EVENT_ON_RESURRECT               =     36,       // (event, player)
+     *     PLAYER_EVENT_ON_LOOT_MONEY              =     37,       // (event, player, amount)
+     *     PLAYER_EVENT_ON_QUEST_ABANDON           =     38,       // (event, player, questId)
+     *     PLAYER_EVENT_ON_LEARN_TALENTS           =     39,       // (event, player, talentId, talentRank, spellid)
+     *     // UNUSED                               =     40,       // (event, player)
+     *     // UNUSED                               =     41,       // (event, player)
+     *     PLAYER_EVENT_ON_COMMAND                 =     42,       // (event, player, command) - player is nil if command used from console. Can return false
+     * };
+     * 
+ * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : [Player] event Id, refer to PlayerEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterPlayerEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_PLAYER); + } + + /** + * Registers a [Guild] event handler. + * + *
+     * enum GuildEvents
+     * {
+     *     // Guild
+     *     GUILD_EVENT_ON_ADD_MEMBER               =     1,       // (event, guild, player, rank)
+     *     GUILD_EVENT_ON_REMOVE_MEMBER            =     2,       // (event, guild, player, isDisbanding)
+     *     GUILD_EVENT_ON_MOTD_CHANGE              =     3,       // (event, guild, newMotd)
+     *     GUILD_EVENT_ON_INFO_CHANGE              =     4,       // (event, guild, newInfo)
+     *     GUILD_EVENT_ON_CREATE                   =     5,       // (event, guild, leader, name)  // Not on TC
+     *     GUILD_EVENT_ON_DISBAND                  =     6,       // (event, guild)
+     *     GUILD_EVENT_ON_MONEY_WITHDRAW           =     7,       // (event, guild, player, amount, isRepair) - Can return new money amount
+     *     GUILD_EVENT_ON_MONEY_DEPOSIT            =     8,       // (event, guild, player, amount) - Can return new money amount
+     *     GUILD_EVENT_ON_ITEM_MOVE                =     9,       // (event, guild, player, item, isSrcBank, srcContainer, srcSlotId, isDestBank, destContainer, destSlotId)   // TODO
+     *     GUILD_EVENT_ON_EVENT                    =     10,      // (event, guild, eventType, plrGUIDLow1, plrGUIDLow2, newRank)  // TODO
+     *     GUILD_EVENT_ON_BANK_EVENT               =     11,      // (event, guild, eventType, tabId, playerGUIDLow, itemOrMoney, itemStackCount, destTabId)
+     *
+     *     GUILD_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : [Guild] event Id, refer to GuildEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterGuildEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_GUILD); + } + + /** + * Registers a [Group] event handler. + * + *
+     * enum GroupEvents
+     * {
+     *     // Group
+     *     GROUP_EVENT_ON_MEMBER_ADD               =     1,       // (event, group, guid)
+     *     GROUP_EVENT_ON_MEMBER_INVITE            =     2,       // (event, group, guid)
+     *     GROUP_EVENT_ON_MEMBER_REMOVE            =     3,       // (event, group, guid, method, kicker, reason)
+     *     GROUP_EVENT_ON_LEADER_CHANGE            =     4,       // (event, group, newLeaderGuid, oldLeaderGuid)
+     *     GROUP_EVENT_ON_DISBAND                  =     5,       // (event, group)
+     *     GROUP_EVENT_ON_CREATE                   =     6,       // (event, group, leaderGuid, groupType)
+     *
+     *     GROUP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : [Group] event Id, refer to GroupEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterGroupEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_GROUP); + } + + /** + * Registers a [BattleGround] event handler. + * + *
+     * enum BGEvents
+     * {
+     *     BG_EVENT_ON_START                               = 1,    // (event, bg, bgId, instanceId) - Needs to be added to TC
+     *     BG_EVENT_ON_END                                 = 2,    // (event, bg, bgId, instanceId, winner) - Needs to be added to TC
+     *     BG_EVENT_ON_CREATE                              = 3,    // (event, bg, bgId, instanceId) - Needs to be added to TC
+     *     BG_EVENT_ON_PRE_DESTROY                         = 4,    // (event, bg, bgId, instanceId) - Needs to be added to TC
+     *     BG_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (event, function) + * @proto cancel = (event, function, shots) + * + * @param uint32 event : [BattleGround] event Id, refer to BGEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterBGEvent(lua_State* L) + { + return RegisterEventHelper(L, Hooks::REGTYPE_BG); + } + + /** + * Registers a [WorldPacket] event handler. + * + *
+     * enum PacketEvents
+     * {
+     *     PACKET_EVENT_ON_PACKET_RECEIVE          =     5,       // (event, packet, player) - Player only if accessible. Can return false, newPacket
+     *     PACKET_EVENT_ON_PACKET_RECEIVE_UNKNOWN  =     6,       // Not Implemented
+     *     PACKET_EVENT_ON_PACKET_SEND             =     7,       // (event, packet, player) - Player only if accessible. Can return false
+     *
+     *     PACKET_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : opcode + * @param uint32 event : packet event Id, refer to PacketEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterPacketEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_PACKET); + } + + /** + * Registers a [Creature] gossip event handler. + * + *
+     * enum GossipEvents
+     * {
+     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
+     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
+     *     GOSSIP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [Creature] entry Id + * @param uint32 event : [Creature] gossip event Id, refer to GossipEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterCreatureGossipEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_CREATURE_GOSSIP); + } + + /** + * Registers a [GameObject] gossip event handler. + * + *
+     * enum GossipEvents
+     * {
+     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
+     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
+     *     GOSSIP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [GameObject] entry Id + * @param uint32 event : [GameObject] gossip event Id, refer to GossipEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterGameObjectGossipEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_GAMEOBJECT_GOSSIP); + } + + /** + * Registers an [Item] event handler. + * + *
+     * enum ItemEvents
+     * {
+     *     ITEM_EVENT_ON_DUMMY_EFFECT                      = 1,    // (event, caster, spellid, effindex, item)
+     *     ITEM_EVENT_ON_USE                               = 2,    // (event, player, item, target) - Can return false to stop the spell casting
+     *     ITEM_EVENT_ON_QUEST_ACCEPT                      = 3,    // (event, player, item, quest) - Can return true
+     *     ITEM_EVENT_ON_EXPIRE                            = 4,    // (event, player, itemid) - Can return true
+     *     ITEM_EVENT_ON_REMOVE                            = 5,    // (event, player, item) - Can return true
+     *     ITEM_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [Item] entry Id + * @param uint32 event : [Item] event Id, refer to ItemEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterItemEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_ITEM); + } + + /** + * Registers an [Item] gossip event handler. + * + *
+     * enum GossipEvents
+     * {
+     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
+     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
+     *     GOSSIP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [Item] entry Id + * @param uint32 event : [Item] gossip event Id, refer to GossipEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterItemGossipEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_ITEM_GOSSIP); + } + + /** + * Registers a [Map] event handler for all instance of a [Map]. + * + *
+     * enum InstanceEvents
+     * {
+     *     INSTANCE_EVENT_ON_INITIALIZE                    = 1,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_ON_LOAD                          = 2,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_ON_UPDATE                        = 3,    // (event, instance_data, map, diff)
+     *     INSTANCE_EVENT_ON_PLAYER_ENTER                  = 4,    // (event, instance_data, map, player)
+     *     INSTANCE_EVENT_ON_CREATURE_CREATE               = 5,    // (event, instance_data, map, creature)
+     *     INSTANCE_EVENT_ON_GAMEOBJECT_CREATE             = 6,    // (event, instance_data, map, go)
+     *     INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS   = 7,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_COUNT
+     * };
+     * 
+ * + * @param uint32 map_id : ID of a [Map] + * @param uint32 event : [Map] event ID, refer to MapEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + */ + int RegisterMapEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_MAP); + } + + /** + * Registers a [Map] event handler for one instance of a [Map]. + * + *
+     * enum InstanceEvents
+     * {
+     *     INSTANCE_EVENT_ON_INITIALIZE                    = 1,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_ON_LOAD                          = 2,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_ON_UPDATE                        = 3,    // (event, instance_data, map, diff)
+     *     INSTANCE_EVENT_ON_PLAYER_ENTER                  = 4,    // (event, instance_data, map, player)
+     *     INSTANCE_EVENT_ON_CREATURE_CREATE               = 5,    // (event, instance_data, map, creature)
+     *     INSTANCE_EVENT_ON_GAMEOBJECT_CREATE             = 6,    // (event, instance_data, map, go)
+     *     INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS   = 7,    // (event, instance_data, map)
+     *     INSTANCE_EVENT_COUNT
+     * };
+     * 
+ * + * @param uint32 instance_id : ID of an instance of a [Map] + * @param uint32 event : [Map] event ID, refer to MapEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + */ + int RegisterInstanceEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_INSTANCE); + } + + /** + * Registers a [Player] gossip event handler. + * + * Note that you can not use `GOSSIP_EVENT_ON_HELLO` with this hook. It does nothing since players dont have an "on hello". + * + *
+     * enum GossipEvents
+     * {
+     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
+     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
+     *     GOSSIP_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (menu_id, event, function) + * @proto cancel = (menu_id, event, function, shots) + * + * @param uint32 menu_id : [Player] gossip menu Id + * @param uint32 event : [Player] gossip event Id, refer to GossipEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterPlayerGossipEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_PLAYER_GOSSIP); + } + + /** + * Registers a [Creature] event handler. + * + *
+     * enum CreatureEvents
+     * {
+     *     CREATURE_EVENT_ON_ENTER_COMBAT                    = 1,  // (event, creature, target) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_LEAVE_COMBAT                    = 2,  // (event, creature) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_TARGET_DIED                     = 3,  // (event, creature, victim) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_DIED                            = 4,  // (event, creature, killer) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SPAWN                           = 5,  // (event, creature) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_REACH_WP                        = 6,  // (event, creature, type, id) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_AIUPDATE                        = 7,  // (event, creature, diff) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_RECEIVE_EMOTE                   = 8,  // (event, creature, player, emoteid) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_DAMAGE_TAKEN                    = 9,  // (event, creature, attacker, damage) - Can return true to stop normal action, can return new damage as second return value.
+     *     CREATURE_EVENT_ON_PRE_COMBAT                      = 10, // (event, creature, target) - Can return true to stop normal action
+     *     // UNUSED
+     *     CREATURE_EVENT_ON_OWNER_ATTACKED                  = 12, // (event, creature, target) - Can return true to stop normal action            // Not on mangos
+     *     CREATURE_EVENT_ON_OWNER_ATTACKED_AT               = 13, // (event, creature, attacker) - Can return true to stop normal action          // Not on mangos
+     *     CREATURE_EVENT_ON_HIT_BY_SPELL                    = 14, // (event, creature, caster, spellid) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SPELL_HIT_TARGET                = 15, // (event, creature, target, spellid) - Can return true to stop normal action
+     *     // UNUSED                                         = 16, // (event, creature)
+     *     // UNUSED                                         = 17, // (event, creature)
+     *     // UNUSED                                         = 18, // (event, creature)
+     *     CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE          = 19, // (event, creature, summon) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN       = 20, // (event, creature, summon) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED          = 21, // (event, creature, summon, killer) - Can return true to stop normal action    // Not on mangos
+     *     CREATURE_EVENT_ON_SUMMONED                        = 22, // (event, creature, summoner) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_RESET                           = 23, // (event, creature)
+     *     CREATURE_EVENT_ON_REACH_HOME                      = 24, // (event, creature) - Can return true to stop normal action
+     *     // UNUSED                                         = 25, // (event, creature)
+     *     CREATURE_EVENT_ON_CORPSE_REMOVED                  = 26, // (event, creature, respawndelay) - Can return true to stop normal action, can return new respawndelay as second return value
+     *     CREATURE_EVENT_ON_MOVE_IN_LOS                     = 27, // (event, creature, unit) - Can return true to stop normal action. Does not actually check LOS, just uses the sight range
+     *     // UNUSED                                         = 28, // (event, creature)
+     *     // UNUSED                                         = 29, // (event, creature)
+     *     CREATURE_EVENT_ON_DUMMY_EFFECT                    = 30, // (event, caster, spellid, effindex, creature)
+     *     CREATURE_EVENT_ON_QUEST_ACCEPT                    = 31, // (event, player, creature, quest) - Can return true
+     *     // UNUSED                                         = 32, // (event, creature)
+     *     // UNUSED                                         = 33, // (event, creature)
+     *     CREATURE_EVENT_ON_QUEST_REWARD                    = 34, // (event, player, creature, quest, opt) - Can return true
+     *     CREATURE_EVENT_ON_DIALOG_STATUS                   = 35, // (event, player, creature)
+     *     CREATURE_EVENT_ON_ADD                             = 36, // (event, creature)
+     *     CREATURE_EVENT_ON_REMOVE                          = 37, // (event, creature)
+     *     CREATURE_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : the ID of one or more [Creature]s + * @param uint32 event : refer to CreatureEvents above + * @param function function : function that will be called when the event occurs + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterCreatureEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_CREATURE); + } + + /** + * Registers a [Creature] event handler for a *single* [Creature]. + * + *
+     * enum CreatureEvents
+     * {
+     *     CREATURE_EVENT_ON_ENTER_COMBAT                    = 1,  // (event, creature, target) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_LEAVE_COMBAT                    = 2,  // (event, creature) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_TARGET_DIED                     = 3,  // (event, creature, victim) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_DIED                            = 4,  // (event, creature, killer) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SPAWN                           = 5,  // (event, creature) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_REACH_WP                        = 6,  // (event, creature, type, id) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_AIUPDATE                        = 7,  // (event, creature, diff) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_RECEIVE_EMOTE                   = 8,  // (event, creature, player, emoteid) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_DAMAGE_TAKEN                    = 9,  // (event, creature, attacker, damage) - Can return true to stop normal action, can return new damage as second return value.
+     *     CREATURE_EVENT_ON_PRE_COMBAT                      = 10, // (event, creature, target) - Can return true to stop normal action
+     *     // UNUSED
+     *     CREATURE_EVENT_ON_OWNER_ATTACKED                  = 12, // (event, creature, target) - Can return true to stop normal action            // Not on mangos
+     *     CREATURE_EVENT_ON_OWNER_ATTACKED_AT               = 13, // (event, creature, attacker) - Can return true to stop normal action          // Not on mangos
+     *     CREATURE_EVENT_ON_HIT_BY_SPELL                    = 14, // (event, creature, caster, spellid) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SPELL_HIT_TARGET                = 15, // (event, creature, target, spellid) - Can return true to stop normal action
+     *     // UNUSED                                         = 16, // (event, creature)
+     *     // UNUSED                                         = 17, // (event, creature)
+     *     // UNUSED                                         = 18, // (event, creature)
+     *     CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE          = 19, // (event, creature, summon) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN       = 20, // (event, creature, summon) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED          = 21, // (event, creature, summon, killer) - Can return true to stop normal action    // Not on mangos
+     *     CREATURE_EVENT_ON_SUMMONED                        = 22, // (event, creature, summoner) - Can return true to stop normal action
+     *     CREATURE_EVENT_ON_RESET                           = 23, // (event, creature)
+     *     CREATURE_EVENT_ON_REACH_HOME                      = 24, // (event, creature) - Can return true to stop normal action
+     *     // UNUSED                                         = 25, // (event, creature)
+     *     CREATURE_EVENT_ON_CORPSE_REMOVED                  = 26, // (event, creature, respawndelay) - Can return true to stop normal action, can return new respawndelay as second return value
+     *     CREATURE_EVENT_ON_MOVE_IN_LOS                     = 27, // (event, creature, unit) - Can return true to stop normal action. Does not actually check LOS, just uses the sight range
+     *     // UNUSED                                         = 28, // (event, creature)
+     *     // UNUSED                                         = 29, // (event, creature)
+     *     CREATURE_EVENT_ON_DUMMY_EFFECT                    = 30, // (event, caster, spellid, effindex, creature)
+     *     CREATURE_EVENT_ON_QUEST_ACCEPT                    = 31, // (event, player, creature, quest) - Can return true
+     *     // UNUSED                                         = 32, // (event, creature)
+     *     // UNUSED                                         = 33, // (event, creature)
+     *     CREATURE_EVENT_ON_QUEST_REWARD                    = 34, // (event, player, creature, quest, opt) - Can return true
+     *     CREATURE_EVENT_ON_DIALOG_STATUS                   = 35, // (event, player, creature)
+     *     CREATURE_EVENT_ON_ADD                             = 36, // (event, creature)
+     *     CREATURE_EVENT_ON_REMOVE                          = 37, // (event, creature)
+     *     CREATURE_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (guid, instance_id, event, function) + * @proto cancel = (guid, instance_id, event, function, shots) + * + * @param ObjectGuid guid : the GUID of a single [Creature] + * @param uint32 instance_id : the instance ID of a single [Creature] + * @param uint32 event : refer to CreatureEvents above + * @param function function : function that will be called when the event occurs + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterUniqueCreatureEvent(lua_State* L) + { + return RegisterUniqueHelper(L, Hooks::REGTYPE_CREATURE); + } + + /** + * Registers a [GameObject] event handler. + * + *
+     * enum GameObjectEvents
+     * {
+     *     GAMEOBJECT_EVENT_ON_AIUPDATE                    = 1,    // (event, go, diff)
+     *     GAMEOBJECT_EVENT_ON_SPAWN                       = 2,    // (event, go)
+     *     GAMEOBJECT_EVENT_ON_DUMMY_EFFECT                = 3,    // (event, caster, spellid, effindex, go) - Can return true to stop normal action
+     *     GAMEOBJECT_EVENT_ON_QUEST_ACCEPT                = 4,    // (event, player, go, quest) - Can return true to stop normal action
+     *     GAMEOBJECT_EVENT_ON_QUEST_REWARD                = 5,    // (event, player, go, quest, opt) - Can return true to stop normal action
+     *     GAMEOBJECT_EVENT_ON_DIALOG_STATUS               = 6,    // (event, player, go)
+     *     GAMEOBJECT_EVENT_ON_DESTROYED                   = 7,    // (event, go, attacker)
+     *     GAMEOBJECT_EVENT_ON_DAMAGED                     = 8,    // (event, go, attacker)
+     *     GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE           = 9,    // (event, go, state)
+     *     GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED            = 10,   // (event, go, state)
+     *     // UNUSED                                       = 11,   // (event, gameobject)
+     *     GAMEOBJECT_EVENT_ON_ADD                         = 12,   // (event, gameobject)
+     *     GAMEOBJECT_EVENT_ON_REMOVE                      = 13,   // (event, gameobject)
+     *     GAMEOBJECT_EVENT_ON_USE                         = 14,   // (event, go, player) - Can return true to stop normal action
+     *     GAMEOBJECT_EVENT_COUNT
+     * };
+     * 
+ * + * @proto cancel = (entry, event, function) + * @proto cancel = (entry, event, function, shots) + * + * @param uint32 entry : [GameObject] entry Id + * @param uint32 event : [GameObject] event Id, refer to GameObjectEvents above + * @param function function : function to register + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" + * + * @return function cancel : a function that cancels the binding when called + */ + int RegisterGameObjectEvent(lua_State* L) + { + return RegisterEntryHelper(L, Hooks::REGTYPE_GAMEOBJECT); + } + + /** + * Reloads the Lua engine. + */ + int ReloadEluna(lua_State* /*L*/) + { + Eluna::ReloadEluna(); + return 0; + } + + /** + * Runs a command. + * + * @param string command : the command to run + */ + int RunCommand(lua_State* L) + { + const char* command = Eluna::CHECKVAL(L, 1); + + eWorld->QueueCliCommand(new CliCommandHolder(0, SEC_CONSOLE, nullptr, command, nullptr, nullptr)); + return 0; + } + + /** + * Sends a message to all [Player]s online. + * + * @param string message : message to send + */ + int SendWorldMessage(lua_State* L) + { + const char* message = Eluna::CHECKVAL(L, 1); + eWorld->SendServerMessage(SERVER_MSG_STRING, message); + return 0; + } + + /** + * Executes a SQL query on the world database and returns an [ElunaQuery]. + * + * The query is always executed synchronously + * (i.e. execution halts until the query has finished and then results are returned). + * + * local Q = WorldDBQuery("SELECT entry, name FROM creature_template LIMIT 10") + * if Q then + * repeat + * local entry, name = Q:GetUInt32(0), Q:GetString(1) + * print(entry, name) + * until not Q:NextRow() + * end + * + * @param string sql : query to execute + * @return [ElunaQuery] results or nil if no rows found or nil if no rows found + */ + int WorldDBQuery(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + + ElunaQuery* result = WorldDatabase.QueryNamed(query); + if (result) + Eluna::Push(L, result); + else + Eluna::Push(L); + return 1; + } + + /** + * Executes a SQL query on the world database. + * + * The query may be executed *asynchronously* (at a later, unpredictable time). + * If you need to execute the query synchronously, use [Global:WorldDBQuery] instead. + * + * Any results produced are ignored. + * If you need results from the query, use [Global:WorldDBQuery] instead. + * + * WorldDBExecute("DELETE FROM my_table") + * + * @param string sql : query to execute + */ + int WorldDBExecute(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + WorldDatabase.Execute(query); + return 0; + } + + /** + * Executes a SQL query on the character database and returns an [ElunaQuery]. + * + * The query is always executed synchronously + * (i.e. execution halts until the query has finished and then results are returned). + * + * For an example see [Global:WorldDBQuery]. + * + * @param string sql : query to execute + * @return [ElunaQuery] results or nil if no rows found + */ + int CharDBQuery(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + + QueryNamedResult* result = CharacterDatabase.QueryNamed(query); + if (result) + Eluna::Push(L, result); + else + Eluna::Push(L); + return 1; + } + + /** + * Executes a SQL query on the character database. + * + * The query may be executed *asynchronously* (at a later, unpredictable time). + * If you need to execute the query synchronously, use [Global:CharDBQuery] instead. + * + * Any results produced are ignored. + * If you need results from the query, use [Global:CharDBQuery] instead. + * + * CharDBExecute("DELETE FROM my_table") + * + * @param string sql : query to execute + */ + int CharDBExecute(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + CharacterDatabase.Execute(query); + return 0; + } + + /** + * Executes a SQL query on the login database and returns an [ElunaQuery]. + * + * The query is always executed synchronously + * (i.e. execution halts until the query has finished and then results are returned). + * + * For an example see [Global:WorldDBQuery]. + * + * @param string sql : query to execute + * @return [ElunaQuery] results or nil if no rows found + */ + int AuthDBQuery(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + + QueryNamedResult* result = LoginDatabase.QueryNamed(query); + if (result) + Eluna::Push(L, result); + else + Eluna::Push(L); + return 1; + } + + /** + * Executes a SQL query on the login database. + * + * The query may be executed *asynchronously* (at a later, unpredictable time). + * If you need to execute the query synchronously, use [Global:AuthDBQuery] instead. + * + * Any results produced are ignored. + * If you need results from the query, use [Global:AuthDBQuery] instead. + * + * AuthDBExecute("DELETE FROM my_table") + * + * @param string sql : query to execute + */ + int AuthDBExecute(lua_State* L) + { + const char* query = Eluna::CHECKVAL(L, 1); + LoginDatabase.Execute(query); + return 0; + } + + /** + * Registers a global timed event. + * + * When the passed function is called, the parameters `(eventId, delay, repeats)` are passed to it. + * + * Repeats will decrease on each call if the event does not repeat indefinitely + * + * @proto eventId = (function, delay) + * @proto eventId = (function, delaytable) + * @proto eventId = (function, delay, repeats) + * @proto eventId = (function, delaytable, repeats) + * + * @param function function : function to trigger when the time has passed + * @param uint32 delay : set time in milliseconds for the event to trigger + * @param table delaytable : a table `{min, max}` containing the minimum and maximum delay time + * @param uint32 repeats = 1 : how many times for the event to repeat, 0 is infinite + * @return int eventId : unique ID for the timed event used to cancel it or nil + */ + int CreateLuaEvent(lua_State* L) + { + luaL_checktype(L, 1, LUA_TFUNCTION); + uint32 min, max; + if (lua_istable(L, 2)) + { + Eluna::Push(L, 1); + lua_gettable(L, 2); + min = Eluna::CHECKVAL(L, -1); + Eluna::Push(L, 2); + lua_gettable(L, 2); + max = Eluna::CHECKVAL(L, -1); + lua_pop(L, 2); + } + else + min = max = Eluna::CHECKVAL(L, 2); + uint32 repeats = Eluna::CHECKVAL(L, 3, 1); + + if (min > max) + return luaL_argerror(L, 2, "min is bigger than max delay"); + + lua_pushvalue(L, 1); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF) + { + Eluna::GetEluna(L)->eventMgr->globalProcessor->AddEvent(functionRef, min, max, repeats); + Eluna::Push(L, functionRef); + } + return 1; + } + + /** + * Removes a global timed event specified by ID. + * + * @param int eventId : event Id to remove + * @param bool all_Events = false : remove from all events, not just global + */ + int RemoveEventById(lua_State* L) + { + int eventId = Eluna::CHECKVAL(L, 1); + bool all_Events = Eluna::CHECKVAL(L, 1, false); + + // not thread safe + if (all_Events) + Eluna::GetEluna(L)->eventMgr->SetState(eventId, LUAEVENT_STATE_ABORT); + else + Eluna::GetEluna(L)->eventMgr->globalProcessor->SetState(eventId, LUAEVENT_STATE_ABORT); + return 0; + } + + /** + * Removes all global timed events. + * + * @param bool all_Events = false : remove all events, not just global + */ + int RemoveEvents(lua_State* L) + { + bool all_Events = Eluna::CHECKVAL(L, 1, false); + + // not thread safe + if (all_Events) + Eluna::GetEluna(L)->eventMgr->SetStates(LUAEVENT_STATE_ABORT); + else + Eluna::GetEluna(L)->eventMgr->globalProcessor->SetStates(LUAEVENT_STATE_ABORT); + return 0; + } + + /** + * Performs an in-game spawn and returns the [Creature] or [GameObject] spawned. + * + * @param int32 spawnType : type of object to spawn, 1 = [Creature], 2 = [GameObject] + * @param uint32 entry : entry ID of the [Creature] or [GameObject] + * @param uint32 mapId : map ID to spawn the [Creature] or [GameObject] in + * @param uint32 instanceId : instance ID to put the [Creature] or [GameObject] in. Non instance is 0 + * @param float x : x coordinate of the [Creature] or [GameObject] + * @param float y : y coordinate of the [Creature] or [GameObject] + * @param float z : z coordinate of the [Creature] or [GameObject] + * @param float o : o facing/orientation of the [Creature] or [GameObject] + * @param bool save = false : optional to save the [Creature] or [GameObject] to the database + * @param uint32 durorresptime = 0 : despawn time of the [Creature] if it's not saved or respawn time of [GameObject] + * @param uint32 phase = 1 : phase to put the [Creature] or [GameObject] in + * @return [WorldObject] worldObject : returns [Creature] or [GameObject] + */ + int PerformIngameSpawn(lua_State* L) + { + int spawntype = Eluna::CHECKVAL(L, 1); + uint32 entry = Eluna::CHECKVAL(L, 2); + uint32 mapID = Eluna::CHECKVAL(L, 3); + uint32 instanceID = Eluna::CHECKVAL(L, 4); + float x = Eluna::CHECKVAL(L, 5); + float y = Eluna::CHECKVAL(L, 6); + float z = Eluna::CHECKVAL(L, 7); + float o = Eluna::CHECKVAL(L, 8); + bool save = Eluna::CHECKVAL(L, 9, false); + uint32 durorresptime = Eluna::CHECKVAL(L, 10, 0); + + Map* map = eMapMgr->FindMap(mapID, instanceID); + if (!map) + { + Eluna::Push(L); + return 1; + } + + if (spawntype == 1) // spawn creature + { + if (save) + { + CreatureInfo const* cinfo = ObjectMgr::GetCreatureTemplate(entry); + if (!cinfo) + { + Eluna::Push(L); + return 1; + } + + CreatureCreatePos pos(map, x, y, z, o); + + Creature* pCreature = new Creature; + // used guids from specially reserved range (can be 0 if no free values) + uint32 lowguid = eObjectMgr->GenerateStaticCreatureLowGuid(); + if (!lowguid) + { + Eluna::Push(L); + return 1; + } + + if (!pCreature->Create(lowguid, pos, cinfo, cinfo->entry)) + { + delete pCreature; + Eluna::Push(L); + return 1; + } + + pCreature->SaveToDB(map->GetId()); + + uint32 db_guid = pCreature->GetGUIDLow(); + + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + pCreature->LoadFromDB(db_guid, map); + + map->Add(pCreature); + eObjectMgr->AddCreatureToGrid(db_guid, eObjectMgr->GetCreatureData(db_guid)); + if (durorresptime) + pCreature->ForcedDespawn(durorresptime); + + Eluna::Push(L, pCreature); + } + else + { + CreatureInfo const* cinfo = ObjectMgr::GetCreatureTemplate(entry); + if (!cinfo) + { + Eluna::Push(L); + return 1; + } + + TemporarySummon* pCreature = new TemporarySummon(ObjectGuid(uint64(0))); + + CreatureCreatePos pos(map, x, y, z, o); + + if (!pCreature->Create(map->GenerateLocalLowGuid(cinfo->GetHighGuid()), pos, cinfo, TEAM_NONE)) + { + delete pCreature; + { + Eluna::Push(L); + return 1; + } + } + + // Active state set before added to map + pCreature->SetActiveObjectState(false); + + // Also initializes the AI and MMGen + pCreature->Summon(durorresptime ? TEMPSUMMON_TIMED_OR_DEAD_DESPAWN : TEMPSUMMON_MANUAL_DESPAWN, durorresptime); + + // Creature Linking, Initial load is handled like respawn + if (pCreature->IsLinkingEventTrigger()) + map->GetCreatureLinkingHolder()->DoCreatureLinkingEvent(LINKING_EVENT_RESPAWN, pCreature); + + Eluna::Push(L, pCreature); + } + + return 1; + } + + if (spawntype == 2) // Spawn object + { + if (save) + { + const GameObjectInfo* gInfo = ObjectMgr::GetGameObjectInfo(entry); + if (!gInfo) + { + Eluna::Push(L); + return 1; + } + + // used guids from specially reserved range (can be 0 if no free values) + uint32 db_lowGUID = eObjectMgr->GenerateStaticGameObjectLowGuid(); + if (!db_lowGUID) + { + Eluna::Push(L); + return 1; + } + + GameObject* pGameObj = new GameObject; + if (!pGameObj->Create(db_lowGUID, gInfo->id, map, x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) // TODO: allow vMangos Eluna Lua func to provide rotation, animprogress, & state + { + delete pGameObj; + Eluna::Push(L); + return 1; + } + + if (durorresptime) + pGameObj->SetRespawnTime(durorresptime); + + // fill the gameobject data and save to the db + pGameObj->SaveToDB(map->GetId()); + + // this will generate a new guid if the object is in an instance + if (!pGameObj->LoadFromDB(db_lowGUID, map)) + + { + delete pGameObj; + Eluna::Push(L); + return 1; + } + + // DEBUG_LOG(GetMangosString(LANG_GAMEOBJECT_CURRENT), gInfo->name, db_lowGUID, x, y, z, o); + + map->Add(pGameObj); + pGameObj->AIM_Initialize(); + + eObjectMgr->AddGameobjectToGrid(db_lowGUID, eObjectMgr->GetGOData(db_lowGUID)); + + Eluna::Push(L, pGameObj); + } + else + { + GameObject* pGameObj = new GameObject; + + if (!pGameObj->Create(map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), entry, map, x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) // TODO: allow vMangos Eluna Lua func to provide rotation, animprogress, & state + { + delete pGameObj; + Eluna::Push(L); + return 1; + } + + pGameObj->SetRespawnTime(durorresptime / IN_MILLISECONDS); + + map->Add(pGameObj); + pGameObj->AIM_Initialize(); + + Eluna::Push(L, pGameObj); + } + return 1; + } + Eluna::Push(L); + return 1; + } + + /** + * Creates a [WorldPacket]. + * + * @param [Opcodes] opcode : the opcode of the packet + * @param uint32 size : the size of the packet + * @return [WorldPacket] packet + */ + int CreatePacket(lua_State* L) + { + uint32 opcode = Eluna::CHECKVAL(L, 1); + size_t size = Eluna::CHECKVAL(L, 2); + if (opcode >= NUM_MSG_TYPES) + return luaL_argerror(L, 1, "valid opcode expected"); + + Eluna::Push(L, new WorldPacket((OpcodesList)opcode, size)); + return 1; + } + + /** + * Adds an [Item] to a vendor and updates the world database. + * + * @param uint32 entry : [Creature] entry Id + * @param uint32 item : [Item] entry Id + * @param int32 maxcount : max [Item] stack count + * @param uint32 incrtime : combined with maxcount, incrtime tells how often (in seconds) the vendor list is refreshed and the limited [Item] copies are restocked + * @param uint32 extendedcost : unique cost of an [Item], such as conquest points for example + */ + int AddVendorItem(lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 item = Eluna::CHECKVAL(L, 2); + int maxcount = Eluna::CHECKVAL(L, 3); + uint32 incrtime = Eluna::CHECKVAL(L, 4); + uint32 extendedcost = Eluna::CHECKVAL(L, 5); + + if (!eObjectMgr->IsVendorItemValid(false, "npc_vendor", entry, item, maxcount, incrtime, 0)) + return 0; + + eObjectMgr->AddVendorItem(entry, item, maxcount, incrtime, 0); // TODO: Allow vMangos Eluna to provide item flags.); + return 0; + } + + /** + * Removes an [Item] from a vendor and updates the database. + * + * @param uint32 entry : [Creature] entry Id + * @param uint32 item : [Item] entry Id + */ + int VendorRemoveItem(lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 item = Eluna::CHECKVAL(L, 2); + if (!eObjectMgr->GetCreatureTemplate(entry)) + return luaL_argerror(L, 1, "valid CreatureEntry expected"); + + eObjectMgr->RemoveVendorItem(entry, item); + return 0; + } + + /** + * Removes all [Item]s from a vendor and updates the database. + * + * @param uint32 entry : [Creature] entry Id + */ + int VendorRemoveAllItems(lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + VendorItemData const* items = eObjectMgr->GetNpcVendorItemList(entry); + if (!items || items->Empty()) + return 0; + + auto const itemlist = items->m_items; + for (auto itr = itemlist.begin(); itr != itemlist.end(); ++itr) + eObjectMgr->RemoveVendorItem(entry, (*itr)->item); + + return 0; + } + + /** + * Kicks a [Player] from the server. + * + * @param [Player] player : [Player] to kick + */ + int Kick(lua_State* L) + { + Player* player = Eluna::CHECKOBJ(L, 1); + player->GetSession()->KickPlayer(); + return 0; + } + + /** + * Ban's a [Player]'s account, character or IP + * + * enum BanMode + * { + * BAN_ACCOUNT = 0, + * BAN_CHARACTER = 1, + * BAN_IP = 2 + * }; + * + * @param [BanMode] banMode : method of ban, refer to BanMode above + * @param string nameOrIP : If BanMode is 0 then accountname, if 1 then charactername if 2 then ip + * @param uint32 duration : duration (in seconds) of the ban + * @param string reason = "" : ban reason, this is optional + * @param string whoBanned = "" : the [Player]'s name that banned the account, character or IP, this is optional + * @return int result : status of the ban. 0 if success, 1 if syntax error, 2 if target not found, 3 if a longer ban already exists, nil if unknown result + */ + int Ban(lua_State* L) + { + int banMode = Eluna::CHECKVAL(L, 1); + std::string nameOrIP = Eluna::CHECKVAL(L, 2); + uint32 duration = Eluna::CHECKVAL(L, 3); + const char* reason = Eluna::CHECKVAL(L, 4, ""); + const char* whoBanned = Eluna::CHECKVAL(L, 5, ""); + + const int BAN_ACCOUNT = 0; + const int BAN_CHARACTER = 1; + const int BAN_IP = 2; + + BanMode mode = BanMode::BAN_ACCOUNT; + + switch (banMode) + { + case BAN_ACCOUNT: + if (!AccountMgr::normalizeString(nameOrIP)) + return luaL_argerror(L, 2, "invalid account name"); + mode = BanMode::BAN_ACCOUNT; + break; + case BAN_CHARACTER: + if (!normalizePlayerName(nameOrIP)) + return luaL_argerror(L, 2, "invalid character name"); + mode = BanMode::BAN_CHARACTER; + break; + case BAN_IP: + if (!IsIPAddress(nameOrIP.c_str())) + return luaL_argerror(L, 2, "invalid ip"); + mode = BanMode::BAN_IP; + break; + default: + return luaL_argerror(L, 1, "unknown banmode"); + } + + BanReturn result; + result = eWorld->BanAccount(mode, nameOrIP, duration, reason, whoBanned); + + switch (result) + { + case BanReturn::BAN_SUCCESS: + Eluna::Push(L, 0); + break; + case BanReturn::BAN_SYNTAX_ERROR: + Eluna::Push(L, 1); + break; + case BanReturn::BAN_NOTFOUND: + Eluna::Push(L, 2); + break; + } + return 1; + } + + /** + * Saves all [Player]s. + */ + int SaveAllPlayers(lua_State* /*L*/) + { + eObjectAccessor()SaveAllPlayers(); + return 0; + } + + /** + * Sends mail to a [Player]. + * + * There can be several item entry-amount pairs at the end of the function. + * There can be maximum of 12 different items. + * + * enum MailStationery + * { + * MAIL_STATIONERY_TEST = 1, + * MAIL_STATIONERY_DEFAULT = 41, + * MAIL_STATIONERY_GM = 61, + * MAIL_STATIONERY_AUCTION = 62, + * MAIL_STATIONERY_VAL = 64, // Valentine + * MAIL_STATIONERY_CHR = 65, // Christmas + * MAIL_STATIONERY_ORP = 67 // Orphan + * }; + * + * @param string subject : title (subject) of the mail + * @param string text : contents of the mail + * @param uint32 receiverGUIDLow : low GUID of the receiver + * @param uint32 senderGUIDLow = 0 : low GUID of the sender + * @param [MailStationery] stationary = MAIL_STATIONERY_DEFAULT : type of mail that is being sent as, refer to MailStationery above + * @param uint32 delay = 0 : mail send delay in milliseconds + * @param uint32 money = 0 : money to send + * @param uint32 cod = 0 : cod money amount + * @param uint32 entry = 0 : entry of an [Item] to send with mail + * @param uint32 amount = 0 : amount of the [Item] to send with mail + * @return uint32 itemGUIDlow : low GUID of the item. Up to 12 values returned, returns nil if no further items are sent + */ + int SendMail(lua_State* L) + { + int i = 0; + std::string subject = Eluna::CHECKVAL(L, ++i); + std::string text = Eluna::CHECKVAL(L, ++i); + uint32 receiverGUIDLow = Eluna::CHECKVAL(L, ++i); + uint32 senderGUIDLow = Eluna::CHECKVAL(L, ++i, 0); + uint32 stationary = Eluna::CHECKVAL(L, ++i, MAIL_STATIONERY_DEFAULT); + uint32 delay = Eluna::CHECKVAL(L, ++i, 0); + uint32 money = Eluna::CHECKVAL(L, ++i, 0); + uint32 cod = Eluna::CHECKVAL(L, ++i, 0); + int argAmount = lua_gettop(L); + + MailSender sender(MAIL_NORMAL, senderGUIDLow, (MailStationery)stationary); + MailDraft draft(subject, text); + + if (cod) + draft.SetCOD(cod); + if (money) + draft.SetMoney(money); + + uint8 addedItems = 0; + while (addedItems <= MAX_MAIL_ITEMS && i + 2 <= argAmount) + { + uint32 entry = Eluna::CHECKVAL(L, ++i); + uint32 amount = Eluna::CHECKVAL(L, ++i); + + ItemTemplate const* item_proto = eObjectMgr->GetItemTemplate(entry); + + if (!item_proto) + { + luaL_error(L, "Item entry %d does not exist", entry); + continue; + } + if (amount < 1 || (item_proto->MaxCount > 0 && amount > uint32(item_proto->MaxCount))) + { + luaL_error(L, "Item entry %d has invalid amount %d", entry, amount); + continue; + } + if (Item* item = Item::CreateItem(entry, amount)) + { + item->SaveToDB(); + draft.AddItem(item); + Eluna::Push(L, item->GetGUIDLow()); + ++addedItems; + } + } + + Player* receiverPlayer = eObjectAccessor()FindPlayer(MAKE_NEW_GUID(receiverGUIDLow, 0, HIGHGUID_PLAYER)); + draft.SendMailTo(MailReceiver(receiverPlayer, MAKE_NEW_GUID(receiverGUIDLow, 0, HIGHGUID_PLAYER)), sender); + return addedItems; + } + + /** + * Performs a bitwise AND (a & b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_and(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a & b); + return 1; + } + + /** + * Performs a bitwise OR (a | b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_or(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a | b); + return 1; + } + + /** + * Performs a bitwise left-shift (a << b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_lshift(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a << b); + return 1; + } + + /** + * Performs a bitwise right-shift (a >> b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_rshift(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a >> b); + return 1; + } + + /** + * Performs a bitwise XOR (a ^ b). + * + * @param uint32 a + * @param uint32 b + * @return uint32 result + */ + int bit_xor(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + uint32 b = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, a ^ b); + return 1; + } + + /** + * Performs a bitwise NOT (~a). + * + * @param uint32 a + * @return uint32 result + */ + int bit_not(lua_State* L) + { + uint32 a = Eluna::CHECKVAL(L, 1); + Eluna::Push(L, ~a); + return 1; + } + + /** + * Adds a taxi path to a specified map, returns the used pathId. + * + * Note that the first taxi point needs to be near the player when he starts the taxi path. + * The function should also be used only **once** per path added so use it on server startup for example. + * + * Related function: [Player:StartTaxi] + * + * -- Execute on startup + * local pathTable = {{mapid, x, y, z}, {mapid, x, y, z}} + * local path = AddTaxiPath(pathTable, 28135, 28135) + * + * -- Execute when the player should fly + * player:StartTaxi(path) + * + * @param table waypoints : table containing waypoints: {map, x, y, z[, actionFlag, delay]} + * @param uint32 mountA : alliance [Creature] entry + * @param uint32 mountH : horde [Creature] entry + * @param uint32 price = 0 : price of the taxi path + * @param uint32 pathId = 0 : path Id of the taxi path + * @return uint32 actualPathId + */ + int AddTaxiPath(lua_State* L) + { + luaL_checktype(L, 1, LUA_TTABLE); + uint32 mountA = Eluna::CHECKVAL(L, 2); + uint32 mountH = Eluna::CHECKVAL(L, 3); + uint32 price = Eluna::CHECKVAL(L, 4, 0); + uint32 pathId = Eluna::CHECKVAL(L, 5, 0); + lua_pushvalue(L, 1); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes} + + std::list nodes; + + int start = lua_gettop(L); + int end = start; + + Eluna::Push(L); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, nil + while (lua_next(L, -2) != 0) + { + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key, value + luaL_checktype(L, -1, LUA_TTABLE); + Eluna::Push(L); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key, value, nil + while (lua_next(L, -2) != 0) + { + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key, value, key2, value2 + lua_insert(L, end++); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, value2, key, value, key2 + } + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, value2, key, value + if (start == end) + continue; + if (end - start < 4) // no mandatory args, dont add + return luaL_argerror(L, 1, "all waypoints do not have mandatory arguments"); + + while (end - start < 8) // fill optional args with 0 + { + Eluna::Push(L, 0); + lua_insert(L, end++); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, node, key, value + } + TaxiPathNodeEntry entry; + // mandatory + entry.mapid = Eluna::CHECKVAL(L, start); + entry.x = Eluna::CHECKVAL(L, start + 1); + entry.y = Eluna::CHECKVAL(L, start + 2); + entry.z = Eluna::CHECKVAL(L, start + 3); + // optional + entry.actionFlag = Eluna::CHECKVAL(L, start + 4, 0); + entry.delay = Eluna::CHECKVAL(L, start + 5, 0); + + nodes.push_back(entry); + + while (end != start) // remove args + if (!lua_isnone(L, --end)) + lua_remove(L, end); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key, value + + lua_pop(L, 1); + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes}, key + } + // Stack: {nodes}, mountA, mountH, price, pathid, {nodes} + lua_pop(L, 1); + // Stack: {nodes}, mountA, mountH, price, pathid + + if (nodes.size() < 2) + return 1; + if (!pathId) + pathId = sTaxiPathNodesByPath.size(); + if (sTaxiPathNodesByPath.size() <= pathId) + sTaxiPathNodesByPath.resize(pathId + 1); + sTaxiPathNodesByPath[pathId].clear(); + sTaxiPathNodesByPath[pathId].resize(nodes.size()); + static uint32 nodeId = sObjectMgr.GetMaxTaxiNodeId(); + uint32 startNode = nodeId; + uint32 index = 0; + for (std::list::iterator it = nodes.begin(); it != nodes.end(); ++it) + { + TaxiPathNodeEntry& entry = *it; + std::unique_ptr nodeEntry = std::make_unique(); + entry.path = pathId; + entry.index = nodeId; + nodeEntry->ID = index; + nodeEntry->map_id = entry.mapid; + nodeEntry->x = entry.x; + nodeEntry->y = entry.y; + nodeEntry->z = entry.z; + nodeEntry->MountCreatureID[0] = mountH; + nodeEntry->MountCreatureID[1] = mountA; + sObjectMgr.SetTaxiNodeEntry(nodeId++, nodeEntry); + + sTaxiPathNodesByPath[pathId].set(index++, new TaxiPathNodeEntry(entry)); + } + if (startNode >= nodeId) + return 1; + sTaxiPathSetBySource[startNode][nodeId - 1] = TaxiPathBySourceAndDestination(pathId, price); + TaxiPathEntry* pathEntry = new TaxiPathEntry(); + pathEntry->from = startNode; + pathEntry->to = nodeId - 1; + pathEntry->price = price; + pathEntry->ID = pathId; + sTaxiPathStore.InsertEntry(pathId, pathEntry); + Eluna::Push(L, pathId); + return 1; + } + + /** + * Returns `true` if the bag and slot is a valid inventory position, otherwise `false`. + * + * Some commonly used combinations: + * + * *Bag 255 (common character inventory)* + * + * - Slots 0-18: equipment + * - Slots 19-22: bag slots + * - Slots 23-38: backpack + * - Slots 39-66: bank main slots + * - Slots 67-74: bank bag slots + * - Slots 86-117: keyring + * + * *Bags 19-22 (equipped bags)* + * + * - Slots 0-35 + * + * *Bags 67-74 (bank bags)* + * + * - Slots 0-35 + * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return bool isInventoryPos + */ + int IsInventoryPos(lua_State* L) + { + uint8 bag = Eluna::CHECKVAL(L, 1); + uint8 slot = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, Player::IsInventoryPos(bag, slot)); + return 1; + } + + /** + * Returns `true` if the bag and slot is a valid equipment position, otherwise `false`. + * + * See [Global:IsInventoryPos] for bag/slot combination examples. + * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return bool isEquipmentPosition + */ + int IsEquipmentPos(lua_State* L) + { + uint8 bag = Eluna::CHECKVAL(L, 1); + uint8 slot = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, Player::IsEquipmentPos(bag, slot)); + return 1; + } + + /** + * Returns `true` if the bag and slot is a valid bank position, otherwise `false`. + * + * See [Global:IsInventoryPos] for bag/slot combination examples. + * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return bool isBankPosition + */ + int IsBankPos(lua_State* L) + { + uint8 bag = Eluna::CHECKVAL(L, 1); + uint8 slot = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, Player::IsBankPos(bag, slot)); + return 1; + } + + /** + * Returns `true` if the bag and slot is a valid bag position, otherwise `false`. + * + * See [Global:IsInventoryPos] for bag/slot combination examples. + * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return bool isBagPosition + */ + int IsBagPos(lua_State* L) + { + uint8 bag = Eluna::CHECKVAL(L, 1); + uint8 slot = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, Player::IsBagPos((bag << 8) + slot)); + return 1; + } + + /** + * Returns `true` if the event is currently active, otherwise `false`. + * + * @param uint16 eventId : the event id to check. + * @return bool isActive + */ + int IsGameEventActive(lua_State* L) + { + uint16 eventId = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, eGameEventMgr->IsActiveEvent(eventId)); + return 1; + } + + /** + * Returns the server's current time. + * + * @return uint32 currTime : the current time, in milliseconds + */ + int GetCurrTime(lua_State* L) + { + Eluna::Push(L, ElunaUtil::GetCurrTime()); + return 1; + } + + /** + * Returns the difference between an old timestamp and the current time. + * + * @param uint32 oldTime : an old timestamp, in milliseconds + * @return uint32 timeDiff : the difference, in milliseconds + */ + int GetTimeDiff(lua_State* L) + { + uint32 oldtimems = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, ElunaUtil::GetTimeDiff(oldtimems)); + return 1; + } + + static std::string GetStackAsString(lua_State* L) + { + std::ostringstream oss; + int top = lua_gettop(L); + for (int i = 1; i <= top; ++i) + { + oss << luaL_tolstring(L, i, NULL); + lua_pop(L, 1); + } + return oss.str(); + } + + /** + * Prints given parameters to the info log. + * + * @param ... + */ + int PrintInfo(lua_State* L) + { + ELUNA_LOG_INFO("%s", GetStackAsString(L).c_str()); + return 0; + } + + /** + * Prints given parameters to the error log. + * + * @param ... + */ + int PrintError(lua_State* L) + { + ELUNA_LOG_ERROR("%s", GetStackAsString(L).c_str()); + return 0; + } + + /** + * Prints given parameters to the debug log. + * + * @param ... + */ + int PrintDebug(lua_State* L) + { + ELUNA_LOG_DEBUG("%s", GetStackAsString(L).c_str()); + return 0; + } + + /** + * Starts the event by eventId, if force is set, the event will force start regardless of previous event state. + * + * @param uint16 eventId : the event id to start. + * @param bool force = false : set `true` to force start the event. + */ + int StartGameEvent(lua_State* L) + { + uint16 eventId = Eluna::CHECKVAL(L, 1); + bool force = Eluna::CHECKVAL(L, 2, false); + + eGameEventMgr->StartEvent(eventId, force); + return 0; + } + + /** + * Stops the event by eventId, if force is set, the event will force stop regardless of previous event state. + * + * @param uint16 eventId : the event id to stop. + * @param bool force = false : set `true` to force stop the event. + */ + int StopGameEvent(lua_State* L) + { + uint16 eventId = Eluna::CHECKVAL(L, 1); + bool force = Eluna::CHECKVAL(L, 2, false); + + eGameEventMgr->StopEvent(eventId, force); + return 0; + } + + /** + * Returns an object representing a `long long` (64-bit) value. + * + * The value by default is 0, but can be initialized to a value by passing a number or long long as a string. + * + * @proto value = () + * @proto value = (n) + * @proto value = (n_ll) + * @proto value = (n_str) + * @param int32 n + * @param int64 n_ll + * @param string n_str + * @return int64 value + */ + int CreateLongLong(lua_State* L) + { + long long init = 0; + if (lua_isstring(L, 1)) + { + std::string str = Eluna::CHECKVAL(L, 1); + std::istringstream iss(str); + iss >> init; + if (iss.bad()) + return luaL_argerror(L, 1, "long long (as string) could not be converted"); + } + else if (!lua_isnoneornil(L, 1)) + init = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, init); + return 1; + } + + /** + * Returns an object representing an `unsigned long long` (64-bit) value. + * + * The value by default is 0, but can be initialized to a value by passing a number or unsigned long long as a string. + * + * @proto value = () + * @proto value = (n) + * @proto value = (n_ull) + * @proto value = (n_str) + * @param uint32 n + * @param uint64 n_ull + * @param string n_str + * @return uint64 value + */ + int CreateULongLong(lua_State* L) + { + unsigned long long init = 0; + if (lua_isstring(L, 1)) + { + std::string str = Eluna::CHECKVAL(L, 1); + std::istringstream iss(str); + iss >> init; + if (iss.bad()) + return luaL_argerror(L, 1, "unsigned long long (as string) could not be converted"); + } + else if (!lua_isnoneornil(L, 1)) + init = Eluna::CHECKVAL(L, 1); + + Eluna::Push(L, init); + return 1; + } + + /** + * Unbinds event handlers for either all [BattleGround] events, or one type of event. + * + * If `event_type` is `nil`, all [BattleGround] event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterBGEvent] + */ + int ClearBattleGroundEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->BGEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->BGEventBindings->Clear(Key((Hooks::BGEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [Creature]'s events, or one type of event. + * + * If `event_type` is `nil`, all the [Creature]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [Creature], not just one. + * To bind and unbind events to a single [Creature], see [Global:RegisterUniqueCreatureEvent] and [Global:ClearUniqueCreatureEvents]. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of one or more [Creature]s whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterCreatureEvent] + */ + int ClearCreatureEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::CREATURE_EVENT_COUNT; ++i) + E->CreatureEventBindings->Clear(Key((Hooks::CreatureEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->CreatureEventBindings->Clear(Key((Hooks::CreatureEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [Creature]'s events, or one type of event. + * + * If `event_type` is `nil`, all the [Creature]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect only a single [Creature]. + * To bind and unbind events to all instances of a [Creature], see [Global:RegisterCreatureEvent] and [Global:ClearCreatureEvent]. + * + * @proto (entry) + * @proto (entry, event_type) + * @param ObjectGuid guid : the GUID of a single [Creature] whose handlers will be cleared + * @param uint32 instance_id : the instance ID of a single [Creature] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterCreatureEvent] + */ + int ClearUniqueCreatureEvents(lua_State* L) + { + typedef UniqueObjectKey Key; + + if (lua_isnoneornil(L, 3)) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + uint32 instanceId = Eluna::CHECKVAL(L, 2); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::CREATURE_EVENT_COUNT; ++i) + E->CreatureUniqueBindings->Clear(Key((Hooks::CreatureEvents)i, guid, instanceId)); + } + else + { + ObjectGuid guid = Eluna::CHECKVAL(L, 1); + uint32 instanceId = Eluna::CHECKVAL(L, 2); + uint32 event_type = Eluna::CHECKVAL(L, 3); + Eluna::GetEluna(L)->CreatureUniqueBindings->Clear(Key((Hooks::CreatureEvents)event_type, guid, instanceId)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [Creature]'s gossip events, or one type of event. + * + * If `event_type` is `nil`, all the [Creature]'s gossip event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [Creature], not just one. + * To bind and unbind gossip events to a single [Creature], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of a [Creature] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterCreatureGossipEvent] + */ + int ClearCreatureGossipEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i) + E->CreatureGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->CreatureGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [GameObject]'s events, or one type of event. + * + * If `event_type` is `nil`, all the [GameObject]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [GameObject], not just one. + * To bind and unbind events to a single [GameObject], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of a [GameObject] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGameObjectEvent] + */ + int ClearGameObjectEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GAMEOBJECT_EVENT_COUNT; ++i) + E->GameObjectEventBindings->Clear(Key((Hooks::GameObjectEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->GameObjectEventBindings->Clear(Key((Hooks::GameObjectEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [GameObject]'s gossip events, or one type of event. + * + * If `event_type` is `nil`, all the [GameObject]'s gossip event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [GameObject], not just one. + * To bind and unbind gossip events to a single [GameObject], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of a [GameObject] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGameObjectGossipEvent] + */ + int ClearGameObjectGossipEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i) + E->GameObjectGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->GameObjectGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all [Group] events, or one type of [Group] event. + * + * If `event_type` is `nil`, all [Group] event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGroupEvent] + */ + int ClearGroupEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->GroupEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->GroupEventBindings->Clear(Key((Hooks::GroupEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all [Guild] events, or one type of [Guild] event. + * + * If `event_type` is `nil`, all [Guild] event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGuildEvent] + */ + int ClearGuildEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->GuildEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->GuildEventBindings->Clear(Key((Hooks::GuildEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of an [Item]'s events, or one type of event. + * + * If `event_type` is `nil`, all the [Item]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [Item], not just one. + * To bind and unbind events to a single [Item], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of an [Item] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterItemEvent] + */ + int ClearItemEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::ITEM_EVENT_COUNT; ++i) + E->ItemEventBindings->Clear(Key((Hooks::ItemEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->ItemEventBindings->Clear(Key((Hooks::ItemEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of an [Item]'s gossip events, or one type of event. + * + * If `event_type` is `nil`, all the [Item]'s gossip event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * **NOTE:** this will affect all instances of the [Item], not just one. + * To bind and unbind gossip events to a single [Item], tell the Eluna developers to implement that. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the ID of an [Item] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterItemGossipEvent] + */ + int ClearItemGossipEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i) + E->ItemGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->ItemGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [WorldPacket] opcode's events, or one type of event. + * + * If `event_type` is `nil`, all the [WorldPacket] opcode's event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto (opcode) + * @proto (opcode, event_type) + * @param uint32 opcode : the type of [WorldPacket] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPacketEvent] + */ + int ClearPacketEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::PACKET_EVENT_COUNT; ++i) + E->PacketEventBindings->Clear(Key((Hooks::PacketEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->PacketEventBindings->Clear(Key((Hooks::PacketEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all [Player] events, or one type of [Player] event. + * + * If `event_type` is `nil`, all [Player] event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPlayerEvent] + */ + int ClearPlayerEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->PlayerEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->PlayerEventBindings->Clear(Key((Hooks::PlayerEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a [Player]'s gossip events, or one type of event. + * + * If `event_type` is `nil`, all the [Player]'s gossip event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto (entry) + * @proto (entry, event_type) + * @param uint32 entry : the low GUID of a [Player] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPlayerGossipEvent] + */ + int ClearPlayerGossipEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::GOSSIP_EVENT_COUNT; ++i) + E->PlayerGossipBindings->Clear(Key((Hooks::GossipEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->PlayerGossipBindings->Clear(Key((Hooks::GossipEvents)event_type, entry)); + } + return 0; + } + + /** + * Unbinds event handlers for either all server events, or one type of event. + * + * If `event_type` is `nil`, all server event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto () + * @proto (event_type) + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterServerEvent] + */ + int ClearServerEvents(lua_State* L) + { + typedef EventKey Key; + + if (lua_isnoneornil(L, 1)) + { + Eluna::GetEluna(L)->ServerEventBindings->Clear(); + } + else + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + Eluna::GetEluna(L)->ServerEventBindings->Clear(Key((Hooks::ServerEvents)event_type)); + } + return 0; + } + + /** + * Unbinds event handlers for either all of a non-instanced [Map]'s events, or one type of event. + * + * If `event_type` is `nil`, all the non-instanced [Map]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto (map_id) + * @proto (map_id, event_type) + * @param uint32 map_id : the ID of a [Map] + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPlayerGossipEvent] + */ + int ClearMapEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::INSTANCE_EVENT_COUNT; ++i) + E->MapEventBindings->Clear(Key((Hooks::InstanceEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->MapEventBindings->Clear(Key((Hooks::InstanceEvents)event_type, entry)); + } + + return 0; + } + + /** + * Unbinds event handlers for either all of an instanced [Map]'s events, or one type of event. + * + * If `event_type` is `nil`, all the instanced [Map]'s event handlers are cleared. + * + * Otherwise, only event handlers for `event_type` are cleared. + * + * @proto (instance_id) + * @proto (instance_id, event_type) + * @param uint32 entry : the ID of an instance of a [Map] + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterInstanceEvent] + */ + int ClearInstanceEvents(lua_State* L) + { + typedef EntryKey Key; + + if (lua_isnoneornil(L, 2)) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + + Eluna* E = Eluna::GetEluna(L); + for (uint32 i = 1; i < Hooks::INSTANCE_EVENT_COUNT; ++i) + E->InstanceEventBindings->Clear(Key((Hooks::InstanceEvents)i, entry)); + } + else + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + Eluna::GetEluna(L)->InstanceEventBindings->Clear(Key((Hooks::InstanceEvents)event_type, entry)); + } + + return 0; + } + + luaL_Reg GlobalMethods[] = + { + // Hooks + { "RegisterPacketEvent", &LuaGlobalFunctions::RegisterPacketEvent }, + { "RegisterServerEvent", &LuaGlobalFunctions::RegisterServerEvent }, + { "RegisterPlayerEvent", &LuaGlobalFunctions::RegisterPlayerEvent }, + { "RegisterGuildEvent", &LuaGlobalFunctions::RegisterGuildEvent }, + { "RegisterGroupEvent", &LuaGlobalFunctions::RegisterGroupEvent }, + { "RegisterCreatureEvent", &LuaGlobalFunctions::RegisterCreatureEvent }, + { "RegisterUniqueCreatureEvent", &LuaGlobalFunctions::RegisterUniqueCreatureEvent }, + { "RegisterCreatureGossipEvent", &LuaGlobalFunctions::RegisterCreatureGossipEvent }, + { "RegisterGameObjectEvent", &LuaGlobalFunctions::RegisterGameObjectEvent }, + { "RegisterGameObjectGossipEvent", &LuaGlobalFunctions::RegisterGameObjectGossipEvent }, + { "RegisterItemEvent", &LuaGlobalFunctions::RegisterItemEvent }, + { "RegisterItemGossipEvent", &LuaGlobalFunctions::RegisterItemGossipEvent }, + { "RegisterPlayerGossipEvent", &LuaGlobalFunctions::RegisterPlayerGossipEvent }, + { "RegisterBGEvent", &LuaGlobalFunctions::RegisterBGEvent }, + { "RegisterMapEvent", &LuaGlobalFunctions::RegisterMapEvent }, + { "RegisterInstanceEvent", &LuaGlobalFunctions::RegisterInstanceEvent }, + + { "ClearBattleGroundEvents", &LuaGlobalFunctions::ClearBattleGroundEvents }, + { "ClearCreatureEvents", &LuaGlobalFunctions::ClearCreatureEvents }, + { "ClearUniqueCreatureEvents", &LuaGlobalFunctions::ClearUniqueCreatureEvents }, + { "ClearCreatureGossipEvents", &LuaGlobalFunctions::ClearCreatureGossipEvents }, + { "ClearGameObjectEvents", &LuaGlobalFunctions::ClearGameObjectEvents }, + { "ClearGameObjectGossipEvents", &LuaGlobalFunctions::ClearGameObjectGossipEvents }, + { "ClearGroupEvents", &LuaGlobalFunctions::ClearGroupEvents }, + { "ClearGuildEvents", &LuaGlobalFunctions::ClearGuildEvents }, + { "ClearItemEvents", &LuaGlobalFunctions::ClearItemEvents }, + { "ClearItemGossipEvents", &LuaGlobalFunctions::ClearItemGossipEvents }, + { "ClearPacketEvents", &LuaGlobalFunctions::ClearPacketEvents }, + { "ClearPlayerEvents", &LuaGlobalFunctions::ClearPlayerEvents }, + { "ClearPlayerGossipEvents", &LuaGlobalFunctions::ClearPlayerGossipEvents }, + { "ClearServerEvents", &LuaGlobalFunctions::ClearServerEvents }, + { "ClearMapEvents", &LuaGlobalFunctions::ClearMapEvents }, + { "ClearInstanceEvents", &LuaGlobalFunctions::ClearInstanceEvents }, + + // Getters + { "GetLuaEngine", &LuaGlobalFunctions::GetLuaEngine }, + { "GetCoreName", &LuaGlobalFunctions::GetCoreName }, + { "GetRealmID", &LuaGlobalFunctions::GetRealmID }, + { "GetCoreVersion", &LuaGlobalFunctions::GetCoreVersion }, + { "GetCoreExpansion", &LuaGlobalFunctions::GetCoreExpansion }, + { "GetQuest", &LuaGlobalFunctions::GetQuest }, + { "GetPlayerByGUID", &LuaGlobalFunctions::GetPlayerByGUID }, + { "GetPlayerByName", &LuaGlobalFunctions::GetPlayerByName }, + { "GetGameTime", &LuaGlobalFunctions::GetGameTime }, + { "GetPlayersInWorld", &LuaGlobalFunctions::GetPlayersInWorld }, + { "GetGuildByName", &LuaGlobalFunctions::GetGuildByName }, + { "GetGuildByLeaderGUID", &LuaGlobalFunctions::GetGuildByLeaderGUID }, + { "GetPlayerCount", &LuaGlobalFunctions::GetPlayerCount }, + { "GetPlayerGUID", &LuaGlobalFunctions::GetPlayerGUID }, + { "GetItemGUID", &LuaGlobalFunctions::GetItemGUID }, + { "GetObjectGUID", &LuaGlobalFunctions::GetObjectGUID }, + { "GetUnitGUID", &LuaGlobalFunctions::GetUnitGUID }, + { "GetGUIDLow", &LuaGlobalFunctions::GetGUIDLow }, + { "GetGUIDType", &LuaGlobalFunctions::GetGUIDType }, + { "GetGUIDEntry", &LuaGlobalFunctions::GetGUIDEntry }, + { "GetAreaName", &LuaGlobalFunctions::GetAreaName }, + { "bit_not", &LuaGlobalFunctions::bit_not }, + { "bit_xor", &LuaGlobalFunctions::bit_xor }, + { "bit_rshift", &LuaGlobalFunctions::bit_rshift }, + { "bit_lshift", &LuaGlobalFunctions::bit_lshift }, + { "bit_or", &LuaGlobalFunctions::bit_or }, + { "bit_and", &LuaGlobalFunctions::bit_and }, + { "GetItemLink", &LuaGlobalFunctions::GetItemLink }, + { "GetMapById", &LuaGlobalFunctions::GetMapById }, + { "GetCurrTime", &LuaGlobalFunctions::GetCurrTime }, + { "GetTimeDiff", &LuaGlobalFunctions::GetTimeDiff }, + { "PrintInfo", &LuaGlobalFunctions::PrintInfo }, + { "PrintError", &LuaGlobalFunctions::PrintError }, + { "PrintDebug", &LuaGlobalFunctions::PrintDebug }, + { "GetActiveGameEvents", &LuaGlobalFunctions::GetActiveGameEvents }, + + // Boolean + { "IsInventoryPos", &LuaGlobalFunctions::IsInventoryPos }, + { "IsEquipmentPos", &LuaGlobalFunctions::IsEquipmentPos }, + { "IsBankPos", &LuaGlobalFunctions::IsBankPos }, + { "IsBagPos", &LuaGlobalFunctions::IsBagPos }, + { "IsGameEventActive", &LuaGlobalFunctions::IsGameEventActive }, + + // Other + { "ReloadEluna", &LuaGlobalFunctions::ReloadEluna }, + { "RunCommand", &LuaGlobalFunctions::RunCommand }, + { "SendWorldMessage", &LuaGlobalFunctions::SendWorldMessage }, + { "WorldDBQuery", &LuaGlobalFunctions::WorldDBQuery }, + { "WorldDBExecute", &LuaGlobalFunctions::WorldDBExecute }, + { "CharDBQuery", &LuaGlobalFunctions::CharDBQuery }, + { "CharDBExecute", &LuaGlobalFunctions::CharDBExecute }, + { "AuthDBQuery", &LuaGlobalFunctions::AuthDBQuery }, + { "AuthDBExecute", &LuaGlobalFunctions::AuthDBExecute }, + { "CreateLuaEvent", &LuaGlobalFunctions::CreateLuaEvent }, + { "RemoveEventById", &LuaGlobalFunctions::RemoveEventById }, + { "RemoveEvents", &LuaGlobalFunctions::RemoveEvents }, + { "PerformIngameSpawn", &LuaGlobalFunctions::PerformIngameSpawn }, + { "CreatePacket", &LuaGlobalFunctions::CreatePacket }, + { "AddVendorItem", &LuaGlobalFunctions::AddVendorItem }, + { "VendorRemoveItem", &LuaGlobalFunctions::VendorRemoveItem }, + { "VendorRemoveAllItems", &LuaGlobalFunctions::VendorRemoveAllItems }, + { "Kick", &LuaGlobalFunctions::Kick }, + { "Ban", &LuaGlobalFunctions::Ban }, + { "SaveAllPlayers", &LuaGlobalFunctions::SaveAllPlayers }, + { "SendMail", &LuaGlobalFunctions::SendMail }, + { "AddTaxiPath", &LuaGlobalFunctions::AddTaxiPath }, + { "CreateInt64", &LuaGlobalFunctions::CreateLongLong }, + { "CreateUint64", &LuaGlobalFunctions::CreateULongLong }, + { "StartGameEvent", &LuaGlobalFunctions::StartGameEvent }, + { "StopGameEvent", &LuaGlobalFunctions::StopGameEvent }, + + { NULL, NULL } + }; +} +#endif diff --git a/src/modules/Eluna/VMangos/GroupMethods.h b/src/modules/Eluna/VMangos/GroupMethods.h new file mode 100644 index 0000000000..ddbb78af85 --- /dev/null +++ b/src/modules/Eluna/VMangos/GroupMethods.h @@ -0,0 +1,473 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef GROUPMETHODS_H +#define GROUPMETHODS_H + +/*** + * Inherits all methods from: none + */ +namespace LuaGroup +{ + /** + * Returns 'true' if the [Player] is the [Group] leader + * + * @param ObjectGuid guid : guid of a possible leader + * @return bool isLeader + */ + int IsLeader(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->IsLeader(guid)); + return 1; + } + + /** + * Returns 'true' if the [Group] is full + * + * @return bool isFull + */ + int IsFull(lua_State* L, Group* group) + { + Eluna::Push(L, group->IsFull()); + return 1; + } + +#if !(defined(CLASSIC) || defined(TBC)) + /** + * Returns 'true' if the [Group] is a LFG group + * + * @return bool isLFGGroup + */ + int IsLFGGroup(lua_State* L, Group* group) + { +#ifdef CMANGOS + Eluna::Push(L, group->IsLFGGroup()); +#else + Eluna::Push(L, group->isLFGGroup()); +#endif + return 1; + } +#endif + + /** + * Returns 'true' if the [Group] is a raid [Group] + * + * @return bool isRaid + */ + int IsRaidGroup(lua_State* L, Group* group) + { +#ifdef CMANGOS + Eluna::Push(L, group->IsRaidGroup()); +#else + Eluna::Push(L, group->isRaidGroup()); +#endif + return 1; + } + + /** + * Returns 'true' if the [Group] is a battleground [Group] + * + * @return bool isBG + */ + int IsBGGroup(lua_State* L, Group* group) + { +#ifdef CMANGOS + Eluna::Push(L, group->IsBattleGroup()); +#else + Eluna::Push(L, group->isBGGroup()); +#endif + return 1; + } + + /** + * Returns 'true' if the [Player] is a member of this [Group] + * + * @param ObjectGuid guid : guid of a player + * @return bool isMember + */ + int IsMember(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->IsMember(guid)); + return 1; + } + + /** + * Returns 'true' if the [Player] is an assistant of this [Group] + * + * @param ObjectGuid guid : guid of a player + * @return bool isAssistant + */ + int IsAssistant(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->IsAssistant(guid)); + return 1; + } + + /** + * Returns 'true' if the [Player]s are in the same subgroup in this [Group] + * + * @param [Player] player1 : first [Player] to check + * @param [Player] player2 : second [Player] to check + * @return bool sameSubGroup + */ + int SameSubGroup(lua_State* L, Group* group) + { + Player* player1 = Eluna::CHECKOBJ(L, 2); + Player* player2 = Eluna::CHECKOBJ(L, 3); + Eluna::Push(L, group->SameSubGroup(player1, player2)); + return 1; + } + + /** + * Returns 'true' if the subgroup has free slots in this [Group] + * + * @param uint8 subGroup : subGroup ID to check + * @return bool hasFreeSlot + */ + int HasFreeSlotSubGroup(lua_State* L, Group* group) + { + uint8 subGroup = Eluna::CHECKVAL(L, 2); + + if (subGroup >= MAX_RAID_SUBGROUPS) + { + luaL_argerror(L, 2, "valid subGroup ID expected"); + return 0; + } + + Eluna::Push(L, group->HasFreeSlotSubGroup(subGroup)); + return 1; + } + + /** + * Adds a new member to the [Group] + * + * @param [Player] player : [Player] to add to the group + * @return bool added : true if member was added + */ + int AddMember(lua_State* L, Group* group) + { + Player* player = Eluna::CHECKOBJ(L, 2); + + if (player->GetGroup() || !group->IsCreated() || group->IsFull()) + { + Eluna::Push(L, false); + return 1; + } + + if (player->GetGroupInvite()) + player->UninviteFromGroup(); + +#if defined TRINITY || AZEROTHCORE + bool success = group->AddMember(player); + if (success) + group->BroadcastGroupUpdate(); +#else + bool success = group->AddMember(player->GetObjectGuid(), player->GetName()); +#endif + + Eluna::Push(L, success); + return 1; + } + + /*int IsLFGGroup(lua_State* L, Group* group) // TODO: Implementation + { + Eluna::Push(L, group->isLFGGroup()); + return 1; + }*/ + + /*int IsBFGroup(lua_State* L, Group* group) // TODO: Implementation + { + Eluna::Push(L, group->isBFGroup()); + return 1; + }*/ + + /** + * Returns a table with the [Player]s in this [Group] + * + * @return table groupPlayers : table of [Player]s + */ + int GetMembers(lua_State* L, Group* group) + { + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (GroupReference* itr = group->GetFirstMember(); itr; itr = itr->next()) + { +#if defined TRINITY || AZEROTHCORE + Player* member = itr->GetSource(); +#else + Player* member = itr->getSource(); +#endif + + if (!member || !member->GetSession()) + continue; + + Eluna::Push(L, member); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); // push table to top of stack + return 1; + } + + /** + * Returns [Group] leader GUID + * + * @return ObjectGuid leaderGUID + */ + int GetLeaderGUID(lua_State* L, Group* group) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, group->GetLeaderGUID()); +#else + Eluna::Push(L, group->GetLeaderGuid()); +#endif + return 1; + } + + /** + * Returns the [Group]'s GUID + * + * @return ObjectGuid groupGUID + */ + int GetGUID(lua_State* L, Group* group) + { +#ifdef CLASSIC + Eluna::Push(L, group->GetId()); +#else + Eluna::Push(L, group->GET_GUID()); +#endif + return 1; + } + + /** + * Returns a [Group] member's GUID by their name + * + * @param string name : the [Player]'s name + * @return ObjectGuid memberGUID + */ + int GetMemberGUID(lua_State* L, Group* group) + { + const char* name = Eluna::CHECKVAL(L, 2); +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, group->GetMemberGUID(name)); +#else + Eluna::Push(L, group->GetMemberGuid(name)); +#endif + return 1; + } + + /** + * Returns the member count of this [Group] + * + * @return uint32 memberCount + */ + int GetMembersCount(lua_State* L, Group* group) + { + Eluna::Push(L, group->GetMembersCount()); + return 1; + } + + /** + * Returns the [Player]'s subgroup ID of this [Group] + * + * @param ObjectGuid guid : guid of the player + * @return uint8 subGroupID : a valid subgroup ID or MAX_RAID_SUBGROUPS+1 + */ + int GetMemberGroup(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->GetMemberGroup(guid)); + return 1; + } + + /** + * Sets the leader of this [Group] + * + * @param ObjectGuid guid : guid of the new leader + */ + int SetLeader(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + group->ChangeLeader(guid); + group->SendUpdate(); + return 0; + } + + /** + * Sends a specified [WorldPacket] to this [Group] + * + * @param [WorldPacket] packet : the [WorldPacket] to send + * @param bool ignorePlayersInBg : ignores [Player]s in a battleground + * @param ObjectGuid ignore : ignore a [Player] by their GUID + */ + int SendPacket(lua_State* L, Group* group) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + bool ignorePlayersInBg = Eluna::CHECKVAL(L, 3); + ObjectGuid ignore = Eluna::CHECKVAL(L, 4); + +#ifdef CMANGOS + group->BroadcastPacket(*data, ignorePlayersInBg, -1, ignore); +#else + group->BroadcastPacket(data, ignorePlayersInBg, -1, ignore); +#endif + return 0; + } + + /** + * Removes a [Player] from this [Group] and returns 'true' if successful + * + *
+     * enum RemoveMethod
+     * {
+     *     GROUP_REMOVEMETHOD_DEFAULT  = 0,
+     *     GROUP_REMOVEMETHOD_KICK     = 1,
+     *     GROUP_REMOVEMETHOD_LEAVE    = 2,
+     *     GROUP_REMOVEMETHOD_KICK_LFG = 3
+     * };
+     * 
+ * + * @param ObjectGuid guid : guid of the player to remove + * @param [RemoveMethod] method : method used to remove the player + * @return bool removed + */ + int RemoveMember(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + uint32 method = Eluna::CHECKVAL(L, 3, 0); + +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, group->RemoveMember(guid, (RemoveMethod)method)); +#else + Eluna::Push(L, group->RemoveMember(guid, method)); +#endif + return 1; + } + + /** + * Disbands this [Group] + * + */ + int Disband(lua_State* /*L*/, Group* group) + { + group->Disband(); + return 0; + } + + /** + * Converts this [Group] to a raid [Group] + * + */ + int ConvertToRaid(lua_State* /*L*/, Group* group) + { + group->ConvertToRaid(); + return 0; + } + + /** + * Sets the member's subGroup + * + * @param ObjectGuid guid : guid of the player to move + * @param uint8 groupID : the subGroup's ID + */ + int SetMembersGroup(lua_State* L, Group* group) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + uint8 subGroup = Eluna::CHECKVAL(L, 3); + + if (subGroup >= MAX_RAID_SUBGROUPS) + { + luaL_argerror(L, 3, "valid subGroup ID expected"); + return 0; + } + + if (!group->HasFreeSlotSubGroup(subGroup)) + return 0; + + group->ChangeMembersGroup(guid, subGroup); + return 0; + } + + /** + * Sets the target icon of an object for the [Group] + * + * @param uint8 icon : the icon (Skull, Square, etc) + * @param ObjectGuid target : GUID of the icon target, 0 is to clear the icon + * @param ObjectGuid setter : GUID of the icon setter + */ + int SetTargetIcon(lua_State* L, Group* group) + { + uint8 icon = Eluna::CHECKVAL(L, 2); + ObjectGuid target = Eluna::CHECKVAL(L, 3); + ObjectGuid setter = Eluna::CHECKVAL(L, 4, ObjectGuid()); + + if (icon >= TARGETICONCOUNT) + return luaL_argerror(L, 2, "valid target icon expected"); + +#if (defined(CLASSIC) || defined(TBC)) + group->SetTargetIcon(icon, target); +#else + group->SetTargetIcon(icon, setter, target); +#endif + return 0; + } + + /*int ConvertToLFG(lua_State* L, Group* group) // TODO: Implementation + { + group->ConvertToLFG(); + return 0; + }*/ + + ElunaRegister GroupMethods[] = + { + // Getters + { "GetMembers", &LuaGroup::GetMembers }, + { "GetLeaderGUID", &LuaGroup::GetLeaderGUID }, + { "GetGUID", &LuaGroup::GetGUID }, + { "GetMemberGroup", &LuaGroup::GetMemberGroup }, + { "GetMemberGUID", &LuaGroup::GetMemberGUID }, + { "GetMembersCount", &LuaGroup::GetMembersCount }, + + // Setters + { "SetLeader", &LuaGroup::SetLeader }, + { "SetMembersGroup", &LuaGroup::SetMembersGroup }, + { "SetTargetIcon", &LuaGroup::SetTargetIcon }, + + // Boolean + { "IsLeader", &LuaGroup::IsLeader }, + { "AddMember", &LuaGroup::AddMember }, + { "RemoveMember", &LuaGroup::RemoveMember }, + { "Disband", &LuaGroup::Disband }, + { "IsFull", &LuaGroup::IsFull }, + { "IsRaidGroup", &LuaGroup::IsRaidGroup }, + { "IsBGGroup", &LuaGroup::IsBGGroup }, + { "IsMember", &LuaGroup::IsMember }, + { "IsAssistant", &LuaGroup::IsAssistant }, + { "SameSubGroup", &LuaGroup::SameSubGroup }, + { "HasFreeSlotSubGroup", &LuaGroup::HasFreeSlotSubGroup }, +#if !(defined(CLASSIC) || defined(TBC)) + { "IsLFGGroup", &LuaGroup::IsLFGGroup }, +#endif + // Other + { "SendPacket", &LuaGroup::SendPacket }, + { "ConvertToRaid", &LuaGroup::ConvertToRaid }, + + // Not implemented methods + { "IsBFGroup", nullptr }, // not implemented + { "ConvertToLFG", nullptr }, // not implemented + { "GetMemberFlags", nullptr }, // not implemented + { "SetMemberFlag", nullptr }, // not implemented + + { NULL, NULL } + }; +}; + +#endif diff --git a/src/modules/Eluna/VMangos/GuildMethods.h b/src/modules/Eluna/VMangos/GuildMethods.h new file mode 100644 index 0000000000..99947491ad --- /dev/null +++ b/src/modules/Eluna/VMangos/GuildMethods.h @@ -0,0 +1,329 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef GUILDMETHODS_H +#define GUILDMETHODS_H + +/*** + * Inherits all methods from: none + */ +namespace LuaGuild +{ + /** + * Returns a table with the [Player]s in this [Guild] + * + * Only the players that are online and on some map. + * + * @return table guildPlayers : table of [Player]s + */ + int GetMembers(lua_State* L, Guild* guild) + { + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 i = 0; + +#if defined(MANGOS) + eObjectAccessor()DoForAllPlayers([&](Player* player) + { + if (player->IsInWorld() && player->GetGuildId() == guild->GetId()) + { + Eluna::Push(L, player); + lua_rawseti(L, tbl, ++i); + } + }); +#else + { +#if defined TRINITY || AZEROTHCORE + std::shared_lock lock(*HashMapHolder::GetLock()); +#else + HashMapHolder::ReadGuard g(HashMapHolder::GetLock()); +#endif + const HashMapHolder::MapType& m = eObjectAccessor()GetPlayers(); + for (HashMapHolder::MapType::const_iterator it = m.begin(); it != m.end(); ++it) + { + if (Player* player = it->second) + { + if (player->IsInWorld() && player->GetGuildId() == guild->GetId()) + { + Eluna::Push(L, player); + lua_rawseti(L, tbl, ++i); + } + } + } + } +#endif + lua_settop(L, tbl); // push table to top of stack + return 1; + } + + /** + * Returns the member count of this [Guild] + * + * @return uint32 memberCount + */ + int GetMemberCount(lua_State* L, Guild* guild) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, guild->GetMemberCount()); +#else + Eluna::Push(L, guild->GetMemberSize()); +#endif + return 1; + } + + /** + * Finds and returns the [Guild] leader by their GUID if logged in + * + * @return [Player] leader + */ + int GetLeader(lua_State* L, Guild* guild) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, eObjectAccessor()FindPlayer(guild->GetLeaderGUID())); +#else + Eluna::Push(L, eObjectAccessor()FindPlayer(guild->GetLeaderGuid())); +#endif + return 1; + } + + /** + * Returns [Guild] leader GUID + * + * @return ObjectGuid leaderGUID + */ + int GetLeaderGUID(lua_State* L, Guild* guild) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, guild->GetLeaderGUID()); +#else + Eluna::Push(L, guild->GetLeaderGuid()); +#endif + return 1; + } + + /** + * Returns the [Guild]s entry ID + * + * @return uint32 entryId + */ + int GetId(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetId()); + return 1; + } + + /** + * Returns the [Guild]s name + * + * @return string guildName + */ + int GetName(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetName()); + return 1; + } + + /** + * Returns the [Guild]s current Message Of The Day + * + * @return string guildMOTD + */ + int GetMOTD(lua_State* L, Guild* guild) + { + Eluna::Push(L, guild->GetMOTD()); + return 1; + } + + /** + * Returns the [Guild]s current info + * + * @return string guildInfo + */ + int GetInfo(lua_State* L, Guild* guild) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, guild->GetInfo()); +#else + Eluna::Push(L, guild->GetGINFO()); +#endif + return 1; + } + +#if defined(CLASSIC) || defined(TBC) || defined(WOTLK) + /** + * Sets the leader of this [Guild] + * + * @param [Player] leader : the [Player] leader to change + */ + int SetLeader(lua_State* L, Guild* guild) + { + Player* player = Eluna::CHECKOBJ(L, 2); + +#if defined TRINITY || AZEROTHCORE + guild->HandleSetLeader(player->GetSession(), player->GetName()); +#else + guild->SetLeader(player->GET_GUID()); +#endif + return 0; + } +#endif + +#ifndef CLASSIC + /** + * Sets the information of the bank tab specified + * + * @param uint8 tabId : the ID of the tab specified + * @param string info : the information to be set to the bank tab + */ + int SetBankTabText(lua_State* L, Guild* guild) + { + uint8 tabId = Eluna::CHECKVAL(L, 2); + const char* text = Eluna::CHECKVAL(L, 3); +#if defined TRINITY || AZEROTHCORE + guild->SetBankTabText(tabId, text); +#else + guild->SetGuildBankTabText(tabId, text); +#endif + return 0; + } +#endif + + // SendPacketToGuild(packet) + /** + * Sends a [WorldPacket] to all the [Player]s in the [Guild] + * + * @param [WorldPacket] packet : the [WorldPacket] to be sent to the [Player]s + */ + int SendPacket(lua_State* L, Guild* guild) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + +#ifdef CMANGOS + guild->BroadcastPacket(*data); +#else + guild->BroadcastPacket(data); +#endif + return 0; + } + + // SendPacketToRankedInGuild(packet, rankId) + /** + * Sends a [WorldPacket] to all the [Player]s at the specified rank in the [Guild] + * + * @param [WorldPacket] packet : the [WorldPacket] to be sent to the [Player]s + * @param uint8 rankId : the rank ID + */ + int SendPacketToRanked(lua_State* L, Guild* guild) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + uint8 ranked = Eluna::CHECKVAL(L, 3); + +#ifdef CMANGOS + guild->BroadcastPacketToRank(*data, ranked); +#else + guild->BroadcastPacketToRank(data, ranked); +#endif + return 0; + } + + /** + * Disbands the [Guild] + */ + int Disband(lua_State* /*L*/, Guild* guild) + { + guild->Disband(); + return 0; + } + + /** + * Adds the specified [Player] to the [Guild] at the specified rank. + * + * If no rank is specified, defaults to none. + * + * @param [Player] player : the [Player] to be added to the guild + * @param uint8 rankId : the rank ID + */ + int AddMember(lua_State* L, Guild* guild) + { + Player* player = Eluna::CHECKOBJ(L, 2); + uint8 rankId = Eluna::CHECKVAL(L, 3, GUILD_RANK_NONE); + +#ifdef TRINITY + CharacterDatabaseTransaction trans(nullptr); + guild->AddMember(trans, player->GET_GUID(), rankId); +#else + guild->AddMember(player->GET_GUID(), rankId); +#endif + return 0; + } + + /** + * Removes the specified [Player] from the [Guild]. + * + * @param [Player] player : the [Player] to be removed from the guild + * @param bool isDisbanding : default 'false', should only be set to 'true' if the guild is triggered to disband + */ + int DeleteMember(lua_State* L, Guild* guild) + { + Player* player = Eluna::CHECKOBJ(L, 2); + bool isDisbanding = Eluna::CHECKVAL(L, 3, false); + +#if defined TRINITY + CharacterDatabaseTransaction trans(nullptr); + guild->DeleteMember(trans, player->GET_GUID(), isDisbanding); +#elif defined AZEROTHCORE + guild->DeleteMember(player->GET_GUID(), isDisbanding); +#else + guild->DelMember(player->GET_GUID(), isDisbanding); +#endif + return 0; + } + + /** + * Promotes/demotes the [Player] to the specified rank. + * + * @param [Player] player : the [Player] to be promoted/demoted + * @param uint8 rankId : the rank ID + */ + int SetMemberRank(lua_State* L, Guild* guild) + { + Player* player = Eluna::CHECKOBJ(L, 2); + uint8 newRank = Eluna::CHECKVAL(L, 3); + + guild->GetMemberSlot(player->GET_GUID())->ChangeRank(newRank); + return 0; + } + + ElunaRegister GuildMethods[] = + { + // Getters + { "GetMembers", &LuaGuild::GetMembers }, + { "GetLeader", &LuaGuild::GetLeader }, + { "GetLeaderGUID", &LuaGuild::GetLeaderGUID }, + { "GetId", &LuaGuild::GetId }, + { "GetName", &LuaGuild::GetName }, + { "GetMOTD", &LuaGuild::GetMOTD }, + { "GetInfo", &LuaGuild::GetInfo }, + { "GetMemberCount", &LuaGuild::GetMemberCount }, + + // Setters + { "SetMemberRank", &LuaGuild::SetMemberRank }, + { "SetLeader", &LuaGuild::SetLeader }, +#ifndef CLASSIC + { "SetBankTabText", &LuaGuild::SetBankTabText }, +#endif + + // Other + { "SendPacket", &LuaGuild::SendPacket }, + { "SendPacketToRanked", &LuaGuild::SendPacketToRanked }, + { "Disband", &LuaGuild::Disband }, + { "AddMember", &LuaGuild::AddMember }, + { "DeleteMember", &LuaGuild::DeleteMember }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/VMangos/ItemMethods.h b/src/modules/Eluna/VMangos/ItemMethods.h new file mode 100644 index 0000000000..6d10712443 --- /dev/null +++ b/src/modules/Eluna/VMangos/ItemMethods.h @@ -0,0 +1,843 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef ITEMMETHODS_H +#define ITEMMETHODS_H + +/*** + * Inherits all methods from: [Object] + */ +namespace LuaItem +{ + /** + * Returns 'true' if the [Item] is soulbound, 'false' otherwise + * + * @return bool isSoulBound + */ + int IsSoulBound(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsSoulBound()); + return 1; + } + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Returns 'true' if the [Item] is account bound, 'false' otherwise + * + * @return bool isAccountBound + */ + int IsBoundAccountWide(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsBoundAccountWide()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Item] is bound to a [Player] by an enchant, 'false' otehrwise + * + * @return bool isBoundByEnchant + */ + int IsBoundByEnchant(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsBoundByEnchant()); + return 1; + } + + /** + * Returns 'true' if the [Item] is not bound to the [Player] specified, 'false' otherwise + * + * @param [Player] player : the [Player] object to check the item against + * @return bool isNotBound + */ + int IsNotBoundToPlayer(lua_State* L, Item* item) + { + Player* player = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, item->IsBindedNotWith(player)); + return 1; + } + + /** + * Returns 'true' if the [Item] is locked, 'false' otherwise + * + * @return bool isLocked + */ + int IsLocked(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsLocked()); + return 1; + } + + /** + * Returns 'true' if the [Item] is a bag, 'false' otherwise + * + * @return bool isBag + */ + int IsBag(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsBag()); + return 1; + } + +#ifndef CLASSIC + /** + * Returns 'true' if the [Item] is a currency token, 'false' otherwise + * + * @return bool isCurrencyToken + */ + int IsCurrencyToken(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsCurrencyToken()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Item] is a not an empty bag, 'false' otherwise + * + * @return bool isNotEmptyBag + */ + int IsNotEmptyBag(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsNotEmptyBag()); + return 1; + } + + /** + * Returns 'true' if the [Item] is broken, 'false' otherwise + * + * @return bool isBroken + */ + int IsBroken(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsBroken()); + return 1; + } + + /** + * Returns 'true' if the [Item] can be traded, 'false' otherwise + * + * @return bool isTradeable + */ + int CanBeTraded(lua_State* L, Item* item) + { +#if (defined(TBC) || defined(CLASSIC)) + Eluna::Push(L, item->CanBeTraded()); +#else + bool mail = Eluna::CHECKVAL(L, 2, false); + Eluna::Push(L, item->CanBeTraded(mail)); +#endif + return 1; + } + + /** + * Returns 'true' if the [Item] is currently in a trade window, 'false' otherwise + * + * @return bool isInTrade + */ + int IsInTrade(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsInTrade()); + return 1; + } + + /** + * Returns 'true' if the [Item] is currently in a bag, 'false' otherwise + * + * @return bool isInBag + */ + int IsInBag(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsInBag()); + return 1; + } + + /** + * Returns 'true' if the [Item] is currently equipped, 'false' otherwise + * + * @return bool isEquipped + */ + int IsEquipped(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsEquipped()); + return 1; + } + + /** + * Returns 'true' if the [Item] has the [Quest] specified tied to it, 'false' otherwise + * + * @param uint32 questId : the [Quest] id to be checked + * @return bool hasQuest + */ + int HasQuest(lua_State* L, Item* item) + { + uint32 quest = Eluna::CHECKVAL(L, 2); +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, item->hasQuest(quest)); +#else + Eluna::Push(L, item->HasQuest(quest)); +#endif + return 1; + } + + /** + * Returns 'true' if the [Item] is a potion, 'false' otherwise + * + * @return bool isPotion + + int IsPotion(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsPotion()); + return 1; + } + */ + +#if defined(WOTLK) + /** + * Returns 'true' if the [Item] is a weapon vellum, 'false' otherwise + * + * @return bool isWeaponVellum + */ + int IsWeaponVellum(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsWeaponVellum()); + return 1; + } + + /** + * Returns 'true' if the [Item] is an armor vellum, 'false' otherwise + * + * @return bool isArmorVellum + */ + int IsArmorVellum(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsArmorVellum()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Item] is a conjured consumable, 'false' otherwise + * + * @return bool isConjuredConsumable + */ + int IsConjuredConsumable(lua_State* L, Item* item) + { + Eluna::Push(L, item->IsConjuredConsumable()); + return 1; + } + + /*int IsRefundExpired(lua_State* L, Item* item)// TODO: Implement core support + { + Eluna::Push(L, item->IsRefundExpired()); + return 1; + }*/ + + /** + * Returns the chat link of the [Item] + * + *
+     * enum LocaleConstant
+     * {
+     *     LOCALE_enUS = 0,
+     *     LOCALE_koKR = 1,
+     *     LOCALE_frFR = 2,
+     *     LOCALE_deDE = 3,
+     *     LOCALE_zhCN = 4,
+     *     LOCALE_zhTW = 5,
+     *     LOCALE_esES = 6,
+     *     LOCALE_esMX = 7,
+     *     LOCALE_ruRU = 8
+     * };
+     * 
+ * + * @param [LocaleConstant] locale = DEFAULT_LOCALE : locale to return the [Item]'s name in + * @return string itemLink + */ + int GetItemLink(lua_State* L, Item* item) + { + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const ItemTemplate* temp = item->GetTemplate(); + std::string name = temp->Name1; + if (ItemLocale const* il = eObjectMgr->GetItemLocale(temp->ItemId)) + name = il->Name[locale]; + +#ifndef CLASSIC + if (int32 itemRandPropId = item->GetItemRandomPropertyId()) + { +#if defined(CATA) || defined (MISTS) + char* suffix = NULL; +#else +#ifdef TRINITY + std::array const* suffix = NULL; +#else + char* const* suffix = NULL; +#endif +#endif + if (itemRandPropId < 0) + { + const ItemRandomSuffixEntry* itemRandEntry = sItemRandomSuffixStore.LookupEntry(-item->GetItemRandomPropertyId()); + if (itemRandEntry) +#ifdef TRINITY + suffix = &itemRandEntry->Name; +#else + suffix = itemRandEntry->nameSuffix; +#endif + } + else + { + const ItemRandomPropertiesEntry* itemRandEntry = sItemRandomPropertiesStore.LookupEntry(item->GetItemRandomPropertyId()); + if (itemRandEntry) +#ifdef TRINITY + suffix = &itemRandEntry->Name; +#else + suffix = itemRandEntry->nameSuffix; +#endif + } + if (suffix) + { + name += ' '; +#if defined TRINITY + name += (*suffix)[(name != temp->Name1) ? locale : uint8(DEFAULT_LOCALE)]; +#else + name += suffix[(name != temp->Name1) ? locale : uint8(DEFAULT_LOCALE)]; +#endif + } + } +#endif + + std::ostringstream oss; + oss << "|c" << std::hex << ItemQualityColors[temp->Quality] << std::dec << + "|Hitem:" << temp->ItemId << ":" << + item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT) << ":" << +#ifndef CLASSIC + item->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT) << ":" << + item->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_2) << ":" << + item->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_3) << ":" << + item->GetEnchantmentId(BONUS_ENCHANTMENT_SLOT) << ":" << +#endif + item->GetItemRandomPropertyId() << ":" << item->GetItemSuffixFactor() << ":" << + (uint32)item->GetOwner()->GetLevel() << "|h[" << name << "]|h|r"; + + Eluna::Push(L, oss.str()); + return 1; + } + + int GetOwnerGUID(lua_State* L, Item* item) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, item->GetOwnerGUID()); +#else + Eluna::Push(L, item->GetOwnerGuid()); +#endif + return 1; + } + + /** + * Returns the [Player] who currently owns the [Item] + * + * @return [Player] player : the [Player] who owns the [Item] + */ + int GetOwner(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetOwner()); + return 1; + } + + /** + * Returns the [Item]s stack count + * + * @return uint32 count + */ + int GetCount(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetCount()); + return 1; + } + + /** + * Returns the [Item]s max stack count + * + * @return uint32 maxCount + */ + int GetMaxStackCount(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetMaxStackCount()); + return 1; + } + + /** + * Returns the [Item]s current slot + * + * @return uint8 slot + */ + int GetSlot(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetSlot()); + return 1; + } + + /** + * Returns the [Item]s current bag slot + * + * @return uint8 bagSlot + */ + int GetBagSlot(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetBagSlot()); + return 1; + } + + /** + * Returns the [Item]s enchantment ID by enchant slot specified + * + * @param [EnchantmentSlot] enchantSlot : the enchant slot specified + * @return uint32 enchantId : the id of the enchant slot specified + */ + int GetEnchantmentId(lua_State* L, Item* item) + { + uint32 enchant_slot = Eluna::CHECKVAL(L, 2); + + if (enchant_slot >= MAX_INSPECTED_ENCHANTMENT_SLOT) + return luaL_argerror(L, 2, "valid EnchantmentSlot expected"); + + Eluna::Push(L, item->GetEnchantmentId(EnchantmentSlot(enchant_slot))); + return 1; + } + + /** + * Returns the spell ID tied to the [Item] by spell index + * + * @param uint32 spellIndex : the spell index specified + * @return uint32 spellId : the id of the spell + */ + int GetSpellId(lua_State* L, Item* item) + { + uint32 index = Eluna::CHECKVAL(L, 2); + if (index >= MAX_ITEM_PROTO_SPELLS) + return luaL_argerror(L, 2, "valid SpellIndex expected"); + + Eluna::Push(L, item->GetTemplate()->Spells[index].SpellId); + return 1; + } + + /** + * Returns the spell trigger tied to the [Item] by spell index + * + * @param uint32 spellIndex : the spell index specified + * @return uint32 spellTrigger : the spell trigger of the specified index + */ + int GetSpellTrigger(lua_State* L, Item* item) + { + uint32 index = Eluna::CHECKVAL(L, 2); + if (index >= MAX_ITEM_PROTO_SPELLS) + return luaL_argerror(L, 2, "valid SpellIndex expected"); + + Eluna::Push(L, item->GetTemplate()->Spells[index].SpellTrigger); + return 1; + } + + /** + * Returns class of the [Item] + * + * @return uint32 class + */ + int GetClass(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->Class); + return 1; + } + + /** + * Returns subclass of the [Item] + * + * @return uint32 subClass + */ + int GetSubClass(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->SubClass); + return 1; + } + + /** + * Returns the name of the [Item] + * + * @return string name + */ + int GetName(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->Name1); + return 1; + } + + /** + * Returns the display ID of the [Item] + * + * @return uint32 displayId + */ + int GetDisplayId(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->DisplayInfoID); + return 1; + } + + /** + * Returns the quality of the [Item] + * + * @return uint32 quality + */ + int GetQuality(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->Quality); + return 1; + } + + /** + * Returns the default purchase count of the [Item] + * + * @return uint32 count + */ + int GetBuyCount(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->BuyCount); + return 1; + } + + /** + * Returns the purchase price of the [Item] + * + * @return uint32 price + */ + int GetBuyPrice(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->BuyPrice); + return 1; + } + + /** + * Returns the sell price of the [Item] + * + * @return uint32 price + */ + int GetSellPrice(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->SellPrice); + return 1; + } + + /** + * Returns the inventory type of the [Item] + * + * @return uint32 inventoryType + */ + int GetInventoryType(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->InventoryType); + return 1; + } + + /** + * Returns the [Player] classes allowed to use this [Item] + * + * @return uint32 allowableClass + */ + int GetAllowableClass(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->AllowableClass); + return 1; + } + + /** + * Returns the [Player] races allowed to use this [Item] + * + * @return uint32 allowableRace + */ + int GetAllowableRace(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->AllowableRace); + return 1; + } + + /** + * Returns the [Item]s level + * + * @return uint32 itemLevel + */ + int GetItemLevel(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->ItemLevel); + return 1; + } + + /** + * Returns the minimum level required to use this [Item] + * + * @return uint32 requiredLevel + */ + int GetRequiredLevel(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->RequiredLevel); + return 1; + } + +#ifdef WOTLK + int GetStatsCount(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->StatsCount); + return 1; + } +#endif + + /** + * Returns the random property ID of this [Item] + * + * @return uint32 randomPropertyId + */ + int GetRandomProperty(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->RandomProperty); + return 1; + } + +#ifndef CLASSIC + int GetRandomSuffix(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->RandomSuffix); + return 1; + } +#endif + + /** + * Returns the item set ID of this [Item] + * + * @return uint32 itemSetId + */ + int GetItemSet(lua_State* L, Item* item) + { + Eluna::Push(L, item->GetTemplate()->ItemSet); + return 1; + } + + /** + * Returns the bag size of this [Item], 0 if [Item] is not a bag + * + * @return uint32 bagSize + */ + int GetBagSize(lua_State* L, Item* item) + { + if (Bag* bag = item->ToBag()) + Eluna::Push(L, bag->GetBagSize()); + else + Eluna::Push(L, 0); + return 1; + } + + /** + * Sets the [Player] specified as the owner of the [Item] + * + * @param [Player] player : the [Player] specified + */ + int SetOwner(lua_State* L, Item* item) + { + Player* player = Eluna::CHECKOBJ(L, 2); +#if defined TRINITY || AZEROTHCORE + item->SetOwnerGUID(player->GET_GUID()); +#else + item->SetOwnerGuid(player->GET_GUID()); +#endif + return 0; + } + + /** + * Sets the binding of the [Item] to 'true' or 'false' + * + * @param bool setBinding + */ + int SetBinding(lua_State* L, Item* item) + { + bool soulbound = Eluna::CHECKVAL(L, 2); + + item->SetBinding(soulbound); + item->SetState(ITEM_CHANGED, item->GetOwner()); + + return 0; + } + + /** + * Sets the stack count of the [Item] + * + * @param uint32 count + */ + int SetCount(lua_State* L, Item* item) + { + uint32 count = Eluna::CHECKVAL(L, 2); + item->SetCount(count); + return 0; + } + + /** + * Sets the specified enchantment of the [Item] to the specified slot + * + * @param uint32 enchantId : the ID of the enchant to be applied + * @param uint32 enchantSlot : the slot for the enchant to be applied to + * @return bool enchantmentSuccess : if enchantment is successfully set to specified slot, returns 'true', otherwise 'false' + */ + int SetEnchantment(lua_State* L, Item* item) + { + Player* owner = item->GetOwner(); + if (!owner) + { + Eluna::Push(L, false); + return 1; + } + + uint32 enchant = Eluna::CHECKVAL(L, 2); + if (!sSpellItemEnchantmentStore.LookupEntry(enchant)) + { + Eluna::Push(L, false); + return 1; + } + + EnchantmentSlot slot = (EnchantmentSlot)Eluna::CHECKVAL(L, 3); + if (slot >= MAX_INSPECTED_ENCHANTMENT_SLOT) + return luaL_argerror(L, 2, "valid EnchantmentSlot expected"); + + owner->ApplyEnchantment(item, slot, false); + item->SetEnchantment(slot, enchant, 0, 0); + owner->ApplyEnchantment(item, slot, true); + Eluna::Push(L, true); + return 1; + } + + /* OTHER */ + /** + * Removes an enchant from the [Item] by the specified slot + * + * @param uint32 enchantSlot : the slot for the enchant to be removed from + * @return bool enchantmentRemoved : if enchantment is successfully removed from specified slot, returns 'true', otherwise 'false' + */ + int ClearEnchantment(lua_State* L, Item* item) + { + Player* owner = item->GetOwner(); + if (!owner) + { + Eluna::Push(L, false); + return 1; + } + + EnchantmentSlot slot = (EnchantmentSlot)Eluna::CHECKVAL(L, 2); + if (slot >= MAX_INSPECTED_ENCHANTMENT_SLOT) + return luaL_argerror(L, 2, "valid EnchantmentSlot expected"); + + if (!item->GetEnchantmentId(slot)) + { + Eluna::Push(L, false); + return 1; + } + + owner->ApplyEnchantment(item, slot, false); + item->ClearEnchantment(slot); + Eluna::Push(L, true); + return 1; + } + + /** + * Saves the [Item] to the database + */ + int SaveToDB(lua_State* /*L*/, Item* item) + { +#if defined TRINITY || defined AZEROTHCORE + CharacterDatabaseTransaction trans = CharacterDatabaseTransaction(nullptr); + item->SaveToDB(trans); +#else + item->SaveToDB(); +#endif + return 0; + } + + ElunaRegister ItemMethods[] = + { + // Getters + { "GetOwnerGUID", &LuaItem::GetOwnerGUID }, + { "GetOwner", &LuaItem::GetOwner }, + { "GetCount", &LuaItem::GetCount }, + { "GetMaxStackCount", &LuaItem::GetMaxStackCount }, + { "GetSlot", &LuaItem::GetSlot }, + { "GetBagSlot", &LuaItem::GetBagSlot }, + { "GetEnchantmentId", &LuaItem::GetEnchantmentId }, + { "GetSpellId", &LuaItem::GetSpellId }, + { "GetSpellTrigger", &LuaItem::GetSpellTrigger }, + { "GetItemLink", &LuaItem::GetItemLink }, + { "GetClass", &LuaItem::GetClass }, + { "GetSubClass", &LuaItem::GetSubClass }, + { "GetName", &LuaItem::GetName }, + { "GetDisplayId", &LuaItem::GetDisplayId }, + { "GetQuality", &LuaItem::GetQuality }, + { "GetBuyCount", &LuaItem::GetBuyCount }, + { "GetBuyPrice", &LuaItem::GetBuyPrice }, + { "GetSellPrice", &LuaItem::GetSellPrice }, + { "GetInventoryType", &LuaItem::GetInventoryType }, + { "GetAllowableClass", &LuaItem::GetAllowableClass }, + { "GetAllowableRace", &LuaItem::GetAllowableRace }, + { "GetItemLevel", &LuaItem::GetItemLevel }, + { "GetRequiredLevel", &LuaItem::GetRequiredLevel }, + { "GetRandomProperty", &LuaItem::GetRandomProperty }, + { "GetItemSet", &LuaItem::GetItemSet }, + { "GetBagSize", &LuaItem::GetBagSize }, +#ifndef CLASSIC + { "GetRandomSuffix", &LuaItem::GetRandomSuffix }, +#endif +#ifdef WOTLK + { "GetStatsCount", &LuaItem::GetStatsCount }, +#endif + + // Setters + { "SetOwner", &LuaItem::SetOwner }, + { "SetBinding", &LuaItem::SetBinding }, + { "SetCount", &LuaItem::SetCount }, + + // Boolean + { "IsSoulBound", &LuaItem::IsSoulBound }, + { "IsBoundByEnchant", &LuaItem::IsBoundByEnchant }, + { "IsNotBoundToPlayer", &LuaItem::IsNotBoundToPlayer }, + { "IsLocked", &LuaItem::IsLocked }, + { "IsBag", &LuaItem::IsBag }, + { "IsNotEmptyBag", &LuaItem::IsNotEmptyBag }, + { "IsBroken", &LuaItem::IsBroken }, + { "CanBeTraded", &LuaItem::CanBeTraded }, + { "IsInTrade", &LuaItem::IsInTrade }, + { "IsInBag", &LuaItem::IsInBag }, + { "IsEquipped", &LuaItem::IsEquipped }, + { "HasQuest", &LuaItem::HasQuest }, + { "IsConjuredConsumable", &LuaItem::IsConjuredConsumable }, + { "SetEnchantment", &LuaItem::SetEnchantment }, + { "ClearEnchantment", &LuaItem::ClearEnchantment }, +#ifndef CLASSIC + { "IsCurrencyToken", &LuaItem::IsCurrencyToken }, +#endif +#if (!defined(TBC) && !defined(CLASSIC)) + { "IsBoundAccountWide", &LuaItem::IsBoundAccountWide }, +#endif +#if defined(WOTLK) + { "IsWeaponVellum", &LuaItem::IsWeaponVellum }, + { "IsArmorVellum", &LuaItem::IsArmorVellum }, +#endif + + // Other + { "SaveToDB", &LuaItem::SaveToDB }, + + // Not implemented methods + { "IsPotion", nullptr }, // not implemented in VMANGOS + { "IsRefundExpired", nullptr }, // not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/VMangos/MapMethods.h b/src/modules/Eluna/VMangos/MapMethods.h new file mode 100644 index 0000000000..38db9f0884 --- /dev/null +++ b/src/modules/Eluna/VMangos/MapMethods.h @@ -0,0 +1,405 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef MAPMETHODS_H +#define MAPMETHODS_H + +#include "ElunaInstanceAI.h" + +/*** + * A game map, e.g. Azeroth, Eastern Kingdoms, the Molten Core, etc. + * + * Inherits all methods from: none + */ +namespace LuaMap +{ + +#ifndef CLASSIC + /** + * Returns `true` if the [Map] is an arena [BattleGround], `false` otherwise. + * + * @return bool isArena + */ + int IsArena(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsBattleArena()); + return 1; + } +#endif + + /** + * Returns `true` if the [Map] is a non-arena [BattleGround], `false` otherwise. + * + * @return bool isBattleGround + */ + int IsBattleground(lua_State* L, Map* map) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, map->IsBattleground()); +#else + Eluna::Push(L, map->IsBattleGround()); +#endif + return 1; + } + + /** + * Returns `true` if the [Map] is a dungeon, `false` otherwise. + * + * @return bool isDungeon + */ + int IsDungeon(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsDungeon()); + return 1; + } + + /** + * Returns `true` if the [Map] has no [Player]s, `false` otherwise. + * + * @return bool isEmpty + */ + int IsEmpty(lua_State* L, Map* map) + { + Eluna::Push(L, map->isEmpty()); + return 1; + } + +#ifndef CLASSIC + /** + * Returns `true` if the [Map] is a heroic, `false` otherwise. + * + * @return bool isHeroic + */ + int IsHeroic(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsHeroic()); + return 1; + } +#endif + + /** + * Returns `true` if the [Map] is a raid, `false` otherwise. + * + * @return bool isRaid + */ + int IsRaid(lua_State* L, Map* map) + { + Eluna::Push(L, map->IsRaid()); + return 1; + } + + /** + * Returns the name of the [Map]. + * + * @return string mapName + */ + int GetName(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetMapName()); + return 1; + } + + /** + * Returns the height of the [Map] at the given X and Y coordinates. + * + * In case of no height found nil is returned + * + * @param float x + * @param float y + * @return float z + */ + int GetHeight(lua_State* L, Map* map) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); +#if (defined(TBC) || defined(CLASSIC)) + float z = map->GetHeight(x, y, MAX_HEIGHT); +#else + uint32 phasemask = Eluna::CHECKVAL(L, 4, 1); + float z = map->GetHeight(phasemask, x, y, MAX_HEIGHT); +#endif + if (z != INVALID_HEIGHT) + Eluna::Push(L, z); + return 1; + } + + /** + * Returns the difficulty of the [Map]. + * + * Always returns 0 if the expansion is pre-TBC. + * + * @return int32 difficulty + */ + int GetDifficulty(lua_State* L, Map* map) + { +#ifndef CLASSIC + Eluna::Push(L, map->GetDifficulty()); +#else + Eluna::Push(L, (Difficulty)0); +#endif + return 1; + } + + /** + * Returns the instance ID of the [Map]. + * + * @return uint32 instanceId + */ + int GetInstanceId(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetInstanceId()); + return 1; + } + + /** + * Returns the player count currently on the [Map] (excluding GMs). + * + * @return uint32 playerCount + */ + int GetPlayerCount(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetPlayersCountExceptGMs()); + return 1; + } + + /** + * Returns the ID of the [Map]. + * + * @return uint32 mapId + */ + int GetMapId(lua_State* L, Map* map) + { + Eluna::Push(L, map->GetId()); + return 1; + } + + /** + * Returns the area ID of the [Map] at the specified X, Y, and Z coordinates. + * + * @param float x + * @param float y + * @param float z + * @param uint32 phasemask = PHASEMASK_NORMAL + * @return uint32 areaId + */ + int GetAreaId(lua_State* L, Map* map) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); +#if defined TRINITY || defined AZEROTHCORE + float phasemask = Eluna::CHECKVAL(L, 5, PHASEMASK_NORMAL); + + Eluna::Push(L, map->GetAreaId(phasemask, x, y, z)); +#else + Eluna::Push(L, map->GetTerrain()->GetAreaId(x, y, z)); +#endif + return 1; + } + + /** + * Returns a [WorldObject] by its GUID from the map if it is spawned. + * + * @param ObjectGuid guid + * @return [WorldObject] object + */ + int GetWorldObject(lua_State* L, Map* map) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + +#if defined TRINITY || AZEROTHCORE + switch (guid.GetHigh()) + { + case HIGHGUID_PLAYER: + Eluna::Push(L, eObjectAccessor()GetPlayer(map, guid)); + break; + case HIGHGUID_TRANSPORT: + case HIGHGUID_MO_TRANSPORT: + case HIGHGUID_GAMEOBJECT: + Eluna::Push(L, map->GetGameObject(guid)); + break; + case HIGHGUID_VEHICLE: + case HIGHGUID_UNIT: + Eluna::Push(L, map->GetCreature(guid)); + break; + case HIGHGUID_PET: + Eluna::Push(L, map->GetPet(guid)); + break; + case HIGHGUID_DYNAMICOBJECT: + Eluna::Push(L, map->GetDynamicObject(guid)); + break; + case HIGHGUID_CORPSE: + Eluna::Push(L, map->GetCorpse(guid)); + break; + default: + break; + } +#else + Eluna::Push(L, map->GetWorldObject(guid)); +#endif + return 1; + } + + /** + * Sets the [Weather] type based on [WeatherType] and grade supplied. + * + * enum WeatherType + * { + * WEATHER_TYPE_FINE = 0, + * WEATHER_TYPE_RAIN = 1, + * WEATHER_TYPE_SNOW = 2, + * WEATHER_TYPE_STORM = 3, + * WEATHER_TYPE_THUNDERS = 86, + * WEATHER_TYPE_BLACKRAIN = 90 + * }; + * + * @param uint32 zone : id of the zone to set the weather for + * @param [WeatherType] type : the [WeatherType], see above available weather types + * @param float grade : the intensity/grade of the [Weather], ranges from 0 to 1 + */ + int SetWeather(lua_State* L, Map* map) + { + (void)map; // ensure that the variable is referenced in order to pass compiler checks + uint32 zoneId = Eluna::CHECKVAL(L, 2); + uint32 weatherType = Eluna::CHECKVAL(L, 3); + float grade = Eluna::CHECKVAL(L, 4); + +#if defined TRINITY + if (Weather * weather = map->GetOrGenerateZoneDefaultWeather(zoneId)) + weather->SetWeather((WeatherType)weatherType, grade); +#elif defined AZEROTHCORE + Weather* weather = WeatherMgr::FindWeather(zoneId); + if (!weather) + weather = WeatherMgr::AddWeather(zoneId); + if (weather) + weather->SetWeather((WeatherType)weatherType, grade); +#else + if (Weather::IsValidWeatherType(weatherType)) + map->SetWeather(zoneId, (WeatherType)weatherType, grade, false); +#endif + return 0; + } + + /** + * Gets the instance data table for the [Map], if it exists. + * + * The instance must be scripted using Eluna for this to succeed. + * If the instance is scripted in C++ this will return `nil`. + * + * @return table instance_data : instance data table, or `nil` + */ + int GetInstanceData(lua_State* L, Map* map) + { +#if defined TRINITY || AZEROTHCORE + ElunaInstanceAI* iAI = NULL; + if (InstanceMap* inst = map->ToInstanceMap()) + iAI = dynamic_cast(inst->GetInstanceScript()); +#else + ElunaInstanceAI* iAI = dynamic_cast(map->GetInstanceData()); +#endif + + if (iAI) + Eluna::GetEluna(L)->PushInstanceData(L, iAI, false); + else + Eluna::Push(L); // nil + + return 1; + } + + /** + * Saves the [Map]'s instance data to the database. + */ + int SaveInstanceData(lua_State* /*L*/, Map* map) + { +#if defined TRINITY || AZEROTHCORE + ElunaInstanceAI* iAI = NULL; + if (InstanceMap* inst = map->ToInstanceMap()) + iAI = dynamic_cast(inst->GetInstanceScript()); +#else + ElunaInstanceAI* iAI = dynamic_cast(map->GetInstanceData()); +#endif + + if (iAI) + iAI->SaveToDB(); + + return 0; + } + + /** + * Returns a table with all the current [Player]s in the map + * + * enum TeamId + * { + * TEAM_ALLIANCE = 0, + * TEAM_HORDE = 1, + * TEAM_NEUTRAL = 2 + * }; + * + * @param [TeamId] team : optional check team of the [Player], Alliance, Horde or Neutral (All) + * @return table mapPlayers + */ + int GetPlayers(lua_State* L, Map* map) + { + uint32 team = Eluna::CHECKVAL(L, 2, TEAM_NEUTRAL); + + lua_newtable(L); + int tbl = lua_gettop(L); + uint32 i = 0; + + Map::PlayerList const& players = map->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { +#if defined TRINITY || AZEROTHCORE + Player* player = itr->GetSource(); +#else + Player* player = itr->getSource(); +#endif + if (!player) + continue; + if (player->GetSession() && (team >= TEAM_NEUTRAL || player->GetTeamId() == team)) + { + Eluna::Push(L, player); + lua_rawseti(L, tbl, ++i); + } + } + + lua_settop(L, tbl); + return 1; + } + + ElunaRegister MapMethods[] = + { + // Getters + { "GetName", &LuaMap::GetName }, + { "GetDifficulty", &LuaMap::GetDifficulty }, + { "GetInstanceId", &LuaMap::GetInstanceId }, + { "GetInstanceData", &LuaMap::GetInstanceData }, + { "GetPlayerCount", &LuaMap::GetPlayerCount }, + { "GetPlayers", &LuaMap::GetPlayers }, + { "GetMapId", &LuaMap::GetMapId }, + { "GetAreaId", &LuaMap::GetAreaId }, + { "GetHeight", &LuaMap::GetHeight }, + { "GetWorldObject", &LuaMap::GetWorldObject }, + + // Setters + { "SetWeather", &LuaMap::SetWeather }, + + // Boolean + { "IsBattleground", &LuaMap::IsBattleground }, + { "IsDungeon", &LuaMap::IsDungeon }, + { "IsEmpty", &LuaMap::IsEmpty }, + { "IsRaid", &LuaMap::IsRaid }, +#ifndef CLASSIC + { "IsArena", &LuaMap::IsArena }, + { "IsHeroic", &LuaMap::IsHeroic }, +#endif + // Other + { "SaveInstanceData", &LuaMap::SaveInstanceData }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/VMangos/ObjectMethods.h b/src/modules/Eluna/VMangos/ObjectMethods.h new file mode 100644 index 0000000000..ea5110e260 --- /dev/null +++ b/src/modules/Eluna/VMangos/ObjectMethods.h @@ -0,0 +1,506 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef OBJECTMETHODS_H +#define OBJECTMETHODS_H + +/*** + * A basic game object (either an [Item] or a [WorldObject]). + * + * Objects in MaNGOS/Trinity are stored an a giant block of "values". + * Subclasses of Object, like [WorldObject], extend the block with more data specific to that subclass. + * Further subclasses, like [Player], extend it even further. + * + * A detailed map of all the fields in this data block can be found in the UpdateFields.h file of your emulator + * (it varies depending on the expansion supported). + * + * The GetValue methods in this class (e.g. [Object:GetInt32Value]) provide low-level access to the data block. + * Other methods, like [Object:HasFlag] and [Object:GetScale], merely wrap the GetValue methods and provide a simpler interface. + * + * Inherits all methods from: none + */ +namespace LuaObject +{ + /** + * Returns `true` if the specified flag is set, otherwise `false`. + * + * @param uint16 index : the index of the flags data in the [Object] + * @param uint32 flag : the flag to check for in the flags data + * @return bool hasFlag + */ + int HasFlag(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 flag = Eluna::CHECKVAL(L, 3); + + Eluna::Push(L, obj->HasFlag(index, flag)); + return 1; + } + + /** + * Returns `true` if the [Object] has been added to its [Map], otherwise `false`. + * + * @return bool inWorld + */ + int IsInWorld(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->IsInWorld()); + return 1; + } + + /** + * Returns the data at the specified index, casted to a signed 32-bit integer. + * + * @param uint16 index + * @return int32 value + */ + int GetInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, obj->GetInt32Value(index)); + return 1; + } + + /** + * Returns the data at the specified index, casted to a unsigned 32-bit integer. + * + * @param uint16 index + * @return uint32 value + */ + int GetUInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, obj->GetUInt32Value(index)); + return 1; + } + + /** + * Returns the data at the specified index, casted to a single-precision floating point value. + * + * @param uint16 index + * @return float value + */ + int GetFloatValue(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, obj->GetFloatValue(index)); + return 1; + } + + /** + * Returns the data at the specified index and offset, casted to an unsigned 8-bit integer. + * + * E.g. if you want the second byte at index 10, you would pass in 1 as the offset. + * + * @param uint16 index + * @param uint8 offset : should be 0, 1, 2, or 3 + * @return uint8 value + */ + int GetByteValue(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetByteValue(index, offset)); + return 1; + } + + /** + * Returns the data at the specified index and offset, casted to a signed 16-bit integer. + * + * E.g. if you want the second half-word at index 10, you would pass in 1 as the offset. + * + * @param uint16 index + * @param uint8 offset : should be 0 or 1 + * @return uint16 value + */ + int GetUInt16Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetUInt16Value(index, offset)); + return 1; + } + + /** + * Returns the scale/size of the [Object]. + * + * This affects the size of a [WorldObject] in-game, but [Item]s don't have a "scale". + * + * @return float scale + */ + int GetScale(lua_State* L, Object* obj) + { +#ifndef AZEROTHCORE + Eluna::Push(L, obj->GetObjectScale()); +#else + Eluna::Push(L, obj->GetFloatValue(OBJECT_FIELD_SCALE_X)); +#endif + return 1; + } + + /** + * Returns the entry of the [Object]. + * + * [Player]s do not have an "entry". + * + * @return uint32 entry + */ + int GetEntry(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GetEntry()); + return 1; + } + + /** + * Returns the GUID of the [Object]. + * + * GUID is an unique identifier for the object. + * + * However on MaNGOS and cMangos creatures and gameobjects inside different maps can share + * the same GUID but not on the same map. + * + * On TrinityCore this value is unique across all maps + * + * @return ObjectGuid guid + */ + int GetGUID(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GET_GUID()); + return 1; + } + + /** + * Returns the low-part of the [Object]'s GUID. + * + * On TrinityCore all low GUIDs are different for all objects of the same type. + * For example creatures in instances are assigned new GUIDs when the Map is created. + * + * On MaNGOS and cMaNGOS low GUIDs are unique only on the same map. + * For example creatures in instances use the same low GUID assigned for that spawn in the database. + * This is why to identify a creature you have to know the instanceId and low GUID. See [Map:GetIntstanceId] + * + * @return uint32 guidLow + */ + int GetGUIDLow(lua_State* L, Object* obj) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, obj->GetGUID().GetCounter()); +#else + Eluna::Push(L, obj->GetGUIDLow()); +#endif + return 1; + } + + /** + * Returns the TypeId of the [Object]. + * + * enum TypeID + * { + * TYPEID_OBJECT = 0, + * TYPEID_ITEM = 1, + * TYPEID_CONTAINER = 2, + * TYPEID_UNIT = 3, + * TYPEID_PLAYER = 4, + * TYPEID_GAMEOBJECT = 5, + * TYPEID_DYNAMICOBJECT = 6, + * TYPEID_CORPSE = 7 + * }; + * + * @return uint8 typeID + */ + int GetTypeId(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->GetTypeId()); + return 1; + } + + /** + * Returns the data at the specified index, casted to an unsigned 64-bit integer. + * + * @param uint16 index + * @return uint64 value + */ + int GetUInt64Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, obj->GetUInt64Value(index)); + return 1; + } + + /** + * Sets the specified flag in the data value at the specified index. + * + * If the flag was already set, it remains set. + * + * To remove a flag, use [Object:RemoveFlag]. + * + * @param uint16 index + * @param uint32 value + */ + int SetFlag(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 flag = Eluna::CHECKVAL(L, 3); + + obj->SetFlag(index, flag); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to a signed 32-bit integer. + * + * @param uint16 index + * @param int32 value + */ + int SetInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + int32 value = Eluna::CHECKVAL(L, 3); + obj->SetInt32Value(index, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to an unsigned 32-bit integer. + * + * @param uint16 index + * @param uint32 value + */ + int SetUInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 value = Eluna::CHECKVAL(L, 3); + obj->SetUInt32Value(index, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to an unsigned 32-bit integer. + * + * @param uint16 index + * @param uint32 value + */ + int UpdateUInt32Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 value = Eluna::CHECKVAL(L, 3); + obj->SetUInt32Value(index, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to a single-precision floating point value. + * + * @param uint16 index + * @param float value + */ + int SetFloatValue(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + float value = Eluna::CHECKVAL(L, 3); + + obj->SetFloatValue(index, value); + return 0; + } + + /** + * Sets the data at the specified index and offset to the given value, converted to an unsigned 8-bit integer. + * + * @param uint16 index + * @param uint8 offset : should be 0, 1, 2, or 3 + * @param uint8 value + */ + int SetByteValue(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + uint8 value = Eluna::CHECKVAL(L, 4); + obj->SetByteValue(index, offset, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to an unsigned 16-bit integer. + * + * @param uint16 index + * @param uint8 offset : should be 0 or 1 + * @param uint16 value + */ + int SetUInt16Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + uint16 value = Eluna::CHECKVAL(L, 4); + obj->SetUInt16Value(index, offset, value); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to a signed 16-bit integer. + * + * @param uint16 index + * @param uint8 offset : should be 0 or 1 + * @param int16 value + */ + int SetInt16Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint8 offset = Eluna::CHECKVAL(L, 3); + int16 value = Eluna::CHECKVAL(L, 4); + obj->SetInt16Value(index, offset, value); + return 0; + } + + /** + * Sets the [Object]'s scale/size to the given value. + * + * @param float scale + */ + int SetScale(lua_State* L, Object* obj) + { + float size = Eluna::CHECKVAL(L, 2); + + obj->SetObjectScale(size); + return 0; + } + + /** + * Sets the data at the specified index to the given value, converted to an unsigned 64-bit integer. + * + * @param uint16 index + * @param uint64 value + */ + int SetUInt64Value(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint64 value = Eluna::CHECKVAL(L, 3); + obj->SetUInt64Value(index, value); + return 0; + } + + /** + * Removes a flag from the value at the specified index. + * + * @param uint16 index + * @param uint32 flag + */ + int RemoveFlag(lua_State* L, Object* obj) + { + uint16 index = Eluna::CHECKVAL(L, 2); + uint32 flag = Eluna::CHECKVAL(L, 3); + + obj->RemoveFlag(index, flag); + return 0; + } + + /** + * Attempts to convert the [Object] to a [Corpse]. + * + * If the [Object] is not a [Corpse], returns `nil`. + * + * @return [Corpse] corpse : the [Object] as a [Corpse], or `nil` + */ + int ToCorpse(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToCorpse()); + return 1; + } + + /** + * Attempts to convert the [Object] to a [GameObject]. + * + * If the [Object] is not a [GameObject], returns `nil`. + * + * @return [GameObject] gameObject : the [Object] as a [GameObject], or `nil` + */ + int ToGameObject(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToGameObject()); + return 1; + } + + /** + * Attempts to convert the [Object] to a [Unit]. + * + * If the [Object] is not a [Unit], returns `nil`. + * + * @return [Unit] unit : the [Object] as a [Unit], or `nil` + */ + int ToUnit(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToUnit()); + return 1; + } + + /** + * Attempts to convert the [Object] to a [Creature]. + * + * If the [Object] is not a [Creature], returns `nil`. + * + * @return [Creature] creature : the [Object] as a [Creature], or `nil` + */ + int ToCreature(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToCreature()); + return 1; + } + + /** + * Attempts to convert the [Object] to a [Player]. + * + * If the [Object] is not a [Player], returns `nil`. + * + * @return [Player] player : the [Object] as a [Player], or `nil` + */ + int ToPlayer(lua_State* L, Object* obj) + { + Eluna::Push(L, obj->ToPlayer()); + return 1; + } + + ElunaRegister ObjectMethods[] = + { + // Getters + { "GetEntry", &LuaObject::GetEntry }, + { "GetGUID", &LuaObject::GetGUID }, + { "GetGUIDLow", &LuaObject::GetGUIDLow }, + { "GetInt32Value", &LuaObject::GetInt32Value }, + { "GetUInt32Value", &LuaObject::GetUInt32Value }, + { "GetFloatValue", &LuaObject::GetFloatValue }, + { "GetByteValue", &LuaObject::GetByteValue }, + { "GetUInt16Value", &LuaObject::GetUInt16Value }, + { "GetUInt64Value", &LuaObject::GetUInt64Value }, + { "GetScale", &LuaObject::GetScale }, + { "GetTypeId", &LuaObject::GetTypeId }, + + // Setters + { "SetInt32Value", &LuaObject::SetInt32Value }, + { "SetUInt32Value", &LuaObject::SetUInt32Value }, + { "UpdateUInt32Value", &LuaObject::UpdateUInt32Value }, + { "SetFloatValue", &LuaObject::SetFloatValue }, + { "SetByteValue", &LuaObject::SetByteValue }, + { "SetUInt16Value", &LuaObject::SetUInt16Value }, + { "SetInt16Value", &LuaObject::SetInt16Value }, + { "SetUInt64Value", &LuaObject::SetUInt64Value }, + { "SetScale", &LuaObject::SetScale }, + { "SetFlag", &LuaObject::SetFlag }, + + // Boolean + { "IsInWorld", &LuaObject::IsInWorld }, + { "HasFlag", &LuaObject::HasFlag }, + + // Other + { "ToGameObject", &LuaObject::ToGameObject }, + { "ToUnit", &LuaObject::ToUnit }, + { "ToCreature", &LuaObject::ToCreature }, + { "ToPlayer", &LuaObject::ToPlayer }, + { "ToCorpse", &LuaObject::ToCorpse }, + { "RemoveFlag", &LuaObject::RemoveFlag }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/VMangos/PlayerMethods.h b/src/modules/Eluna/VMangos/PlayerMethods.h new file mode 100644 index 0000000000..05ea35cc90 --- /dev/null +++ b/src/modules/Eluna/VMangos/PlayerMethods.h @@ -0,0 +1,4477 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef PLAYERMETHODS_H +#define PLAYERMETHODS_H + +/*** + * Inherits all methods from: [Object], [WorldObject], [Unit] + */ +namespace LuaPlayer +{ +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Returns 'true' if the [Player] can Titan Grip, 'false' otherwise. + * + * @return bool canTitanGrip + */ + int CanTitanGrip(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanTitanGrip()); + return 1; + } + + /** + * Returns 'true' if the [Player] has a talent by ID in specified spec, 'false' otherwise. + * + * @param uint32 spellId : talent spellId to check + * @param uint8 spec : specified spec. 0 for primary, 1 for secondary. + * @return bool hasTalent + */ + int HasTalent(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); +#ifdef MANGOS + uint8 maxSpecs = MAX_TALENT_SPEC_COUNT; +#else + uint8 maxSpecs = MAX_TALENT_SPECS; +#endif + uint8 spec = Eluna::CHECKVAL(L, 3); + if (spec >= maxSpecs) + return 1; + Eluna::Push(L, player->HasTalent(spellId, spec)); + return 1; + } + + /** + * Returns 'true' if the [Player] has completed the specified achievement, 'false' otherwise. + * + * @param uint32 achievementId + * @return bool hasAchieved + */ + int HasAchieved(lua_State* L, Player* player) + { + uint32 achievementId = Eluna::CHECKVAL(L, 2); +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, player->HasAchieved(achievementId)); +#else + Eluna::Push(L, player->GetAchievementMgr().HasAchievement(achievementId)); +#endif + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] has an active [Quest] by specific ID, 'false' otherwise. + * + * @param uint32 questId + * @return bool hasQuest + */ + int HasQuest(lua_State* L, Player* player) + { + uint32 quest = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->IsActiveQuest(quest)); + return 1; + } + + /** + * Returns 'true' if the [Player] has a skill by specific ID, 'false' otherwise. + * + * @param uint32 skill + * @return bool hasSkill + */ + int HasSkill(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasSkill(skill)); + return 1; + } + + /** + * Returns 'true' if the [Player] has a [Spell] by specific ID, 'false' otherwise. + * + * @param uint32 spellId + * @return bool hasSpell + */ + int HasSpell(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasSpell(id)); + return 1; + } + + /** + * Returns true if [Player] has specified login flag + * + * @param uint32 flag + * @return bool hasLoginFlag + */ + int HasAtLoginFlag(lua_State* L, Player* player) + { + uint32 flag = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasAtLoginFlag((AtLoginFlags)flag)); + return 1; + } + + /** + * Returns true if [Player] has [Quest] for [GameObject] + * + * @param int32 entry : entry of a [GameObject] + * @return bool hasQuest + */ + int HasQuestForGO(lua_State* L, Player* player) + { + int32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasQuestForGO(entry)); + return 1; + } + +#ifndef CLASSIC + /** + * Returns 'true' if the [Player] has a title by specific ID, 'false' otherwise. + * + * @param uint32 titleId + * @return bool hasTitle + */ + int HasTitle(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); + if (titleInfo) + Eluna::Push(L, player->HasTitle(titleInfo)); + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] has the given amount of item entry specified, 'false' otherwise. + * + * @param uint32 itemId : entry of the item + * @param uint32 count = 1 : amount of items the player needs should have + * @param bool check_bank = false : determines if the item can be in player bank + * @return bool hasItem + */ + int HasItem(lua_State* L, Player* player) + { + uint32 itemId = Eluna::CHECKVAL(L, 2); + uint32 count = Eluna::CHECKVAL(L, 3, 1); + bool check_bank = Eluna::CHECKVAL(L, 4, false); + Eluna::Push(L, player->HasItemCount(itemId, count, check_bank)); + return 1; + } + + /** + * Returns 'true' if the [Player] has a quest for the item entry specified, 'false' otherwise. + * + * @param uint32 entry : entry of the item + * @return bool hasQuest + */ + int HasQuestForItem(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->HasQuestForItem(entry)); + return 1; + } + + /** + * Returns 'true' if the [Player] can use the item or item entry specified, 'false' otherwise. + * + * @proto canUse = (item) + * @proto canUse = (entry) + * @param [Item] item : an instance of an item + * @param uint32 entry : entry of the item + * @return bool canUse + */ + int CanUseItem(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2, false); + if (item) + Eluna::Push(L, player->CanUseItem(item) == EQUIP_ERR_OK); + else + { + uint32 entry = Eluna::CHECKVAL(L, 2); + const ItemTemplate* temp = eObjectMgr->GetItemTemplate(entry); + if (temp) + Eluna::Push(L, player->CanUseItem(temp) == EQUIP_ERR_OK); + else + Eluna::Push(L, false); + } + return 1; + } + + /** + * Returns 'true' if the [Spell] specified by ID is currently on cooldown for the [Player], 'false' otherwise. + * + * @param uint32 spellId + * @return bool hasSpellCooldown + */ + int HasSpellCooldown(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->IsSpellReady(spellId)); + return 1; + } + + /** + * Returns 'true' if the [Player] can share [Quest] specified by ID, 'false' otherwise. + * + * @param uint32 entryId + * @return bool hasSpellCooldown + */ + int CanShareQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->CanShareQuest(entry)); + return 1; + } + + /** + * Returns 'true' if the [Player] can currently communicate through chat, 'false' otherwise. + * + * @return bool canSpeak + */ + int CanSpeak(lua_State* L, Player* player) + { +#ifdef TRINITY + Eluna::Push(L, player->GetSession()->CanSpeak()); +#else + Eluna::Push(L, player->CanSpeak()); +#endif + return 1; + } + + /** + * Returns 'true' if the [Player] has permission to uninvite others from the current group, 'false' otherwise. + * + * @return bool canUninviteFromGroup + */ + int CanUninviteFromGroup(lua_State* L, Player* player) + { + uint64 guid = Eluna::CHECKVAL(L, 2, player->GET_GUID()); + Eluna::Push(L, player->CanUninviteFromGroup(ObjectGuid(guid)) == ERR_PARTY_RESULT_OK); + return 1; + } + +#ifndef CLASSIC + /** + * Returns 'true' if the [Player] can fly, 'false' otherwise. + * + * @return bool canFly + */ + int CanFly(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanFly()); + return 1; + } +#endif + +#ifdef CLASSIC + /** + * Returns [Player] kills + * + * @param bool honorable = true : if victims are honorable + * @return uint32 kills + */ + int GetHonorStoredKills(lua_State* L, Player* player) + { + bool honorable = Eluna::CHECKVAL(L, 2, true); + + Eluna::Push(L, player->GetHonorMgr().GetStoredHK()); + return 1; + } + + /** + * Returns rank points + * + * @return float rankPoints + */ + int GetRankPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetHonorMgr().GetRankPoints()); + return 1; + } + + /** + * Returns last week's standing position + * + * @return int32 standingPos + */ + int GetHonorLastWeekStandingPos(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetHonorMgr().GetStanding()); // TODO: Probably not exactly what we need. Not week-based(?) + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] is currently in water, 'false' otherwise. + * + * @return bool isInWater + */ + int IsInWater(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsInWater()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently moving, 'false' otherwise. + * + * @return bool isMoving + */ + int IsMoving(lua_State* L, Player* player) // enable for unit when mangos support it + { + Eluna::Push(L, player->IsMoving()); + return 1; + } + +#ifdef CLASSIC + /** + * Updates the [Player]s weekly honor status + */ + int UpdateHonor(lua_State* L, Player* player) + { + player->GetHonorMgr().Update(); + return 0; + } + + /** + * Resets the [Player]s weekly honor status + */ + int ResetHonor(lua_State* L, Player* player) + { + player->GetHonorMgr().Reset(); + return 0; + } + + /** + * Clears all of [Player]s weekly honor status + */ + int ClearHonorInfo(lua_State* L, Player* player) + { + player->GetHonorMgr().ClearHonorData(); // TODO: Probably not exactly what we need. Not week-based + return 0; + } +#endif + +#ifndef CLASSIC + /** + * Returns 'true' if the [Player] is currently flying, 'false' otherwise. + * + * @return bool isFlying + */ + int IsFlying(lua_State* L, Player* player) // enable for unit when mangos support it + { + Eluna::Push(L, player->IsFlying()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] is in a [Group], 'false' otherwise. + * + * @return bool isInGroup + */ + int IsInGroup(lua_State* L, Player* player) + { + Eluna::Push(L, (player->GetGroup() != NULL)); + return 1; + } + + /** + * Returns 'true' if the [Player] is in a [Guild], 'false' otherwise. + * + * @return bool isInGuild + */ + int IsInGuild(lua_State* L, Player* player) + { + Eluna::Push(L, (player->GetGuildId() != 0)); + return 1; + } + + /** + * Returns 'true' if the [Player] is a Game Master, 'false' otherwise. + * + * Note: This is only true when GM tag is activated! For alternative see [Player:GetGMRank] + * + * @return bool isGM + */ + int IsGM(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsGameMaster()); + return 1; + } + +#ifndef CLASSIC + /** + * Returns 'true' if the [Player] is in an arena team specified by type, 'false' otherwise. + * + * @param uint32 type + * @return bool isInArenaTeam + */ + int IsInArenaTeam(lua_State* L, Player* player) + { + uint32 type = Eluna::CHECKVAL(L, 2); + if (type < MAX_ARENA_SLOT && player->GetArenaTeamId(type)) + Eluna::Push(L, true); + else + Eluna::Push(L, false); + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] is immune to everything. + * + * @return bool isImmune + */ + int IsImmuneToDamage(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsTotalImmune()); + return 1; + } + + /** + * Returns 'true' if the [Player] satisfies all requirements to complete the quest entry. + * + * @param uint32 entry + * @return bool canComplete + */ + int CanCompleteQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->CanCompleteQuest(entry)); + return 1; + } + + /** + * Returns 'true' if the [Player] is a part of the Horde faction, 'false' otherwise. + * + * @return bool isHorde + */ + int IsHorde(lua_State* L, Player* player) + { +#ifdef AZEROTHCORE + Eluna::Push(L, (player->GetTeamId() == TEAM_HORDE)); +#else + Eluna::Push(L, (player->GetTeam() == HORDE)); +#endif + return 1; + } + + /** + * Returns 'true' if the [Player] is a part of the Alliance faction, 'false' otherwise. + * + * @return bool isAlliance + */ + int IsAlliance(lua_State* L, Player* player) + { +#ifdef AZEROTHCORE + Eluna::Push(L, (player->GetTeamId() == TEAM_ALLIANCE)); +#else + Eluna::Push(L, (player->GetTeam() == ALLIANCE)); +#endif + return 1; + } + + /** + * Returns 'true' if the [Player] is 'Do Not Disturb' flagged, 'false' otherwise. + * + * @return bool isDND + */ + int IsDND(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsDND()); + return 1; + } + + /** + * Returns 'true' if the [Player] is 'Away From Keyboard' flagged, 'false' otherwise. + * + * @return bool isAFK + */ + int IsAFK(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsAFK()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently falling, 'false' otherwise. + * + * @return bool isFalling + */ + int IsFalling(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsFalling()); + return 1; + } + + int IsGroupVisibleFor(lua_State* L, Player* player) + { + Player* target = Eluna::CHECKOBJ(L, 2); + Eluna::Push(L, player->IsGroupVisibleFor(target)); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently in the same raid as another [Player] by object, 'false' otherwise. + * + * @param [Player] player + * @return bool isInSameRaidWith + */ + int IsInSameRaidWith(lua_State* L, Player* player) + { + Player* target = Eluna::CHECKOBJ(L, 2); + Eluna::Push(L, player->IsInSameRaidWith(target)); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently in the same [Group] as another [Player] by object, 'false' otherwise. + * + * @param [Player] player + * @return bool isInSameGroupWith + */ + int IsInSameGroupWith(lua_State* L, Player* player) + { + Player* target = Eluna::CHECKOBJ(L, 2); + Eluna::Push(L, player->IsInSameGroupWith(target)); + return 1; + } + + /** + * Returns 'true' if the [Player] is eligible for Honor or XP gain by [Unit] specified, 'false' otherwise. + * + * @param [Unit] unit + * @return bool isHonorOrXPTarget + */ + int IsHonorOrXPTarget(lua_State* L, Player* player) + { + Unit* victim = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, player->IsHonorOrXPTarget(victim)); + return 1; + } + + /** + * Returns 'true' if the [Player] can see anoter [Player] specified by object, 'false' otherwise. + * + * @param [Player] player + * @return bool isVisibleForPlayer + */ + int IsVisibleForPlayer(lua_State* L, Player* player) + { + Player* target = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, player->IsVisibleGloballyFor(target)); + return 1; + } + + int IsGMVisible(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsGMVisible()); + return 1; + } + + /** + * Returns 'true' if the [Player] has taxi cheat activated, 'false' otherwise. + * + * @return bool isTaxiCheater + */ + int IsTaxiCheater(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsTaxiCheater()); + return 1; + } + + int IsGMChat(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsGMChat()); + return 1; + } + + /** + * Returns 'true' if the [Player] is accepting whispers, 'false' otherwise. + * + * @return bool isAcceptingWhispers + */ + int IsAcceptingWhispers(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsAcceptWhispers()); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently rested, 'false' otherwise. + * + * @return bool isRested + */ + int IsRested(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetRestBonus() > 0.0f); + return 1; + } + + /** + * Returns 'true' if the [Player] is currently in a [BattleGround] queue, 'false' otherwise. + * + * @return bool inBattlegroundQueue + */ + int InBattlegroundQueue(lua_State* L, Player* player) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, player->InBattlegroundQueue()); +#else + Eluna::Push(L, player->InBattleGroundQueue()); +#endif + return 1; + } + +#ifndef CLASSIC + /** + * Returns 'true' if the [Player] is currently in an arena, 'false' otherwise. + * + * @return bool inArena + */ + int InArena(lua_State* L, Player* player) + { + Eluna::Push(L, player->InArena()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Player] is currently in a [BattleGround], 'false' otherwise. + * + * @return bool inBattleGround + */ + int InBattleground(lua_State* L, Player* player) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, player->InBattleground()); +#else + Eluna::Push(L, player->InBattleGround()); +#endif + return 1; + } + + /** + * Returns 'true' if the [Player] can block incomming attacks, 'false' otherwise. + * + * @return bool canBlock + */ + int CanBlock(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanBlock()); + return 1; + } + + /** + * Returns 'true' if the [Player] can parry incomming attacks, 'false' otherwise. + * + * @return bool canParry + */ + int CanParry(lua_State* L, Player* player) + { + Eluna::Push(L, player->CanParry()); + return 1; + } + + /*int HasReceivedQuestReward(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->IsQuestRewarded(entry)); + return 1; + }*/ + + /*int IsOutdoorPvPActive(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsOutdoorPvPActive()); + return 1; + }*/ + + /*int IsImmuneToEnvironmentalDamage(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsImmuneToEnvironmentalDamage()); + return 1; + }*/ + + /*int InRandomLfgDungeon(lua_State* L, Player* player) + { + Eluna::Push(L, player->inRandomLfgDungeon()); + return 1; + }*/ + + /*int IsUsingLfg(lua_State* L, Player* player) + { + Eluna::Push(L, player->isUsingLfg()); + return 1; + }*/ + + /*int IsNeverVisible(lua_State* L, Player* player) + { + Eluna::Push(L, player->IsNeverVisible()); + return 1; + }*/ + + /*int CanFlyInZone(lua_State* L, Player* player) + { + uint32 mapid = Eluna::CHECKVAL(L, 2); + uint32 zone = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->IsKnowHowFlyIn(mapid, zone)); + return 1; + }*/ + + /*int HasPendingBind(lua_State* L, Player* player) + { + Eluna::Push(L, player->PendingHasPendingBind()); + return 1; + }*/ + + /*int IsARecruiter(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->IsARecruiter() || (player->GetSession()->GetRecruiterId() != 0)); + return 1; + }*/ + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Returns the amount of available specs the [Player] currently has + * + * @return uint8 specCount + */ + int GetSpecsCount(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSpecsCount()); + return 1; + } + + /** + * Returns the [Player]s active spec ID + * + * @return uint32 specId + */ + int GetActiveSpec(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetActiveSpec()); + return 1; + } +#endif + +#ifdef WOTLK + /** + * Returns the normal phase of the player instead of the actual phase possibly containing GM phase + * + * @return uint32 phasemask + */ + int GetPhaseMaskForSpawn(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetPhaseMaskForSpawn()); + return 1; + } +#endif + +#if defined(TBC) || defined (WOTLK) + /** + * Returns the [Player]s current amount of Arena Points + * + * @return uint32 arenaPoints + */ + int GetArenaPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetArenaPoints()); + return 1; + } + + /** + * Returns the [Player]s current amount of Honor Points + * + * @return uint32 honorPoints + */ + int GetHonorPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetHonorPoints()); + return 1; + } +#endif +#if defined(CLASSIC) || defined(TBC) || defined (WOTLK) + /** + * Returns the [Player]s current shield block value + * + * @return uint32 blockValue + */ + int GetShieldBlockValue(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetShieldBlockValue()); + return 1; + } +#endif + + /** + * Returns the [Player]s cooldown delay by specified [Spell] ID + * + * @param uint32 spellId + * @return uint32 spellCooldownDelay + */ + int GetSpellCooldownDelay(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + +#ifdef TRINITY + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId)) + Eluna::Push(L, player->GetSpellHistory()->GetRemainingCooldown(spellInfo)); + else + Eluna::Push(L, 0); +#else + Eluna::Push(L, uint32(player->GetSpellCooldownDelay(spellId))); +#endif + return 1; + } + + /** + * Returns the [Player]s current latency in MS + * + * @return uint32 latency + */ + int GetLatency(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetLatency()); + return 1; + } + +#if defined TRINITY || AZEROTHCORE + /** + * Returns the faction ID the [Player] is currently flagged as champion for + * + * @return uint32 championingFaction + */ + int GetChampioningFaction(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetChampioningFaction()); + return 1; + } +#endif + + /** + * Returns [Player]s original sub group + * + * @return uint8 subGroup + */ + int GetOriginalSubGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetOriginalSubGroup()); + return 1; + } + + /** + * Returns [Player]s original [Group] object + * + * @return [Group] group + */ + int GetOriginalGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetOriginalGroup()); + return 1; + } + + /** + * Returns a random Raid Member [Player] object within radius specified of [Player] + * + * @param float radius + * @return [Player] player + */ + int GetNextRandomRaidMember(lua_State* L, Player* player) + { + float radius = Eluna::CHECKVAL(L, 2); + +#ifndef CMANGOS + Eluna::Push(L, player->GetNextRandomRaidMember(radius)); +#else + Eluna::Push(L, player->GetNextRandomRaidMember(radius, SPELL_AURA_NONE)); +#endif + return 1; + } + + /** + * Returns [Player]s current sub group + * + * @return uint8 subGroup + */ + int GetSubGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSubGroup()); + return 1; + } + + /** + * Returns [Group] invitation + * + * @return [Group] group + */ + int GetGroupInvite(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetGroupInvite()); + return 1; + } + + /** + * Returns rested experience bonus + * + * @param uint32 xp + * @return uint32 xpBonus + */ + int GetXPRestBonus(lua_State* L, Player* player) + { + uint32 xp = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetXPRestBonus(xp)); + return 1; + } + + /** + * Returns the [Player]s current [BattleGround] type ID + * + * @return [BattleGroundTypeId] typeId + */ + int GetBattlegroundTypeId(lua_State* L, Player* player) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, player->GetBattlegroundTypeId()); +#else + Eluna::Push(L, player->GetBattleGroundTypeId()); +#endif + return 1; + } + + /** + * Returns the [Player]s current [BattleGround] ID + * + * @return uint32 battleGroundId + */ + int GetBattlegroundId(lua_State* L, Player* player) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, player->GetBattlegroundId()); +#else + Eluna::Push(L, player->GetBattleGroundId()); +#endif + return 1; + } + + /** + * Returns the [Player]s reputation rank of faction specified + * + * @param uint32 faction + * @return [ReputationRank] rank + */ + int GetReputationRank(lua_State* L, Player* player) + { + uint32 faction = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetReputationRank(faction)); + return 1; + } + + /** + * Returns the [Player]s current level of intoxication + * + * @return uint16 drunkValue + */ + int GetDrunkValue(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetDrunkValue()); + return 1; + } + + /** + * Returns skill temporary bonus value + * + * @param uint32 skill + * @param int16 bonusVal + */ + int GetSkillTempBonusValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, player->GetSkillBonusTemporary(skill)); + return 1; + } + + /** + * Returns skill permanent bonus value + * + * @param uint32 skill + * @param int16 bonusVal + */ + int GetSkillPermBonusValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, player->GetSkillBonusPermanent(skill)); + return 1; + } + + /** + * Returns skill value without bonus' + * + * @param uint32 skill + * @return uint16 pureVal + */ + int GetPureSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, player->GetSkillValuePure(skill)); + return 1; + } + + /** + * Returns base skill value + * + * @param uint32 skill + * @return uint16 baseVal + */ + int GetBaseSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, player->GetSkillValueBase(skill)); + return 1; + } + + /** + * Returns skill value + * + * @param uint32 skill + * @return uint16 val + */ + int GetSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetSkillValue(skill)); + return 1; + } + + /** + * Returns max value of specified skill without bonus' + * + * @param uint32 skill + * @return uint16 pureVal + */ + int GetPureMaxSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, player->GetSkillMaxPure(skill)); + return 1; + } + + /** + * Returns max value of specified skill + * + * @param uint32 skill + * @return uint16 val + */ + int GetMaxSkillValue(lua_State* L, Player* player) + { + uint32 skill = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, player->GetSkillMax(skill)); + return 1; + } + + /** + * Returns mana bonus from amount of intellect + * + * @return float bonus + */ + int GetManaBonusFromIntellect(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetManaBonusFromIntellect()); + return 1; + } + + /** + * Returns health bonus from amount of stamina + * + * @return float bonus + */ + int GetHealthBonusFromStamina(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetHealthBonusFromStamina()); + return 1; + } + + /** + * Returns raid or dungeon difficulty + * + * @param bool isRaid = true : argument is TrinityCore only + * @return int32 difficulty + */ + int GetDifficulty(lua_State* L, Player* player) + { +#ifdef TBC + Eluna::Push(L, player->GetDifficulty()); +#elif defined(CLASSIC) + Eluna::Push(L, (Difficulty)0); +#else + bool isRaid = Eluna::CHECKVAL(L, 2, true); + Eluna::Push(L, player->GetDifficulty(isRaid)); +#endif + return 1; + } + + /** + * Returns the [Player]s current guild rank + * + * @return uint32 guildRank + */ + int GetGuildRank(lua_State* L, Player* player) // TODO: Move to Guild Methods + { + Eluna::Push(L, player->GetRank()); + return 1; + } + + /** + * Returns the [Player]s free talent point amount + * + * @return uint32 freeTalentPointAmt + */ + int GetFreeTalentPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetFreeTalentPoints()); + return 1; + } + + /** + * Returns the name of the [Player]s current [Guild] + * + * @return string guildName + */ + int GetGuildName(lua_State* L, Player* player) + { + if (!player->GetGuildId()) + return 1; + Eluna::Push(L, eGuildMgr->GetGuildNameById(player->GetGuildId())); + return 1; + } + + /** + * Returns the amount of reputation the [Player] has with the faction specified + * + * @param uint32 faction + * @return int32 reputationAmt + */ + int GetReputation(lua_State* L, Player* player) + { + uint32 faction = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetReputationMgr().GetReputation(faction)); + return 1; + } + + /** + * Returns [Unit] target combo points are on + * + * @return [Unit] target + */ + int GetComboTarget(lua_State* L, Player* player) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, player->GetComboTarget()); +#else + Eluna::Push(L, player->GetMap()->GetUnit(player->GetComboTargetGuid())); +#endif + return 1; + } + + /** + * Returns [Player]'s combo points + * + * @return uint8 comboPoints + */ + int GetComboPoints(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetComboPoints()); + return 1; + } + + /** + * Returns the amount of time the [Player] has spent ingame + * + * @return uint32 inGameTime + */ + int GetInGameTime(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetInGameTime()); + return 1; + } + + /** + * Returns the status of the [Player]s [Quest] specified by entry ID + * + * @param uint32 questId + * @return [QuestStatus] questStatus + */ + int GetQuestStatus(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetQuestStatus(entry)); + return 1; + } + + /** + * Returns 'true' if the [Player]s [Quest] specified by entry ID has been rewarded, 'false' otherwise. + * + * @param uint32 questId + * @return bool questRewardStatus + */ + int GetQuestRewardStatus(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetQuestRewardStatus(questId)); + return 1; + } + + /** + * Returns [Quest] required [Creature] or [GameObject] count + * + * @param uint32 quest : entry of a quest + * @param int32 entry : entry of required [Creature] + * @return uint16 count + */ + int GetReqKillOrCastCurrentCount(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + int32 entry = Eluna::CHECKVAL(L, 3); + + Quest const* qInfo = sObjectMgr.GetQuestTemplate(questId); + QuestStatusData const* q_status = player->GetQuestStatusData(questId); + + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAG_KILL_OR_CAST)) + { + bool found = false; + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) + { + if (qInfo->ReqCreatureOrGOId[j] == entry || qInfo->ReqSpell[j] == entry) + { + found = true; + Eluna::Push(L, q_status->m_creatureOrGOcount[j]); + } + } + if (!found) + { + return luaL_argerror(L, 3, "Entry is not valid for this quest."); + } + } + else + { + return luaL_argerror(L, 2, "Quest is not a kill or cast quest."); + } + return 1; + } + + /** + * Returns the quest level of the [Player]s [Quest] specified by object + * + * @param uint32 questId + * @return [QuestStatus] questRewardStatus + */ + int GetQuestLevel(lua_State* L, Player* player) + { + Quest* quest = Eluna::CHECKOBJ(L, 2); + +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, player->GetQuestLevel(quest)); +#else + Eluna::Push(L, player->GetQuestLevelForPlayer(quest)); +#endif + return 1; + } + + /** + * Returns a [Player]s [Item] object by gear slot specified + * + * @param uint8 slot + * @return [Item] item + */ + int GetEquippedItemBySlot(lua_State* L, Player* player) + { + uint8 slot = Eluna::CHECKVAL(L, 2); + if (slot >= EQUIPMENT_SLOT_END) + return 1; + + Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); + Eluna::Push(L, item); + return 1; + } + + /** + * Returns the [Player]s current resting bonus + * + * @return float restBonus + */ + int GetRestBonus(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetRestBonus()); + return 1; + } + + /** + * Returns active GM chat tag + * + * @return uint8 tag + */ + int GetChatTag(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetChatTag()); + return 1; + } + + /** + * Returns an item in given bag on given slot. + * + *
+     * Possible and most commonly used combinations:
+     *
+     * bag = 255
+     * slots 0-18 equipment
+     * slots 19-22 equipped bag slots
+     * slots 23-38 backpack
+     * slots 39-66 bank main slots
+     * slots 67-74 bank bag slots
+     * slots 86-117 keyring
+     *
+     * bag = 19-22
+     * slots 0-35 for equipped bags
+     *
+     * bag = 67-74
+     * slots 0-35 for bank bags
+     * 
+ * + * @param uint8 bag : the bag the [Item] is in, you can get this with [Item:GetBagSlot] + * @param uint8 slot : the slot the [Item] is in within the bag, you can get this with [Item:GetSlot] + * @return [Item] item : [Item] or nil + */ + int GetItemByPos(lua_State* L, Player* player) + { + uint8 bag = Eluna::CHECKVAL(L, 2); + uint8 slot = Eluna::CHECKVAL(L, 3); + + Eluna::Push(L, player->GetItemByPos(bag, slot)); + return 1; + } + + /** + * Returns an [Item] from the player by guid. + * + * The item can be equipped, in bags or in bank. + * + * @param ObjectGuid guid : an item guid + * @return [Item] item + */ + int GetItemByGUID(lua_State* L, Player* player) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetItemByGuid(guid)); + return 1; + } + + /** + * Returns a mailed [Item] by guid. + * + * @param ObjectGuid guid : an item guid + * @return [Item] item + + int GetMailItem(lua_State* L, Player* player) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetMItem(guid.GetCounter())); + return 1; + } + */ + + /** + * Returns an [Item] from the player by entry. + * + * The item can be equipped, in bags or in bank. + * + * @param uint32 entryId + * @return [Item] item + */ + int GetItemByEntry(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, player->GetItemByEntry(entry)); + return 1; + } + + /** + * Returns the database textID of the [WorldObject]'s gossip header text for the [Player] + * + * @param [WorldObject] object + * @return uint32 textId : key to npc_text database table + */ + int GetGossipTextId(lua_State* L, Player* player) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + Eluna::Push(L, player->GetGossipTextId(obj)); + return 1; + } + + /** + * Returns the [Player]s currently selected [Unit] object + * + * @return [Unit] unit + */ + int GetSelection(lua_State* L, Player* player) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, player->GetSelectedUnit()); +#else + Eluna::Push(L, player->GetMap()->GetUnit(player->GetSelectionGuid())); +#endif + return 1; + } + + /** + * Returns the [Player]s GM Rank + * + * @return [AccountTypes] gmRank + */ + int GetGMRank(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetSecurity()); + return 1; + } + + /** + * Returns the [Player]s amount of money in copper + * + * @return uint32 coinage + */ + int GetCoinage(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetMoney()); + return 1; + } + + /** + * Returns the [Player]s current [Guild] ID + * + * @return uint32 guildId + */ + int GetGuildId(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetGuildId()); + return 1; + } + + /** + * Returns the [Player]s [TeamId] + * + * @return [TeamId] teamId + */ + int GetTeam(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetTeamId()); + return 1; + } + + /** + * Returns amount of the specified [Item] the [Player] has. + * + * @param uint32 entry : entry of the item + * @param bool checkinBank = false : also counts the items in player's bank if true + * @return uint32 itemamount + */ + int GetItemCount(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + bool checkinBank = Eluna::CHECKVAL(L, 3, false); + Eluna::Push(L, player->GetItemCount(entry, checkinBank)); + return 1; + } + + /** + * Returns the [Player]s lifetime Honorable Kills + * + * @return uint32 lifeTimeKils + */ + int GetLifetimeKills(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS)); + return 1; + } + + /** + * Returns the [Player]s IP address + * + * @return string ip + */ + int GetPlayerIP(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetRemoteAddress()); + return 1; + } + + /** + * Returns the [Player]s time played at current level + * + * @return uint32 currLevelPlayTime + */ + int GetLevelPlayedTime(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetLevelPlayedTime()); + return 1; + } + + /** + * Returns the [Player]s total time played + * + * @return uint32 totalPlayTime + */ + int GetTotalPlayedTime(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetTotalPlayedTime()); + return 1; + } + + /** + * Returns the [Player]s [Guild] object + * + * @return [Guild] guild + */ + int GetGuild(lua_State* L, Player* player) + { + Eluna::Push(L, eGuildMgr->GetGuildById(player->GetGuildId())); + return 1; + } + + /** + * Returns the [Player]s [Group] object + * + * @return [Group] group + */ + int GetGroup(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetGroup()); + return 1; + } + + /** + * Returns the [Player]s account ID + * + * @return uint32 accountId + */ + int GetAccountId(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetAccountId()); + return 1; + } + + /** + * Returns the [Player]s account name + * + * @return string accountName + */ + int GetAccountName(lua_State* L, Player* player) + { + std::string accName; +#ifndef AZEROTHCORE + if (eAccountMgr->GetName(player->GetSession()->GetAccountId(), accName)) +#else + if (AccountMgr::GetName(player->GetSession()->GetAccountId(), accName)) +#endif + Eluna::Push(L, accName); + return 1; + } + + /** + * Returns the [Player]s [Corpse] object + * + * @return [Corpse] corpse + */ + int GetCorpse(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetCorpse()); + return 1; + } + + /** + * Returns the [Player]s database locale index + * + * @return int localeIndex + */ + int GetDbLocaleIndex(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetSessionDbLocaleIndex()); + return 1; + } + + /** + * Returns the [Player]s game client locale + * + * @return [LocaleConstant] locale + */ + int GetDbcLocale(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetSessionDbcLocale()); + return 1; + } + + /*int GetRecruiterId(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSession()->GetRecruiterId()); + return 1; + }*/ + + /*int GetSelectedPlayer(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSelectedPlayer()); + return 1; + }*/ + + /*int GetSelectedUnit(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetSelectedUnit()); + return 1; + }*/ + + /*int GetNearbyGameObject(lua_State* L, Player* player) + { + Eluna::Push(L, ChatHandler(player->GetSession()).GetNearbyGameObject()); + return 1; + }*/ + + /** + * Locks the player controls and disallows all movement and casting. + * + * @param bool apply = true : lock if true and unlock if false + */ + int SetPlayerLock(lua_State* L, Player* player) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + if (apply) + { + player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED | UNIT_FLAG_SILENCED); +#ifndef CMANGOS + player->SetClientControl(player, 0); +#else + player->UpdateClientControl(player, 0); +#endif + } + else + { + player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED | UNIT_FLAG_SILENCED); +#ifndef CMANGOS + player->SetClientControl(player, 1); +#else + player->UpdateClientControl(player, 1); +#endif + } + return 0; + } + + /** + * Sets the [Player]s login flag to the flag specified + * + * @param uint32 flag + */ + int SetAtLoginFlag(lua_State* L, Player* player) + { + uint32 flag = Eluna::CHECKVAL(L, 2); + + player->SetAtLoginFlag((AtLoginFlags)flag); + return 0; + } + + /** + * Sets the [Player]s sheathe state to the state specified + * + * @param uint32 sheatheState + */ + int SetSheath(lua_State* L, Player* player) + { + uint32 sheathed = Eluna::CHECKVAL(L, 2); + if (sheathed >= MAX_SHEATH_STATE) + return 0; + + player->SetSheath((SheathState)sheathed); + return 0; + } + + /** + * Sets the [Player]s intoxication level to the level specified + * + * @param uint8 drunkValue + */ + int SetDrunkValue(lua_State* L, Player* player) + { + uint8 newDrunkValue = Eluna::CHECKVAL(L, 2); + + player->SetDrunkValue(newDrunkValue); + return 0; + } + + /** + * Sets the [Player]s faction standing to that of the race specified + * + * @param uint8 raceId + */ + int SetFactionForRace(lua_State* L, Player* player) + { + uint8 race = Eluna::CHECKVAL(L, 2); + + player->SetFactionForRace(race); + return 0; + } + + /** + * Sets (increases) skill of the [Player] + * + * @param uint16 id + * @param uint16 step + * @param uint16 currVal + * @param uint16 maxVal + */ + int SetSkill(lua_State* L, Player* player) + { + uint16 id = Eluna::CHECKVAL(L, 2); + uint16 step = Eluna::CHECKVAL(L, 3); + uint16 currVal = Eluna::CHECKVAL(L, 4); + uint16 maxVal = Eluna::CHECKVAL(L, 5); + +#ifdef TRINITY + player->SetSkill(id, step, currVal, maxVal); +#else + player->SetSkill(id, currVal, maxVal, step); +#endif + return 0; + } + + /** + * Sets the [Player]s guild rank to the rank specified + * + * @param uint8 rank + */ + int SetGuildRank(lua_State* L, Player* player) // TODO: Move to Guild Methods + { + uint8 rank = Eluna::CHECKVAL(L, 2); + + if (!player->GetGuildId()) + return 0; + + player->SetRank(rank); + return 0; + } + + /** + * Sets the [Player]s free talent points to the amount specified for the current spec + * + * @param uint32 talentPointAmt + */ + int SetFreeTalentPoints(lua_State* L, Player* player) + { + uint32 points = Eluna::CHECKVAL(L, 2); + + player->SetFreeTalentPoints(points); +#if (!defined(TBC) && !defined(CLASSIC)) + player->SendTalentsInfoData(false); +#endif + return 0; + } + + /** + * Sets the [Player]s reputation amount for the faction specified + * + * @param uint32 factionId + * @param int32 reputationValue + */ + int SetReputation(lua_State* L, Player* player) + { + uint32 faction = Eluna::CHECKVAL(L, 2); + int32 value = Eluna::CHECKVAL(L, 3); + FactionEntry const* factionEntry = sObjectMgr.GetFactionEntry(faction); + player->GetReputationMgr().SetReputation(factionEntry, value); + return 0; + } + + /** + * Sets [Quest] state + * + * @param uint32 entry : entry of a quest + * @param uint32 status + */ + int SetQuestStatus(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + uint32 status = Eluna::CHECKVAL(L, 3); + if (status >= MAX_QUEST_STATUS) + return 0; + + player->SetQuestStatus(entry, (QuestStatus)status); + return 0; + } + + /** + * Sets the [Player]s rest bonus to the amount specified + * + * @param float restBonus + */ + int SetRestBonus(lua_State* L, Player* player) + { + float bonus = Eluna::CHECKVAL(L, 2); + + player->SetRestBonus(bonus); + return 0; + } + + /** + * Toggles whether the [Player] accepts whispers or not + * + * @param bool acceptWhispers = true + */ + int SetAcceptWhispers(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetAcceptWhispers(on); + return 0; + } + + /** + * Toggles PvP Death + * + * @param bool on = true + */ + int SetPvPDeath(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetPvPDeath(on); + return 0; + } + + /** + * Toggles whether the [Player] has GM visibility on or off + * + * @param bool gmVisible = true + */ + int SetGMVisible(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetGMVisible(on); + return 0; + } + + /** + * Toggles whether the [Player] has taxi cheat enabled or not + * + * @param bool taxiCheat = true + */ + int SetTaxiCheat(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetTaxiCheater(on); + return 0; + } + + /** + * Toggle Blizz (GM) tag + * + * @param bool on = true + */ + int SetGMChat(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetGMChat(on); + return 0; + } + + /** + * Toggles the [Player]s GM mode on or off + * + * @param bool setGmMode = true + */ + int SetGameMaster(lua_State* L, Player* player) + { + bool on = Eluna::CHECKVAL(L, 2, true); + + player->SetGameMaster(on); + return 0; + } + + /** + * Sets the [Player]s gender to gender specified + * + * - GENDER_MALE = 0 + * - GENDER_FEMALE = 1 + * + * @param [Gender] gender + */ + int SetGender(lua_State* L, Player* player) + { + uint32 _gender = Eluna::CHECKVAL(L, 2); + + Gender gender; + switch (_gender) + { + case 0: + gender = GENDER_MALE; + break; + case 1: + gender = GENDER_FEMALE; + break; + default: + return luaL_argerror(L, 2, "valid Gender expected"); + } + + player->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender); + player->SetByteValue(PLAYER_BYTES_3, 0, gender); + player->InitPlayerDisplayIds(); + return 0; + } + +#if defined(TBC) || defined(WOTLK) + /** + * Sets the [Player]s Arena Points to the amount specified + * + * @param uint32 arenaPoints + */ + int SetArenaPoints(lua_State* L, Player* player) + { + uint32 arenaP = Eluna::CHECKVAL(L, 2); + player->SetArenaPoints(arenaP); + return 0; + } + + /** + * Sets the [Player]s Honor Points to the amount specified + * + * @param uint32 honorPoints + */ + int SetHonorPoints(lua_State* L, Player* player) + { + uint32 honorP = Eluna::CHECKVAL(L, 2); + player->SetHonorPoints(honorP); + return 0; + } +#endif + +#ifdef CLASSIC + /** + * Sets kills + * + * @param uint32 kills + * @param bool honorable = true : if victims were honorable + */ + int SetHonorStoredKills(lua_State* L, Player* player) + { + uint32 kills = Eluna::CHECKVAL(L, 2); + bool honorable = Eluna::CHECKVAL(L, 3, true); + + if (honorable) + { + player->GetHonorMgr().SetStoredHK(kills); + } + else + { + player->GetHonorMgr().SetStoredDK(kills); + } + return 0; + } + + /** + * Sets rank points + * + * @param float rankPoints + */ + int SetRankPoints(lua_State* L, Player* player) + { + float rankPoints = Eluna::CHECKVAL(L, 2); + + player->GetHonorMgr().SetRankPoints(rankPoints); + return 0; + } + + /** + * Sets last week's honor standing position + * + * @param int32 standingPos + */ + int SetHonorLastWeekStandingPos(lua_State* L, Player* player) + { + int32 standingPos = Eluna::CHECKVAL(L, 2); + + player->GetHonorMgr().SetStanding(standingPos); // Not sure if this is correct, not mentioned explicitly as week-based. + return 0; + } +#endif + + /** + * Sets the [Player]s amount of Lifetime Honorable Kills to the value specified + * + * @param uint32 honorableKills + */ + int SetLifetimeKills(lua_State* L, Player* player) + { + uint32 val = Eluna::CHECKVAL(L, 2); + player->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, val); + return 0; + } + + /** + * Sets the [Player]s amount of money to copper specified + * + * @param uint32 copperAmt + */ + int SetCoinage(lua_State* L, Player* player) + { + uint32 amt = Eluna::CHECKVAL(L, 2); + player->SetMoney(amt); + return 0; + } + + /** + * Sets the [Player]s home location to the location specified + * + * @param float x : X Coordinate + * @param float y : Y Coordinate + * @param float z : Z Coordinate + * @param uint32 mapId : Map ID + * @param uint32 areaId : Area ID + */ + int SetBindPoint(lua_State* L, Player* player) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + uint32 mapId = Eluna::CHECKVAL(L, 5); + uint32 areaId = Eluna::CHECKVAL(L, 6); + + WorldLocation loc(mapId, x, y, z); +#if defined TRINITY || AZEROTHCORE + player->SetHomebind(loc, areaId); +#else + player->SetHomebindToLocation(loc, areaId); +#endif + return 0; + } + +#ifndef CLASSIC + /** + * Adds the specified title to the [Player]s list of known titles + * + * @param uint32 titleId + */ + int SetKnownTitle(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + CharTitlesEntry const* t = sCharTitlesStore.LookupEntry(id); + if (t) + player->SetTitle(t, false); + return 0; + } + + +#if defined(TRINITY) || defined(AZEROTHCORE) + /** + * Adds the specified achievement to the [Player]s + * + * @param uint32 achievementid + */ + int SetAchievement(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + AchievementEntry const* t = sAchievementStore.LookupEntry(id); + if (t) + player->CompletedAchievement(t); + return 0; + } +#endif + +#endif + +#if !defined TRINITY && !AZEROTHCORE + /** + * Toggle the [Player]s FFA flag + * + * @param bool applyFFA = true + */ + int SetFFA(lua_State* L, Player* player) + { + bool apply = Eluna::CHECKVAL(L, 2, true); +#ifdef CMANGOS + player->SetPvPFreeForAll(apply); +#else + player->SetFFAPvP(apply); +#endif + return 0; + } +#endif + + /*int SetMovement(lua_State* L, Player* player) + { + int32 pType = Eluna::CHECKVAL(L, 2); + + player->SetMovement((PlayerMovementType)pType); + return 0; + }*/ + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Resets the [Player]s pets talent points + */ + int ResetPetTalents(lua_State* /*L*/, Player* player) + { +#ifndef TRINITY + Pet* pet = player->GetPet(); + Pet::resetTalentsForAllPetsOf(player, pet); + if (pet) + player->SendTalentsInfoData(true); +#else + player->ResetPetTalents(); + player->SendTalentsInfoData(true); +#endif + return 0; + } + + /** + * Reset the [Player]s completed achievements + */ + int ResetAchievements(lua_State* /*L*/, Player* player) + { +#if defined TRINITY || AZEROTHCORE + player->ResetAchievements(); +#else + player->GetAchievementMgr().Reset(); +#endif + return 0; + } +#endif + + /** + * Shows the mailbox window to the player from specified guid. + * + * @param ObjectGuid guid = playerguid : guid of the mailbox window sender + */ + int SendShowMailBox(lua_State* L, Player* player) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2, player->GET_GUID()); + +#if (defined(CLASSIC) || defined(TBC)) + WorldPacket data(CMSG_GET_MAIL_LIST, 8); + data << guid; + player->GetSession()->HandleGetMailList(data); +#else + player->GetSession()->SendShowMailBox(guid); +#endif + return 0; + } + +#if defined(TBC) || defined(WOTLK) + /** + * Adds or detracts from the [Player]s current Arena Points + * + * @param int32 amount + */ + int ModifyArenaPoints(lua_State* L, Player* player) + { + int32 amount = Eluna::CHECKVAL(L, 2); + + player->ModifyArenaPoints(amount); + return 0; + } + + /** + * Adds or detracts from the [Player]s current Honor Points + * + * @param int32 amount + */ + int ModifyHonorPoints(lua_State* L, Player* player) + { + int32 amount = Eluna::CHECKVAL(L, 2); + + player->ModifyHonorPoints(amount); + return 0; + } +#endif + + /** + * Saves the [Player] to the database + */ + int SaveToDB(lua_State* /*L*/, Player* player) + { +#ifndef AZEROTHCORE + player->SaveToDB(); +#else + player->SaveToDB(false, false); +#endif + return 0; + } + + /** + * Sends a summon request to the player from the given summoner + * + * @param [Unit] summoner + */ + int SummonPlayer(lua_State* L, Player* player) + { + Unit* summoner = Eluna::CHECKOBJ(L, 2); + +#ifdef TRINITY + player->SendSummonRequestFrom(summoner); +#else + float x, y, z; + summoner->GetPosition(x,y,z); +#ifndef CMANGOS + player->SetSummonPoint(summoner->GetMapId(), x, y, z); +#else + player->SetSummonPoint(summoner->GetMapId(), x, y, z, summoner->GetMasterGuid()); +#endif + + WorldPacket data(SMSG_SUMMON_REQUEST, 8 + 4 + 4); + data << summoner->GET_GUID(); + data << uint32(summoner->GetZoneId()); + data << uint32(MAX_PLAYER_SUMMON_DELAY * IN_MILLISECONDS); +#ifdef CMANGOS + player->GetSession()->SendPacket(data); +#else + player->GetSession()->SendPacket(&data); +#endif +#endif + return 0; + } + + /** + * Mutes the [Player] for the amount of seconds specified + * + * @param uint32 muteTime + */ + int Mute(lua_State* L, Player* player) + { + uint32 muteseconds = Eluna::CHECKVAL(L, 2); + /*const char* reason = luaL_checkstring(E, 2);*/ // Mangos does not have a reason field in database. + + time_t muteTime = time(NULL) + muteseconds; + player->GetSession()->m_muteTime = muteTime; + std::ostringstream oss; + oss << "UPDATE account SET mutetime = " << muteTime << " WHERE id = " << player->GetSession()->GetAccountId(); + LoginDatabase.PExecute("%s", oss.str().c_str()); + return 0; + } + + /** + * Rewards the given quest entry for the [Player] if he has completed it. + * + * @param uint32 entry : quest entry + */ + int RewardQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* quest = eObjectMgr->GetQuestTemplate(entry); + + // If player doesn't have the quest + if (!quest || player->GetQuestStatus(entry) != QUEST_STATUS_COMPLETE) + return 0; + + player->RewardQuest(quest, 0, player); + return 0; + } + + /** + * Sends an auction house window to the [Player] from the [Unit] specified + * + * @param [Unit] sender + */ + int SendAuctionMenu(lua_State* L, Player* player) + { + Unit* unit = Eluna::CHECKOBJ(L, 2); + +#if defined(TRINITY) || defined(AZEROTHCORE) + AuctionHouseEntry const* ahEntry = AuctionHouseMgr::GetAuctionHouseEntry(unit->GetFaction()); +#else + AuctionHouseEntry const* ahEntry = AuctionHouseMgr::GetAuctionHouseEntry(unit); +#endif + if (!ahEntry) + return 0; + + WorldPacket data(MSG_AUCTION_HELLO, 12); + data << unit->GET_GUID(); +#ifdef TRINITY + data << uint32(ahEntry->ID); +#else + data << uint32(ahEntry->houseId); +#endif + data << uint8(1); +#ifdef CMANGOS + player->GetSession()->SendPacket(data); +#else + player->GetSession()->SendPacket(&data); +#endif + return 0; + } + + /** + * Sends a flightmaster window to the [Player] from the [Creature] specified + * + * @param [Creature] sender + */ + int SendTaxiMenu(lua_State* L, Player* player) + { + Creature* creature = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendTaxiMenu(creature); + return 0; + } + + /** + * Sends a spirit resurrection request to the [Player] + */ + int SendSpiritResurrect(lua_State* /*L*/, Player* player) + { + player->GetSession()->SendSpiritResurrect(); + return 0; + } + + /** + * Sends a tabard vendor window to the [Player] from the [WorldObject] specified + * + * @param [WorldObject] sender + */ + int SendTabardVendorActivate(lua_State* L, Player* player) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendTabardVendorActivate(obj->GET_GUID()); + return 0; + } + + /** + * Sends a bank window to the [Player] from the [WorldObject] specified. + * + * @param [WorldObject] sender + */ + int SendShowBank(lua_State* L, Player* player) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendShowBank(obj->GET_GUID()); + return 0; + } + + /** + * Sends a vendor window to the [Player] from the [WorldObject] specified. + * + * @param [WorldObject] sender + */ + int SendListInventory(lua_State* L, Player* player) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + + player->GetSession()->SendListInventory(obj->GET_GUID()); + return 0; + } + + /** + * Sends a trainer window to the [Player] from the [Creature] specified + * + * @param [Creature] sender + */ + int SendTrainerList(lua_State* L, Player* player) + { + Creature* obj = Eluna::CHECKOBJ(L, 2); + +#ifdef TRINITY + player->GetSession()->SendTrainerList(obj); +#else + player->GetSession()->SendTrainerList(obj->GET_GUID()); +#endif + return 0; + } + + /** + * Sends a guild invitation from the [Player]s [Guild] to the [Player] object specified + * + * @param [Player] invitee + */ + int SendGuildInvite(lua_State* L, Player* player) + { + Player* plr = Eluna::CHECKOBJ(L, 2); + +#if defined TRINITY || AZEROTHCORE + if (Guild* guild = player->GetGuild()) + guild->HandleInviteMember(player->GetSession(), plr->GetName()); +#else + player->GetSession()->SendGuildInvite(plr); +#endif + return 0; + } + + /** + * Sends an update for the world state to the [Player] + * + * @param uint32 field + * @param uint32 value + */ + int SendUpdateWorldState(lua_State* L, Player* player) + { + uint32 field = Eluna::CHECKVAL(L, 2); + uint32 value = Eluna::CHECKVAL(L, 3); + + player->SendUpdateWorldState(field, value); + return 0; + } + + /** + * Forces the [Player] to log out + * + * @param bool saveToDb = true + */ + int LogoutPlayer(lua_State* L, Player* player) + { + bool save = Eluna::CHECKVAL(L, 2, true); +#ifndef CMANGOS + player->GetSession()->LogoutPlayer(save); +#else + player->GetSession()->LogoutPlayer(); +#endif + return 0; + } + + /** + * Forcefully removes the [Player] from a [BattleGround] raid group + */ + int RemoveFromBattlegroundRaid(lua_State* /*L*/, Player* player) + { +#if defined TRINITY || AZEROTHCORE + player->RemoveFromBattlegroundOrBattlefieldRaid(); +#else + player->RemoveFromBattleGroundRaid(); +#endif + return 0; + } + + /** + * Unbinds the [Player] from his instances except the one he currently is in. + * + * Difficulty is not used on classic. + * + * @param uint32 map = true + * @param uint32 difficulty = 0 + */ + int UnbindInstance(lua_State* L, Player* player) + { + uint32 map = Eluna::CHECKVAL(L, 2); +#ifndef CLASSIC + uint32 difficulty = Eluna::CHECKVAL(L, 3, 0); + + if (difficulty < MAX_DIFFICULTY) +#ifndef AZEROTHCORE + player->UnbindInstance(map, (Difficulty)difficulty); +#else + sInstanceSaveMgr->PlayerUnbindInstance(player->GetGUID(), map, Difficulty(difficulty), true, player); +#endif//AZEROTHCORE +#else//CLASSIC + player->UnbindInstance(map); +#endif + return 0; + } + + /** + * Unbinds the [Player] from his instances except the one he currently is in. + */ + int UnbindAllInstances(lua_State* /*L*/, Player* player) + { +#ifdef CLASSIC + Player::BoundInstancesMap& binds = player->GetBoundInstances(); + for (Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) + { + if (itr->first != player->GetMapId()) + player->UnbindInstance(itr); + else + ++itr; + } +#elif defined AZEROTHCORE + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + const BoundInstancesMap& binds = sInstanceSaveMgr->PlayerGetBoundInstances(player->GetGUID(), Difficulty(i)); + for (BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end();) + { + if (itr->first != player->GetMapId()) + { + sInstanceSaveMgr->PlayerUnbindInstance(player->GetGUID(), itr->first, Difficulty(i), true, player); + itr = binds.begin(); + } + else + { + ++itr; + } + } + } +#else + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Player::BoundInstancesMap& binds = player->GetBoundInstances(Difficulty(i)); + for (Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) + { + if (itr->first != player->GetMapId()) + player->UnbindInstance(itr, Difficulty(i)); + else + ++itr; + } + } +#endif + return 0; + } + + /** + * Forces the [Player] to leave a [BattleGround] + * + * @param bool teleToEntry = true + */ + int LeaveBattleground(lua_State* L, Player* player) + { + (void)L; // ensure that the variable is referenced in order to pass compiler checks +#ifndef AZEROTHCORE + bool teleToEntryPoint = Eluna::CHECKVAL(L, 2, true); + player->LeaveBattleground(teleToEntryPoint); +#else + player->LeaveBattleground(); +#endif + return 0; + } + + /** + * Repairs [Item] at specified position. + * + * @param uint16 position + * @param bool cost = true + * @param float discountMod = 1.0 + */ + int DurabilityRepair(lua_State* L, Player* player) + { + uint16 position = Eluna::CHECKVAL(L, 2); + bool takeCost = Eluna::CHECKVAL(L, 3, true); + float discountMod = Eluna::CHECKVAL(L, 4, 1.0f); + +#ifdef CLASSIC + player->DurabilityRepair(position, takeCost, discountMod); +#elif defined(TRINITY) + player->DurabilityRepair(position, takeCost, discountMod); +#else + player->DurabilityRepair(position, takeCost, discountMod, false); +#endif + return 0; + } + + /** + * Repairs all [Item]s. + * + * @param bool takeCost = true + * @param float discountMod = 1.0 + * @param bool guidBank = false + */ + int DurabilityRepairAll(lua_State* L, Player* player) + { + bool takeCost = Eluna::CHECKVAL(L, 2, true); + float discountMod = Eluna::CHECKVAL(L, 3, 1.0f); + bool guildBank = Eluna::CHECKVAL(L, 4, false); + +#ifdef CLASSIC + player->DurabilityRepairAll(takeCost, discountMod); +#else + player->DurabilityRepairAll(takeCost, discountMod, guildBank); +#endif + return 0; + } + + /** + * Sets durability loss for an [Item] in the specified slot + * + * @param int32 slot + */ + int DurabilityPointLossForEquipSlot(lua_State* L, Player* player) + { + int32 slot = Eluna::CHECKVAL(L, 2); + + if (slot >= EQUIPMENT_SLOT_START && slot < EQUIPMENT_SLOT_END) + player->DurabilityPointLossForEquipSlot((EquipmentSlots)slot); + return 0; + } + + /** + * Sets durability loss on all [Item]s equipped + * + * If inventory is true, sets durability loss for [Item]s in bags + * + * @param int32 points + * @param bool inventory = true + */ + int DurabilityPointsLossAll(lua_State* L, Player* player) + { + int32 points = Eluna::CHECKVAL(L, 2); + bool inventory = Eluna::CHECKVAL(L, 3, true); + + player->DurabilityPointsLossAll(points, inventory); + return 0; + } + + /** + * Sets durability loss for the specified [Item] + * + * @param [Item] item + * @param int32 points + */ + int DurabilityPointsLoss(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2); + int32 points = Eluna::CHECKVAL(L, 3); + + player->DurabilityPointsLoss(item, points); + return 0; + } + + /** + * Damages specified [Item] + * + * @param [Item] item + * @param double percent + */ + int DurabilityLoss(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2); + double percent = Eluna::CHECKVAL(L, 3); + + player->DurabilityLoss(item, percent); + return 0; + } + + /** + * Damages all [Item]s equipped. If inventory is true, damages [Item]s in bags + * + * @param double percent + * @param bool inventory = true + */ + int DurabilityLossAll(lua_State* L, Player* player) + { + double percent = Eluna::CHECKVAL(L, 2); + bool inventory = Eluna::CHECKVAL(L, 3, true); + + player->DurabilityLossAll(percent, inventory); + return 0; + } + + /** + * Kills the [Player] + */ + int KillPlayer(lua_State* /*L*/, Player* player) + { + player->KillPlayer(); + return 0; + } + + /** + * Forces the [Player] to leave a [Group] + */ + int RemoveFromGroup(lua_State* /*L*/, Player* player) + { + if (!player->GetGroup()) + return 0; + + player->RemoveFromGroup(); + return 0; + } + + /** + * Returns the [Player]s accumulated talent reset cost + * + * @return uint32 resetCost + */ + int ResetTalentsCost(lua_State* L, Player* player) + { + Eluna::Push(L, player->GetResetTalentsCost()); + return 1; + } + + /** + * Resets the [Player]s talents + * + * @param bool noCost = true + */ + int ResetTalents(lua_State* L, Player* player) + { + bool no_cost = Eluna::CHECKVAL(L, 2, true); + player->ResetTalents(no_cost); + + return 0; + } + + /** + * Removes the [Spell] from the [Player] + * + * @param uint32 entry : entry of a [Spell] + */ + int RemoveSpell(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + player->RemoveSpell(entry); + + return 0; + } + + /** + * Clears the [Player]s combo points + */ + int ClearComboPoints(lua_State* /*L*/, Player* player) + { + player->ClearComboPoints(); + return 0; + } + + /** + * Adds combo points to the [Player] + * + * @param [Unit] target + * @param int8 count + */ + int AddComboPoints(lua_State* L, Player* player) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + int8 count = Eluna::CHECKVAL(L, 3); + + player->AddComboPoints(target, count); + return 0; + } + + /** + * Gives [Quest] monster talked to credit + * + * @param uint32 entry : entry of a [Creature] + * @param [Creature] creature + */ + int TalkedToCreature(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + Creature* creature = Eluna::CHECKOBJ(L, 3); + + player->TalkedToCreature(entry, creature->GET_GUID()); + return 0; + } + + /** + * Gives [Quest] monster killed credit + * + * @param uint32 entry : entry of a [Creature] + */ + int KilledMonsterCredit(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->KilledMonsterCredit(entry, player->GET_GUID()); + return 0; + } + + /** + * Completes a [Quest] if in a [Group] + * + * @param uint32 quest : entry of a quest + * @param [WorldObject] obj + */ + int GroupEventHappens(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + WorldObject* obj = Eluna::CHECKOBJ(L, 3); + + player->GroupEventHappens(questId, obj); + return 0; + } + + /** + * Completes the [Quest] if a [Quest] area is explored, or completes the [Quest] + * + * @param uint32 quest : entry of a [Quest] + */ + int AreaExploredOrEventHappens(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + + player->AreaExploredOrEventHappens(questId); + return 0; + } + + /** + * Sets the given [Quest] entry failed for the [Player]. + * + * @param uint32 entry : entry of a [Quest] + */ + int FailQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->FailQuest(entry); + return 0; + } + + /** + * Sets the given quest entry incomplete for the [Player]. + * + * @param uint32 entry : quest entry + */ + int IncompleteQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->IncompleteQuest(entry); + return 0; + } + + /** + * Completes the given quest entry for the [Player] and tries to satisfy all quest requirements. + * + * The player should have the quest to complete it. + * + * @param uint32 entry : quest entry + */ + int CompleteQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* quest = eObjectMgr->GetQuestTemplate(entry); + + // If player doesn't have the quest + if (!quest || player->GetQuestStatus(entry) == QUEST_STATUS_NONE) + return 0; + + // Add quest items for quests that require items + for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x) + { +#if defined TRINITY || AZEROTHCORE + uint32 id = quest->RequiredItemId[x]; + uint32 count = quest->RequiredItemCount[x]; +#else + uint32 id = quest->ReqItemId[x]; + uint32 count = quest->ReqItemCount[x]; +#endif + + if (!id || !count) + continue; + + uint32 curItemCount = player->GetItemCount(id, true); + + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count - curItemCount); + if (msg == EQUIP_ERR_OK) + { + Item* item = player->StoreNewItem(dest, id, true); + player->SendNewItem(item, count - curItemCount, true, false); + } + } + + // All creature/GO slain/cast (not required, but otherwise it will display "Creature slain 0/10") + for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) + { +#if defined TRINITY || AZEROTHCORE + int32 creature = quest->RequiredNpcOrGo[i]; + uint32 creatureCount = quest->RequiredNpcOrGoCount[i]; + + if (creature > 0) + { + if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creature)) + for (uint16 z = 0; z < creatureCount; ++z) + player->KilledMonster(creatureInfo, ObjectGuid::Empty); + } + else if (creature < 0) + for (uint16 z = 0; z < creatureCount; ++z) + player->KillCreditGO(creature); +#else + int32 creature = quest->ReqCreatureOrGOId[i]; + uint32 creaturecount = quest->ReqCreatureOrGOCount[i]; + + if (uint32 spell_id = quest->ReqSpell[i]) + { + for (uint16 z = 0; z < creaturecount; ++z) + player->CastedCreatureOrGO(creature, ObjectGuid(), spell_id); + } + else if (creature > 0) + { + if (CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(creature)) + for (uint16 z = 0; z < creaturecount; ++z) +#ifndef CMANGOS + player->KilledMonster(cInfo, ObjectGuid()); +#else + player->KilledMonster(cInfo, nullptr); +#endif + } + else if (creature < 0) + { + for (uint16 z = 0; z < creaturecount; ++z) + player->CastedCreatureOrGO(-creature, ObjectGuid(), 0); + } +#endif + } + + + // If the quest requires reputation to complete + if (uint32 repFaction = quest->GetRepObjectiveFaction()) + { + uint32 repValue = quest->GetRepObjectiveValue(); + uint32 curRep = player->GetReputationMgr().GetReputation(repFaction); + if (curRep < repValue) + if (FactionEntry const* factionEntry = sObjectMgr.GetFactionEntry(repFaction)) + player->GetReputationMgr().SetReputation(factionEntry, repValue); + } + +#if defined TRINITY || AZEROTHCORE + // If the quest requires a SECOND reputation to complete + if (uint32 repFaction = quest->GetRepObjectiveFaction2()) + { + uint32 repValue2 = quest->GetRepObjectiveValue2(); + uint32 curRep = player->GetReputationMgr().GetReputation(repFaction); + if (curRep < repValue2) + if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(repFaction)) + player->GetReputationMgr().SetReputation(factionEntry, repValue2); + } +#endif + + // If the quest requires money + int32 ReqOrRewMoney = quest->GetRewOrReqMoney(); + if (ReqOrRewMoney < 0) + player->ModifyMoney(-ReqOrRewMoney); + +#ifdef TRINITY + if (sWorld->getBoolConfig(CONFIG_QUEST_ENABLE_QUEST_TRACKER)) // check if Quest Tracker is enabled + { + // prepare Quest Tracker datas + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_QUEST_TRACK_GM_COMPLETE); + stmt->setUInt32(0, quest->GetQuestId()); + stmt->setUInt32(1, player->GetGUID().GetCounter()); + + // add to Quest Tracker + CharacterDatabase.Execute(stmt); + } +#endif + + player->CompleteQuest(entry); + return 0; + } + + /** + * Tries to add the given quest entry for the [Player]. + * + * @param uint32 entry : quest entry + */ + int AddQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* quest = eObjectMgr->GetQuestTemplate(entry); + + if (!quest) + return 0; + + // check item starting quest (it can work incorrectly if added without item in inventory) + for (const auto& item : sObjectMgr.GetItemPrototypeMap()) + { + uint32 i = item.first; + ItemPrototype const* pProto = &item.second; + if (!pProto) + continue; + + if (pProto->StartQuest == entry) + return 0; + } + + // ok, normal (creature/GO starting) quest + if (player->CanAddQuest(quest, true)) + { + player->AddQuest(quest, NULL); + + if (player->CanCompleteQuest(entry)) + player->CompleteQuest(entry); + } + + return 0; + } + + /** + * Removes the given quest entry from the [Player]. + * + * @param uint32 entry : quest entry + */ + int RemoveQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + Quest const* quest = eObjectMgr->GetQuestTemplate(entry); + + if (!quest) + return 0; + + player->RemoveQuest(entry); + + // set quest status to not started (will updated in DB at next save) + player->SetQuestStatus(entry, QUEST_STATUS_NONE); + + // reset rewarded for restart repeatable quest + player->getQuestStatusMap()[entry].m_rewarded = false; + return 0; + } + + /** + * Sends whisper text from the [Player] + * + * @param string text + * @param uint32 lang : language the [Player] will speak + * @param [Player] receiver : is the [Player] that will receive the whisper, if TrinityCore + * @param ObjectGuid guid : is the GUID of a [Player] that will receive the whisper, not TrinityCore + */ + int Whisper(lua_State* L, Player* player) + { + std::string text = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); +#ifdef TRINITY + Player* receiver = Eluna::CHECKOBJ(L, 4); +#else + ObjectGuid guid = Eluna::CHECKVAL(L, 4); +#endif +#if defined(TRINITY) || defined(AZEROTHCORE) + player->Whisper(text, (Language)lang, receiver); +#else + player->Whisper(text, lang, guid); +#endif + return 0; + } + + /** + * Sends a text emote from the [Player] + * + * @param string emoteText + */ + int TextEmote(lua_State* L, Player* player) + { + std::string text = Eluna::CHECKVAL(L, 2); + + player->TextEmote(text.c_str()); + return 0; + } + + /** + * Sends yell text from the [Player] + * + * @param string text : text for the [Player] to yells + * @param uint32 lang : language the [Player] will speak + */ + int Yell(lua_State* L, Player* player) + { + std::string text = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); +#if defined(TRINITY) || defined(AZEROTHCORE) + player->Yell(text, (Language)lang); +#else + player->Yell(text.c_str(), lang); +#endif + return 0; + } + + /** + * Sends say text from the [Player] + * + * @param string text : text for the [Player] to say + * @param uint32 lang : language the [Player] will speak + */ + int Say(lua_State* L, Player* player) + { + std::string text = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); +#if defined(TRINITY) || defined(AZEROTHCORE) + player->Say(text, (Language)lang); +#else + player->Say(text.c_str(), lang); +#endif + return 0; + } + + /** + * Gives the [Player] experience + * + * @param uint32 xp : experience to give + * @param [Unit] victim = nil + */ + int GiveXP(lua_State* L, Player* player) + { + uint32 xp = Eluna::CHECKVAL(L, 2); + Unit* victim = Eluna::CHECKOBJ(L, 3, false); + +#ifndef CMANGOS + player->GiveXP(xp, victim); +#else + player->GiveXP(xp, nullptr); +#endif + return 0; + } + + /** + * Toggle the [Player]s 'Do Not Disturb' flag + */ + int ToggleDND(lua_State* /*L*/, Player* player) + { + player->ToggleDND(); + return 0; + } + + /** + * Toggle the [Player]s 'Away From Keyboard' flag + */ + int ToggleAFK(lua_State* /*L*/, Player* player) + { + player->ToggleAFK(); + return 0; + } + + /** + * Equips the given item or item entry to the given slot. Returns the equipped item or nil. + * + * enum EquipmentSlots // 19 slots + * { + * EQUIPMENT_SLOT_START = 0, + * EQUIPMENT_SLOT_HEAD = 0, + * EQUIPMENT_SLOT_NECK = 1, + * EQUIPMENT_SLOT_SHOULDERS = 2, + * EQUIPMENT_SLOT_BODY = 3, + * EQUIPMENT_SLOT_CHEST = 4, + * EQUIPMENT_SLOT_WAIST = 5, + * EQUIPMENT_SLOT_LEGS = 6, + * EQUIPMENT_SLOT_FEET = 7, + * EQUIPMENT_SLOT_WRISTS = 8, + * EQUIPMENT_SLOT_HANDS = 9, + * EQUIPMENT_SLOT_FINGER1 = 10, + * EQUIPMENT_SLOT_FINGER2 = 11, + * EQUIPMENT_SLOT_TRINKET1 = 12, + * EQUIPMENT_SLOT_TRINKET2 = 13, + * EQUIPMENT_SLOT_BACK = 14, + * EQUIPMENT_SLOT_MAINHAND = 15, + * EQUIPMENT_SLOT_OFFHAND = 16, + * EQUIPMENT_SLOT_RANGED = 17, + * EQUIPMENT_SLOT_TABARD = 18, + * EQUIPMENT_SLOT_END = 19 + * }; + * + * enum InventorySlots // 4 slots + * { + * INVENTORY_SLOT_BAG_START = 19, + * INVENTORY_SLOT_BAG_END = 23 + * }; + * + * @proto equippedItem = (item, slot) + * @proto equippedItem = (entry, slot) + * @param [Item] item : item to equip + * @param uint32 entry : entry of the item to equip + * @param uint32 slot : equipment slot to equip the item to The slot can be [EquipmentSlots] or [InventorySlots] + * @return [Item] equippedItem : item or nil if equipping failed + */ + int EquipItem(lua_State* L, Player* player) + { + uint16 dest = 0; + Item* item = Eluna::CHECKOBJ(L, 2, false); + uint32 slot = Eluna::CHECKVAL(L, 3); + + if (slot >= INVENTORY_SLOT_BAG_END) + return 1; + + if (!item) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + item = Item::CreateItem(entry, 1, player->GetObjectGuid()); + if (!item) + return 1; + + InventoryResult result = player->CanEquipItem(slot, dest, item, false); + if (result != EQUIP_ERR_OK) + { + delete item; + return 1; + } + player->ItemAddedQuestCheck(entry, 1); +#if (!defined(TBC) && !defined(CLASSIC)) + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, entry, 1); +#endif + } + else + { + InventoryResult result = player->CanEquipItem(slot, dest, item, false); + if (result != EQUIP_ERR_OK) + return 1; + player->RemoveItem(item->GetBagSlot(), item->GetSlot(), true); + } + + Eluna::Push(L, player->EquipItem(dest, item, true)); + player->AutoUnequipOffhandIfNeed(); + return 1; + } + + /** + * Returns true if the player can equip the given [Item] or item entry to the given slot, false otherwise. + * + * @proto canEquip = (item, slot) + * @proto canEquip = (entry, slot) + * @param [Item] item : item to equip + * @param uint32 entry : entry of the item to equip + * @param uint32 slot : equipment slot to test + * @return bool canEquip + */ + int CanEquipItem(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2, false); + uint32 slot = Eluna::CHECKVAL(L, 3); + if (slot >= EQUIPMENT_SLOT_END) + { + Eluna::Push(L, false); + return 1; + } + + if (!item) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + uint16 dest; + InventoryResult msg = player->CanEquipNewItem(slot, dest, entry, false); + if (msg != EQUIP_ERR_OK) + { + Eluna::Push(L, false); + return 1; + } + } + else + { + uint16 dest; + InventoryResult msg = player->CanEquipItem(slot, dest, item, false); + if (msg != EQUIP_ERR_OK) + { + Eluna::Push(L, false); + return 1; + } + } + Eluna::Push(L, true); + return 1; + } + +#ifndef CLASSIC + /** + * Removes a title by ID from the [Player]s list of known titles + * + * @param uint32 titleId + */ + int UnsetKnownTitle(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + CharTitlesEntry const* t = sCharTitlesStore.LookupEntry(id); + if (t) + player->SetTitle(t, true); + return 0; + } +#endif + + /** + * Advances all of the [Player]s weapon skills to the maximum amount available + */ + int AdvanceSkillsToMax(lua_State* /*L*/, Player* player) + { +#ifdef TRINITY + player->UpdateWeaponsSkillsToMaxSkillsForLevel(); +#else + player->UpdateSkillsToMaxSkillsForLevel(); +#endif + return 0; + } + + /** + * Advances all of the [Player]s skills to the amount specified + * + * @param uint32 skillStep + */ + int AdvanceAllSkills(lua_State* L, Player* player) + { + uint32 step = Eluna::CHECKVAL(L, 2); + + if (!step) + return 0; + + for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i) + { + if (SkillLineEntry const* entry = sSkillLineStore.LookupEntry(i)) + { +#ifdef TRINITY + if (entry->CategoryID == SKILL_CATEGORY_LANGUAGES || entry->CategoryID == SKILL_CATEGORY_GENERIC) + continue; + + if (player->HasSkill(entry->ID)) + player->UpdateSkill(entry->ID, step); +#else + if (entry->categoryId == SKILL_CATEGORY_LANGUAGES || entry->categoryId == SKILL_CATEGORY_GENERIC) + continue; + + if (player->HasSkill(entry->id)) + player->UpdateSkill(entry->id, step); +#endif + } + } + + return 0; + } + + /** + * Advances a [Player]s specific skill to the amount specified + * + * @param uint32 skillId + * @param uint32 skillStep + */ + int AdvanceSkill(lua_State* L, Player* player) + { + uint32 _skillId = Eluna::CHECKVAL(L, 2); + uint32 _step = Eluna::CHECKVAL(L, 3); + if (_skillId && _step) + { + if (player->HasSkill(_skillId)) + player->UpdateSkill(_skillId, _step); + } + return 0; + } + + /** + * Teleports a [Player] to the location specified + * + * @param uint32 mappId + * @param float xCoord + * @param float yCoord + * @param float zCoord + * @param float orientation + */ + int Teleport(lua_State* L, Player* player) + { + uint32 mapId = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + if (player->IsTaxiFlying()) + { + player->GetMotionMaster()->MovementExpired(); + player->GetTaxi().ClearTaxiDestinations(); + } + Eluna::Push(L, player->TeleportTo(mapId, x, y, z, o)); + return 1; + } + + int AddLifetimeKills(lua_State* L, Player* player) + { + uint32 val = Eluna::CHECKVAL(L, 2); + uint32 currentKills = player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS); + player->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, currentKills + val); + return 0; + } + + /** + * Adds the given amount of the specified item entry to the player. + * + * @param uint32 entry : entry of the item to add + * @param uint32 itemCount = 1 : amount of the item to add + * @return [Item] item : the item that was added or nil + */ + int AddItem(lua_State* L, Player* player) + { + uint32 itemId = Eluna::CHECKVAL(L, 2); + uint32 itemCount = Eluna::CHECKVAL(L, 3, 1); + +#if defined TRINITY || AZEROTHCORE + uint32 noSpaceForCount = 0; + ItemPosCountVec dest; + InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, itemCount, &noSpaceForCount); + if (msg != EQUIP_ERR_OK) + itemCount -= noSpaceForCount; + + if (itemCount == 0 || dest.empty()) + return 1; +#ifndef AZEROTHCORE + Item* item = player->StoreNewItem(dest, itemId, true, GenerateItemRandomPropertyId(itemId)); +#else + Item* item = player->StoreNewItem(dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId)); +#endif + if (item) + player->SendNewItem(item, itemCount, true, false); + Eluna::Push(L, item); +#else + Eluna::Push(L, player->StoreNewItemInInventorySlot(itemId, itemCount)); +#endif + return 1; + } + + /** + * Removes the given amount of the specified [Item] from the player. + * + * @proto (item, itemCount) + * @proto (entry, itemCount) + * @param [Item] item : item to remove + * @param uint32 entry : entry of the item to remove + * @param uint32 itemCount = 1 : amount of the item to remove + */ + int RemoveItem(lua_State* L, Player* player) + { + Item* item = Eluna::CHECKOBJ(L, 2, false); + uint32 itemCount = Eluna::CHECKVAL(L, 3); + if (!item) + { + uint32 itemId = Eluna::CHECKVAL(L, 2); + player->DestroyItemCount(itemId, itemCount, true); + } + else + { + bool all = itemCount >= item->GetCount(); + player->DestroyItemCount(item, itemCount, true); + if (all) + Eluna::CHECKOBJ(L, 2)->Invalidate(); + } + return 0; + } + + /** + * Removes specified amount of lifetime kills + * + * @param uint32 val : kills to remove + */ + int RemoveLifetimeKills(lua_State* L, Player* player) + { + uint32 val = Eluna::CHECKVAL(L, 2); + uint32 currentKills = player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS); + if (val > currentKills) + val = currentKills; + player->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, currentKills - val); + return 0; + } + + /** + * Resets cooldown of the specified spell + * + * @param uint32 spellId + * @param bool update = true + */ + int ResetSpellCooldown(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + bool update = Eluna::CHECKVAL(L, 3, true); + + SpellEntry const* spellEntry = sSpellMgr.GetSpellEntry(spellId); + player->RemoveSpellCooldown(*spellEntry, update); + return 0; + } + + /** + * Resets cooldown of the specified category + * + * @param uint32 category + * @param bool update = true + */ + int ResetTypeCooldowns(lua_State* L, Player* player) + { + uint32 category = Eluna::CHECKVAL(L, 2); + bool update = Eluna::CHECKVAL(L, 3, true); + (void)update; // ensure that the variable is referenced in order to pass compiler checks + +#ifdef TRINITY + player->GetSpellHistory()->ResetCooldowns([category](SpellHistory::CooldownStorageType::iterator itr) -> bool + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); + return spellInfo && spellInfo->GetCategory() == category; + }, update); +#else +#ifndef AZEROTHCORE + player->RemoveSpellCategoryCooldown(category, update); +#else + player->RemoveCategoryCooldown(category); +#endif +#endif + return 0; + } + + /** + * Resets all of the [Player]'s cooldowns + */ + int ResetAllCooldowns(lua_State* /*L*/, Player* player) + { +#ifdef TRINITY + player->GetSpellHistory()->ResetAllCooldowns(); +#elif CMANGOS + player->RemoveAllCooldowns(); +#else + player->RemoveAllSpellCooldown(); +#endif + return 0; + } + + /** + * Sends a Broadcast Message to the [Player] + * + * @param string message + */ + int SendBroadcastMessage(lua_State* L, Player* player) + { + const char* message = Eluna::CHECKVAL(L, 2); + if (std::string(message).length() > 0) + ChatHandler(player->GetSession()).SendSysMessage(message); + return 0; + } + + /** + * Sends an Area Trigger Message to the [Player] + * + * @param string message + */ + int SendAreaTriggerMessage(lua_State* L, Player* player) + { + std::string msg = Eluna::CHECKVAL(L, 2); + if (msg.length() > 0) + player->GetSession()->SendAreaTriggerMessage("%s", msg.c_str()); + return 0; + } + + /** + * Sends a Notification to the [Player] + * + * @param string message + */ + int SendNotification(lua_State* L, Player* player) + { + std::string msg = Eluna::CHECKVAL(L, 2); + if (msg.length() > 0) + player->GetSession()->SendNotification("%s", msg.c_str()); + return 0; + } + + /** + * Sends a [WorldPacket] to the [Player] + * + * @param [WorldPacket] packet + * @param bool selfOnly = true + */ + int SendPacket(lua_State* L, Player* player) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); + bool selfOnly = Eluna::CHECKVAL(L, 3, true); +#ifdef CMANGOS + if (selfOnly) + player->GetSession()->SendPacket(*data); + else + player->SendMessageToSet(*data, true); +#else + if (selfOnly) + player->GetSession()->SendPacket(data); + else + player->SendMessageToSet(data, true); +#endif + return 0; + } + + /** + * Sends addon message to the [Player] receiver + * + * @param string prefix + * @param string message + * @param [ChatMsg] channel + * @param [Player] receiver + * + */ + int SendAddonMessage(lua_State* L, Player* player) + { + std::string prefix = Eluna::CHECKVAL(L, 2); + std::string message = Eluna::CHECKVAL(L, 3); + uint8 channel = Eluna::CHECKVAL(L, 4); + Player* receiver = Eluna::CHECKOBJ(L, 5); + + std::string fullmsg = prefix + "\t" + message; + + WorldPacket data(SMSG_MESSAGECHAT, 100); + data << uint8(channel); + data << int32(LANG_ADDON); + data << player->GET_GUID(); +#ifndef CLASSIC + data << uint32(0); + data << receiver->GET_GUID(); +#endif + data << uint32(fullmsg.length() + 1); + data << fullmsg; + data << uint8(0); +#ifdef CMANGOS + receiver->GetSession()->SendPacket(data); +#else + receiver->GetSession()->SendPacket(&data); +#endif + return 0; + } + + /** + * Kicks the [Player] from the server + */ + int KickPlayer(lua_State* /*L*/, Player* player) + { +#ifdef TRINITY + player->GetSession()->KickPlayer("PlayerMethods::KickPlayer Kick the player"); +#else + player->GetSession()->KickPlayer(); +#endif + return 0; + } + + /** + * Adds or subtracts from the [Player]s money in copper + * + * @param int32 copperAmt : negative to remove, positive to add + */ + int ModifyMoney(lua_State* L, Player* player) + { + int32 amt = Eluna::CHECKVAL(L, 2); + + player->ModifyMoney(amt); + return 1; + } + + /** + * Teaches the [Player] the [Spell] specified by entry ID + * + * @param uint32 spellId + */ + int LearnSpell(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + + player->LearnSpell(id, false); + return 0; + } + + /** + * Learn the [Player] the talent specified by talent_id and talentRank + * + * @param uint32 talent_id + * @param uint32 talentRank + */ + int LearnTalent(lua_State* L, Player* player) + { + uint32 id = Eluna::CHECKVAL(L, 2); + uint32 rank = Eluna::CHECKVAL(L, 3); + + player->LearnTalent(id, rank); + return 0; + } + +#if !defined(CLASSIC) + /** + * Remove cooldowns on spells that have less than 10 minutes of cooldown from the [Player], similarly to when you enter an arena. + */ + int RemoveArenaSpellCooldowns(lua_State* /*L*/, Player* player) + { + player->RemoveArenaSpellCooldowns(); + return 0; + } +#endif + + /** + * Resurrects the [Player]. + * + * @param float healthPercent = 100.0f + * @param bool ressSickness = false + */ + int ResurrectPlayer(lua_State* L, Player* player) + { + float percent = Eluna::CHECKVAL(L, 2, 100.0f); + bool sickness = Eluna::CHECKVAL(L, 3, false); + player->ResurrectPlayer(percent, sickness); + player->SpawnCorpseBones(); + return 0; + } + + /** + * Adds a new item to the gossip menu shown to the [Player] on next call to [Player:GossipSendMenu]. + * + * sender and intid are numbers which are passed directly to the gossip selection handler. Internally they are partly used for the database gossip handling. + * code specifies whether to show a box to insert text to. The player inserted text is passed to the gossip selection handler. + * money specifies an amount of money the player needs to have to click the option. An error message is shown if the player doesn't have enough money. + * Note that the money amount is only checked client side and is not removed from the player either. You will need to check again in your code before taking action. + * + * See also: [Player:GossipSendMenu], [Player:GossipAddQuests], [Player:GossipComplete], [Player:GossipClearMenu] + * + * @param uint32 icon : number that specifies used icon + * @param string msg : label on the gossip item + * @param uint32 sender : number passed to gossip handlers + * @param uint32 intid : number passed to gossip handlers + * @param bool code = false : show text input on click if true + * @param string popup = nil : if non empty string, a popup with given text shown on click + * @param uint32 money = 0 : required money in copper + */ + int GossipMenuAddItem(lua_State* L, Player* player) + { + uint32 _icon = Eluna::CHECKVAL(L, 2); + const char* msg = Eluna::CHECKVAL(L, 3); + uint32 _sender = Eluna::CHECKVAL(L, 4); + uint32 _intid = Eluna::CHECKVAL(L, 5); + bool _code = Eluna::CHECKVAL(L, 6, false); + const char* _promptMsg = Eluna::CHECKVAL(L, 7, ""); + uint32 _money = Eluna::CHECKVAL(L, 8, 0); +#if defined(TRINITY) + player->PlayerTalkClass->GetGossipMenu().AddMenuItem(-1, GossipOptionIcon(_icon), msg, _sender, _intid, _promptMsg, _money, _code); +#elif defined(AZEROTHCORE) + player->PlayerTalkClass->GetGossipMenu().AddMenuItem(-1, _icon, msg, _sender, _intid, _promptMsg, _money, _code); +#elif defined(CMANGOS) && !defined(CLASSIC) + player->GetPlayerMenu()->GetGossipMenu().AddMenuItem(_icon, msg, _sender, _intid, _promptMsg, _money, _code); +#elif defined(CMANGOS) && defined(CLASSIC) + player->GetPlayerMenu()->GetGossipMenu().AddMenuItem(_icon, msg, _sender, _intid, _promptMsg, _code); +#elif !defined(CLASSIC) && !defined(CMANGOS) + player->PlayerTalkClass->GetGossipMenu().AddMenuItem(_icon, msg, _sender, _intid, _promptMsg, _money, _code); +#else + player->PlayerTalkClass->GetGossipMenu().AddMenuItem(_icon, msg, _sender, _intid, _promptMsg, _code); +#endif + return 0; + } + + /** + * Closes the [Player]s currently open Gossip Menu. + * + * See also: [Player:GossipMenuAddItem], [Player:GossipAddQuests], [Player:GossipSendMenu], [Player:GossipClearMenu] + */ + int GossipComplete(lua_State* /*L*/, Player* player) + { +#if defined TRINITY || AZEROTHCORE + player->PlayerTalkClass->SendCloseGossip(); +#elif CMANGOS + player->GetPlayerMenu()->CloseGossip(); +#else + player->PlayerTalkClass->CloseGossip(); +#endif + return 0; + } + + /** + * Sends the current gossip items of the player to him as a gossip menu with header text from the given textId. + * + * If sender is a [Player] then menu_id is mandatory, otherwise it is not used for anything. + * menu_id is the ID used to trigger the OnGossipSelect registered for players. See [Global:RegisterPlayerGossipEvent] + * + * See also: [Player:GossipMenuAddItem], [Player:GossipAddQuests], [Player:GossipComplete], [Player:GossipClearMenu] + * + * @proto (npc_text, sender) + * @proto (npc_text, sender, menu_id) + * @param uint32 npc_text : entry ID of a header text in npc_text database table, common default is 100 + * @param [Object] sender : object acting as the source of the sent gossip menu + * @param uint32 menu_id : if sender is a [Player] then menu_id is mandatory + */ + int GossipSendMenu(lua_State* L, Player* player) + { + uint32 npc_text = Eluna::CHECKVAL(L, 2); + Object* sender = Eluna::CHECKOBJ(L, 3); + if (sender->GetTypeId() == TYPEID_PLAYER) + { + uint32 menu_id = Eluna::CHECKVAL(L, 4); +#ifndef CMANGOS + player->PlayerTalkClass->GetGossipMenu().SetMenuId(menu_id); +#else + player->GetPlayerMenu()->GetGossipMenu().SetMenuId(menu_id); +#endif + } +#ifndef CMANGOS + player->PlayerTalkClass->SendGossipMenu(npc_text, sender->GET_GUID()); +#else + player->GetPlayerMenu()->SendGossipMenu(npc_text, sender->GET_GUID()); +#endif + return 0; + } + + /** + * Clears the [Player]s current gossip item list. + * + * See also: [Player:GossipMenuAddItem], [Player:GossipSendMenu], [Player:GossipAddQuests], [Player:GossipComplete] + * + * Note: This is needed when you show a gossip menu without using gossip hello or select hooks which do this automatically. + * Usually this is needed when using [Player] is the sender of a Gossip Menu. + */ + int GossipClearMenu(lua_State* /*L*/, Player* player) + { +#ifndef CMANGOS + player->PlayerTalkClass->ClearMenus(); +#else + player->GetPlayerMenu()->ClearMenus(); +#endif + return 0; + } + + /** + * Attempts to start the taxi/flying to the given pathID + * + * @param uint32 pathId : pathId from DBC or [Global:AddTaxiPath] + */ + int StartTaxi(lua_State* L, Player* player) + { + uint32 pathId = Eluna::CHECKVAL(L, 2); + + player->ActivateTaxiPathTo(pathId); + return 0; + } + + /** + * Sends POI to the location on your map + * + * @param float x + * @param float y + * @param uint32 icon : map icon to show + * @param uint32 flags + * @param uint32 data + * @param string iconText + */ + int GossipSendPOI(lua_State* L, Player* player) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + uint32 icon = Eluna::CHECKVAL(L, 4); + uint32 flags = Eluna::CHECKVAL(L, 5); + uint32 data = Eluna::CHECKVAL(L, 6); + std::string iconText = Eluna::CHECKVAL(L, 7); + + WorldPacket packet(SMSG_GOSSIP_POI, 4 + 4 + 4 + 4 + 4 + 10); + packet << flags; + packet << x; + packet << y; + packet << icon; + packet << data; + packet << iconText; +#ifdef CMANGOS + player->GetSession()->SendPacket(packet); +#else + player->GetSession()->SendPacket(&packet); +#endif + return 0; + } + + /** + * Adds the gossip items to the [Player]'s gossip for the quests the given [WorldObject] can offer to the player. + * + * @param [WorldObject] source : a questgiver with quests + */ + int GossipAddQuests(lua_State* L, Player* player) + { + WorldObject* source = Eluna::CHECKOBJ(L, 2); + + if (source->GetTypeId() == TYPEID_UNIT) + { + if (source->GetUInt32Value(UNIT_NPC_FLAGS) & UNIT_NPC_FLAG_QUESTGIVER) + player->PrepareQuestMenu(source->GET_GUID()); + } + else if (source->GetTypeId() == TYPEID_GAMEOBJECT) + { + if (source->ToGameObject()->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + player->PrepareQuestMenu(source->GET_GUID()); + } + return 0; + } + + /** + * Shows a quest accepting window to the [Player] for the given quest. + * + * @param uint32 questId : entry of a quest + * @param bool activateAccept = true : auto finish the quest + */ + int SendQuestTemplate(lua_State* L, Player* player) + { + uint32 questId = Eluna::CHECKVAL(L, 2); + bool activateAccept = Eluna::CHECKVAL(L, 3, true); + + Quest const* quest = eObjectMgr->GetQuestTemplate(questId); + if (!quest) + return 0; + +#ifndef CMANGOS + player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, player->GET_GUID(), activateAccept); +#else + player->GetPlayerMenu()->SendQuestGiverQuestDetails(quest, player->GET_GUID(), activateAccept); +#endif + return 0; + } + + /** + * Converts [Player]'s corpse to bones + */ + int SpawnBones(lua_State* /*L*/, Player* player) + { + player->SpawnCorpseBones(); + return 0; + } + + /** + * Loots [Player]'s bones for insignia + * + * @param [Player] looter + */ + int RemovedInsignia(lua_State* L, Player* player) + { + Player* looter = Eluna::CHECKOBJ(L, 2); + player->RemovedInsignia(looter, player->GetCorpse()); + return 0; + } + + /** + * Makes the [Player] invite another player to a group. + * + * @param [Player] invited : player to invite to group + * @return bool success : true if the player was invited to a group + */ + int GroupInvite(lua_State* L, Player* player) + { + Player* invited = Eluna::CHECKOBJ(L, 2); + + if (invited->GetGroup() || invited->GetGroupInvite()) + { + Eluna::Push(L, false); + return 1; + } + + // Get correct existing group if any + Group* group = player->GetGroup(); +#ifndef CMANGOS + if (group && group->isBGGroup()) +#else + if (group && group->IsBattleGroup()) +#endif + group = player->GetOriginalGroup(); + + bool success = false; + + // Try invite if group found + if (group) + success = !group->IsFull() && group->AddInvite(invited); + else + { + // Create new group if one not found + group = new Group; + success = group->AddLeaderInvite(player) && group->AddInvite(invited); + if (!success) + delete group; + } + + if (success) + { +#if defined(CLASSIC) || defined(TBC) + WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size + data << player->GetName(); +#ifdef CMANGOS + invited->GetSession()->SendPacket(data); +#else + invited->GetSession()->SendPacket(&data); +#endif +#else + WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size + data << uint8(1); // invited/already in group flag + data << player->GetName(); // max len 48 + data << uint32(0); // unk + data << uint8(0); // count + data << uint32(0); // unk +#ifdef CMANGOS + invited->GetSession()->SendPacket(data); +#else + invited->GetSession()->SendPacket(&data); +#endif +#endif + } + + Eluna::Push(L, success); + return 1; + } + + /** + * Creates a new [Group] with the creator [Player] as leader. + * + * @param [Player] invited : player to add to group + * @return [Group] createdGroup : the created group or nil + */ + int GroupCreate(lua_State* L, Player* player) + { + Player* invited = Eluna::CHECKOBJ(L, 2); + + if (player->GetGroup() || invited->GetGroup()) + return 0; + + if (player->GetGroupInvite()) + player->UninviteFromGroup(); + if (invited->GetGroupInvite()) + invited->UninviteFromGroup(); + + // Try create new group + Group* group = new Group; + if (!group->AddLeaderInvite(player)) + { + delete group; + return 0; + } + + // Forming a new group, create it + if (!group->IsCreated()) + { + group->RemoveInvite(player); +#if defined TRINITY || AZEROTHCORE + group->Create(player); + sGroupMgr->AddGroup(group); +#else + if (!group->Create(group->GetLeaderGuid(), group->GetLeaderName())) + return 0; + sObjectMgr.AddGroup(group); +#endif + } + +#if defined TRINITY || AZEROTHCORE + if (!group->AddMember(invited)) + return 0; + group->BroadcastGroupUpdate(); +#else + if (!group->AddMember(invited->GetObjectGuid(), invited->GetName())) + return 0; +#endif + Eluna::Push(L, group); + return 1; + } + + /** + * Starts a cinematic for the [Player] + * + * @param uint32 CinematicSequenceId : entry of a cinematic + */ + int SendCinematicStart(lua_State* L, Player* player) + { + uint32 CinematicSequenceId = Eluna::CHECKVAL(L, 2); + + player->SendCinematicStart(CinematicSequenceId); + return 0; + } + +#if !defined(CLASSIC) && !defined(TBC) + /** + * Starts a movie for the [Player] + * + * @param uint32 MovieId : entry of a movie + */ + int SendMovieStart(lua_State* L, Player* player) + { + uint32 MovieId = Eluna::CHECKVAL(L, 2); + + player->SendMovieStart(MovieId); + return 0; + } +#endif + + /*int BindToInstance(lua_State* L, Player* player) + { + player->BindToInstance(); + return 0; + }*/ + + /*int AddTalent(lua_State* L, Player* player) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + uint8 spec = Eluna::CHECKVAL(L, 3); + bool learning = Eluna::CHECKVAL(L, 4, true); + if (spec >= MAX_TALENT_SPECS) + Eluna::Push(L, false); + else + Eluna::Push(L, player->AddTalent(spellId, spec, learning)); + return 1; + }*/ + + /*int GainSpellComboPoints(lua_State* L, Player* player) + { + int8 count = Eluna::CHECKVAL(L, 2); + + player->GainSpellComboPoints(count); + return 0; + }*/ + + /*int KillGOCredit(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + ObjectGuid guid = Eluna::CHECKVAL(L, 3); + player->KillCreditGO(entry, guid); + return 0; + }*/ + + /*int KilledPlayerCredit(lua_State* L, Player* player) + { + player->KilledPlayerCredit(); + return 0; + }*/ + + /*int RemoveRewardedQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->RemoveRewardedQuest(entry); + return 0; + }*/ + + /*int RemoveActiveQuest(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + + player->RemoveActiveQuest(entry); + return 0; + }*/ + + /*int SummonPet(lua_State* L, Player* player) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + uint32 petType = Eluna::CHECKVAL(L, 7); + uint32 despwtime = Eluna::CHECKVAL(L, 8); + + if (petType >= MAX_PET_TYPE) + return 0; + + player->SummonPet(entry, x, y, z, o, (PetType)petType, despwtime); + return 0; + }*/ + + /*int RemovePet(lua_State* L, Player* player) + { + int mode = Eluna::CHECKVAL(L, 2, PET_SAVE_AS_DELETED); + bool returnreagent = Eluna::CHECKVAL(L, 2, false); + + if (!player->GetPet()) + return 0; + + player->RemovePet(player->GetPet(), (PetSaveMode)mode, returnreagent); + return 0; + }*/ + + ElunaRegister PlayerMethods[] = + { + // Getters + { "GetSelection", &LuaPlayer::GetSelection }, + { "GetGMRank", &LuaPlayer::GetGMRank }, + { "GetGuildId", &LuaPlayer::GetGuildId }, + { "GetCoinage", &LuaPlayer::GetCoinage }, + { "GetTeam", &LuaPlayer::GetTeam }, + { "GetItemCount", &LuaPlayer::GetItemCount }, + { "GetGroup", &LuaPlayer::GetGroup }, + { "GetGuild", &LuaPlayer::GetGuild }, + { "GetAccountId", &LuaPlayer::GetAccountId }, + { "GetAccountName", &LuaPlayer::GetAccountName }, + { "GetLifetimeKills", &LuaPlayer::GetLifetimeKills }, + { "GetPlayerIP", &LuaPlayer::GetPlayerIP }, + { "GetLevelPlayedTime", &LuaPlayer::GetLevelPlayedTime }, + { "GetTotalPlayedTime", &LuaPlayer::GetTotalPlayedTime }, + { "GetItemByPos", &LuaPlayer::GetItemByPos }, + { "GetItemByEntry", &LuaPlayer::GetItemByEntry }, + { "GetItemByGUID", &LuaPlayer::GetItemByGUID }, + { "GetReputation", &LuaPlayer::GetReputation }, + { "GetEquippedItemBySlot", &LuaPlayer::GetEquippedItemBySlot }, + { "GetQuestLevel", &LuaPlayer::GetQuestLevel }, + { "GetChatTag", &LuaPlayer::GetChatTag }, + { "GetRestBonus", &LuaPlayer::GetRestBonus }, + { "GetReqKillOrCastCurrentCount", &LuaPlayer::GetReqKillOrCastCurrentCount }, + { "GetQuestStatus", &LuaPlayer::GetQuestStatus }, + { "GetInGameTime", &LuaPlayer::GetInGameTime }, + { "GetComboPoints", &LuaPlayer::GetComboPoints }, + { "GetComboTarget", &LuaPlayer::GetComboTarget }, + { "GetGuildName", &LuaPlayer::GetGuildName }, + { "GetFreeTalentPoints", &LuaPlayer::GetFreeTalentPoints }, + { "GetSpellCooldownDelay", &LuaPlayer::GetSpellCooldownDelay }, + { "GetGuildRank", &LuaPlayer::GetGuildRank }, + { "GetDifficulty", &LuaPlayer::GetDifficulty }, + { "GetHealthBonusFromStamina", &LuaPlayer::GetHealthBonusFromStamina }, + { "GetManaBonusFromIntellect", &LuaPlayer::GetManaBonusFromIntellect }, + { "GetMaxSkillValue", &LuaPlayer::GetMaxSkillValue }, + { "GetPureMaxSkillValue", &LuaPlayer::GetPureMaxSkillValue }, + { "GetSkillValue", &LuaPlayer::GetSkillValue }, + { "GetBaseSkillValue", &LuaPlayer::GetBaseSkillValue }, + { "GetPureSkillValue", &LuaPlayer::GetPureSkillValue }, + { "GetSkillPermBonusValue", &LuaPlayer::GetSkillPermBonusValue }, + { "GetSkillTempBonusValue", &LuaPlayer::GetSkillTempBonusValue }, + { "GetReputationRank", &LuaPlayer::GetReputationRank }, + { "GetDrunkValue", &LuaPlayer::GetDrunkValue }, + { "GetBattlegroundId", &LuaPlayer::GetBattlegroundId }, + { "GetBattlegroundTypeId", &LuaPlayer::GetBattlegroundTypeId }, + { "GetXPRestBonus", &LuaPlayer::GetXPRestBonus }, + { "GetGroupInvite", &LuaPlayer::GetGroupInvite }, + { "GetSubGroup", &LuaPlayer::GetSubGroup }, + { "GetNextRandomRaidMember", &LuaPlayer::GetNextRandomRaidMember }, + { "GetOriginalGroup", &LuaPlayer::GetOriginalGroup }, + { "GetOriginalSubGroup", &LuaPlayer::GetOriginalSubGroup }, + { "GetLatency", &LuaPlayer::GetLatency }, + { "GetDbLocaleIndex", &LuaPlayer::GetDbLocaleIndex }, + { "GetDbcLocale", &LuaPlayer::GetDbcLocale }, + { "GetCorpse", &LuaPlayer::GetCorpse }, + { "GetGossipTextId", &LuaPlayer::GetGossipTextId }, + { "GetQuestRewardStatus", &LuaPlayer::GetQuestRewardStatus }, + { "GetShieldBlockValue", &LuaPlayer::GetShieldBlockValue }, +#if defined(CLASSIC) + { "GetHonorStoredKills", &LuaPlayer::GetHonorStoredKills }, + { "GetRankPoints", &LuaPlayer::GetRankPoints }, + { "GetHonorLastWeekStandingPos", &LuaPlayer::GetHonorLastWeekStandingPos }, +#endif +#if defined(TBC) || defined (WOTLK) + { "GetArenaPoints", &LuaPlayer::GetArenaPoints }, + { "GetHonorPoints", &LuaPlayer::GetHonorPoints }, +#endif +#ifdef WOTLK + { "GetPhaseMaskForSpawn", &LuaPlayer::GetPhaseMaskForSpawn }, +#endif +#if (!defined(TBC) && !defined(CLASSIC)) + { "GetActiveSpec", &LuaPlayer::GetActiveSpec }, + { "GetSpecsCount", &LuaPlayer::GetSpecsCount }, +#endif + + // Setters + { "AdvanceSkillsToMax", &LuaPlayer::AdvanceSkillsToMax }, + { "AdvanceSkill", &LuaPlayer::AdvanceSkill }, + { "AdvanceAllSkills", &LuaPlayer::AdvanceAllSkills }, + { "AddLifetimeKills", &LuaPlayer::AddLifetimeKills }, + { "SetCoinage", &LuaPlayer::SetCoinage }, + { "SetBindPoint", &LuaPlayer::SetBindPoint }, + { "SetLifetimeKills", &LuaPlayer::SetLifetimeKills }, + { "SetGameMaster", &LuaPlayer::SetGameMaster }, + { "SetGMChat", &LuaPlayer::SetGMChat }, + { "SetTaxiCheat", &LuaPlayer::SetTaxiCheat }, + { "SetGMVisible", &LuaPlayer::SetGMVisible }, + { "SetPvPDeath", &LuaPlayer::SetPvPDeath }, + { "SetAcceptWhispers", &LuaPlayer::SetAcceptWhispers }, + { "SetRestBonus", &LuaPlayer::SetRestBonus }, + { "SetQuestStatus", &LuaPlayer::SetQuestStatus }, + { "SetReputation", &LuaPlayer::SetReputation }, + { "SetFreeTalentPoints", &LuaPlayer::SetFreeTalentPoints }, + { "SetGuildRank", &LuaPlayer::SetGuildRank }, + { "SetSkill", &LuaPlayer::SetSkill }, + { "SetFactionForRace", &LuaPlayer::SetFactionForRace }, + { "SetDrunkValue", &LuaPlayer::SetDrunkValue }, + { "SetAtLoginFlag", &LuaPlayer::SetAtLoginFlag }, + { "SetPlayerLock", &LuaPlayer::SetPlayerLock }, + { "SetGender", &LuaPlayer::SetGender }, + { "SetSheath", &LuaPlayer::SetSheath }, +#if defined(CLASSIC) + { "SetHonorStoredKills", &LuaPlayer::SetHonorStoredKills }, + { "SetRankPoints", &LuaPlayer::SetRankPoints }, + { "SetHonorLastWeekStandingPos", &LuaPlayer::SetHonorLastWeekStandingPos }, +#endif +#ifndef CLASSIC + { "SetKnownTitle", &LuaPlayer::SetKnownTitle }, + { "UnsetKnownTitle", &LuaPlayer::UnsetKnownTitle }, +#endif +#if defined(TBC) || defined(WOTLK) + { "SetArenaPoints", &LuaPlayer::SetArenaPoints }, + { "SetHonorPoints", &LuaPlayer::SetHonorPoints }, +#endif + + // Boolean + { "IsInGroup", &LuaPlayer::IsInGroup }, + { "IsInGuild", &LuaPlayer::IsInGuild }, + { "IsGM", &LuaPlayer::IsGM }, + { "IsImmuneToDamage", &LuaPlayer::IsImmuneToDamage }, + { "IsAlliance", &LuaPlayer::IsAlliance }, + { "IsHorde", &LuaPlayer::IsHorde }, + { "HasItem", &LuaPlayer::HasItem }, + { "Teleport", &LuaPlayer::Teleport }, + { "AddItem", &LuaPlayer::AddItem }, + { "CanCompleteQuest", &LuaPlayer::CanCompleteQuest }, + { "CanEquipItem", &LuaPlayer::CanEquipItem }, + { "IsFalling", &LuaPlayer::IsFalling }, + { "ToggleAFK", &LuaPlayer::ToggleAFK }, + { "ToggleDND", &LuaPlayer::ToggleDND }, + { "IsAFK", &LuaPlayer::IsAFK }, + { "IsDND", &LuaPlayer::IsDND }, + { "IsAcceptingWhispers", &LuaPlayer::IsAcceptingWhispers }, + { "IsGMChat", &LuaPlayer::IsGMChat }, + { "IsTaxiCheater", &LuaPlayer::IsTaxiCheater }, + { "IsGMVisible", &LuaPlayer::IsGMVisible }, + { "HasQuest", &LuaPlayer::HasQuest }, + { "InBattlegroundQueue", &LuaPlayer::InBattlegroundQueue }, + { "CanSpeak", &LuaPlayer::CanSpeak }, + { "HasAtLoginFlag", &LuaPlayer::HasAtLoginFlag }, + { "CanUninviteFromGroup", &LuaPlayer::CanUninviteFromGroup }, + { "IsRested", &LuaPlayer::IsRested }, + { "IsVisibleForPlayer", &LuaPlayer::IsVisibleForPlayer }, + { "HasQuestForItem", &LuaPlayer::HasQuestForItem }, + { "HasQuestForGO", &LuaPlayer::HasQuestForGO }, + { "CanShareQuest", &LuaPlayer::CanShareQuest }, + { "IsInSameGroupWith", &LuaPlayer::IsInSameGroupWith }, + { "IsInSameRaidWith", &LuaPlayer::IsInSameRaidWith }, + { "IsGroupVisibleFor", &LuaPlayer::IsGroupVisibleFor }, + { "HasSkill", &LuaPlayer::HasSkill }, + { "IsHonorOrXPTarget", &LuaPlayer::IsHonorOrXPTarget }, + { "CanParry", &LuaPlayer::CanParry }, + { "CanBlock", &LuaPlayer::CanBlock }, + { "InBattleground", &LuaPlayer::InBattleground }, + { "CanUseItem", &LuaPlayer::CanUseItem }, + { "HasSpell", &LuaPlayer::HasSpell }, + { "HasSpellCooldown", &LuaPlayer::HasSpellCooldown }, + { "IsInWater", &LuaPlayer::IsInWater }, + { "IsMoving", &LuaPlayer::IsMoving }, +#ifndef CLASSIC + { "HasTitle", &LuaPlayer::HasTitle }, + { "IsInArenaTeam", &LuaPlayer::IsInArenaTeam }, + { "InArena", &LuaPlayer::InArena }, + { "CanFly", &LuaPlayer::CanFly }, + { "IsFlying", &LuaPlayer::IsFlying }, +#endif +#if (!defined(TBC) && !defined(CLASSIC)) + { "HasAchieved", &LuaPlayer::HasAchieved }, + { "HasTalent", &LuaPlayer::HasTalent }, + { "CanTitanGrip", &LuaPlayer::CanTitanGrip }, +#endif + + + // Gossip + { "GossipMenuAddItem", &LuaPlayer::GossipMenuAddItem }, + { "GossipSendMenu", &LuaPlayer::GossipSendMenu }, + { "GossipComplete", &LuaPlayer::GossipComplete }, + { "GossipClearMenu", &LuaPlayer::GossipClearMenu }, + + // Other + { "SendBroadcastMessage", &LuaPlayer::SendBroadcastMessage }, + { "SendAreaTriggerMessage", &LuaPlayer::SendAreaTriggerMessage }, + { "SendNotification", &LuaPlayer::SendNotification }, + { "SendPacket", &LuaPlayer::SendPacket }, + { "SendAddonMessage", &LuaPlayer::SendAddonMessage }, + { "ModifyMoney", &LuaPlayer::ModifyMoney }, + { "LearnSpell", &LuaPlayer::LearnSpell }, + { "LearnTalent", &LuaPlayer::LearnTalent }, + { "RemoveItem", &LuaPlayer::RemoveItem }, + { "RemoveLifetimeKills", &LuaPlayer::RemoveLifetimeKills }, + { "ResurrectPlayer", &LuaPlayer::ResurrectPlayer }, + { "EquipItem", &LuaPlayer::EquipItem }, + { "ResetSpellCooldown", &LuaPlayer::ResetSpellCooldown }, + { "ResetTypeCooldowns", &LuaPlayer::ResetTypeCooldowns }, + { "ResetAllCooldowns", &LuaPlayer::ResetAllCooldowns }, + { "GiveXP", &LuaPlayer::GiveXP }, + { "Say", &LuaPlayer::Say }, + { "Yell", &LuaPlayer::Yell }, + { "TextEmote", &LuaPlayer::TextEmote }, + { "Whisper", &LuaPlayer::Whisper }, + { "CompleteQuest", &LuaPlayer::CompleteQuest }, + { "IncompleteQuest", &LuaPlayer::IncompleteQuest }, + { "FailQuest", &LuaPlayer::FailQuest }, + { "AddQuest", &LuaPlayer::AddQuest }, + { "RemoveQuest", &LuaPlayer::RemoveQuest }, + { "AreaExploredOrEventHappens", &LuaPlayer::AreaExploredOrEventHappens }, + { "GroupEventHappens", &LuaPlayer::GroupEventHappens }, + { "KilledMonsterCredit", &LuaPlayer::KilledMonsterCredit }, + { "TalkedToCreature", &LuaPlayer::TalkedToCreature }, + { "AddComboPoints", &LuaPlayer::AddComboPoints }, + { "ClearComboPoints", &LuaPlayer::ClearComboPoints }, + { "RemoveSpell", &LuaPlayer::RemoveSpell }, + { "ResetTalents", &LuaPlayer::ResetTalents }, + { "ResetTalentsCost", &LuaPlayer::ResetTalentsCost }, + { "RemoveFromGroup", &LuaPlayer::RemoveFromGroup }, + { "KillPlayer", &LuaPlayer::KillPlayer }, + { "DurabilityLossAll", &LuaPlayer::DurabilityLossAll }, + { "DurabilityLoss", &LuaPlayer::DurabilityLoss }, + { "DurabilityPointsLoss", &LuaPlayer::DurabilityPointsLoss }, + { "DurabilityPointsLossAll", &LuaPlayer::DurabilityPointsLossAll }, + { "DurabilityPointLossForEquipSlot", &LuaPlayer::DurabilityPointLossForEquipSlot }, + { "DurabilityRepairAll", &LuaPlayer::DurabilityRepairAll }, + { "DurabilityRepair", &LuaPlayer::DurabilityRepair }, + { "LeaveBattleground", &LuaPlayer::LeaveBattleground }, + { "UnbindInstance", &LuaPlayer::UnbindInstance }, + { "UnbindAllInstances", &LuaPlayer::UnbindAllInstances }, + { "RemoveFromBattlegroundRaid", &LuaPlayer::RemoveFromBattlegroundRaid }, + { "KickPlayer", &LuaPlayer::KickPlayer }, + { "LogoutPlayer", &LuaPlayer::LogoutPlayer }, + { "SendTrainerList", &LuaPlayer::SendTrainerList }, + { "SendListInventory", &LuaPlayer::SendListInventory }, + { "SendShowBank", &LuaPlayer::SendShowBank }, + { "SendTabardVendorActivate", &LuaPlayer::SendTabardVendorActivate }, + { "SendSpiritResurrect", &LuaPlayer::SendSpiritResurrect }, + { "SendTaxiMenu", &LuaPlayer::SendTaxiMenu }, + { "SendUpdateWorldState", &LuaPlayer::SendUpdateWorldState }, + { "RewardQuest", &LuaPlayer::RewardQuest }, + { "SendAuctionMenu", &LuaPlayer::SendAuctionMenu }, + { "SendShowMailBox", &LuaPlayer::SendShowMailBox }, + { "StartTaxi", &LuaPlayer::StartTaxi }, + { "GossipSendPOI", &LuaPlayer::GossipSendPOI }, + { "GossipAddQuests", &LuaPlayer::GossipAddQuests }, + { "SendQuestTemplate", &LuaPlayer::SendQuestTemplate }, + { "SpawnBones", &LuaPlayer::SpawnBones }, + { "RemovedInsignia", &LuaPlayer::RemovedInsignia }, + { "SendGuildInvite", &LuaPlayer::SendGuildInvite }, + { "Mute", &LuaPlayer::Mute }, + { "SummonPlayer", &LuaPlayer::SummonPlayer }, + { "SaveToDB", &LuaPlayer::SaveToDB }, + { "GroupInvite", &LuaPlayer::GroupInvite }, + { "GroupCreate", &LuaPlayer::GroupCreate }, + { "SendCinematicStart", &LuaPlayer::SendCinematicStart }, +#if defined(CLASSIC) + { "UpdateHonor", &LuaPlayer::UpdateHonor }, + { "ResetHonor", &LuaPlayer::ResetHonor }, + { "ClearHonorInfo", &LuaPlayer::ClearHonorInfo }, +#endif +#ifndef CLASSIC + { "RemoveArenaSpellCooldowns", &LuaPlayer::RemoveArenaSpellCooldowns }, +#endif +#if (!defined(TBC) && !defined(CLASSIC)) + { "ResetPetTalents", &LuaPlayer::ResetPetTalents }, + { "ResetAchievements", &LuaPlayer::ResetAchievements }, + { "SendMovieStart", &LuaPlayer::SendMovieStart }, +#endif +#if defined(TBC) || defined(WOTLK) + { "ModifyHonorPoints", &LuaPlayer::ModifyHonorPoints }, + { "ModifyArenaPoints", &LuaPlayer::ModifyArenaPoints }, +#endif + + // Not implemented methods + { "GetChampioningFaction", nullptr }, // not implemented + { "GetRecruiterId", nullptr }, // not implemented + { "GetMailItem", nullptr }, //not implemented in VMaNGOS + { "SetMovement", nullptr }, // not implemented + { "SetFFA", nullptr }, // not implemented + { "IsImmuneToEnvironmentalDamage", nullptr }, // not implemented + { "InRandomLfgDungeon", nullptr }, // not implemented + { "HasPendingBind", nullptr }, // not implemented + { "CanFlyInZone", nullptr }, // not implemented + { "IsNeverVisible", nullptr }, // not implemented, + { "IsUsingLfg", nullptr }, // not implemented, + { "HasReceivedQuestReward", nullptr }, // not implemented, + { "IsOutdoorPvPActive", nullptr }, // not implemented, + { "IsARecruiter", nullptr }, // not implemented, + { "RemovePet", nullptr }, // not implemented + { "SummonPet", nullptr }, // not implemented + { "RemoveActiveQuest", nullptr }, // not implemented + { "RemoveRewardedQuest", nullptr }, // not implemented + { "KilledPlayerCredit", nullptr }, // not implemented + { "KillGOCredit", nullptr }, // not implemented + { "GainSpellComboPoints", nullptr }, // not implemented + { "AddTalent", nullptr }, // not implemented + { "BindToInstance", nullptr }, // not implemented + { "SetAchievement", nullptr }, // not implemented + { "GetMailCount", nullptr }, // not implemented + { "GetXP", nullptr }, // not implemented + { "GetXPForNextLevel", nullptr }, // not implemented + { "CanCompleteRepeatableQuest", nullptr }, // not implemented + { "CanRewardQuest", nullptr }, // not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/VMangos/QuestMethods.h b/src/modules/Eluna/VMangos/QuestMethods.h new file mode 100644 index 0000000000..31b7d79f07 --- /dev/null +++ b/src/modules/Eluna/VMangos/QuestMethods.h @@ -0,0 +1,212 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef QUESTMETHODS_H +#define QUESTMETHODS_H + +/*** + * Inherits all methods from: none + */ +namespace LuaQuest +{ + /** + * Returns 'true' if the [Quest] has the specified flag, false otherwise. + * Below flags are based off of 3.3.5a. Subject to change. + * + *
+     * enum QuestFlags
+     * {
+     *     // Flags used at server and sent to client
+     *     QUEST_FLAGS_NONE                    = 0x0,
+     *     QUEST_FLAGS_STAY_ALIVE              = 0x1,       // Not used currently
+     *     QUEST_FLAGS_PARTY_ACCEPT            = 0x2,       // Not used currently. If player in party, all players that can accept this quest will receive confirmation box to accept quest CMSG_QUEST_CONFIRM_ACCEPT/SMSG_QUEST_CONFIRM_ACCEPT
+     *     QUEST_FLAGS_EXPLORATION             = 0x4,       // Not used currently
+     *     QUEST_FLAGS_SHARABLE                = 0x8,       // Can be shared: Player::CanShareQuest()
+     *     QUEST_FLAGS_HAS_CONDITION           = 0x10,      // Not used currently
+     *     QUEST_FLAGS_HIDE_REWARD_POI         = 0x20,      // Not used currently: Unsure of content
+     *     QUEST_FLAGS_RAID                    = 0x40,      // Not used currently
+     *     QUEST_FLAGS_TBC                     = 0x80,      // Not used currently: Available if TBC expansion enabled only
+     *     QUEST_FLAGS_NO_MONEY_FROM_XP        = 0x100,     // Not used currently: Experience is not converted to gold at max level
+     *     QUEST_FLAGS_HIDDEN_REWARDS          = 0x200,     // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE))
+     *     QUEST_FLAGS_TRACKING                = 0x400,     // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
+     *     QUEST_FLAGS_DEPRECATE_REPUTATION    = 0x800,     // Not used currently
+     *     QUEST_FLAGS_DAILY                   = 0x1000,    // Used to know quest is Daily one
+     *     QUEST_FLAGS_FLAGS_PVP               = 0x2000,    // Having this quest in log forces PvP flag
+     *     QUEST_FLAGS_UNAVAILABLE             = 0x4000,    // Used on quests that are not generically available
+     *     QUEST_FLAGS_WEEKLY                  = 0x8000,
+     *     QUEST_FLAGS_AUTOCOMPLETE            = 0x10000,   // auto complete
+     *     QUEST_FLAGS_DISPLAY_ITEM_IN_TRACKER = 0x20000,   // Displays usable item in quest tracker
+     *     QUEST_FLAGS_OBJ_TEXT                = 0x40000,   // use Objective text as Complete text
+     *     QUEST_FLAGS_AUTO_ACCEPT             = 0x80000,   // The client recognizes this flag as auto-accept. However, NONE of the current quests (3.3.5a) have this flag. Maybe blizz used to use it, or will use it in the future.
+     *
+     *     // ... 4.x added flags up to 0x80000000 - all unknown for now
+     * };
+     * 
+ * + * @param [QuestFlags] flag : all available flags can be seen above + * @return bool hasFlag + */ + int HasFlag(lua_State* L, Quest* quest) + { + uint32 flag = Eluna::CHECKVAL(L, 2); +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, quest->HasFlag(flag)); +#else + Eluna::Push(L, quest->HasQuestFlag((QuestFlags)flag)); +#endif + return 1; + } + +#ifndef CLASSIC + /** + * Returns 'true' if the [Quest] is a daily quest, false otherwise. + * + * @return bool isDaily + */ + int IsDaily(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->IsDaily()); + return 1; + } +#endif + + /** + * Returns 'true' if the [Quest] is repeatable, false otherwise. + * + * @return bool isRepeatable + */ + int IsRepeatable(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->IsRepeatable()); + return 1; + } + + /** + * Returns entry ID of the [Quest]. + * + * @return uint32 entryId + */ + int GetId(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetQuestId()); + return 1; + } + + /** + * Returns the [Quest]'s level. + * + * @return uint32 level + */ + int GetLevel(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetQuestLevel()); + return 1; + } + + /** + * Returns the minimum level required to pick up the [Quest]. + * + * @return uint32 minLevel + */ + int GetMinLevel(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetMinLevel()); + return 1; + } + + /** + * Returns the next [Quest] entry ID. + * + * @return int32 entryId + */ + int GetNextQuestId(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetNextQuestId()); + return 1; + } + + /** + * Returns the previous [Quest] entry ID. + * + * @return int32 entryId + */ + int GetPrevQuestId(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetPrevQuestId()); + return 1; + } + + /** + * Returns the next [Quest] entry ID in the specific [Quest] chain. + * + * @return int32 entryId + */ + int GetNextQuestInChain(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetNextQuestInChain()); + return 1; + } + + /** + * Returns the [Quest]'s flags. + * + * @return [QuestFlags] flags + */ + int GetFlags(lua_State* L, Quest* quest) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, quest->GetFlags()); +#else + Eluna::Push(L, quest->GetQuestFlags()); +#endif + return 1; + } + + /** + * Returns the [Quest]'s type. + * + * TODO: Document types available. + * + * @return uint32 type + */ + int GetType(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetType()); + return 1; + } + + /*int GetMaxLevel(lua_State* L, Quest* quest) + { + Eluna::Push(L, quest->GetMaxLevel()); + return 1; + }*/ + + ElunaRegister QuestMethods[] = + { + // Getters + { "GetId", &LuaQuest::GetId }, + { "GetLevel", &LuaQuest::GetLevel }, + { "GetMinLevel", &LuaQuest::GetMinLevel }, + { "GetNextQuestId", &LuaQuest::GetNextQuestId }, + { "GetPrevQuestId", &LuaQuest::GetPrevQuestId }, + { "GetNextQuestInChain", &LuaQuest::GetNextQuestInChain }, + { "GetFlags", &LuaQuest::GetFlags }, + { "GetType", &LuaQuest::GetType }, + + // Boolean + { "HasFlag", &LuaQuest::HasFlag }, + { "IsRepeatable", &LuaQuest::IsRepeatable }, +#ifndef CLASSIC + { "IsDaily", &LuaQuest::IsDaily }, +#endif + + // Not implemented methods + { "GetMaxLevel", nullptr }, // not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/VMangos/SpellMethods.h b/src/modules/Eluna/VMangos/SpellMethods.h new file mode 100644 index 0000000000..541c739a8f --- /dev/null +++ b/src/modules/Eluna/VMangos/SpellMethods.h @@ -0,0 +1,218 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef SPELLMETHODS_H +#define SPELLMETHODS_H + +/*** + * An instance of a spell, created when the spell is cast by a [Unit]. + * + * Inherits all methods from: none + */ +namespace LuaSpell +{ + /** + * Returns `true` if the [Spell] is automatically repeating, `false` otherwise. + * + * @return bool isAutoRepeating + */ + int IsAutoRepeat(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->IsAutoRepeat()); + return 1; + } + + /** + * Returns the [Unit] that casted the [Spell]. + * + * @return [Unit] caster + */ + int GetCaster(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->GetCaster()); + return 1; + } + + /** + * Returns the cast time of the [Spell]. + * + * @return int32 castTime + */ + int GetCastTime(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->GetCastTime()); + return 1; + } + + /** + * Returns the entry ID of the [Spell]. + * + * @return uint32 entryId + */ + int GetEntry(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->m_spellInfo->Id); + return 1; + } + + /** + * Returns the power cost of the [Spell]. + * + * @return uint32 powerCost + */ + int GetPowerCost(lua_State* L, Spell* spell) + { + Eluna::Push(L, spell->GetPowerCost()); + return 1; + } + + /** + * Returns the spell duration of the [Spell]. + * + * @return int32 duration + */ + int GetDuration(lua_State* L, Spell* spell) + { +#if defined TRINITY || AZEROTHCORE || defined VMANGOS + Eluna::Push(L, spell->GetSpellInfo()->GetDuration()); +#else + Eluna::Push(L, GetSpellDuration(spell->m_spellInfo)); +#endif + return 1; + } + + /** + * Returns the target destination coordinates of the [Spell]. + * + * @return float x : x coordinate of the [Spell] + * @return float y : y coordinate of the [Spell] + * @return float z : z coordinate of the [Spell] + */ + int GetTargetDest(lua_State* L, Spell* spell) + { +#if defined TRINITY || AZEROTHCORE + if (!spell->m_targets.HasDst()) + return 3; + float x, y, z; + spell->m_targets.GetDstPos()->GetPosition(x, y, z); +#else + if (!(spell->m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) + return 3; + float x, y, z; + spell->m_targets.getDestination(x, y, z); +#endif + Eluna::Push(L, x); + Eluna::Push(L, y); + Eluna::Push(L, z); + return 3; + } + + /** + * Returns the target [Object] of the [Spell]. + * + * The target can be any of the following [Object] types: + * - [Player] + * - [Creature] + * - [GameObject] + * - [Item] + * - [Corpse] + * + * @return [Object] target + */ + int GetTarget(lua_State* L, Spell* spell) + { +#if defined TRINITY || AZEROTHCORE + if (GameObject* target = spell->m_targets.GetGOTarget()) + Eluna::Push(L, target); + else if (Item* target = spell->m_targets.GetItemTarget()) + Eluna::Push(L, target); + else if (Corpse* target = spell->m_targets.GetCorpseTarget()) + Eluna::Push(L, target); + else if (Unit* target = spell->m_targets.GetUnitTarget()) + Eluna::Push(L, target); + else if (WorldObject* target = spell->m_targets.GetObjectTarget()) + Eluna::Push(L, target); +#else + if (GameObject* target = spell->m_targets.getGOTarget()) + Eluna::Push(L, target); + else if (Item* target = spell->m_targets.getItemTarget()) + Eluna::Push(L, target); + else if (Corpse* target = spell->GetCaster()->GetMap()->GetCorpse(spell->m_targets.getCorpseTargetGuid())) + Eluna::Push(L, target); + else if (Unit* target = spell->m_targets.getUnitTarget()) + Eluna::Push(L, target); +#endif + return 1; + } + + /** + * Sets the [Spell] to automatically repeat. + * + * @param bool repeat : set variable to 'true' for spell to automatically repeat + */ + int SetAutoRepeat(lua_State* L, Spell* spell) + { + bool repeat = Eluna::CHECKVAL(L, 2); + spell->SetAutoRepeat(repeat); + return 0; + } + + /** + * Casts the [Spell]. + * + * @param bool skipCheck = false : skips initial checks to see if the [Spell] can be casted or not, this is optional + */ + int Cast(lua_State* L, Spell* spell) + { + bool skipCheck = Eluna::CHECKVAL(L, 2, false); + spell->cast(skipCheck); + return 0; + } + + /** + * Cancels the [Spell]. + */ + int Cancel(lua_State* /*L*/, Spell* spell) + { + spell->cancel(); + return 0; + } + + /** + * Finishes the [Spell]. + */ + int Finish(lua_State* /*L*/, Spell* spell) + { + spell->finish(); + return 0; + } + + ElunaRegister SpellMethods[] = + { + // Getters + { "GetCaster", &LuaSpell::GetCaster }, + { "GetCastTime", &LuaSpell::GetCastTime }, + { "GetEntry", &LuaSpell::GetEntry }, + { "GetDuration", &LuaSpell::GetDuration }, + { "GetPowerCost", &LuaSpell::GetPowerCost }, + { "GetTargetDest", &LuaSpell::GetTargetDest }, + { "GetTarget", &LuaSpell::GetTarget }, + + // Setters + { "SetAutoRepeat", &LuaSpell::SetAutoRepeat }, + + // Boolean + { "IsAutoRepeat", &LuaSpell::IsAutoRepeat }, + + // Other + { "Cancel", &LuaSpell::Cancel }, + { "Cast", &LuaSpell::Cast }, + { "Finish", &LuaSpell::Finish }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/VMangos/UnitMethods.h b/src/modules/Eluna/VMangos/UnitMethods.h new file mode 100644 index 0000000000..27f59b81e3 --- /dev/null +++ b/src/modules/Eluna/VMangos/UnitMethods.h @@ -0,0 +1,3165 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef UNITMETHODS_H +#define UNITMETHODS_H + +/*** + * Inherits all methods from: [Object], [WorldObject] + */ +namespace LuaUnit +{ + /** + * The [Unit] tries to attack a given target + * + * @param [Unit] who : [Unit] to attack + * @param bool meleeAttack = false: attack with melee or not + * @return didAttack : if the [Unit] did not attack + */ + int Attack(lua_State* L, Unit* unit) + { + Unit* who = Eluna::CHECKOBJ(L, 2); + bool meleeAttack = Eluna::CHECKVAL(L, 3, false); + + Eluna::Push(L, unit->Attack(who, meleeAttack)); + return 1; + } + + /** + * The [Unit] stops attacking its target + * + * @return bool isAttacking : if the [Unit] wasn't attacking already + */ + int AttackStop(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->AttackStop()); + return 1; + } + + /** + * Returns true if the [Unit] is standing. + * + * @return bool isStanding + */ + int IsStandState(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsStandingUp()); + return 1; + } + + /** + * Returns true if the [Unit] is mounted. + * + * @return bool isMounted + */ + int IsMounted(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsMounted()); + return 1; + } + + /** + * Returns true if the [Unit] is rooted. + * + * @return bool isRooted + */ + int IsRooted(lua_State* L, Unit* unit) + { +#ifdef AZEROTHCORE + Eluna::Push(L, unit->isInRoots() || unit->HasUnitMovementFlag(MOVEMENTFLAG_ROOT)); +#endif +#ifdef TRINITY + Eluna::Push(L, unit->IsRooted() || unit->HasUnitMovementFlag(MOVEMENTFLAG_ROOT)); +#endif +#ifdef CMANGOS + Eluna::Push(L, unit->isInRoots() || unit->IsRooted()); +#endif +#ifdef MANGOS + Eluna::Push(L, unit->IsInRoots() || unit->IsRooted()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] has full health. + * + * @return bool hasFullHealth + */ + int IsFullHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsFullHealth()); + return 1; + } + + /** + * Returns true if the [Unit] is in an accessible place for the given [Creature]. + * + * @param [WorldObject] obj + * @param float radius + * @return bool isAccessible + */ + int IsInAccessiblePlaceFor(lua_State* L, Unit* unit) + { + Creature* creature = Eluna::CHECKOBJ(L, 2); + + Eluna::Push(L, unit->IsInAccessablePlaceFor(creature)); + return 1; + } + + /** + * Returns true if the [Unit] an auctioneer. + * + * @return bool isAuctioneer + */ + int IsAuctioneer(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsAuctioner()); + return 1; + } + + /** + * Returns true if the [Unit] a guild master. + * + * @return bool isGuildMaster + */ + int IsGuildMaster(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isGuildMaster()); +#else + Eluna::Push(L, unit->IsGuildMaster()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] an innkeeper. + * + * @return bool isInnkeeper + */ + int IsInnkeeper(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isInnkeeper()); +#else + Eluna::Push(L, unit->IsInnkeeper()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] a trainer. + * + * @return bool isTrainer + */ + int IsTrainer(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isTrainer()); +#else + Eluna::Push(L, unit->IsTrainer()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] is able to show a gossip window. + * + * @return bool hasGossip + */ + int IsGossip(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isGossip()); +#else + Eluna::Push(L, unit->IsGossip()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] is a taxi master. + * + * @return bool isTaxi + */ + int IsTaxi(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isTaxi()); +#else + Eluna::Push(L, unit->IsTaxi()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] is a spirit healer. + * + * @return bool isSpiritHealer + */ + int IsSpiritHealer(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isSpiritHealer()); +#else + Eluna::Push(L, unit->IsSpiritHealer()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] is a spirit guide. + * + * @return bool isSpiritGuide + */ + int IsSpiritGuide(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isSpiritGuide()); +#else + Eluna::Push(L, unit->IsSpiritGuide()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] is a tabard designer. + * + * @return bool isTabardDesigner + */ + int IsTabardDesigner(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isTabardDesigner()); +#else + Eluna::Push(L, unit->IsTabardDesigner()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] provides services like vendor, training and auction. + * + * @return bool isTabardDesigner + */ + int IsServiceProvider(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isServiceProvider()); +#else + Eluna::Push(L, unit->IsServiceProvider()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] is a spirit guide or spirit healer. + * + * @return bool isSpiritService + */ + int IsSpiritService(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isSpiritService()); +#else + Eluna::Push(L, unit->IsSpiritService()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] is alive. + * + * @return bool isAlive + */ + int IsAlive(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsAlive()); + return 1; + } + + /** + * Returns true if the [Unit] is dead. + * + * @return bool isDead + */ + int IsDead(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsDead()); + return 1; + } + + /** + * Returns true if the [Unit] is dying. + * + * @return bool isDying + */ + int IsDying(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsDying()); + return 1; + } + + /** + * Returns true if the [Unit] is a banker. + * + * @return bool isBanker + */ + int IsBanker(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isBanker()); +#else + Eluna::Push(L, unit->IsBanker()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] is a vendor. + * + * @return bool isVendor + */ + int IsVendor(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isVendor()); +#else + Eluna::Push(L, unit->IsVendor()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] is a battle master. + * + * @return bool isBattleMaster + */ + int IsBattleMaster(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isBattleMaster()); +#else + Eluna::Push(L, unit->IsBattleMaster()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] is a charmed. + * + * @return bool isCharmed + */ + int IsCharmed(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsCharmed()); + return 1; + } + + /** + * Returns true if the [Unit] is an armorer and can repair equipment. + * + * @return bool isArmorer + */ + int IsArmorer(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isArmorer()); +#else + Eluna::Push(L, unit->IsArmorer()); +#endif + return 1; + } + + /** + * Returns true if the [Unit] is attacking a player. + * + * @return bool isAttackingPlayer + */ + int IsAttackingPlayer(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isAttackingPlayer()); + return 1; + } + + /** + * Returns true if the [Unit] flagged for PvP. + * + * @return bool isPvP + */ + int IsPvPFlagged(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsPvP()); + return 1; + } + +#ifndef CLASSIC + /** + * Returns true if the [Unit] is on a [Vehicle]. + * + * @return bool isOnVehicle + */ + int IsOnVehicle(lua_State* L, Unit* unit) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->GetVehicle()); +#else + Eluna::Push(L, unit->IsBoarded()); +#endif + return 1; + } +#endif + + /** + * Returns true if the [Unit] is in combat. + * + * @return bool inCombat + */ + int IsInCombat(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsInCombat()); + return 1; + } + + /** + * Returns true if the [Unit] is under water. + * + * @return bool underWater + */ + int IsUnderWater(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsUnderwater()); + return 1; + } + + /** + * Returns true if the [Unit] is in water. + * + * @return bool inWater + */ + int IsInWater(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsInWater()); + return 1; + } + + /** + * Returns true if the [Unit] is not moving. + * + * @return bool notMoving + */ + int IsStopped(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsStopped()); + return 1; + } + + /** + * Returns true if the [Unit] is a quest giver. + * + * @return bool questGiver + */ + int IsQuestGiver(lua_State* L, Unit* unit) + { +#ifdef CMANGOS + Eluna::Push(L, unit->isQuestGiver()); +#else + Eluna::Push(L, unit->IsQuestGiver()); +#endif + return 1; + } + + /** + * Returns true if the [Unit]'s health is below the given percentage. + * + * @param int32 healthpct : percentage in integer from + * @return bool isBelow + */ + int HealthBelowPct(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->HealthBelowPct(Eluna::CHECKVAL(L, 2))); + return 1; + } + + /** + * Returns true if the [Unit]'s health is above the given percentage. + * + * @param int32 healthpct : percentage in integer from + * @return bool isAbove + */ + int HealthAbovePct(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->HealthAbovePct(Eluna::CHECKVAL(L, 2))); + return 1; + } + + /** + * Returns true if the [Unit] has an aura from the given spell entry. + * + * @param uint32 spell : entry of the aura spell + * @return bool hasAura + */ + int HasAura(lua_State* L, Unit* unit) + { + uint32 spell = Eluna::CHECKVAL(L, 2); + + Eluna::Push(L, unit->HasAura(spell)); + return 1; + } + + /** + * Returns true if the [Unit] is casting a spell + * + * @return bool isCasting + */ + int IsCasting(lua_State* L, Unit* unit) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->HasUnitState(UNIT_STATE_CASTING)); +#else + Eluna::Push(L, unit->IsNonMeleeSpellCasted(false)); +#endif + return 1; + } + + /** + * Returns true if the [Unit] has the given unit state. + * + * @param [UnitState] state : an unit state + * @return bool hasState + */ + int HasUnitState(lua_State* L, Unit* unit) + { + uint32 state = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, unit->HasUnitState(state)); + return 1; + } + + /*int IsVisible(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsVisible()); + return 1; + }*/ + + /*int IsMoving(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->isMoving()); + return 1; + }*/ + + /*int IsFlying(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->IsFlying()); + return 1; + }*/ + + /** + * Returns the [Unit]'s owner. + * + * @return [Unit] owner + */ + int GetOwner(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetOwner()); + return 1; + } + + /** + * Returns the [Unit]'s owner's GUID. + * + * @return ObjectGuid ownerGUID + */ + int GetOwnerGUID(lua_State* L, Unit* unit) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->GetOwnerGUID()); +#else + Eluna::Push(L, unit->GetOwnerGuid()); +#endif + return 1; + } + + /** + * Returns the [Unit]'s mount's modelID. + * + * @return uint32 mountId : displayId of the mount + */ + int GetMountId(lua_State* L, Unit* unit) + { +#ifdef TRINITY + Eluna::Push(L, unit->GetMountDisplayId()); +#else + Eluna::Push(L, unit->GetMountID()); +#endif + return 1; + } + + /** + * Returns the [Unit]'s creator's GUID. + * + * @return ObjectGuid creatorGUID + */ + int GetCreatorGUID(lua_State* L, Unit* unit) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->GetCreatorGUID()); +#else + Eluna::Push(L, unit->GetCreatorGuid()); +#endif + return 1; + } + + /** + * Returns the [Unit]'s charmer's GUID. + * + * @return ObjectGuid charmerGUID + */ + int GetCharmerGUID(lua_State* L, Unit* unit) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->GetCharmerGUID()); +#else + Eluna::Push(L, unit->GetCharmerGuid()); +#endif + return 1; + } + + /** + * Returns the GUID of the [Unit]'s charmed entity. + * + * @return ObjectGuid charmedGUID + */ + int GetCharmGUID(lua_State* L, Unit* unit) + { +#if defined AZEROTHCORE + Eluna::Push(L, unit->GetCharmGUID()); +#elif defined TRINITY + Eluna::Push(L, unit->GetCharmedGUID()); +#else + Eluna::Push(L, unit->GetCharmGuid()); +#endif + return 1; + } + + /** + * Returns the GUID of the [Unit]'s pet. + * + * @return ObjectGuid petGUID + */ + int GetPetGUID(lua_State* L, Unit* unit) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->GetPetGUID()); +#else + Eluna::Push(L, unit->GetPetGuid()); +#endif + return 1; + } + + /** + * Returns the GUID of the [Unit]'s charmer or owner. + * + * @return ObjectGuid controllerGUID + */ + int GetControllerGUID(lua_State* L, Unit* unit) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->GetCharmerOrOwnerGUID()); +#else + Eluna::Push(L, unit->GetCharmerOrOwnerGuid()); +#endif + return 1; + } + + /** + * Returns the GUID of the [Unit]'s charmer or owner or its own GUID. + * + * @return ObjectGuid controllerGUID + */ + int GetControllerGUIDS(lua_State* L, Unit* unit) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->GetCharmerOrOwnerOrOwnGUID()); +#else + Eluna::Push(L, unit->GetCharmerOrOwnerOrOwnGuid()); +#endif + return 1; + } + + /** + * Returns [Unit]'s specified stat + * + * @param uint32 statType + * @return float stat + */ + int GetStat(lua_State* L, Unit* unit) + { + uint32 stat = Eluna::CHECKVAL(L, 2); + + if (stat >= MAX_STATS) + return 1; + + Eluna::Push(L, unit->GetStat((Stats)stat)); + return 1; + } + + /** + * Returns the [Unit]'s base spell power + * + * @param uint32 spellSchool + * @return uint32 spellPower + */ + int GetBaseSpellPower(lua_State* L, Unit* unit) + { + uint32 spellschool = Eluna::CHECKVAL(L, 2); + + if (spellschool >= MAX_SPELL_SCHOOL) + return 1; + + Eluna::Push(L, unit->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + spellschool)); + return 1; + } + + /** + * Returns the [Unit]'s current victim target or nil. + * + * @return [Unit] victim + */ + int GetVictim(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetVictim()); + return 1; + } + + /** + * Returns the currently casted [Spell] of given type or nil. + * + *
+     * enum CurrentSpellTypes
+     * {
+     *     CURRENT_MELEE_SPELL             = 0,
+     *     CURRENT_GENERIC_SPELL           = 1,
+     *     CURRENT_CHANNELED_SPELL         = 2,
+     *     CURRENT_AUTOREPEAT_SPELL        = 3
+     * };
+     * 
+ * + * @param [CurrentSpellTypes] spellType + * @return [Spell] castedSpell + */ + int GetCurrentSpell(lua_State* L, Unit* unit) + { + uint32 type = Eluna::CHECKVAL(L, 2); + if (type >= CURRENT_MAX_SPELL) + return luaL_argerror(L, 2, "valid CurrentSpellTypes expected"); + Eluna::Push(L, unit->GetCurrentSpell(CurrentSpellTypes(type))); + return 1; + } + + /** + * Returns the [Unit]'s current stand state. + * + * @return uint8 standState + */ + int GetStandState(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetStandState()); + return 1; + } + + /** + * Returns the [Unit]'s current display ID. + * + * @return uint32 displayId + */ + int GetDisplayId(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetDisplayId()); + return 1; + } + + /** + * Returns the [Unit]'s native/original display ID. + * + * @return uint32 displayId + */ + int GetNativeDisplayId(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetNativeDisplayId()); + return 1; + } + + /** + * Returns the [Unit]'s level. + * + * @return uint8 level + */ + int GetLevel(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetLevel()); + return 1; + } + + /** + * Returns the [Unit]'s health amount. + * + * @return uint32 healthAmount + */ + int GetHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetHealth()); + return 1; + } + + Powers PowerSelectorHelper(lua_State* L, Unit* unit, int powerType = -1) + { +#ifdef TRINITY + if (powerType == -1) + return unit->GetPowerType(); +#elif AZEROTHCORE + if (powerType == -1) + return unit->getPowerType(); +#else + if (powerType == -1) + return unit->GetPowerType(); +#endif + + if (powerType < 0 || powerType >= int(MAX_POWERS)) + luaL_argerror(L, 2, "valid Powers expected"); + + return (Powers)powerType; + } + + /** + * Returns the [Unit]'s power amount for given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + * @return uint32 powerAmount + */ + int GetPower(lua_State* L, Unit* unit) + { + int type = Eluna::CHECKVAL(L, 2, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + Eluna::Push(L, unit->GetPower(power)); + return 1; + } + + /** + * Returns the [Unit]'s max power amount for given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + * @return uint32 maxPowerAmount + */ + int GetMaxPower(lua_State* L, Unit* unit) + { + int type = Eluna::CHECKVAL(L, 2, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + Eluna::Push(L, unit->GetMaxPower(power)); + return 1; + } + + /** + * Returns the [Unit]'s power percent for given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + * @return float powerPct + */ + int GetPowerPct(lua_State* L, Unit* unit) + { + int type = Eluna::CHECKVAL(L, 2, -1); + Powers power = PowerSelectorHelper(L, unit, type); + +#if (!defined(TRINITY) && defined(WOTLK)) + float percent = ((float)unit->GetPower(power) / (float)unit->GetMaxPower(power)) * 100.0f; +#else + float percent = ((float)unit->GetPower(power) / (float)unit->GetMaxPower(power)) * 100.0f; +#endif + Eluna::Push(L, percent); + return 1; + } + + /** + * Returns the [Unit]'s current power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @return [Powers] powerType + */ + int GetPowerType(lua_State* L, Unit* unit) + { +#ifdef TRINITY + Eluna::Push(L, unit->GetPowerType()); +#elif AZEROTHCORE + Eluna::Push(L, unit->getPowerType()); +#else + Eluna::Push(L, unit->GetPowerType()); +#endif + return 1; + } + + /** + * Returns the [Unit]'s max health. + * + * @return uint32 maxHealth + */ + int GetMaxHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetMaxHealth()); + return 1; + } + + /** + * Returns the [Unit]'s health percent. + * + * @return float healthPct + */ + int GetHealthPct(lua_State* L, Unit* unit) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->GetHealthPct()); +#else + Eluna::Push(L, unit->GetHealthPercent()); +#endif + return 1; + } + + /** + * Returns the [Unit]'s gender. + * + * @return uint8 gender : 0 for male, 1 for female and 2 for none + */ + int GetGender(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetGender()); + return 1; + } + + /** + * Returns the [Unit]'s race ID. + * + * @return [Races] race + */ + int GetRace(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetRace()); + return 1; + } + + /** + * Returns the [Unit]'s class ID. + * + * @return [Classes] class + */ + int GetClass(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetClass()); + return 1; + } + + /** + * Returns the race mask + * + * @return uint32 racemask + */ + int GetRaceMask(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetRaceMask()); + return 1; + } + + /** + * Returns the class mask + * + * @return uint32 classmask + */ + int GetClassMask(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetClassMask()); + return 1; + } + + /** + * Returns the [Unit]'s creature type ID (enumerated in CreatureType.dbc). + * + *
+     * enum CreatureType
+     * {
+     *     CREATURE_TYPE_BEAST            = 1,
+     *     CREATURE_TYPE_DRAGONKIN        = 2,
+     *     CREATURE_TYPE_DEMON            = 3,
+     *     CREATURE_TYPE_ELEMENTAL        = 4,
+     *     CREATURE_TYPE_GIANT            = 5,
+     *     CREATURE_TYPE_UNDEAD           = 6,
+     *     CREATURE_TYPE_HUMANOID         = 7,
+     *     CREATURE_TYPE_CRITTER          = 8,
+     *     CREATURE_TYPE_MECHANICAL       = 9,
+     *     CREATURE_TYPE_NOT_SPECIFIED    = 10,
+     *     CREATURE_TYPE_TOTEM            = 11,
+     *     CREATURE_TYPE_NON_COMBAT_PET   = 12,     // This and below is TBC+
+     *     CREATURE_TYPE_GAS_CLOUD        = 13
+     * };
+     * 
+ * + * @return [CreatureType] creatureType + */ + int GetCreatureType(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetCreatureType()); + return 1; + } + + /** + * Returns the [Unit]'s class' name in given or default locale or nil. + * + *
+     * enum LocaleConstant
+     * {
+     *     LOCALE_enUS = 0,
+     *     LOCALE_koKR = 1,
+     *     LOCALE_frFR = 2,
+     *     LOCALE_deDE = 3,
+     *     LOCALE_zhCN = 4,
+     *     LOCALE_zhTW = 5,
+     *     LOCALE_esES = 6,
+     *     LOCALE_esMX = 7,
+     *     LOCALE_ruRU = 8
+     * };
+     * 
+ * + * @param [LocaleConstant] locale = DEFAULT_LOCALE + * @return string className : class name or nil + */ + int GetClassAsString(lua_State* L, Unit* unit) + { + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const ChrClassesEntry* entry = sChrClassesStore.LookupEntry(unit->GetClass()); + + if (!entry) + return 1; + +#ifdef TRINITY + Eluna::Push(L, entry->Name[locale]); +#else + Eluna::Push(L, entry->name[locale]); +#endif + return 1; + } + + /** + * Returns the [Unit]'s race's name in given or default locale or nil. + * + *
+     * enum LocaleConstant
+     * {
+     *     LOCALE_enUS = 0,
+     *     LOCALE_koKR = 1,
+     *     LOCALE_frFR = 2,
+     *     LOCALE_deDE = 3,
+     *     LOCALE_zhCN = 4,
+     *     LOCALE_zhTW = 5,
+     *     LOCALE_esES = 6,
+     *     LOCALE_esMX = 7,
+     *     LOCALE_ruRU = 8
+     * };
+     * 
+ * + * @param [LocaleConstant] locale = DEFAULT_LOCALE : locale to return the race name in + * @return string raceName : race name or nil + */ + int GetRaceAsString(lua_State* L, Unit* unit) + { + uint8 locale = Eluna::CHECKVAL(L, 2, DEFAULT_LOCALE); + if (locale >= TOTAL_LOCALES) + return luaL_argerror(L, 2, "valid LocaleConstant expected"); + + const ChrRacesEntry* entry = sChrRacesStore.LookupEntry(unit->GetRace()); + if (!entry) + return 1; + +#ifdef TRINITY + Eluna::Push(L, entry->Name[locale]); +#else + Eluna::Push(L, entry->name[locale]); +#endif + return 1; + } + + /** + * Returns the [Unit]'s faction ID. + * + * @return uint32 faction + */ + int GetFaction(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetFactionTemplateId()); + return 1; + } + + /** + * Returns the [Aura] of the given spell entry on the [Unit] or nil. + * + * @param uint32 spellID : entry of the aura spell + * @return [Aura] aura : aura object or nil + */ + int GetAura(lua_State* L, Unit* unit) + { + uint32 spellID = Eluna::CHECKVAL(L, 2); +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->GetAura(spellID)); +#else + Eluna::Push(L, unit->GetAura(spellID, EFFECT_INDEX_0)); +#endif + return 1; + } + + /** + * Returns a table containing friendly [Unit]'s within given range of the [Unit]. + * + * @param float range = 533.333 : search radius + * @return table friendyUnits : table filled with friendly units + */ + int GetFriendlyUnitsInRange(lua_State* L, Unit* unit) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + + std::list list; +#ifdef TRINITY + Trinity::AnyFriendlyUnitInObjectRangeCheck checker(unit, unit, range); + Trinity::UnitListSearcher searcher(unit, list, checker); + Cell::VisitAllObjects(unit, searcher, range); +#elif AZEROTHCORE + Acore::AnyFriendlyUnitInObjectRangeCheck checker(unit, unit, range); + Acore::UnitListSearcher searcher(unit, list, checker); + Cell::VisitAllObjects(unit, searcher, range); +#elif CMANGOS + MaNGOS::AnyFriendlyUnitInObjectRangeCheck checker(unit, range); + MaNGOS::UnitListSearcher searcher(list, checker); + Cell::VisitGridObjects(unit, searcher, range); +#else + MaNGOS::AnyFriendlyUnitInObjectRangeCheck checker(unit, range); + MaNGOS::UnitListSearcher searcher(list, checker); + Cell::VisitGridObjects(unit, searcher, range); +#endif + ElunaUtil::ObjectGUIDCheck guidCheck(unit->GET_GUID()); + list.remove_if(guidCheck); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns a table containing unfriendly [Unit]'s within given range of the [Unit]. + * + * @param float range = 533.333 : search radius + * @return table unfriendyUnits : table filled with unfriendly units + */ + int GetUnfriendlyUnitsInRange(lua_State* L, Unit* unit) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + + std::list list; + MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck checker(unit, unit, range); + MaNGOS::UnitListSearcher searcher(list, checker); + Cell::VisitGridObjects(unit, searcher, range); + ElunaUtil::ObjectGUIDCheck guidCheck(unit->GET_GUID()); + list.remove_if(guidCheck); + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Returns [Unit]'s [Vehicle] methods + * + * @return [Vehicle] vehicle + */ + int GetVehicleKit(lua_State* L, Unit* unit) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->GetVehicleKit()); +#else + Eluna::Push(L, unit->GetVehicleInfo()); +#endif + return 1; + } + + /* + int GetVehicle(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetVehicle()); + return 1; + } + */ + + /** + * Returns the Critter Guid + * + * @return ObjectGuid critterGuid + */ + int GetCritterGUID(lua_State* L, Unit* unit) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->GetCritterGUID()); +#else + Eluna::Push(L, unit->GetCritterGuid()); +#endif + return 1; + } +#endif + + /** + * Returns the [Unit]'s speed of given [UnitMoveType]. + * + *
+     * enum UnitMoveType
+     * {
+     *     MOVE_WALK           = 0,
+     *     MOVE_RUN            = 1,
+     *     MOVE_RUN_BACK       = 2,
+     *     MOVE_SWIM           = 3,
+     *     MOVE_SWIM_BACK      = 4,
+     *     MOVE_TURN_RATE      = 5,
+     *     MOVE_FLIGHT         = 6,
+     *     MOVE_FLIGHT_BACK    = 7,
+     *     MOVE_PITCH_RATE     = 8
+     * };
+     * 
+ * + * @param [UnitMoveType] type + * @return float speed + */ + int GetSpeed(lua_State* L, Unit* unit) + { + uint32 type = Eluna::CHECKVAL(L, 2); + if (type >= MAX_MOVE_TYPE) + return luaL_argerror(L, 2, "valid UnitMoveType expected"); + +#ifndef TRINITY + Eluna::Push(L, unit->GetSpeedRate((UnitMoveType)type)); +#else + Eluna::Push(L, unit->GetSpeed((UnitMoveType)type)); +#endif + return 1; + } + + /** + * Returns the current movement type for this [Unit]. + * + *
+     * enum MovementGeneratorType
+     * {
+     *     IDLE_MOTION_TYPE                = 0,
+     *     RANDOM_MOTION_TYPE              = 1,
+     *     WAYPOINT_MOTION_TYPE            = 2,
+     *     MAX_DB_MOTION_TYPE              = 3,
+     *     ANIMAL_RANDOM_MOTION_TYPE       = 3, // TC
+     *
+     *     CONFUSED_MOTION_TYPE            = 4,
+     *     CHASE_MOTION_TYPE               = 5,
+     *     HOME_MOTION_TYPE                = 6,
+     *     FLIGHT_MOTION_TYPE              = 7,
+     *     POINT_MOTION_TYPE               = 8,
+     *     FLEEING_MOTION_TYPE             = 9,
+     *     DISTRACT_MOTION_TYPE            = 10,
+     *     ASSISTANCE_MOTION_TYPE          = 11,
+     *     ASSISTANCE_DISTRACT_MOTION_TYPE = 12,
+     *     TIMED_FLEEING_MOTION_TYPE       = 13,
+     *     FOLLOW_MOTION_TYPE              = 14,
+     *     EFFECT_MOTION_TYPE              = 15, // mangos
+     *     ROTATE_MOTION_TYPE              = 15, // TC
+     *     EFFECT_MOTION_TYPE              = 16, // TC
+     *     NULL_MOTION_TYPE                = 17, // TC
+     * };
+     * 
+ * + * @return [MovementGeneratorType] movementType + */ + int GetMovementType(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->GetMotionMaster()->GetCurrentMovementGeneratorType()); + return 1; + } + + /** + * Sets the [Unit]'s owner GUID to given GUID. + * + * @param ObjectGuid guid : new owner guid + */ + int SetOwnerGUID(lua_State* L, Unit* unit) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + +#if defined TRINITY || AZEROTHCORE + unit->SetOwnerGUID(guid); +#else + unit->SetOwnerGuid(guid); +#endif + return 0; + } + + /** + * Sets the [Unit]'s PvP on or off. + * + * @param bool apply = true : true if set on, false if off + */ + int SetPvP(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + unit->SetPvP(apply); + return 0; + } + + /** + * Sets the [Unit]'s sheath state. + * + * enum SheathState + * { + * SHEATH_STATE_UNARMED = 0, // non prepared weapon + * SHEATH_STATE_MELEE = 1, // prepared melee weapon + * SHEATH_STATE_RANGED = 2 // prepared ranged weapon + * }; + * + * @param [SheathState] sheathState : valid SheathState + */ + int SetSheath(lua_State* L, Unit* unit) + { + uint32 sheathed = Eluna::CHECKVAL(L, 2); + if (sheathed >= MAX_SHEATH_STATE) + return luaL_argerror(L, 2, "valid SheathState expected"); + + unit->SetSheath((SheathState)sheathed); + return 0; + } + + /** + * Sets the [Unit]'s name internally. + * + * @param string name : new name + */ + int SetName(lua_State* L, Unit* unit) + { + const char* name = Eluna::CHECKVAL(L, 2); + if (std::string(name).length() > 0) + unit->SetName(name); + return 0; + } + + /** + * Sets the [Unit]'s speed of given [UnitMoveType] to given rate. + * If forced, packets sent to clients forcing the visual change. + * + *
+     * enum UnitMoveType
+     * {
+     *     MOVE_WALK           = 0,
+     *     MOVE_RUN            = 1,
+     *     MOVE_RUN_BACK       = 2,
+     *     MOVE_SWIM           = 3,
+     *     MOVE_SWIM_BACK      = 4,
+     *     MOVE_TURN_RATE      = 5,
+     *     MOVE_FLIGHT         = 6,
+     *     MOVE_FLIGHT_BACK    = 7,
+     *     MOVE_PITCH_RATE     = 8
+     * };
+     * 
+ * + * @param [UnitMoveType] type + * @param float rate + * @param bool forced = false + */ + int SetSpeed(lua_State* L, Unit* unit) + { + uint32 type = Eluna::CHECKVAL(L, 2); + float rate = Eluna::CHECKVAL(L, 3); + bool forced = Eluna::CHECKVAL(L, 4, false); + (void)forced; // ensure that the variable is referenced in order to pass compiler checks + if (type >= MAX_MOVE_TYPE) + return luaL_argerror(L, 2, "valid UnitMoveType expected"); + unit->SetSpeedRate((UnitMoveType)type, rate); + return 0; + } + + /** + * Sets the [Unit]'s faction. + * + * @param uint32 faction : new faction ID + */ + int SetFaction(lua_State* L, Unit* unit) + { + uint32 factionId = Eluna::CHECKVAL(L, 2); + unit->SetFactionTemplateId(factionId); + return 0; + } + + /** + * Sets the [Unit]'s level. + * + * @param uint8 level : new level + */ + int SetLevel(lua_State* L, Unit* unit) + { + uint8 newlevel = Eluna::CHECKVAL(L, 2); + + if (newlevel < 1) + return luaL_argerror(L, 2, "level cannot be below 1"); + + if (Player* player = unit->ToPlayer()) + { + player->GiveLevel(newlevel); + player->InitTalentForLevel(); + player->SetUInt32Value(PLAYER_XP, 0); + } + else + unit->SetLevel(newlevel); + + return 0; + } + + /** + * Sets the [Unit]'s health. + * + * @param uint32 health : new health + */ + int SetHealth(lua_State* L, Unit* unit) + { + uint32 amt = Eluna::CHECKVAL(L, 2); + unit->SetHealth(amt); + return 0; + } + + /** + * Sets the [Unit]'s max health. + * + * @param uint32 maxHealth : new max health + */ + int SetMaxHealth(lua_State* L, Unit* unit) + { + uint32 amt = Eluna::CHECKVAL(L, 2); + unit->SetMaxHealth(amt); + return 0; + } + + /** + * Sets the [Unit]'s power amount for the given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param uint32 amount : new power amount + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + */ + int SetPower(lua_State* L, Unit* unit) + { + uint32 amt = Eluna::CHECKVAL(L, 2); + int type = Eluna::CHECKVAL(L, 3, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + unit->SetPower(power, amt); + return 0; + } + + /** + * modifies the [Unit]'s power amount for the given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int32 amount : amount to modify + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + */ + int ModifyPower(lua_State* L, Unit* unit) + { + int32 amt = Eluna::CHECKVAL(L, 2); + int type = Eluna::CHECKVAL(L, 3, -1); + Powers power = PowerSelectorHelper(L, unit, type); + + unit->ModifyPower(power, amt); + return 0; + } + + /** + * Sets the [Unit]'s max power amount for the given power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param int type = -1 : a valid power type from [Powers] or -1 for the [Unit]'s current power type + * @param uint32 maxPower : new max power amount + */ + int SetMaxPower(lua_State* L, Unit* unit) + { + int type = Eluna::CHECKVAL(L, 2, -1); + uint32 amt = Eluna::CHECKVAL(L, 3); + Powers power = PowerSelectorHelper(L, unit, type); + + unit->SetMaxPower(power, amt); + return 0; + } + + /** + * Sets the [Unit]'s power type. + * + * enum Powers + * { + * POWER_MANA = 0, + * POWER_RAGE = 1, + * POWER_FOCUS = 2, + * POWER_ENERGY = 3, + * POWER_HAPPINESS = 4, + * POWER_RUNE = 5, + * POWER_RUNIC_POWER = 6, + * MAX_POWERS = 7, + * POWER_ALL = 127, // default for class? + * POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) + * }; + * + * @param [Powers] type : a valid power type + */ + int SetPowerType(lua_State* L, Unit* unit) + { + uint32 type = Eluna::CHECKVAL(L, 2); + if (type >= int(MAX_POWERS)) + return luaL_argerror(L, 2, "valid Powers expected"); + +#ifdef TRINITY + unit->SetPowerType((Powers)type); +#elif AZEROTHCORE + unit->setPowerType((Powers)type); +#else + unit->SetPowerType((Powers)type); +#endif + return 0; + } + + /** + * Sets the [Unit]'s modelID. + * + * @param uint32 displayId + */ + int SetDisplayId(lua_State* L, Unit* unit) + { + uint32 model = Eluna::CHECKVAL(L, 2); + unit->SetDisplayId(model); + return 0; + } + + /** + * Sets the [Unit]'s native/default modelID. + * + * @param uint32 displayId + */ + int SetNativeDisplayId(lua_State* L, Unit* unit) + { + uint32 model = Eluna::CHECKVAL(L, 2); + unit->SetNativeDisplayId(model); + return 0; + } + + /** + * Sets the [Unit]'s facing/orientation. + * + * @param uint32 orientation + */ + int SetFacing(lua_State* L, Unit* unit) + { + float o = Eluna::CHECKVAL(L, 2); + unit->SetFacingTo(o); + return 0; + } + + /** + * Sets the [Unit] to face the given [WorldObject]'s direction. + * + * @param [WorldObject] target + */ + int SetFacingToObject(lua_State* L, Unit* unit) + { + WorldObject* obj = Eluna::CHECKOBJ(L, 2); + unit->SetFacingToObject(obj); + return 0; + } + + /** + * Sets creator GUID + * + * @param ObjectGuid guid + */ + int SetCreatorGUID(lua_State* L, Unit* unit) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); +#if defined TRINITY || AZEROTHCORE + unit->SetCreatorGUID(guid); +#else + unit->SetCreatorGuid(guid); +#endif + return 0; + } + + /** + * Sets pet GUID + * + * @param ObjectGuid guid + */ + int SetPetGUID(lua_State* L, Unit* unit) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); +#if defined TRINITY || AZEROTHCORE + unit->SetPetGUID(guid); +#else + unit->SetPetGuid(guid); +#endif + return 0; + } + + /** + * Toggles (Sets) [Unit]'s water walking + * + * @param bool enable = true + */ + int SetWaterWalk(lua_State* L, Unit* unit) + { + bool enable = Eluna::CHECKVAL(L, 2, true); + unit->SetWaterWalking(enable); + return 0; + } + + /** + * Sets the [Unit]'s stand state + * + * @param uint8 state : stand state + */ + int SetStandState(lua_State* L, Unit* unit) + { + uint8 state = Eluna::CHECKVAL(L, 2); +#ifdef TRINITY + unit->SetStandState(UnitStandStateType(state)); +#else + unit->SetStandState(state); +#endif + return 0; + } + + /** + * Sets the [Unit] in combat with the `enemy` [Unit]. + * + * @param [Unit] enemy : the [Unit] to start combat with + */ + int SetInCombatWith(lua_State* L, Unit* unit) + { + Unit* enemy = Eluna::CHECKOBJ(L, 2); + unit->SetInCombatWith(enemy); + return 0; + } + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Sets the [Unit]'s FFA flag on or off. + * + * @param bool apply = true + */ + int SetFFA(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + +#ifdef TRINITY + if (apply) + { + unit->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + for (Unit::ControlList::iterator itr = unit->m_Controlled.begin(); itr != unit->m_Controlled.end(); ++itr) + (*itr)->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + } + else + { + unit->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + for (Unit::ControlList::iterator itr = unit->m_Controlled.begin(); itr != unit->m_Controlled.end(); ++itr) + (*itr)->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + } +#elif AZEROTHCORE + if (apply) + { + unit->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + for (Unit::ControlSet::iterator itr = unit->m_Controlled.begin(); itr != unit->m_Controlled.end(); ++itr) + (*itr)->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + } + else + { + unit->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + for (Unit::ControlSet::iterator itr = unit->m_Controlled.begin(); itr != unit->m_Controlled.end(); ++itr) + (*itr)->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + } +#elif CMANGOS + unit->SetPvPFreeForAll(apply); +#else + unit->SetFFAPvP(apply); +#endif + return 0; + } + + /** + * Sets the [Unit]'s sanctuary flag on or off. + * + * @param bool apply = true + */ + int SetSanctuary(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + if (apply) + { +#ifndef CMANGOS + unit->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY); +#else + unit->SetPvPSanctuary(true); +#endif + unit->CombatStop(); + unit->CombatStopWithPets(); + } + else +#ifndef CMANGOS + unit->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY); +#else + unit->SetPvPSanctuary(false); +#endif + + return 0; + } + + int SetCritterGUID(lua_State* L, Unit* unit) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); +#if defined TRINITY || AZEROTHCORE + unit->SetCritterGUID(guid); +#else + unit->SetCritterGuid(guid); +#endif + return 0; + } +#endif + + /*int SetStunned(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + unit->SetControlled(apply, UNIT_STATE_STUNNED); + return 0; + }*/ + + /** + * Roots the [Unit] to the ground, if 'false' specified, unroots the [Unit]. + * + * @param bool apply = true + */ + int SetRooted(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + unit->SetRooted(apply); + return 0; + } + + /** + * Confuses the [Unit], if 'false' specified, the [Unit] is no longer confused. + * + * @param bool apply = true + */ + int SetConfused(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); +#if defined TRINITY || AZEROTHCORE + unit->SetControlled(apply, UNIT_STATE_CONFUSED); +#else + unit->SetConfused(apply); +#endif + return 0; + } + + /** + * Fears the [Unit], if 'false' specified, the [Unit] is no longer feared. + * + * @param bool apply = true + */ + int SetFeared(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); +#if defined TRINITY || AZEROTHCORE + unit->SetControlled(apply, UNIT_STATE_FLEEING); +#elif defined CMANGOS + unit->SetFleeing(apply); +#else + unit->SetFeared(apply); +#endif + return 0; + } + + /*int SetCanFly(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + unit->SetCanFly(apply); + return 0; + }*/ + + /*int SetVisible(lua_State* L, Unit* unit) + { + bool x = Eluna::CHECKVAL(L, 2, true); + unit->SetVisible(x); + return 0; + }*/ + + /** + * Clears the [Unit]'s threat list. + */ + int ClearThreatList(lua_State* /*L*/, Unit* unit) + { +#ifdef TRINITY + unit->GetThreatManager().ClearAllThreat(); +#elif AZEROTHCORE + unit->getThreatMgr().clearReferences(); +#elif CMANGOS + unit->getThreatManager().clearReferences(); +#else + unit->GetThreatManager().clearReferences(); +#endif + return 0; + } + + /** + * Mounts the [Unit] on the given displayID/modelID. + * + * @param uint32 displayId + */ + int Mount(lua_State* L, Unit* unit) + { + uint32 displayId = Eluna::CHECKVAL(L, 2); + + unit->Mount(displayId); + return 0; + } + + /** + * Dismounts the [Unit]. + */ + int Dismount(lua_State* /*L*/, Unit* unit) + { + if (unit->IsMounted()) + { +#if defined TRINITY || AZEROTHCORE + unit->Dismount(); + unit->RemoveAurasByType(SPELL_AURA_MOUNTED); +#else + unit->Unmount(); + unit->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); +#endif + } + + return 0; + } + + /** + * Makes the [Unit] perform the given emote. + * + * @param uint32 emoteId + */ + int PerformEmote(lua_State* L, Unit* unit) + { +#ifdef TRINITY + Emote emote = static_cast(Eluna::CHECKVAL(L, 2)); + unit->HandleEmoteCommand(emote); +#else + unit->HandleEmoteCommand(Eluna::CHECKVAL(L, 2)); +#endif + return 0; + } + + /** + * Makes the [Unit] perform the given emote continuously. + * + * @param uint32 emoteId + */ + int EmoteState(lua_State* L, Unit* unit) + { + uint32 emoteId = Eluna::CHECKVAL(L, 2); + + unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, emoteId); + return 0; + } + + /** + * Returns calculated percentage from Health + * + * @return int32 percentage + */ + int CountPctFromCurHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->CountPctFromCurHealth(Eluna::CHECKVAL(L, 2))); + return 1; + } + + /** + * Returns calculated percentage from Max Health + * + * @return int32 percentage + */ + int CountPctFromMaxHealth(lua_State* L, Unit* unit) + { + Eluna::Push(L, unit->CountPctFromMaxHealth(Eluna::CHECKVAL(L, 2))); + return 1; + } + + /** + * Sends chat message to [Player] + * + * @param uint8 type : chat, whisper, etc + * @param uint32 lang : language to speak + * @param string msg + * @param [Player] target + */ + int SendChatMessageToPlayer(lua_State* L, Unit* unit) + { + uint8 type = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); + std::string msg = Eluna::CHECKVAL(L, 4); + Player* target = Eluna::CHECKOBJ(L, 5); + + if (type >= MAX_CHAT_MSG_TYPE) + return luaL_argerror(L, 2, "valid ChatMsg expected"); + if (lang >= LANGUAGES_COUNT) + return luaL_argerror(L, 3, "valid Language expected"); + + WorldPacket data; +#if defined TRINITY || AZEROTHCORE + ChatHandler::BuildChatPacket(data, ChatMsg(type), Language(lang), unit, target, msg); +#else + ChatHandler::BuildChatPacket(data, ChatMsg(type), msg.c_str(), Language(lang), 0, unit->GET_GUID(), unit->GetName(), target->GET_GUID(), target->GetName()); +#endif +#ifdef CMANGOS + target->GetSession()->SendPacket(data); +#else + target->GetSession()->SendPacket(&data); +#endif + return 0; + } + + /*static void PrepareMove(Unit* unit) + { + unit->GetMotionMaster()->MovementExpired(); // Chase + unit->StopMoving(); // Some + unit->GetMotionMaster()->Clear(); // all + }*/ + + /** + * Stops the [Unit]'s movement + */ + int MoveStop(lua_State* /*L*/, Unit* unit) + { + unit->StopMoving(); + return 0; + } + + /** + * The [Unit]'s movement expires and clears movement + * + * @param bool reset = true : cleans movement + */ + int MoveExpire(lua_State* L, Unit* unit) + { +#ifdef TRINITY + (void) L; // ensure that the variable is referenced in order to pass compiler checks + unit->GetMotionMaster()->Clear(); +#else + bool reset = Eluna::CHECKVAL(L, 2, true); + unit->GetMotionMaster()->MovementExpired(reset); +#endif + return 0; + } + + /** + * Clears the [Unit]'s movement + * + * @param bool reset = true : clean movement + */ + int MoveClear(lua_State* L, Unit* unit) + { +#ifdef TRINITY + (void) L; // ensure that the variable is referenced in order to pass compiler checks + unit->GetMotionMaster()->Clear(); +#else + bool reset = Eluna::CHECKVAL(L, 2, true); + unit->GetMotionMaster()->Clear(reset); +#endif + return 0; + } + + /** + * The [Unit] will be idle + */ + int MoveIdle(lua_State* /*L*/, Unit* unit) + { + unit->GetMotionMaster()->MoveIdle(); + return 0; + } + + /** + * The [Unit] will move at random + * + * @param float radius : limit on how far the [Unit] will move at random + */ + int MoveRandom(lua_State* L, Unit* unit) + { + float radius = Eluna::CHECKVAL(L, 2); + float x, y, z; + unit->GetPosition(x, y, z); + unit->GetMotionMaster()->MoveRandom(true, radius); // TODO: allow vMangos Eluna to set "use_current_position" instead of magic 'true' + return 0; + } + + /** + * The [Unit] will move to its set home location + */ + int MoveHome(lua_State* /*L*/, Unit* unit) + { + unit->GetMotionMaster()->MoveTargetedHome(); + return 0; + } + + /** + * The [Unit] will follow the target + * + * @param [Unit] target : target to follow + * @param float dist = 0 : distance to start following + * @param float angle = 0 + */ + int MoveFollow(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + float dist = Eluna::CHECKVAL(L, 3, 0.0f); + float angle = Eluna::CHECKVAL(L, 4, 0.0f); + unit->GetMotionMaster()->MoveFollow(target, dist, angle); + return 0; + } + + /** + * The [Unit] will chase the target + * + * @param [Unit] target : target to chase + * @param float dist = 0 : distance start chasing + * @param float angle = 0 + */ + int MoveChase(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + float dist = Eluna::CHECKVAL(L, 3, 0.0f); + float angle = Eluna::CHECKVAL(L, 4, 0.0f); + unit->GetMotionMaster()->MoveChase(target, dist, angle); + return 0; + } + + /** + * The [Unit] will move confused + */ + int MoveConfused(lua_State* /*L*/, Unit* unit) + { + unit->GetMotionMaster()->MoveConfused(); + return 0; + } + + /** + * The [Unit] will flee + * + * @param [Unit] target + * @param uint32 time = 0 : flee delay + */ + int MoveFleeing(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + uint32 time = Eluna::CHECKVAL(L, 3, 0); + unit->GetMotionMaster()->MoveFleeing(target, time); + return 0; + } + + /** + * The [Unit] will move to the coordinates + * + * @param uint32 id : unique waypoint Id + * @param float x + * @param float y + * @param float z + * @param bool genPath = true : if true, generates path + */ + int MoveTo(lua_State* L, Unit* unit) + { + uint32 id = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + bool genPath = Eluna::CHECKVAL(L, 6, true); +#ifndef CMANGOS + unit->GetMotionMaster()->MovePoint(id, x, y, z, genPath); +#else + unit->GetMotionMaster()->MovePoint(id, x, y, z, FORCED_MOVEMENT_NONE, genPath); +#endif + return 0; + } + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Makes the [Unit] jump to the coordinates + * + * @param float x + * @param float y + * @param float z + * @param float zSpeed : start velocity + * @param float maxHeight : maximum height + * @param uint32 id = 0 : unique movement Id + */ + int MoveJump(lua_State* L, Unit* unit) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float zSpeed = Eluna::CHECKVAL(L, 5); + float maxHeight = Eluna::CHECKVAL(L, 6); + uint32 id = Eluna::CHECKVAL(L, 7, 0); + +#if (defined(CMANGOS) || defined(MANGOS)) && defined(WOTLK) + unit->GetMotionMaster()->MoveJump(x, y, z, zSpeed, maxHeight, id); +#else + Position pos(x, y, z); + unit->GetMotionMaster()->MoveJump(pos, zSpeed, maxHeight, id); +#endif + return 0; + } +#endif + + /** + * The [Unit] will whisper the message to a [Player] + * + * @param string msg : message for the [Unit] to emote + * @param uint32 lang : language for the [Unit] to speak + * @param [Player] receiver : specific [Unit] to receive the message + * @param bool bossWhisper = false : is a boss whisper + */ + int SendUnitWhisper(lua_State* L, Unit* unit) + { + const char* msg = Eluna::CHECKVAL(L, 2); + uint32 lang = Eluna::CHECKVAL(L, 3); + (void)lang; // ensure that the variable is referenced in order to pass compiler checks + Player* receiver = Eluna::CHECKOBJ(L, 4); + bool bossWhisper = Eluna::CHECKVAL(L, 5, false); + if (std::string(msg).length() > 0) +#if defined(TRINITY) || defined(AZEROTHCORE) + unit->Whisper(msg, (Language)lang, receiver, bossWhisper); +#else + unit->MonsterWhisper(msg, receiver, bossWhisper); +#endif + return 0; + } + + /** + * The [Unit] will emote the message + * + * @param string msg : message for the [Unit] to emote + * @param [Unit] receiver = nil : specific [Unit] to receive the message + * @param bool bossEmote = false : is a boss emote + */ + int SendUnitEmote(lua_State* L, Unit* unit) + { + const char* msg = Eluna::CHECKVAL(L, 2); + Unit* receiver = Eluna::CHECKOBJ(L, 3, false); + bool bossEmote = Eluna::CHECKVAL(L, 4, false); + if (std::string(msg).length() > 0) +#if defined(TRINITY) || defined(AZEROTHCORE) + unit->TextEmote(msg, receiver, bossEmote); +#else + unit->MonsterTextEmote(msg, receiver, bossEmote); +#endif + return 0; + } + + /** + * The [Unit] will say the message + * + * @param string msg : message for the [Unit] to say + * @param uint32 language : language for the [Unit] to speak + */ + int SendUnitSay(lua_State* L, Unit* unit) + { + const char* msg = Eluna::CHECKVAL(L, 2); + uint32 language = Eluna::CHECKVAL(L, 3); + if (std::string(msg).length() > 0) +#if defined(TRINITY) || defined(AZEROTHCORE) + unit->Say(msg, (Language)language, unit); +#else + unit->MonsterSay(msg, language, unit); +#endif + return 0; + } + + /** + * The [Unit] will yell the message + * + * @param string msg : message for the [Unit] to yell + * @param uint32 language : language for the [Unit] to speak + */ + int SendUnitYell(lua_State* L, Unit* unit) + { + const char* msg = Eluna::CHECKVAL(L, 2); + uint32 language = Eluna::CHECKVAL(L, 3); + if (std::string(msg).length() > 0) +#if defined(TRINITY) || defined(AZEROTHCORE) + unit->Yell(msg, (Language)language, unit); +#else + unit->MonsterYell(msg, language, unit); +#endif + return 0; + } + + /** + * Unmorphs the [Unit] setting it's display ID back to the native display ID. + */ + int DeMorph(lua_State* /*L*/, Unit* unit) + { + unit->DeMorph(); + return 0; + } + + /** + * Makes the [Unit] cast the spell on the target. + * + * @param [Unit] target = nil : can be self or another unit + * @param uint32 spell : entry of a spell + * @param bool triggered = false : if true the spell is instant and has no cost + */ + int CastSpell(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2, false); + uint32 spell = Eluna::CHECKVAL(L, 3); + bool triggered = Eluna::CHECKVAL(L, 4, false); +#ifdef CMANGOS + SpellEntry const* spellEntry = GetSpellStore()->LookupEntry(spell); +#endif +#ifdef MANGOS + SpellEntry const* spellEntry = sSpellStore.LookupEntry(spell); +#endif + SpellEntry const* spellEntry = sSpellMgr.GetSpellEntry(spell); + if (!spellEntry) + return 0; + +#ifdef CMANGOS + unit->CastSpell(target, spell, triggered ? TRIGGERED_OLD_TRIGGERED : 0); +#else + unit->CastSpell(target, spell, triggered); +#endif + return 0; + } + + /** + * Casts the [Spell] at target [Unit] with custom basepoints or casters. + * See also [Unit:CastSpell]. + * + * @param [Unit] target = nil + * @param uint32 spell + * @param bool triggered = false + * @param int32 bp0 = nil : custom basepoints for [Spell] effect 1. If nil, no change is made + * @param int32 bp1 = nil : custom basepoints for [Spell] effect 2. If nil, no change is made + * @param int32 bp2 = nil : custom basepoints for [Spell] effect 3. If nil, no change is made + * @param [Item] castItem = nil + * @param ObjectGuid originalCaster = ObjectGuid() + */ + int CastCustomSpell(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2, false); + uint32 spell = Eluna::CHECKVAL(L, 3); + bool triggered = Eluna::CHECKVAL(L, 4, false); + bool has_bp0 = !lua_isnoneornil(L, 5); + int32 bp0 = Eluna::CHECKVAL(L, 5, 0); + bool has_bp1 = !lua_isnoneornil(L, 6); + int32 bp1 = Eluna::CHECKVAL(L, 6, 0); + bool has_bp2 = !lua_isnoneornil(L, 7); + int32 bp2 = Eluna::CHECKVAL(L, 7, 0); + Item* castItem = Eluna::CHECKOBJ(L, 8, false); + ObjectGuid originalCaster = Eluna::CHECKVAL(L, 9, ObjectGuid()); + +#ifdef TRINITY + CastSpellExtraArgs args; + if (has_bp0) + args.AddSpellMod(SPELLVALUE_BASE_POINT0, bp0); + if (has_bp1) + args.AddSpellMod(SPELLVALUE_BASE_POINT1, bp1); + if (has_bp2) + args.AddSpellMod(SPELLVALUE_BASE_POINT2, bp2); + if (triggered) + args.TriggerFlags = TRIGGERED_FULL_MASK; + if (castItem) + args.SetCastItem(castItem); + if (originalCaster) + args.SetOriginalCaster(originalCaster); + unit->CastSpell(target, spell, args); +#else + unit->CastCustomSpell(target, spell, has_bp0 ? bp0 : NULL, has_bp1 ? bp1 : NULL, has_bp2 ? bp2 : NULL, triggered, castItem, NULL, ObjectGuid(originalCaster)); +#endif + return 0; + } + + /** + * Makes the [Unit] cast the spell to the given coordinates, used for area effect spells. + * + * @param float x + * @param float y + * @param float z + * @param uint32 spell : entry of a spell + * @param bool triggered = true : if true the spell is instant and has no cost + */ + int CastSpellAoF(lua_State* L, Unit* unit) + { + float _x = Eluna::CHECKVAL(L, 2); + float _y = Eluna::CHECKVAL(L, 3); + float _z = Eluna::CHECKVAL(L, 4); + uint32 spell = Eluna::CHECKVAL(L, 5); + bool triggered = Eluna::CHECKVAL(L, 6, true); +#ifdef CMANGOS + unit->CastSpell(_x, _y, _z, spell, triggered ? TRIGGERED_OLD_TRIGGERED : 0); +#endif +#ifdef MANGOS + unit->CastSpell(_x, _y, _z, spell, triggered); +#endif +#ifdef AZEROTHCORE + unit->CastSpell(_x, _y, _z, spell, triggered); +#endif +#ifdef TRINITY + CastSpellExtraArgs args; + if (triggered) + args.TriggerFlags = TRIGGERED_FULL_MASK; + unit->CastSpell(Position(_x, _y, _z), spell, args); +#endif + return 0; + } + + /** + * Clears the [Unit]'s combat + */ + int ClearInCombat(lua_State* /*L*/, Unit* unit) + { + unit->ClearInCombat(); + return 0; + } + + /** + * Stops the [Unit]'s current spell cast + * + * @param uint32 spell = 0 : entry of a spell + */ + int StopSpellCast(lua_State* L, Unit* unit) + { + uint32 spellId = Eluna::CHECKVAL(L, 2, 0); + for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) + if (Spell* spell = unit->GetCurrentSpell(CurrentSpellTypes(i))) + if (spell->getState() == SPELL_STATE_PREPARING && spell->GetCastedTime()) + if (spell->m_spellInfo->IsNonCombatSpell()) + unit->InterruptSpell(CurrentSpellTypes(i), false); + return 0; + } + + /** + * Interrupts [Unit]'s spell state, casting, etc. + * + * if spell is not interruptible, it will return + * + * @param int32 spellType : type of spell to interrupt + * @param bool delayed = true : skips if the spell is delayed + */ + int InterruptSpell(lua_State* L, Unit* unit) + { + int spellType = Eluna::CHECKVAL(L, 2); + bool delayed = Eluna::CHECKVAL(L, 3, true); + switch (spellType) + { + case 0: + spellType = CURRENT_MELEE_SPELL; + break; + case 1: + spellType = CURRENT_GENERIC_SPELL; + break; + case 2: + spellType = CURRENT_CHANNELED_SPELL; + break; + case 3: + spellType = CURRENT_AUTOREPEAT_SPELL; + break; + default: + return luaL_argerror(L, 2, "valid CurrentSpellTypes expected"); + } + + unit->InterruptSpell((CurrentSpellTypes)spellType, delayed); + return 0; + } + + /** + * Adds the [Aura] of the given spell entry on the given target from the [Unit]. + * + * @param uint32 spell : entry of a spell + * @param [Unit] target : aura will be applied on the target + * @return [Aura] aura + */ + int AddAura(lua_State* L, Unit* unit) + { + uint32 spell = Eluna::CHECKVAL(L, 2); + Unit* target = Eluna::CHECKOBJ(L, 3); + SpellEntry const* spellEntry = sSpellMgr.GetSpellEntry(spell); + + if (!spellEntry) + return 1; + +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, unit->AddAura(spell, target)); +#elif defined VMANGOS + SpellAuraHolder* spellAuraHolder = unit->AddAura(spell, 0, target); + Aura* aura = nullptr; + if (spellAuraHolder) + { + aura = spellAuraHolder->GetAuraByEffectIndex(SpellEffIndex(0)); + } + else + { + aura = unit->GetAura(spell, SpellEffIndex(0)); + } + Eluna::Push(L, aura); // TODO: 0 is magic number for "addAuraFlags" +#else + if (!IsSpellAppliesAura(spellEntry) && !IsSpellHaveEffect(spellEntry, SPELL_EFFECT_PERSISTENT_AREA_AURA)) + return 1; + + SpellAuraHolder* holder = CreateSpellAuraHolder(spellEntry, target, unit); + + for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) + { + uint8 eff = spellEntry->Effect[i]; +#ifndef CMANGOS + if (eff >= TOTAL_SPELL_EFFECTS) +#else + if (eff >= MAX_SPELL_EFFECTS) +#endif + continue; + if (IsAreaAuraEffect(eff) || + eff == SPELL_EFFECT_APPLY_AURA || + eff == SPELL_EFFECT_PERSISTENT_AREA_AURA) + { +#ifndef CMANGOS + Aura* aur = CreateAura(spellEntry, SpellEffIndex(i), NULL, holder, target); +#else + Aura* aur = CreateAura(spellEntry, SpellEffIndex(i), NULL, NULL, holder, target); +#endif + holder->AddAura(aur, SpellEffIndex(i)); + } + } + Eluna::Push(L, target->AddSpellAuraHolder(holder)); +#endif + return 1; + } + + /** + * Removes [Aura] of the given spell entry from the [Unit]. + * + * @param uint32 spell : entry of a spell + */ + int RemoveAura(lua_State* L, Unit* unit) + { + uint32 spellId = Eluna::CHECKVAL(L, 2); + unit->RemoveAurasDueToSpell(spellId); + return 0; + } + + /** + * Removes all [Aura]'s from the [Unit]. + * + * Note: talents and racials are also auras, use with caution + */ + int RemoveAllAuras(lua_State* /*L*/, Unit* unit) + { + unit->RemoveAllAuras(); + return 0; + } + +#if !defined(CLASSIC) + /** + * Removes all positive visible [Aura]'s from the [Unit]. + */ + int RemoveArenaAuras(lua_State* /*L*/, Unit* unit) + { + unit->RemoveArenaAuras(); + return 0; + } +#endif + + /** + * Adds the given unit state for the [Unit]. + * + * @param [UnitState] state + */ + int AddUnitState(lua_State* L, Unit* unit) + { + uint32 state = Eluna::CHECKVAL(L, 2); + + unit->AddUnitState(state); + return 0; + } + + /** + * Removes the given unit state from the [Unit]. + * + * @param [UnitState] state + */ + int ClearUnitState(lua_State* L, Unit* unit) + { + uint32 state = Eluna::CHECKVAL(L, 2); + + unit->ClearUnitState(state); + return 0; + } + + /** + * Makes the [Unit] teleport to given coordinates within same map. + * + * @param float x + * @param float y + * @param float z + * @param float o : orientation + */ + int NearTeleport(lua_State* L, Unit* unit) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float o = Eluna::CHECKVAL(L, 5); + + unit->NearTeleportTo(x, y, z, o); + return 0; + } + + /** + * Makes the [Unit] damage the target [Unit] + * + *
+     * enum SpellSchools
+     * {
+     *     SPELL_SCHOOL_NORMAL  = 0,
+     *     SPELL_SCHOOL_HOLY    = 1,
+     *     SPELL_SCHOOL_FIRE    = 2,
+     *     SPELL_SCHOOL_NATURE  = 3,
+     *     SPELL_SCHOOL_FROST   = 4,
+     *     SPELL_SCHOOL_SHADOW  = 5,
+     *     SPELL_SCHOOL_ARCANE  = 6,
+     *     MAX_SPELL_SCHOOL     = 7
+     * };
+     * 
+ * + * @param [Unit] target : [Unit] to damage + * @param uint32 damage : amount to damage + * @param bool durabilityloss = true : if false, the damage does not do durability damage + * @param [SpellSchools] school = MAX_SPELL_SCHOOL : school the damage is done in or MAX_SPELL_SCHOOL for direct damage + * @param uint32 spell = 0 : spell that inflicts the damage + */ + int DealDamage(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + uint32 damage = Eluna::CHECKVAL(L, 3); + bool durabilityloss = Eluna::CHECKVAL(L, 4, true); + uint32 school = Eluna::CHECKVAL(L, 5, MAX_SPELL_SCHOOL); + uint32 spell = Eluna::CHECKVAL(L, 6, 0); + if (school > MAX_SPELL_SCHOOL) + return luaL_argerror(L, 6, "valid SpellSchool expected"); + + // flat melee damage without resistence/etc reduction + if (school == MAX_SPELL_SCHOOL) + { + unit->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, durabilityloss); + unit->SendAttackStateUpdate(HITINFO_AFFECTS_VICTIM, target, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); + return 0; + } + + SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); + +#if defined TRINITY || AZEROTHCORE + if (Unit::IsDamageReducedByArmor(schoolmask)) + damage = Unit::CalcArmorReducedDamage(unit, target, damage, NULL, BASE_ATTACK); +#else + if (schoolmask & SPELL_SCHOOL_MASK_NORMAL) +#ifndef CMANGOS + damage = unit->CalcArmorReducedDamage(target, damage); +#else + damage = unit->CalcArmorReducedDamage(unit, target, damage); +#endif +#endif + +#ifdef TRINITY + // melee damage by specific school + if (!spell) + { + DamageInfo dmgInfo(unit, target, damage, nullptr, schoolmask, SPELL_DIRECT_DAMAGE, BASE_ATTACK); + unit->CalcAbsorbResist(dmgInfo); + + if (!dmgInfo.GetDamage()) + damage = 0; + else + damage = dmgInfo.GetDamage(); + + uint32 absorb = dmgInfo.GetAbsorb(); + uint32 resist = dmgInfo.GetResist(); + unit->DealDamageMods(target, damage, &absorb); +#ifdef TRINITY + Unit::DealDamage(unit, target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); +#else + unit->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); +#endif + unit->SendAttackStateUpdate(HITINFO_AFFECTS_VICTIM, target, 0, schoolmask, damage, absorb, resist, VICTIMSTATE_HIT, 0); + return 0; + } + + if (!spell) + return 0; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell); + if (!spellInfo) + return 0; + + SpellNonMeleeDamage dmgInfo(unit, target, spell, spellInfo->GetSchoolMask()); +#ifdef TRINITY + Unit::DealDamageMods(dmgInfo.target, dmgInfo.damage, &dmgInfo.absorb); +#else + damage = unit->SpellDamageBonusDone(target, spellInfo, damage, SPELL_DIRECT_DAMAGE; + damage = target->SpellDamageBonusTaken(unit, spellInfo, damage, SPELL_DIRECT_DAMAGE); + unit->CalculateSpellDamageTaken(&dmgInfo, damage, spellInfo); + unit->DealDamageMods(dmgInfo.target, dmgInfo.damage, &dmgInfo.absorb); +#endif + + unit->SendSpellNonMeleeDamageLog(&dmgInfo); + unit->DealSpellDamage(&dmgInfo, true); + return 0; +#elif AZEROTHCORE + if (!spell) + { + DamageInfo dmgInfo(unit, target, damage, nullptr, schoolmask, SPELL_DIRECT_DAMAGE); + unit->CalcAbsorbResist(dmgInfo); + + if (!dmgInfo.GetDamage()) + damage = 0; + else + damage = dmgInfo.GetDamage(); + + uint32 absorb = dmgInfo.GetAbsorb(); + uint32 resist = dmgInfo.GetResist(); + unit->DealDamageMods(target, damage, &absorb); + Unit::DealDamage(unit, target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); + unit->SendAttackStateUpdate(HITINFO_AFFECTS_VICTIM, target, 0, schoolmask, damage, absorb, resist, VICTIMSTATE_HIT, 0); + return 0; + } + + if (!spell) + return 0; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell); + if (!spellInfo) + return 0; + + SpellNonMeleeDamage dmgInfo(unit, target, spellInfo, spellInfo->GetSchoolMask()); + Unit::DealDamageMods(dmgInfo.target, dmgInfo.damage, &dmgInfo.absorb); + unit->SendSpellNonMeleeDamageLog(&dmgInfo); + unit->DealSpellDamage(&dmgInfo, true); + return 0; +#else + // melee damage by specific school + if (!spell) + { + uint32 absorb = 0; + int32 resist = 0; + target->CalculateDamageAbsorbAndResist(unit, schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + + if (damage <= absorb + resist) + damage = 0; + else + damage -= absorb + resist; + + unit->DealDamageMods(target, damage, &absorb); + unit->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); + unit->SendAttackStateUpdate(HITINFO_AFFECTS_VICTIM, target, schoolmask, damage, absorb, resist, VICTIMSTATE_NORMAL, 0); + return 0; + } + + // non-melee damage + unit->SendSpellNonMeleeDamageLog(target, spell, damage, SPELL_SCHOOL_MASK_NONE, 0, 0, false, 0); + return 0; +#endif + } + + /** + * Makes the [Unit] heal the target [Unit] with given spell + * + * @param [Unit] target : [Unit] to heal + * @param uint32 spell : spell that causes the healing + * @param uint32 amount : amount to heal + * @param bool critical = false : if true, heal is logged as critical + */ + int DealHeal(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + uint32 spell = Eluna::CHECKVAL(L, 3); + uint32 amount = Eluna::CHECKVAL(L, 4); + bool critical = Eluna::CHECKVAL(L, 5, false); + +#if defined TRINITY || AZEROTHCORE + if (const SpellInfo* info = sSpellMgr->GetSpellInfo(spell)) + { + HealInfo healInfo(unit, target, amount, info, info->GetSchoolMask()); + unit->HealBySpell(healInfo, critical); + } +#else + SpellEntry const* spellEntry = sSpellMgr.GetSpellEntry(spell); + if (spellEntry) + unit->DealHeal(target, amount, spellEntry, critical); +#endif + return 0; + } + + /** + * Makes the [Unit] kill the target [Unit] + * + * @param [Unit] target : [Unit] to kill + * @param bool durLoss = true : when true, the target's items suffer durability loss + */ + int Kill(lua_State* L, Unit* unit) + { + Unit* target = Eluna::CHECKOBJ(L, 2); + bool durLoss = Eluna::CHECKVAL(L, 3, true); + +#if defined TRINITY || AZEROTHCORE + Unit::Kill(unit, target, durLoss); +#elif defined CMANGOS + unit->DealDamage(unit, target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, durLoss); +#else + unit->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, durLoss); +#endif + return 0; + } + + /** + * Adds threat to the [Unit] from the victim. + * + *
+     * enum SpellSchoolMask
+     * {
+     *     SPELL_SCHOOL_MASK_NONE    = 0,
+     *     SPELL_SCHOOL_MASK_NORMAL  = 1,
+     *     SPELL_SCHOOL_MASK_HOLY    = 2,
+     *     SPELL_SCHOOL_MASK_FIRE    = 4,
+     *     SPELL_SCHOOL_MASK_NATURE  = 8,
+     *     SPELL_SCHOOL_MASK_FROST   = 16,
+     *     SPELL_SCHOOL_MASK_SHADOW  = 32,
+     *     SPELL_SCHOOL_MASK_ARCANE  = 64,
+     * }
+     * 
+ * + * @param [Unit] victim : [Unit] that caused the threat + * @param float threat : threat amount + * @param [SpellSchoolMask] schoolMask = 0 : [SpellSchoolMask] of the threat causer + * @param uint32 spell = 0 : spell entry used for threat + */ + int AddThreat(lua_State* L, Unit* unit) + { + Unit* victim = Eluna::CHECKOBJ(L, 2); + float threat = Eluna::CHECKVAL(L, 3, true); + uint32 spell = Eluna::CHECKVAL(L, 4, 0); + +#ifdef TRINITY + unit->GetThreatManager().AddThreat(victim, threat, spell ? sSpellMgr->GetSpellInfo(spell) : NULL, true, true); +#elif AZEROTHCORE + uint32 schoolMask = Eluna::CHECKVAL(L, 5, 0); + if (schoolMask > SPELL_SCHOOL_MASK_ALL) + { + return luaL_argerror(L, 4, "valid SpellSchoolMask expected"); + } + unit->AddThreat(victim, threat, (SpellSchoolMask)schoolMask, spell ? sSpellMgr->GetSpellInfo(spell) : NULL); +#else + SpellEntry const* spellEntry = sSpellMgr.GetSpellEntry(spell); + unit->AddThreat(victim, threat, false, spellEntry ? GetSchoolMask(spellEntry->School) : SPELL_SCHOOL_MASK_NONE, spellEntry); +#endif + return 0; + } + + /*int RestoreDisplayId(lua_State* L, Unit* unit) + { + unit->RestoreDisplayId(); + return 0; + }*/ + + /*int RestoreFaction(lua_State* L, Unit* unit) + { + unit->RestoreFaction(); + return 0; + }*/ + + /*int RemoveBindSightAuras(lua_State* L, Unit* unit) + { + unit->RemoveBindSightAuras(); + return 0; + }*/ + + /*int RemoveCharmAuras(lua_State* L, Unit* unit) + { + unit->RemoveCharmAuras(); + return 0; + }*/ + + /*int DisableMelee(lua_State* L, Unit* unit) + { + bool apply = Eluna::CHECKVAL(L, 2, true); + + if (apply) + unit->AddUnitState(UNIT_STATE_CANNOT_AUTOATTACK); + else + unit->ClearUnitState(UNIT_STATE_CANNOT_AUTOATTACK); + return 0; + }*/ + + /*int SummonGuardian(lua_State* L, Unit* unit) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + uint32 desp = Eluna::CHECKVAL(L, 7, 0); + + SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(61); + if (!properties) + return 1; + Position pos; + pos.Relocate(x,y,z,o); + TempSummon* summon = unit->GetMap()->SummonCreature(entry, pos, properties, desp, unit); + + if (!summon) + return 1; + + if (summon->HasUnitTypeMask(UNIT_MASK_GUARDIAN)) + ((Guardian*)summon)->InitStatsForLevel(unit->getLevel()); + + if (properties && properties->Category == SUMMON_CATEGORY_ALLY) + summon->setFaction(unit->getFaction()); + if (summon->GetEntry() == 27893) + { + if (uint32 weapon = unit->GetUInt32Value(PLAYER_VISIBLE_ITEM_16_ENTRYID)) + { + summon->SetDisplayId(11686); + summon->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, weapon); + } + else + summon->SetDisplayId(1126); + } + summon->AI()->EnterEvadeMode(); + + Eluna::Push(L, summon); + return 1; + }*/ + + ElunaRegister UnitMethods[] = + { + // Getters + { "GetLevel", &LuaUnit::GetLevel }, + { "GetHealth", &LuaUnit::GetHealth }, + { "GetDisplayId", &LuaUnit::GetDisplayId }, + { "GetNativeDisplayId", &LuaUnit::GetNativeDisplayId }, + { "GetPower", &LuaUnit::GetPower }, + { "GetMaxPower", &LuaUnit::GetMaxPower }, + { "GetPowerType", &LuaUnit::GetPowerType }, + { "GetMaxHealth", &LuaUnit::GetMaxHealth }, + { "GetHealthPct", &LuaUnit::GetHealthPct }, + { "GetPowerPct", &LuaUnit::GetPowerPct }, + { "GetGender", &LuaUnit::GetGender }, + { "GetRace", &LuaUnit::GetRace }, + { "GetClass", &LuaUnit::GetClass }, + { "GetRaceMask", &LuaUnit::GetRaceMask }, + { "GetClassMask", &LuaUnit::GetClassMask }, + { "GetRaceAsString", &LuaUnit::GetRaceAsString }, + { "GetClassAsString", &LuaUnit::GetClassAsString }, + { "GetAura", &LuaUnit::GetAura }, + { "GetFaction", &LuaUnit::GetFaction }, + { "GetCurrentSpell", &LuaUnit::GetCurrentSpell }, + { "GetCreatureType", &LuaUnit::GetCreatureType }, + { "GetMountId", &LuaUnit::GetMountId }, + { "GetOwner", &LuaUnit::GetOwner }, + { "GetFriendlyUnitsInRange", &LuaUnit::GetFriendlyUnitsInRange }, + { "GetUnfriendlyUnitsInRange", &LuaUnit::GetUnfriendlyUnitsInRange }, + { "GetOwnerGUID", &LuaUnit::GetOwnerGUID }, + { "GetCreatorGUID", &LuaUnit::GetCreatorGUID }, + { "GetMinionGUID", &LuaUnit::GetPetGUID }, + { "GetCharmerGUID", &LuaUnit::GetCharmerGUID }, + { "GetCharmGUID", &LuaUnit::GetCharmGUID }, + { "GetPetGUID", &LuaUnit::GetPetGUID }, + { "GetControllerGUID", &LuaUnit::GetControllerGUID }, + { "GetControllerGUIDS", &LuaUnit::GetControllerGUIDS }, + { "GetStandState", &LuaUnit::GetStandState }, + { "GetVictim", &LuaUnit::GetVictim }, + { "GetSpeed", &LuaUnit::GetSpeed }, + { "GetStat", &LuaUnit::GetStat }, + { "GetBaseSpellPower", &LuaUnit::GetBaseSpellPower }, + { "GetMovementType", &LuaUnit::GetMovementType }, +#if (!defined(TBC) && !defined(CLASSIC)) + { "GetVehicleKit", &LuaUnit::GetVehicleKit }, + { "GetCritterGUID", &LuaUnit::GetCritterGUID }, +#endif + + // Setters + { "SetFaction", &LuaUnit::SetFaction }, + { "SetLevel", &LuaUnit::SetLevel }, + { "SetHealth", &LuaUnit::SetHealth }, + { "SetMaxHealth", &LuaUnit::SetMaxHealth }, + { "SetPower", &LuaUnit::SetPower }, + { "SetMaxPower", &LuaUnit::SetMaxPower }, + { "SetPowerType", &LuaUnit::SetPowerType }, + { "SetDisplayId", &LuaUnit::SetDisplayId }, + { "SetNativeDisplayId", &LuaUnit::SetNativeDisplayId }, + { "SetFacing", &LuaUnit::SetFacing }, + { "SetFacingToObject", &LuaUnit::SetFacingToObject }, + { "SetSpeed", &LuaUnit::SetSpeed }, + { "SetRooted", &LuaUnit::SetRooted}, + { "SetConfused", &LuaUnit::SetConfused}, + { "SetFeared", &LuaUnit::SetFeared}, + { "SetPvP", &LuaUnit::SetPvP }, + { "SetOwnerGUID", &LuaUnit::SetOwnerGUID }, + { "SetName", &LuaUnit::SetName }, + { "SetSheath", &LuaUnit::SetSheath }, + { "SetCreatorGUID", &LuaUnit::SetCreatorGUID }, + { "SetMinionGUID", &LuaUnit::SetPetGUID }, + { "SetPetGUID", &LuaUnit::SetPetGUID }, + { "SetWaterWalk", &LuaUnit::SetWaterWalk }, + { "SetStandState", &LuaUnit::SetStandState }, + { "SetInCombatWith", &LuaUnit::SetInCombatWith }, + { "ModifyPower", &LuaUnit::ModifyPower }, +#if (!defined(TBC) && !defined(CLASSIC)) + { "SetFFA", &LuaUnit::SetFFA }, + { "SetSanctuary", &LuaUnit::SetSanctuary }, + { "SetCritterGUID", &LuaUnit::SetCritterGUID }, +#endif + + // Boolean + { "IsAlive", &LuaUnit::IsAlive }, + { "IsDead", &LuaUnit::IsDead }, + { "IsDying", &LuaUnit::IsDying }, + { "IsPvPFlagged", &LuaUnit::IsPvPFlagged }, + { "IsInCombat", &LuaUnit::IsInCombat }, + { "IsBanker", &LuaUnit::IsBanker }, + { "IsBattleMaster", &LuaUnit::IsBattleMaster }, + { "IsCharmed", &LuaUnit::IsCharmed }, + { "IsArmorer", &LuaUnit::IsArmorer }, + { "IsAttackingPlayer", &LuaUnit::IsAttackingPlayer }, + { "IsInWater", &LuaUnit::IsInWater }, + { "IsUnderWater", &LuaUnit::IsUnderWater }, + { "IsAuctioneer", &LuaUnit::IsAuctioneer }, + { "IsGuildMaster", &LuaUnit::IsGuildMaster }, + { "IsInnkeeper", &LuaUnit::IsInnkeeper }, + { "IsTrainer", &LuaUnit::IsTrainer }, + { "IsGossip", &LuaUnit::IsGossip }, + { "IsTaxi", &LuaUnit::IsTaxi }, + { "IsSpiritHealer", &LuaUnit::IsSpiritHealer }, + { "IsSpiritGuide", &LuaUnit::IsSpiritGuide }, + { "IsTabardDesigner", &LuaUnit::IsTabardDesigner }, + { "IsServiceProvider", &LuaUnit::IsServiceProvider }, + { "IsSpiritService", &LuaUnit::IsSpiritService }, + { "HealthBelowPct", &LuaUnit::HealthBelowPct }, + { "HealthAbovePct", &LuaUnit::HealthAbovePct }, + { "IsMounted", &LuaUnit::IsMounted }, + { "AttackStop", &LuaUnit::AttackStop }, + { "Attack", &LuaUnit::Attack }, + { "IsStopped", &LuaUnit::IsStopped }, + { "HasUnitState", &LuaUnit::HasUnitState }, + { "IsQuestGiver", &LuaUnit::IsQuestGiver }, + { "IsInAccessiblePlaceFor", &LuaUnit::IsInAccessiblePlaceFor }, + { "IsVendor", &LuaUnit::IsVendor }, + { "IsRooted", &LuaUnit::IsRooted }, + { "IsFullHealth", &LuaUnit::IsFullHealth }, + { "HasAura", &LuaUnit::HasAura }, + { "IsCasting", &LuaUnit::IsCasting }, + { "IsStandState", &LuaUnit::IsStandState }, +#if !defined(CLASSIC) + { "IsOnVehicle", &LuaUnit::IsOnVehicle }, +#endif + + // Other + { "AddAura", &LuaUnit::AddAura }, + { "RemoveAura", &LuaUnit::RemoveAura }, + { "RemoveAllAuras", &LuaUnit::RemoveAllAuras }, + { "ClearInCombat", &LuaUnit::ClearInCombat }, + { "DeMorph", &LuaUnit::DeMorph }, + { "SendUnitWhisper", &LuaUnit::SendUnitWhisper }, + { "SendUnitEmote", &LuaUnit::SendUnitEmote }, + { "SendUnitSay", &LuaUnit::SendUnitSay }, + { "SendUnitYell", &LuaUnit::SendUnitYell }, + { "CastSpell", &LuaUnit::CastSpell }, + { "CastCustomSpell", &LuaUnit::CastCustomSpell }, + { "CastSpellAoF", &LuaUnit::CastSpellAoF }, + { "Kill", &LuaUnit::Kill }, + { "StopSpellCast", &LuaUnit::StopSpellCast }, + { "InterruptSpell", &LuaUnit::InterruptSpell }, + { "SendChatMessageToPlayer", &LuaUnit::SendChatMessageToPlayer }, + { "PerformEmote", &LuaUnit::PerformEmote }, + { "EmoteState", &LuaUnit::EmoteState }, + { "CountPctFromCurHealth", &LuaUnit::CountPctFromCurHealth }, + { "CountPctFromMaxHealth", &LuaUnit::CountPctFromMaxHealth }, + { "Dismount", &LuaUnit::Dismount }, + { "Mount", &LuaUnit::Mount }, + { "ClearThreatList", &LuaUnit::ClearThreatList }, + { "ClearUnitState", &LuaUnit::ClearUnitState }, + { "AddUnitState", &LuaUnit::AddUnitState }, + { "NearTeleport", &LuaUnit::NearTeleport }, + { "MoveIdle", &LuaUnit::MoveIdle }, + { "MoveRandom", &LuaUnit::MoveRandom }, + { "MoveHome", &LuaUnit::MoveHome }, + { "MoveFollow", &LuaUnit::MoveFollow }, + { "MoveChase", &LuaUnit::MoveChase }, + { "MoveConfused", &LuaUnit::MoveConfused }, + { "MoveFleeing", &LuaUnit::MoveFleeing }, + { "MoveTo", &LuaUnit::MoveTo }, + { "MoveStop", &LuaUnit::MoveStop }, + { "MoveExpire", &LuaUnit::MoveExpire }, + { "MoveClear", &LuaUnit::MoveClear }, + { "DealDamage", &LuaUnit::DealDamage }, + { "DealHeal", &LuaUnit::DealHeal }, + { "AddThreat", &LuaUnit::AddThreat }, +#if !defined(CLASSIC) + { "RemoveArenaAuras", &LuaUnit::RemoveArenaAuras }, +#endif +#if (!defined(TBC) && !defined(CLASSIC)) + { "MoveJump", &LuaUnit::MoveJump }, +#endif + + // Not implemented mehtods + { "GetVehicle", nullptr }, // not implemented + { "SetStunned", nullptr }, // not implemented + { "SetCanFly", nullptr }, // not implemented + { "SetVisible", nullptr }, // not implemented + { "IsVisible", nullptr }, // not implemented, + { "IsMoving", nullptr }, // not implemented + { "IsFlying", nullptr }, // not implemented + { "RestoreDisplayId", nullptr }, // not implemented + { "RestoreFaction", nullptr }, // not implemented + { "RemoveBindSightAuras", nullptr }, // not implemented + { "RemoveCharmAuras", nullptr }, // not implemented + { "DisableMelee", nullptr }, // not implemented + { "SummonGuardian", nullptr }, // not implemented + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/VMangos/VehicleMethods.h b/src/modules/Eluna/VMangos/VehicleMethods.h new file mode 100644 index 0000000000..7be79cd3f2 --- /dev/null +++ b/src/modules/Eluna/VMangos/VehicleMethods.h @@ -0,0 +1,128 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef VEHICLEMETHODS_H +#define VEHICLEMETHODS_H +#ifndef CLASSIC +#ifndef TBC + +/*** + * Inherits all methods from: none + */ +namespace LuaVehicle +{ + /** + * Returns true if the [Unit] passenger is on board + * + * @param [Unit] passenger + * @return bool isOnBoard + */ + int IsOnBoard(lua_State* L, Vehicle* vehicle) + { + Unit* passenger = Eluna::CHECKOBJ(L, 2); +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, passenger->IsOnVehicle(vehicle->GetBase())); +#else + Eluna::Push(L, vehicle->HasOnBoard(passenger)); +#endif + return 1; + } + + /** + * Returns the [Vehicle]'s owner + * + * @return [Unit] owner + */ + int GetOwner(lua_State* L, Vehicle* vehicle) + { +#if defined TRINITY || AZEROTHCORE + Eluna::Push(L, vehicle->GetBase()); +#else + Eluna::Push(L, vehicle->GetOwner()); +#endif + return 1; + } + + /** + * Returns the [Vehicle]'s entry + * + * @return uint32 entry + */ + int GetEntry(lua_State* L, Vehicle* vehicle) + { + Eluna::Push(L, vehicle->GetVehicleEntry()->m_ID); + return 1; + } + + /** + * Returns the [Vehicle]'s passenger in the specified seat + * + * @param int8 seat + * @return [Unit] passenger + */ + int GetPassenger(lua_State* L, Vehicle* vehicle) + { + int8 seatId = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, vehicle->GetPassenger(seatId)); + return 1; + } + + /** + * Adds [Unit] passenger to a specified seat in the [Vehicle] + * + * @param [Unit] passenger + * @param int8 seat + */ + int AddPassenger(lua_State* L, Vehicle* vehicle) + { + Unit* passenger = Eluna::CHECKOBJ(L, 2); + int8 seatId = Eluna::CHECKVAL(L, 3); +#if defined TRINITY || AZEROTHCORE + vehicle->AddPassenger(passenger, seatId); +#else + if (vehicle->CanBoard(passenger)) + vehicle->Board(passenger, seatId); +#endif + return 0; + } + + /** + * Removes [Unit] passenger from the [Vehicle] + * + * @param [Unit] passenger + */ + int RemovePassenger(lua_State* L, Vehicle* vehicle) + { + Unit* passenger = Eluna::CHECKOBJ(L, 2); +#if defined TRINITY || AZEROTHCORE + vehicle->RemovePassenger(passenger); +#else + vehicle->UnBoard(passenger, false); +#endif + return 0; + } + + ElunaRegister VehicleMethods[] = + { + // Getters + { "GetOwner", &LuaVehicle::GetOwner }, + { "GetEntry", &LuaVehicle::GetEntry }, + { "GetPassenger", &LuaVehicle::GetPassenger }, + + // Boolean + { "IsOnBoard", &LuaVehicle::IsOnBoard }, + + // Other + { "AddPassenger", &LuaVehicle::AddPassenger }, + { "RemovePassenger", &LuaVehicle::RemovePassenger }, + + { NULL, NULL } + }; +} + +#endif // CLASSIC +#endif // TBC +#endif // VEHICLEMETHODS_H diff --git a/src/modules/Eluna/VMangos/WorldObjectMethods.h b/src/modules/Eluna/VMangos/WorldObjectMethods.h new file mode 100644 index 0000000000..574b55c47d --- /dev/null +++ b/src/modules/Eluna/VMangos/WorldObjectMethods.h @@ -0,0 +1,1231 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef WORLDOBJECTMETHODS_H +#define WORLDOBJECTMETHODS_H + +/*** + * Inherits all methods from: [Object] + */ +namespace LuaWorldObject +{ + /** + * Returns the name of the [WorldObject] + * + * @return string name + */ + int GetName(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetName()); + return 1; + } + + /** + * Returns the current [Map] object of the [WorldObject] + * + * @return [Map] mapObject + */ + int GetMap(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetMap()); + return 1; + } + +#if (!defined(TBC) && !defined(CLASSIC)) + /** + * Returns the current phase of the [WorldObject] + * + * @return uint32 phase + */ + int GetPhaseMask(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPhaseMask()); + return 1; + } + + /** + * Sets the [WorldObject]'s phase mask. + * + * @param uint32 phaseMask + * @param bool update = true : update visibility to nearby objects + */ + int SetPhaseMask(lua_State* L, WorldObject* obj) + { + uint32 phaseMask = Eluna::CHECKVAL(L, 2); + bool update = Eluna::CHECKVAL(L, 3, true); + obj->SetPhaseMask(phaseMask, update); + return 0; + } +#endif + + /** + * Returns the current instance ID of the [WorldObject] + * + * @return uint32 instanceId + */ + int GetInstanceId(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetInstanceId()); + return 1; + } + + /** + * Returns the current area ID of the [WorldObject] + * + * @return uint32 areaId + */ + int GetAreaId(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetAreaId()); + return 1; + } + + /** + * Returns the current zone ID of the [WorldObject] + * + * @return uint32 zoneId + */ + int GetZoneId(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetZoneId()); + return 1; + } + + /** + * Returns the current map ID of the [WorldObject] + * + * @return uint32 mapId + */ + int GetMapId(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetMapId()); + return 1; + } + + /** + * Returns the current X coordinate of the [WorldObject] + * + * @return float x + */ + int GetX(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPositionX()); + return 1; + } + + /** + * Returns the current Y coordinate of the [WorldObject] + * + * @return float y + */ + int GetY(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPositionY()); + return 1; + } + + /** + * Returns the current Z coordinate of the [WorldObject] + * + * @return float z + */ + int GetZ(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPositionZ()); + return 1; + } + + /** + * Returns the current orientation of the [WorldObject] + * + * @return float orientation / facing + */ + int GetO(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetOrientation()); + return 1; + } + + /** + * Returns the coordinates and orientation of the [WorldObject] + * + * @return float x : x coordinate of the [WorldObject] + * @return float y : y coordinate of the [WorldObject] + * @return float z : z coordinate (height) of the [WorldObject] + * @return float o : facing / orientation of the [WorldObject] + */ + int GetLocation(lua_State* L, WorldObject* obj) + { + Eluna::Push(L, obj->GetPositionX()); + Eluna::Push(L, obj->GetPositionY()); + Eluna::Push(L, obj->GetPositionZ()); + Eluna::Push(L, obj->GetOrientation()); + return 4; + } + + /** + * Returns the nearest [Player] object in sight of the [WorldObject] or within the given range + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return [Player] nearestPlayer + */ + int GetNearestPlayer(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 hostile = Eluna::CHECKVAL(L, 3, 0); + uint32 dead = Eluna::CHECKVAL(L, 4, 1); + + Unit* target = NULL; + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_PLAYER, 0, hostile, dead); + MaNGOS::UnitLastSearcher searcher(target, checker); + Cell::VisitWorldObjects(obj, searcher, range); + + Eluna::Push(L, target); + return 1; + } + + /** + * Returns the nearest [GameObject] object in sight of the [WorldObject] or within the given range and/or with a specific entry ID + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 entryId = 0 : optionally set entry ID of game object to find + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * + * @return [GameObject] nearestGameObject + */ + int GetNearestGameObject(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 entry = Eluna::CHECKVAL(L, 3, 0); + uint32 hostile = Eluna::CHECKVAL(L, 4, 0); + + GameObject* target = NULL; + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_GAMEOBJECT, entry, hostile); +#ifdef TRINITY + Trinity::GameObjectLastSearcher searcher(obj, target, checker); + Cell::VisitAllObjects(obj, searcher, range); +#elif AZEROTHCORE + Acore::GameObjectLastSearcher searcher(obj, target, checker); + Cell::VisitAllObjects(obj, searcher, range); +#else + MaNGOS::GameObjectLastSearcher searcher(target, checker); + Cell::VisitGridObjects(obj, searcher, range); +#endif + + Eluna::Push(L, target); + return 1; + } + + /** + * Returns the nearest [Creature] object in sight of the [WorldObject] or within the given range and/or with a specific entry ID + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 entryId = 0 : optionally set entry ID of creature to find + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return [Creature] nearestCreature + */ + int GetNearestCreature(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 entry = Eluna::CHECKVAL(L, 3, 0); + uint32 hostile = Eluna::CHECKVAL(L, 4, 0); + uint32 dead = Eluna::CHECKVAL(L, 5, 1); + + Creature* target = NULL; + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, TYPEMASK_UNIT, entry, hostile, dead); +#ifdef TRINITY + Trinity::CreatureLastSearcher searcher(obj, target, checker); + Cell::VisitAllObjects(obj, searcher, range); +#elif AZEROTHCORE + Acore::CreatureLastSearcher searcher(obj, target, checker); + Cell::VisitAllObjects(obj, searcher, range); +#else + MaNGOS::CreatureLastSearcher searcher(target, checker); + Cell::VisitGridObjects(obj, searcher, range); + +#endif + + Eluna::Push(L, target); + return 1; + } + + /** + * Returns a table of [Player] objects in sight of the [WorldObject] or within the given range + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return table playersInRange : table of [Player]s + */ + int GetPlayersInRange(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 hostile = Eluna::CHECKVAL(L, 3, 0); + uint32 dead = Eluna::CHECKVAL(L, 4, 1); + + std::list list; + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_PLAYER, 0, hostile, dead); +#ifdef TRINITY + Trinity::PlayerListSearcher searcher(obj, list, checker); + Cell::VisitAllObjects(obj, searcher, range); +#elif AZEROTHCORE + Acore::PlayerListSearcher searcher(obj, list, checker); + Cell::VisitAllObjects(obj, searcher, range); +#else + MaNGOS::PlayerListSearcher searcher(list, checker); + Cell::VisitWorldObjects(obj, searcher, range); +#endif + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns a table of [Creature] objects in sight of the [WorldObject] or within the given range and/or with a specific entry ID + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 entryId = 0 : optionally set entry ID of creatures to find + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return table creaturesInRange : table of [Creature]s + */ + int GetCreaturesInRange(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 entry = Eluna::CHECKVAL(L, 3, 0); + uint32 hostile = Eluna::CHECKVAL(L, 4, 0); + uint32 dead = Eluna::CHECKVAL(L, 5, 1); + + std::list list; + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_UNIT, entry, hostile, dead); +#ifdef TRINITY + Trinity::CreatureListSearcher searcher(obj, list, checker); + Cell::VisitAllObjects(obj, searcher, range); +#elif defined AZEROTHCORE + Acore::CreatureListSearcher searcher(obj, list, checker); + Cell::VisitAllObjects(obj, searcher, range); +#else + MaNGOS::CreatureListSearcher searcher(list, checker); + Cell::VisitGridObjects(obj, searcher, range); +#endif + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns a table of [GameObject] objects in sight of the [WorldObject] or within the given range and/or with a specific entry ID + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param uint32 entryId = 0 : optionally set entry ID of game objects to find + * @param uint32 hostile = 0 : 0 both, 1 hostile, 2 friendly + * + * @return table gameObjectsInRange : table of [GameObject]s + */ + int GetGameObjectsInRange(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint32 entry = Eluna::CHECKVAL(L, 3, 0); + uint32 hostile = Eluna::CHECKVAL(L, 4, 0); + + std::list list; + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, TYPEMASK_GAMEOBJECT, entry, hostile); +#ifdef TRINITY + Trinity::GameObjectListSearcher searcher(obj, list, checker); + Cell::VisitAllObjects(obj, searcher, range); +#elif AZEROTHCORE + Acore::GameObjectListSearcher searcher(obj, list, checker); + Cell::VisitAllObjects(obj, searcher, range); +#else + MaNGOS::GameObjectListSearcher searcher(list, checker); + Cell::VisitGridObjects(obj, searcher, range); +#endif + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns nearest [WorldObject] in sight of the [WorldObject]. + * The distance, type, entry and hostility requirements the [WorldObject] must match can be passed. + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param [TypeMask] type = 0 : the [TypeMask] that the [WorldObject] must be. This can contain multiple types. 0 will be ingored + * @param uint32 entry = 0 : the entry of the [WorldObject], 0 will be ingored + * @param uint32 hostile = 0 : specifies whether the [WorldObject] needs to be 1 hostile, 2 friendly or 0 either + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return [WorldObject] worldObject + */ + int GetNearObject(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint16 type = Eluna::CHECKVAL(L, 3, 0); // TypeMask + uint32 entry = Eluna::CHECKVAL(L, 4, 0); + uint32 hostile = Eluna::CHECKVAL(L, 5, 0); // 0 none, 1 hostile, 2 friendly + uint32 dead = Eluna::CHECKVAL(L, 6, 1); // 0 both, 1 alive, 2 dead + + float x, y, z; + obj->GetPosition(x, y, z); + ElunaUtil::WorldObjectInRangeCheck checker(true, obj, range, type, entry, hostile, dead); + + WorldObject* target = NULL; +#ifdef TRINITY + Trinity::WorldObjectLastSearcher searcher(obj, target, checker); + Cell::VisitAllObjects(obj, searcher, range); +#elif AZEROTHCORE + Acore::WorldObjectLastSearcher searcher(obj, target, checker); + Cell::VisitAllObjects(obj, searcher, range); +#else + MaNGOS::WorldObjectLastSearcher searcher(target, checker); + Cell::VisitAllObjects(obj, searcher, range); +#endif + + Eluna::Push(L, target); + return 1; + } + + /** + * Returns a table of [WorldObject]s in sight of the [WorldObject]. + * The distance, type, entry and hostility requirements the [WorldObject] must match can be passed. + * + * @param float range = 533.33333 : optionally set range. Default range is grid size + * @param [TypeMask] type = 0 : the [TypeMask] that the [WorldObject] must be. This can contain multiple types. 0 will be ingored + * @param uint32 entry = 0 : the entry of the [WorldObject], 0 will be ingored + * @param uint32 hostile = 0 : specifies whether the [WorldObject] needs to be 1 hostile, 2 friendly or 0 either + * @param uint32 dead = 1 : 0 both, 1 alive, 2 dead + * + * @return table worldObjectList : table of [WorldObject]s + */ + int GetNearObjects(lua_State* L, WorldObject* obj) + { + float range = Eluna::CHECKVAL(L, 2, SIZE_OF_GRIDS); + uint16 type = Eluna::CHECKVAL(L, 3, 0); // TypeMask + uint32 entry = Eluna::CHECKVAL(L, 4, 0); + uint32 hostile = Eluna::CHECKVAL(L, 5, 0); // 0 none, 1 hostile, 2 friendly + uint32 dead = Eluna::CHECKVAL(L, 6, 1); // 0 both, 1 alive, 2 dead + + float x, y, z; + obj->GetPosition(x, y, z); + ElunaUtil::WorldObjectInRangeCheck checker(false, obj, range, type, entry, hostile, dead); + + std::list list; +#ifdef TRINITY + Trinity::WorldObjectListSearcher searcher(obj, list, checker); + Cell::VisitAllObjects(obj, searcher, range); +#elif AZEROTHCORE + Acore::WorldObjectListSearcher searcher(obj, list, checker); + Cell::VisitAllObjects(obj, searcher, range); +#else + MaNGOS::WorldObjectListSearcher searcher(list, checker); + Cell::VisitAllObjects(obj, searcher, range); +#endif + + lua_createtable(L, list.size(), 0); + int tbl = lua_gettop(L); + uint32 i = 0; + + for (std::list::const_iterator it = list.begin(); it != list.end(); ++it) + { + Eluna::Push(L, *it); + lua_rawseti(L, tbl, ++i); + } + + lua_settop(L, tbl); + return 1; + } + + /** + * Returns the distance from this [WorldObject] to another [WorldObject], or from this [WorldObject] to a point in 3d space. + * + * The function takes into account the given object sizes. See also [WorldObject:GetExactDistance], [WorldObject:GetDistance2d] + * + * @proto dist = (obj) + * @proto dist = (x, y, z) + * + * @param [WorldObject] obj + * @param float x : the X-coordinate of the point + * @param float y : the Y-coordinate of the point + * @param float z : the Z-coordinate of the point + * + * @return float dist : the distance in yards + */ + int GetDistance(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + Eluna::Push(L, obj->GetDistance(target)); + else + { + float X = Eluna::CHECKVAL(L, 2); + float Y = Eluna::CHECKVAL(L, 3); + float Z = Eluna::CHECKVAL(L, 4); + Eluna::Push(L, obj->GetDistance(X, Y, Z)); + } + return 1; + } + + /** + * Returns the distance from this [WorldObject] to another [WorldObject], or from this [WorldObject] to a point in 3d space. + * + * The function does not take into account the given object sizes, which means only the object coordinates are compared. See also [WorldObject:GetDistance], [WorldObject:GetDistance2d] + * + * @proto dist = (obj) + * @proto dist = (x, y, z) + * + * @param [WorldObject] obj + * @param float x : the X-coordinate of the point + * @param float y : the Y-coordinate of the point + * @param float z : the Z-coordinate of the point + * + * @return float dist : the distance in yards + */ + int GetExactDistance(lua_State* L, WorldObject* obj) + { + float x, y, z; + obj->GetPosition(x, y, z); + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + { + float x2, y2, z2; + target->GetPosition(x2, y2, z2); + x -= x2; + y -= y2; + z -= z2; + } + else + { + x -= Eluna::CHECKVAL(L, 2); + y -= Eluna::CHECKVAL(L, 3); + z -= Eluna::CHECKVAL(L, 4); + } + + Eluna::Push(L, std::sqrt(x*x + y*y + z*z)); + return 1; + } + + /** + * Returns the distance from this [WorldObject] to another [WorldObject], or from this [WorldObject] to a point in 2d space. + * + * The function takes into account the given object sizes. See also [WorldObject:GetDistance], [WorldObject:GetExactDistance2d] + * + * @proto dist = (obj) + * @proto dist = (x, y) + * + * @param [WorldObject] obj + * @param float x : the X-coordinate of the point + * @param float y : the Y-coordinate of the point + * + * @return float dist : the distance in yards + */ + int GetDistance2d(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + Eluna::Push(L, obj->GetDistance2d(target)); + else + { + float X = Eluna::CHECKVAL(L, 2); + float Y = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetDistance2d(X, Y)); + } + return 1; + } + + /** + * Returns the distance from this [WorldObject] to another [WorldObject], or from this [WorldObject] to a point in 2d space. + * + * The function does not take into account the given object sizes, which means only the object coordinates are compared. See also [WorldObject:GetDistance], [WorldObject:GetDistance2d] + * + * @proto dist = (obj) + * @proto dist = (x, y) + * + * @param [WorldObject] obj + * @param float x : the X-coordinate of the point + * @param float y : the Y-coordinate of the point + * + * @return float dist : the distance in yards + */ + int GetExactDistance2d(lua_State* L, WorldObject* obj) + { + float x, y, z; + obj->GetPosition(x, y, z); + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + if (target) + { + float x2, y2, z2; + target->GetPosition(x2, y2, z2); + x -= x2; + y -= y2; + } + else + { + x -= Eluna::CHECKVAL(L, 2); + y -= Eluna::CHECKVAL(L, 3); + } + + Eluna::Push(L, std::sqrt(x*x + y*y)); + return 1; + } + + /** + * Returns the x, y and z of a point dist away from the [WorldObject]. + * + * @param float distance : specifies the distance of the point from the [WorldObject] in yards + * @param float angle : specifies the angle of the point relative to the orientation / facing of the [WorldObject] in radians + * + * @return float x + * @return float y + * @return float z + */ + int GetRelativePoint(lua_State* L, WorldObject* obj) + { + float dist = Eluna::CHECKVAL(L, 2); + float rad = Eluna::CHECKVAL(L, 3); + + float x, y, z; + obj->GetClosePoint(x, y, z, 0.0f, dist, rad); + + Eluna::Push(L, x); + Eluna::Push(L, y); + Eluna::Push(L, z); + return 3; + } + + /** + * Returns the angle between this [WorldObject] and another [WorldObject] or a point. + * + * The angle is the angle between two points and orientation will be ignored. + * + * @proto dist = (obj) + * @proto dist = (x, y) + * + * @param [WorldObject] object + * @param float x + * @param float y + * + * @return float angle : angle in radians in range 0..2*pi + */ + int GetAngle(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); +#if defined TRINITY && !AZEROTHCORE + if (target) + Eluna::Push(L, obj->GetAbsoluteAngle(target)); + else + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetAbsoluteAngle(x, y)); + } +#else + if (target) + Eluna::Push(L, obj->GetAngle(target)); + else + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + Eluna::Push(L, obj->GetAngle(x, y)); + } +#endif + return 1; + } + + /** + * Sends a [WorldPacket] to [Player]s in sight of the [WorldObject]. + * + * @param [WorldPacket] packet + */ + int SendPacket(lua_State* L, WorldObject* obj) + { + WorldPacket* data = Eluna::CHECKOBJ(L, 2); +#ifdef CMANGOS + obj->SendMessageToSet(*data, true); +#else + obj->SendMessageToSet(data, true); +#endif + return 0; + } + + /** + * Spawns a [GameObject] at specified location. + * + * @param uint32 entry : [GameObject] entry ID + * @param float x + * @param float y + * @param float z + * @param float o + * @param uint32 respawnDelay = 30 : respawn time in seconds + * @return [GameObject] gameObject + */ + int SummonGameObject(lua_State* L, WorldObject* obj) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + uint32 respawnDelay = Eluna::CHECKVAL(L, 7, 30); +#ifdef TRINITY + QuaternionData rot = QuaternionData::fromEulerAnglesZYX(o, 0.f, 0.f); + Eluna::Push(L, obj->SummonGameObject(entry, Position(x, y, z, o), rot, Seconds(respawnDelay))); +#elif AZEROTHCORE + Eluna::Push(L, obj->SummonGameObject(entry, x, y, z, o, 0, 0, 0, 0, respawnDelay)); +#else + Eluna::Push(L, obj->SummonGameObject(entry, x, y, z, o, respawnDelay)); +#endif + return 1; + } + + /** + * Spawns the creature at specified location. + * + * enum TempSummonType + * { + * TEMPSUMMON_TIMED_OR_DEAD_DESPAWN = 1, // despawns after a specified time OR when the creature disappears + * TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN = 2, // despawns after a specified time OR when the creature dies + * TEMPSUMMON_TIMED_DESPAWN = 3, // despawns after a specified time + * TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT = 4, // despawns after a specified time after the creature is out of combat + * TEMPSUMMON_CORPSE_DESPAWN = 5, // despawns instantly after death + * TEMPSUMMON_CORPSE_TIMED_DESPAWN = 6, // despawns after a specified time after death + * TEMPSUMMON_DEAD_DESPAWN = 7, // despawns when the creature disappears + * TEMPSUMMON_MANUAL_DESPAWN = 8, // despawns when UnSummon() is called + * TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN = 9, // despawns after a specified time (OOC) OR when the creature dies + * TEMPSUMMON_TIMED_OOC_OR_DEAD_DESPAWN = 10 // despawns after a specified time (OOC) OR when the creature disappears + * }; + * + * @param uint32 entry : [Creature]'s entry ID + * @param float x + * @param float y + * @param float z + * @param float o + * @param [TempSummonType] spawnType = MANUAL_DESPAWN : defines how and when the creature despawns + * @param uint32 despawnTimer = 0 : despawn time in milliseconds + * @return [Creature] spawnedCreature + */ + int SpawnCreature(lua_State* L, WorldObject* obj) + { + uint32 entry = Eluna::CHECKVAL(L, 2); + float x = Eluna::CHECKVAL(L, 3); + float y = Eluna::CHECKVAL(L, 4); + float z = Eluna::CHECKVAL(L, 5); + float o = Eluna::CHECKVAL(L, 6); + uint32 spawnType = Eluna::CHECKVAL(L, 7, 8); + uint32 despawnTimer = Eluna::CHECKVAL(L, 8, 0); + + TempSummonType type; + switch (spawnType) + { + case 1: + type = TEMPSUMMON_TIMED_OR_DEAD_DESPAWN; + break; + case 2: + type = TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN; + break; + case 3: + type = TEMPSUMMON_TIMED_DESPAWN; + break; + case 4: + type = TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT; + break; + case 5: + type = TEMPSUMMON_CORPSE_DESPAWN; + break; + case 6: + type = TEMPSUMMON_CORPSE_TIMED_DESPAWN; + break; + case 7: + type = TEMPSUMMON_DEAD_DESPAWN; + break; + case 8: + type = TEMPSUMMON_MANUAL_DESPAWN; + break; + default: + return luaL_argerror(L, 7, "valid SpawnType expected"); + } + +#ifdef TRINITY + Eluna::Push(L, obj->SummonCreature(entry, x, y, z, o, type, Milliseconds(despawnTimer))); +#else + Eluna::Push(L, obj->SummonCreature(entry, x, y, z, o, type, despawnTimer)); +#endif + return 1; + } + + /** + * Registers a timed event to the [WorldObject] + * When the passed function is called, the parameters `(eventId, delay, repeats, worldobject)` are passed to it. + * Repeats will decrease on each call if the event does not repeat indefinitely + * + * Note that for [Creature] and [GameObject] the timed event timer ticks only if the creature is in sight of someone + * For all [WorldObject]s the timed events are removed when the object is destoryed. This means that for example a [Player]'s events are removed on logout. + * + * local function Timed(eventid, delay, repeats, worldobject) + * print(worldobject:GetName()) + * end + * worldobject:RegisterEvent(Timed, 1000, 5) -- do it after 1 second 5 times + * worldobject:RegisterEvent(Timed, {1000, 10000}, 0) -- do it after 1 to 10 seconds forever + * + * @proto eventId = (function, delay) + * @proto eventId = (function, delaytable) + * @proto eventId = (function, delay, repeats) + * @proto eventId = (function, delaytable, repeats) + * + * @param function function : function to trigger when the time has passed + * @param uint32 delay : set time in milliseconds for the event to trigger + * @param table delaytable : a table `{min, max}` containing the minimum and maximum delay time + * @param uint32 repeats = 1 : how many times for the event to repeat, 0 is infinite + * @return int eventId : unique ID for the timed event used to cancel it or nil + */ + int RegisterEvent(lua_State* L, WorldObject* obj) + { + luaL_checktype(L, 2, LUA_TFUNCTION); + uint32 min, max; + if (lua_istable(L, 3)) + { + Eluna::Push(L, 1); + lua_gettable(L, 3); + min = Eluna::CHECKVAL(L, -1); + Eluna::Push(L, 2); + lua_gettable(L, 3); + max = Eluna::CHECKVAL(L, -1); + lua_pop(L, 2); + } + else + min = max = Eluna::CHECKVAL(L, 3); + uint32 repeats = Eluna::CHECKVAL(L, 4, 1); + + if (min > max) + return luaL_argerror(L, 3, "min is bigger than max delay"); + + lua_pushvalue(L, 2); + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); + if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF) + { + obj->elunaEvents->AddEvent(functionRef, min, max, repeats); + Eluna::Push(L, functionRef); + } + return 1; + } + + /** + * Removes the timed event from a [WorldObject] by the specified event ID + * + * @param int eventId : event Id to remove + */ + int RemoveEventById(lua_State* L, WorldObject* obj) + { + int eventId = Eluna::CHECKVAL(L, 2); + obj->elunaEvents->SetState(eventId, LUAEVENT_STATE_ABORT); + return 0; + } + + /** + * Removes all timed events from a [WorldObject] + * + */ + int RemoveEvents(lua_State* /*L*/, WorldObject* obj) + { + obj->elunaEvents->SetStates(LUAEVENT_STATE_ABORT); + return 0; + } + + /** + * Returns true if the given [WorldObject] or coordinates are in the [WorldObject]'s line of sight + * + * @proto isInLoS = (worldobject) + * @proto isInLoS = (x, y, z) + * + * @param [WorldObject] worldobject + * @param float x + * @param float y + * @param float z + * @return bool isInLoS + */ + int IsWithinLoS(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, false); + + if (target) + Eluna::Push(L, obj->IsWithinLOSInMap(target)); + else + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + Eluna::Push(L, obj->IsWithinLOS(x, y, z)); + } + + return 1; + } + + /** + * Returns true if the [WorldObject]s are on the same map + * + * @param [WorldObject] worldobject + * @return bool isInMap + */ + int IsInMap(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, true); + Eluna::Push(L, obj->IsInMap(target)); + return 1; + } + + /** + * Returns true if the point is in the given distance of the [WorldObject] + * + * Notice that the distance is measured from the edge of the [WorldObject]. + * + * @param float x + * @param float y + * @param float z + * @param float distance + * @return bool isInDistance + */ + int IsWithinDist3d(lua_State* L, WorldObject* obj) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float dist = Eluna::CHECKVAL(L, 5); + Eluna::Push(L, obj->IsWithinDist3d(x, y, z, dist)); + return 1; + } + + /** + * Returns true if the point is in the given distance of the [WorldObject] + * + * The distance is measured only in x,y coordinates. + * Notice that the distance is measured from the edge of the [WorldObject]. + * + * @param float x + * @param float y + * @param float distance + * @return bool isInDistance + */ + int IsWithinDist2d(lua_State* L, WorldObject* obj) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float dist = Eluna::CHECKVAL(L, 4); + Eluna::Push(L, obj->IsWithinDist2d(x, y, dist)); + return 1; + } + + /** + * Returns true if the target is in the given distance of the [WorldObject] + * + * Notice that the distance is measured from the edge of the [WorldObject]s. + * + * @param [WorldObject] target + * @param float distance + * @param bool is3D = true : if false, only x,y coordinates used for checking + * @return bool isInDistance + */ + int IsWithinDist(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2, true); + float distance = Eluna::CHECKVAL(L, 3); + bool is3D = Eluna::CHECKVAL(L, 4, true); + Eluna::Push(L, obj->IsWithinDist(target, distance, is3D)); + return 1; + } + + /** + * Returns true if the [WorldObject] is on the same map and within given distance + * + * Notice that the distance is measured from the edge of the [WorldObject]s. + * + * @param [WorldObject] target + * @param float distance + * @param bool is3D = true : if false, only x,y coordinates used for checking + * @return bool isInDistance + */ + int IsWithinDistInMap(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2); + float distance = Eluna::CHECKVAL(L, 3); + bool is3D = Eluna::CHECKVAL(L, 4, true); + + Eluna::Push(L, obj->IsWithinDistInMap(target, distance, is3D)); + return 1; + } + + /** + * Returns true if the target is within given range + * + * Notice that the distance is measured from the edge of the [WorldObject]s. + * + * @param [WorldObject] target + * @param float minrange + * @param float maxrange + * @param bool is3D = true : if false, only x,y coordinates used for checking + * @return bool isInDistance + */ + int IsInRange(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2); + float minrange = Eluna::CHECKVAL(L, 3); + float maxrange = Eluna::CHECKVAL(L, 4); + bool is3D = Eluna::CHECKVAL(L, 5, true); + + Eluna::Push(L, obj->IsInRange(target, minrange, maxrange, is3D)); + return 1; + } + + /** + * Returns true if the point is within given range + * + * Notice that the distance is measured from the edge of the [WorldObject]. + * + * @param float x + * @param float y + * @param float minrange + * @param float maxrange + * @return bool isInDistance + */ + int IsInRange2d(lua_State* L, WorldObject* obj) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float minrange = Eluna::CHECKVAL(L, 4); + float maxrange = Eluna::CHECKVAL(L, 5); + + Eluna::Push(L, obj->IsInRange2d(x, y, minrange, maxrange)); + return 1; + } + + /** + * Returns true if the point is within given range + * + * Notice that the distance is measured from the edge of the [WorldObject]. + * + * @param float x + * @param float y + * @param float z + * @param float minrange + * @param float maxrange + * @return bool isInDistance + */ + int IsInRange3d(lua_State* L, WorldObject* obj) + { + float x = Eluna::CHECKVAL(L, 2); + float y = Eluna::CHECKVAL(L, 3); + float z = Eluna::CHECKVAL(L, 4); + float minrange = Eluna::CHECKVAL(L, 5); + float maxrange = Eluna::CHECKVAL(L, 6); + + Eluna::Push(L, obj->IsInRange3d(x, y, z, minrange, maxrange)); + return 1; + } + + /** + * Returns true if the target is in the given arc in front of the [WorldObject] + * + * @param [WorldObject] target + * @param float arc = pi + * @return bool isInFront + */ + int IsInFront(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2); + float arc = Eluna::CHECKVAL(L, 3, static_cast(M_PI)); + + Eluna::Push(L, obj->IsWithinDist(target, arc) && obj->HasInArc(target, M_PI)); + return 1; + } + + /** + * Returns true if the target is in the given arc behind the [WorldObject] + * + * @param [WorldObject] target + * @param float arc = pi + * @return bool isInBack + */ + int IsInBack(lua_State* L, WorldObject* obj) + { + WorldObject* target = Eluna::CHECKOBJ(L, 2); + float arc = Eluna::CHECKVAL(L, 3, static_cast(M_PI)); + + Eluna::Push(L, obj->IsWithinDist(target, arc) && !obj->HasInArc(target, M_PI)); + return 1; + } + + /** + * The [WorldObject] plays music to a [Player] + * + * If no [Player] provided it will play the music to everyone near. + * This method does not interrupt previously played music. + * + * See also [WorldObject:PlayDistanceSound], [WorldObject:PlayDirectSound] + * + * @param uint32 music : entry of a music + * @param [Player] player = nil : [Player] to play the music to + */ + int PlayMusic(lua_State* L, WorldObject* obj) + { + uint32 musicid = Eluna::CHECKVAL(L, 2); + Player* player = Eluna::CHECKOBJ(L, 3, false); + + WorldPacket data(SMSG_PLAY_MUSIC, 4); + data << uint32(musicid); + if (player) + player->SendDirectMessage(&data); + else + obj->SendMessageToSet(&data, true); + return 0; + } + + /** + * The [WorldObject] plays a sound to a [Player] + * + * If no [Player] provided it will play the sound to everyone near. + * This method will play sound and does not interrupt prvious sound. + * + * See also [WorldObject:PlayDistanceSound], [WorldObject:PlayMusic] + * + * @param uint32 sound : entry of a sound + * @param [Player] player = nil : [Player] to play the sound to + */ + int PlayDirectSound(lua_State* L, WorldObject* obj) + { + uint32 soundId = Eluna::CHECKVAL(L, 2); + Player* player = Eluna::CHECKOBJ(L, 3, false); + if (!sObjectMgr.GetSoundEntry(soundId)) + return 0; + + if (player) + obj->PlayDirectSound(soundId, player); + else + obj->PlayDirectSound(soundId); + return 0; + } + + /** + * The [WorldObject] plays a sound to a [Player] + * + * If no [Player] it will play the sound to everyone near. + * Sound will fade the further you are from the [WorldObject]. + * This method interrupts previously playing sound. + * + * See also [WorldObject:PlayDirectSound], [WorldObject:PlayMusic] + * + * @param uint32 sound : entry of a sound + * @param [Player] player = nil : [Player] to play the sound to + */ + int PlayDistanceSound(lua_State* L, WorldObject* obj) + { + uint32 soundId = Eluna::CHECKVAL(L, 2); + Player* player = Eluna::CHECKOBJ(L, 3, false); + if (!sObjectMgr.GetSoundEntry(soundId)) + return 0; + + if (player) + obj->PlayDistanceSound(soundId, player); + else + obj->PlayDistanceSound(soundId); + return 0; + } + + ElunaRegister WorldObjectMethods[] = + { + // Getters + { "GetName", &LuaWorldObject::GetName }, + { "GetMap", &LuaWorldObject::GetMap }, +#if (!defined(TBC) && !defined(CLASSIC)) + { "GetPhaseMask", &LuaWorldObject::GetPhaseMask }, + { "SetPhaseMask", &LuaWorldObject::SetPhaseMask }, +#endif + { "GetInstanceId", &LuaWorldObject::GetInstanceId }, + { "GetAreaId", &LuaWorldObject::GetAreaId }, + { "GetZoneId", &LuaWorldObject::GetZoneId }, + { "GetMapId", &LuaWorldObject::GetMapId }, + { "GetX", &LuaWorldObject::GetX }, + { "GetY", &LuaWorldObject::GetY }, + { "GetZ", &LuaWorldObject::GetZ }, + { "GetO", &LuaWorldObject::GetO }, + { "GetLocation", &LuaWorldObject::GetLocation }, + { "GetPlayersInRange", &LuaWorldObject::GetPlayersInRange }, + { "GetCreaturesInRange", &LuaWorldObject::GetCreaturesInRange }, + { "GetGameObjectsInRange", &LuaWorldObject::GetGameObjectsInRange }, + { "GetNearestPlayer", &LuaWorldObject::GetNearestPlayer }, + { "GetNearestGameObject", &LuaWorldObject::GetNearestGameObject }, + { "GetNearestCreature", &LuaWorldObject::GetNearestCreature }, + { "GetNearObject", &LuaWorldObject::GetNearObject }, + { "GetNearObjects", &LuaWorldObject::GetNearObjects }, + { "GetDistance", &LuaWorldObject::GetDistance }, + { "GetExactDistance", &LuaWorldObject::GetExactDistance }, + { "GetDistance2d", &LuaWorldObject::GetDistance2d }, + { "GetExactDistance2d", &LuaWorldObject::GetExactDistance2d }, + { "GetRelativePoint", &LuaWorldObject::GetRelativePoint }, + { "GetAngle", &LuaWorldObject::GetAngle }, + + // Boolean + { "IsWithinLoS", &LuaWorldObject::IsWithinLoS }, + { "IsInMap", &LuaWorldObject::IsInMap }, + { "IsWithinDist3d", &LuaWorldObject::IsWithinDist3d }, + { "IsWithinDist2d", &LuaWorldObject::IsWithinDist2d }, + { "IsWithinDist", &LuaWorldObject::IsWithinDist }, + { "IsWithinDistInMap", &LuaWorldObject::IsWithinDistInMap }, + { "IsInRange", &LuaWorldObject::IsInRange }, + { "IsInRange2d", &LuaWorldObject::IsInRange2d }, + { "IsInRange3d", &LuaWorldObject::IsInRange3d }, + { "IsInFront", &LuaWorldObject::IsInFront }, + { "IsInBack", &LuaWorldObject::IsInBack }, + + // Other + { "SummonGameObject", &LuaWorldObject::SummonGameObject }, + { "SpawnCreature", &LuaWorldObject::SpawnCreature }, + { "SendPacket", &LuaWorldObject::SendPacket }, + { "RegisterEvent", &LuaWorldObject::RegisterEvent }, + { "RemoveEventById", &LuaWorldObject::RemoveEventById }, + { "RemoveEvents", &LuaWorldObject::RemoveEvents }, + { "PlayMusic", &LuaWorldObject::PlayMusic }, + { "PlayDirectSound", &LuaWorldObject::PlayDirectSound }, + { "PlayDistanceSound", &LuaWorldObject::PlayDistanceSound }, + + { NULL, NULL } + }; +}; +#endif diff --git a/src/modules/Eluna/VMangos/WorldPacketMethods.h b/src/modules/Eluna/VMangos/WorldPacketMethods.h new file mode 100644 index 0000000000..8fba876d32 --- /dev/null +++ b/src/modules/Eluna/VMangos/WorldPacketMethods.h @@ -0,0 +1,346 @@ +/* +* Copyright (C) 2010 - 2016 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef WORLDPACKETMETHODS_H +#define WORLDPACKETMETHODS_H + +/*** + * A packet used to pass messages between the server and a client. + * + * Each packet has an opcode that determines the type of message being sent, + * e.g. if a CMSG_LOGOUT_REQUEST packet is sent to the server, + * the client has sent a message that its [Player] wants to logout. + * + * The packet can contain further data, the format of which depends on the opcode. + * + * Inherits all methods from: none + */ +namespace LuaPacket +{ + /** + * Returns the opcode of the [WorldPacket]. + * + * @return uint16 opcode + */ + int GetOpcode(lua_State* L, WorldPacket* packet) + { + Eluna::Push(L, packet->GetOpcode()); + return 1; + } + + /** + * Returns the size of the [WorldPacket]. + * + * @return uint32 size + */ + int GetSize(lua_State* L, WorldPacket* packet) + { + Eluna::Push(L, packet->size()); + return 1; + } + + /** + * Sets the opcode of the [WorldPacket] to the specified opcode. + * + * @param [Opcodes] opcode : see Opcodes.h for all known opcodes + */ + int SetOpcode(lua_State* L, WorldPacket* packet) + { + uint32 opcode = Eluna::CHECKVAL(L, 2); + if (opcode >= NUM_MSG_TYPES) + return luaL_argerror(L, 2, "valid opcode expected"); + packet->SetOpcode((OpcodesList)opcode); + return 0; + } + + /** + * Reads and returns a signed 8-bit integer value from the [WorldPacket]. + * + * @return int8 value + */ + int ReadByte(lua_State* L, WorldPacket* packet) + { + int8 _byte; + (*packet) >> _byte; + Eluna::Push(L, _byte); + return 1; + } + + /** + * Reads and returns an unsigned 8-bit integer value from the [WorldPacket]. + * + * @return uint8 value + */ + int ReadUByte(lua_State* L, WorldPacket* packet) + { + uint8 _ubyte; + (*packet) >> _ubyte; + Eluna::Push(L, _ubyte); + return 1; + } + + /** + * Reads and returns a signed 16-bit integer value from the [WorldPacket]. + * + * @return int16 value + */ + int ReadShort(lua_State* L, WorldPacket* packet) + { + int16 _short; + (*packet) >> _short; + Eluna::Push(L, _short); + return 1; + } + + /** + * Reads and returns an unsigned 16-bit integer value from the [WorldPacket]. + * + * @return uint16 value + */ + int ReadUShort(lua_State* L, WorldPacket* packet) + { + uint16 _ushort; + (*packet) >> _ushort; + Eluna::Push(L, _ushort); + return 1; + } + + /** + * Reads and returns a signed 32-bit integer value from the [WorldPacket]. + * + * @return int32 value + */ + int ReadLong(lua_State* L, WorldPacket* packet) + { + int32 _long; + (*packet) >> _long; + Eluna::Push(L, _long); + return 1; + } + + /** + * Reads and returns an unsigned 32-bit integer value from the [WorldPacket]. + * + * @return uint32 value + */ + int ReadULong(lua_State* L, WorldPacket* packet) + { + uint32 _ulong; + (*packet) >> _ulong; + Eluna::Push(L, _ulong); + return 1; + } + + /** + * Reads and returns a single-precision floating-point value from the [WorldPacket]. + * + * @return float value + */ + int ReadFloat(lua_State* L, WorldPacket* packet) + { + float _val; + (*packet) >> _val; + Eluna::Push(L, _val); + return 1; + } + + /** + * Reads and returns a double-precision floating-point value from the [WorldPacket]. + * + * @return double value + */ + int ReadDouble(lua_State* L, WorldPacket* packet) + { + double _val; + (*packet) >> _val; + Eluna::Push(L, _val); + return 1; + } + + /** + * Reads and returns an unsigned 64-bit integer value from the [WorldPacket]. + * + * @return ObjectGuid value : value returned as string + */ + int ReadGUID(lua_State* L, WorldPacket* packet) + { + ObjectGuid guid; + (*packet) >> guid; + Eluna::Push(L, guid); + return 1; + } + + /** + * Reads and returns a string value from the [WorldPacket]. + * + * @return string value + */ + int ReadString(lua_State* L, WorldPacket* packet) + { + std::string _val; + (*packet) >> _val; + Eluna::Push(L, _val); + return 1; + } + + /** + * Writes an unsigned 64-bit integer value to the [WorldPacket]. + * + * @param ObjectGuid value : the value to be written to the [WorldPacket] + */ + int WriteGUID(lua_State* L, WorldPacket* packet) + { + ObjectGuid guid = Eluna::CHECKVAL(L, 2); + (*packet) << guid; + return 0; + } + + /** + * Writes a string to the [WorldPacket]. + * + * @param string value : the string to be written to the [WorldPacket] + */ + int WriteString(lua_State* L, WorldPacket* packet) + { + std::string _val = Eluna::CHECKVAL(L, 2); + (*packet) << _val; + return 0; + } + + /** + * Writes a signed 8-bit integer value to the [WorldPacket]. + * + * @param int8 value : the int8 value to be written to the [WorldPacket] + */ + int WriteByte(lua_State* L, WorldPacket* packet) + { + int8 byte = Eluna::CHECKVAL(L, 2); + (*packet) << byte; + return 0; + } + + /** + * Writes an unsigned 8-bit integer value to the [WorldPacket]. + * + * @param uint8 value : the uint8 value to be written to the [WorldPacket] + */ + int WriteUByte(lua_State* L, WorldPacket* packet) + { + uint8 byte = Eluna::CHECKVAL(L, 2); + (*packet) << byte; + return 0; + } + + /** + * Writes a signed 16-bit integer value to the [WorldPacket]. + * + * @param int16 value : the int16 value to be written to the [WorldPacket] + */ + int WriteShort(lua_State* L, WorldPacket* packet) + { + int16 _short = Eluna::CHECKVAL(L, 2); + (*packet) << _short; + return 0; + } + + /** + * Writes an unsigned 16-bit integer value to the [WorldPacket]. + * + * @param uint16 value : the uint16 value to be written to the [WorldPacket] + */ + int WriteUShort(lua_State* L, WorldPacket* packet) + { + uint16 _ushort = Eluna::CHECKVAL(L, 2); + (*packet) << _ushort; + return 0; + } + + /** + * Writes a signed 32-bit integer value to the [WorldPacket]. + * + * @param int32 value : the int32 value to be written to the [WorldPacket] + */ + int WriteLong(lua_State* L, WorldPacket* packet) + { + int32 _long = Eluna::CHECKVAL(L, 2); + (*packet) << _long; + return 0; + } + + /** + * Writes an unsigned 32-bit integer value to the [WorldPacket]. + * + * @param uint32 value : the uint32 value to be written to the [WorldPacket] + */ + int WriteULong(lua_State* L, WorldPacket* packet) + { + uint32 _ulong = Eluna::CHECKVAL(L, 2); + (*packet) << _ulong; + return 0; + } + + /** + * Writes a 32-bit floating-point value to the [WorldPacket]. + * + * @param float value : the float value to be written to the [WorldPacket] + */ + int WriteFloat(lua_State* L, WorldPacket* packet) + { + float _val = Eluna::CHECKVAL(L, 2); + (*packet) << _val; + return 0; + } + + /** + * Writes a 64-bit floating-point value to the [WorldPacket]. + * + * @param double value : the double value to be written to the [WorldPacket] + */ + int WriteDouble(lua_State* L, WorldPacket* packet) + { + double _val = Eluna::CHECKVAL(L, 2); + (*packet) << _val; + return 0; + } + + ElunaRegister PacketMethods[] = + { + // Getters + { "GetOpcode", &LuaPacket::GetOpcode }, + { "GetSize", &LuaPacket::GetSize }, + + // Setters + { "SetOpcode", &LuaPacket::SetOpcode }, + + // Readers + { "ReadByte", &LuaPacket::ReadByte }, + { "ReadUByte", &LuaPacket::ReadUByte }, + { "ReadShort", &LuaPacket::ReadShort }, + { "ReadUShort", &LuaPacket::ReadUShort }, + { "ReadLong", &LuaPacket::ReadLong }, + { "ReadULong", &LuaPacket::ReadULong }, + { "ReadGUID", &LuaPacket::ReadGUID }, + { "ReadString", &LuaPacket::ReadString }, + { "ReadFloat", &LuaPacket::ReadFloat }, + { "ReadDouble", &LuaPacket::ReadDouble }, + + // Writers + { "WriteByte", &LuaPacket::WriteByte }, + { "WriteUByte", &LuaPacket::WriteUByte }, + { "WriteShort", &LuaPacket::WriteShort }, + { "WriteUShort", &LuaPacket::WriteUShort }, + { "WriteLong", &LuaPacket::WriteLong }, + { "WriteULong", &LuaPacket::WriteULong }, + { "WriteGUID", &LuaPacket::WriteGUID }, + { "WriteString", &LuaPacket::WriteString }, + { "WriteFloat", &LuaPacket::WriteFloat }, + { "WriteDouble", &LuaPacket::WriteDouble }, + + { NULL, NULL } + }; +}; + +#endif diff --git a/src/modules/Eluna/docs/DOC_GEN.md b/src/modules/Eluna/docs/DOC_GEN.md index d1c1c3527d..6acac22bbf 100644 --- a/src/modules/Eluna/docs/DOC_GEN.md +++ b/src/modules/Eluna/docs/DOC_GEN.md @@ -1,5 +1,5 @@ # Documentation generation -Eluna uses a custom made documentation generator to create it's [web documentation](http://elunaluaengine.github.io/). +Eluna uses a custom made documentation generator to create it's [web documentation](http://elunaluaengine.github.io/). The generator is written in python by Patman. It works by parsing Eluna's source files for comments and then generates the HTML and javascript for the documentation based on them. This page guides you through generating the web documentation locally and explains the standards of the documentation comments for you to help us improve our documentation. To contribute with your documentation changes, create a [pull request](https://help.github.com/articles/using-pull-requests/) diff --git a/src/modules/Eluna/docs/ElunaDoc/__main__.py b/src/modules/Eluna/docs/ElunaDoc/__main__.py index d6c7842b52..7da996bc05 100644 --- a/src/modules/Eluna/docs/ElunaDoc/__main__.py +++ b/src/modules/Eluna/docs/ElunaDoc/__main__.py @@ -63,8 +63,9 @@ def make_root(level): shutil.copytree('ElunaDoc/static', 'build/static') # Load up all files with methods we need to parse. + # Hard-coded to the TC files for now. Will have to add core support later on. print 'Finding Eluna method files...' - class_files = find_class_files('../') + class_files = find_class_files('../TrinityCore/') # Parse all the method files. classes = [] diff --git a/src/modules/Eluna/docs/ElunaDoc/static/main.js b/src/modules/Eluna/docs/ElunaDoc/static/main.js index 84ee789c20..cb3f4bfc94 100644 --- a/src/modules/Eluna/docs/ElunaDoc/static/main.js +++ b/src/modules/Eluna/docs/ElunaDoc/static/main.js @@ -118,7 +118,7 @@ * A function to compute the Levenshtein distance between two strings * Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported * Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode - * This code is an unmodified version of the code written by Marco de Wit + * This code is an unmodified version of the code written by Marco de Wit * and was found at http://stackoverflow.com/a/18514751/745719 */ var levenshtein = (function() { @@ -224,7 +224,7 @@ }); } } else if ( - (lev_distance = levenshtein(searchWords[j], val)) <= + (lev_distance = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) { if (typeFilter < 0 || typeFilter === searchIndex[j].ty) { results.push({ @@ -350,16 +350,16 @@ function validateResult(name, path, keys, parent) { for (var i=0; i < keys.length; ++i) { // each check is for validation so we negate the conditions and invalidate - if (!( + if (!( // check for an exact name match name.toLowerCase().indexOf(keys[i]) > -1 || // then an exact path match path.toLowerCase().indexOf(keys[i]) > -1 || // next if there is a parent, check for exact parent match - (parent !== undefined && + (parent !== undefined && parent.name.toLowerCase().indexOf(keys[i]) > -1) || // lastly check to see if the name was a levenshtein match - levenshtein(name.toLowerCase(), keys[i]) <= + levenshtein(name.toLowerCase(), keys[i]) <= MAX_LEV_DISTANCE)) { return false; } diff --git a/src/modules/Eluna/docs/ElunaDoc/templates/_base.html b/src/modules/Eluna/docs/ElunaDoc/templates/_base.html index 5b46ac90ae..b6ba653011 100644 --- a/src/modules/Eluna/docs/ElunaDoc/templates/_base.html +++ b/src/modules/Eluna/docs/ElunaDoc/templates/_base.html @@ -100,6 +100,6 @@

Search tricks

Generated on
-
©2016 - Eluna Lua Engine
+
©2023 - Eluna Lua Engine
diff --git a/src/modules/Eluna/docs/ElunaDoc/templates/index.html b/src/modules/Eluna/docs/ElunaDoc/templates/index.html index 49c4caccb8..04fb3467a5 100644 --- a/src/modules/Eluna/docs/ElunaDoc/templates/index.html +++ b/src/modules/Eluna/docs/ElunaDoc/templates/index.html @@ -33,7 +33,7 @@

Each fork there has Eluna already integrated, so you just need to compile and go!

- Follow us on our Twitter page to view the latest news about what's going on with Eluna. + Join our community Discord server to keep up with Eluna development and user provided support.

@@ -74,4 +74,4 @@

Classes

{%- endfor %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/modules/Eluna/docs/INSTALL.md b/src/modules/Eluna/docs/INSTALL.md index da5eb41cc4..6affaacee1 100644 --- a/src/modules/Eluna/docs/INSTALL.md +++ b/src/modules/Eluna/docs/INSTALL.md @@ -3,17 +3,17 @@ This page will help you get a cMaNGOS and a TrinityCore source with Eluna. If you are looking to get MaNGOS source with Eluna head over to [MaNGOS forum](http://getmangos.eu/) for the installation and updating instructions - however read this page also as it contains important information. -If you are having trouble with the installation or updating the core source, head over to our [support forum](../README.md#documentation). +If you are having trouble with the installation or updating the core source, head over to our [support forum](../README.md#documentation). If you are looking for a way to merge eluna with a fork of the official repositories see [merging](MERGING.md). ### Requirements and dependencies: -**Eluna uses `C++11` so you need a compiler that supports it.** -**Eluna can use ACE or BOOST for filesystem library.** +**Eluna uses `C++11` so you need a compiler that supports it.** +**Eluna can use ACE or BOOST for filesystem library.** Additionally see you desired core's documentation and installation instructions for it's requirements and dependencies. ### Installation 1. Open [git bash](http://git-scm.com/) and navigate to where you want the core source -2. Choose the git address of your desired core and patch below and clone the core with `git clone
`. +2. Choose the git address of your desired core and patch below and clone the core with `git clone
`. For example `git clone https://github.com/ElunaLuaEngine/ElunaTrinityWotlk.git` * TrinityCore WoTLK: `https://github.com/ElunaLuaEngine/ElunaTrinityWotlk.git` * cMaNGOS Classic: `https://github.com/ElunaLuaEngine/ElunaMangosClassic.git` @@ -33,10 +33,10 @@ After installing Eluna you should check out these: - [Eluna features](IMPL_DETAILS.md) ### Updating -Updating is essentially handled in the same manner as you would normally update the core and database. +Updating is essentially handled in the same manner as you would normally update the core and database. To get the newest core source code open `git bash` and navigate to your local source folder. -Then execute use `git pull` followed by `git submodule init` and `git submodule update`. -After updating the source you need to recompile the core normally. Simply use `CMake` if needed and compile. +Then execute use `git pull` followed by `git submodule init` and `git submodule update`. +After updating the source you need to recompile the core normally. Simply use `CMake` if needed and compile. To update the databases refer to the core's or database's official updating documents: * [TrinityCore](http://collab.kpsn.org/display/tc/Databases+Installation) * [cMaNGOS](https://github.com/cmangos/issues/wiki/Installation-Instructions) diff --git a/src/modules/Eluna/docs/MERGING.md b/src/modules/Eluna/docs/MERGING.md index 240d1fe01e..2e488e44e8 100644 --- a/src/modules/Eluna/docs/MERGING.md +++ b/src/modules/Eluna/docs/MERGING.md @@ -1,10 +1,10 @@ # Merging Eluna -Eluna can be added to various sources by applying the core changes required for Eluna to function. -Below you find the guides for merging Eluna with each core or a fork of it. +Eluna can be added to various sources by applying the core changes required for Eluna to function. +Below you find the guides for merging Eluna with each core or a fork of it. If you choose to merge you should be able to maintain and update yourself - we do not maintain your core. View Unofficial Merging below. We also do not fix any merging errors you may have, but you are free to ask about them on the [support forum](../README.md#documentation) and we may assist. -We recommend using the [installation guide](INSTALL.md) especially if you are not familiar with git and updating the code. +We recommend using the [installation guide](INSTALL.md) especially if you are not familiar with git and updating the code. It allows you to simply use `git pull` followed by `git submodule update` to update your source and we will handle the merging and maintenance with the official core source. Naturally you still need to handle updating the database as instructed by the core's wiki or instructions. ### Merging Eluna with MaNGOS diff --git a/src/modules/Eluna/extensions/StackTracePlus/README.md b/src/modules/Eluna/extensions/StackTracePlus/README.md index 8504868b35..8216333f40 100644 --- a/src/modules/Eluna/extensions/StackTracePlus/README.md +++ b/src/modules/Eluna/extensions/StackTracePlus/README.md @@ -9,10 +9,10 @@ function names when they're not available, etc, so, instead of lua5.1.exe: D:\trunk_git\sources\stacktraceplus\test\test.lua:10: attempt to concatenate a nil value stack traceback: - D:\trunk_git\sources\stacktraceplus\test\test.lua:10: in function - (tail call): ? - D:\trunk_git\sources\stacktraceplus\test\test.lua:15: in main chunk - [C]: ? + D:\trunk_git\sources\stacktraceplus\test\test.lua:10: in function + (tail call): ? + D:\trunk_git\sources\stacktraceplus\test\test.lua:15: in main chunk + [C]: ? you'll get @@ -21,13 +21,13 @@ you'll get =============== (2) C function 'function: 00A8F418' (3) Lua function 'g' at file 'D:\trunk_git\sources\stacktraceplus\test\test.lua:10' (best guess) - Local variables: - fun = table module - str = string: "hey" - tb = table: 027DCBE0 {dummy:1, blah:true, foo:bar} - (*temporary) = nil - (*temporary) = string: "text" - (*temporary) = string: "attempt to concatenate a nil value" + Local variables: + fun = table module + str = string: "hey" + tb = table: 027DCBE0 {dummy:1, blah:true, foo:bar} + (*temporary) = nil + (*temporary) = string: "text" + (*temporary) = string: "attempt to concatenate a nil value" (4) tail call (5) main chunk of file 'D:\trunk_git\sources\stacktraceplus\test\test.lua' at line 15 (6) C function 'function: 002CA480' @@ -42,13 +42,13 @@ local STP = require "StackTracePlus" debug.traceback = STP.stacktrace function test() - local s = "this is a string" - local n = 42 - local t = { foo = "bar" } - local co = coroutine - local cr = coroutine.create + local s = "this is a string" + local n = 42 + local t = { foo = "bar" } + local co = coroutine + local cr = coroutine.create - error("an error") + error("an error") end test() ``` @@ -80,15 +80,15 @@ local STP = require "StackTracePlus" debug.traceback = STP.stacktrace local my_table = { - f = function() end + f = function() end } function my_function() end function test(data, func) - local s = "this is a string" + local s = "this is a string" - error("an error") + error("an error") end STP.add_known_table(my_table, "A description for my_table") diff --git a/src/modules/Eluna/extensions/StackTracePlus/StackTracePlus.ext b/src/modules/Eluna/extensions/StackTracePlus/StackTracePlus.ext index 409f1a5bbc..40c25c11d2 100644 --- a/src/modules/Eluna/extensions/StackTracePlus/StackTracePlus.ext +++ b/src/modules/Eluna/extensions/StackTracePlus/StackTracePlus.ext @@ -16,16 +16,16 @@ local string_sub = string.sub local table_concat = table.concat local _M = { - max_tb_output_len = 70 -- controls the maximum length of the 'stringified' table before cutting with ' (more...)' + max_tb_output_len = 70 -- controls the maximum length of the 'stringified' table before cutting with ' (more...)' } -- this tables should be weak so the elements in them won't become uncollectable local m_known_tables = { [_G] = "_G (global table)" } local function add_known_module(name, desc) - local ok, mod = pcall(require, name) - if ok then - m_known_tables[mod] = desc - end + local ok, mod = pcall(require, name) + if ok then + m_known_tables[mod] = desc + end end add_known_module("string", "string module") @@ -48,44 +48,44 @@ local m_user_known_tables = {} local m_known_functions = {} for _, name in ipairs{ - -- Lua 5.2, 5.1 - "assert", - "collectgarbage", - "dofile", - "error", - "getmetatable", - "ipairs", - "load", - "loadfile", - "next", - "pairs", - "pcall", - "print", - "rawequal", - "rawget", - "rawlen", - "rawset", - "require", - "select", - "setmetatable", - "tonumber", - "tostring", - "type", - "xpcall", - - -- Lua 5.1 - "gcinfo", - "getfenv", - "loadstring", - "module", - "newproxy", - "setfenv", - "unpack", - -- TODO: add table.* etc functions + -- Lua 5.2, 5.1 + "assert", + "collectgarbage", + "dofile", + "error", + "getmetatable", + "ipairs", + "load", + "loadfile", + "next", + "pairs", + "pcall", + "print", + "rawequal", + "rawget", + "rawlen", + "rawset", + "require", + "select", + "setmetatable", + "tonumber", + "tostring", + "type", + "xpcall", + + -- Lua 5.1 + "gcinfo", + "getfenv", + "loadstring", + "module", + "newproxy", + "setfenv", + "unpack", + -- TODO: add table.* etc functions } do - if _G[name] then - m_known_functions[_G[name]] = name - end + if _G[name] then + m_known_functions[_G[name]] = name + end end @@ -93,37 +93,37 @@ end local m_user_known_functions = {} local function safe_tostring (value) - local ok, err = pcall(tostring, value) - if ok then return err else return (": '%s'"):format(err) end + local ok, err = pcall(tostring, value) + if ok then return err else return (": '%s'"):format(err) end end -- Private: -- Parses a line, looking for possible function definitions (in a very na?ve way) -- Returns '(anonymous)' if no function name was found in the line local function ParseLine(line) - assert(type(line) == "string") - --print(line) - local match = line:match("^%s*function%s+(%w+)") - if match then - --print("+++++++++++++function", match) - return match - end - match = line:match("^%s*local%s+function%s+(%w+)") - if match then - --print("++++++++++++local", match) - return match - end - match = line:match("^%s*local%s+(%w+)%s+=%s+function") - if match then - --print("++++++++++++local func", match) - return match - end - match = line:match("%s*function%s*%(") -- this is an anonymous function - if match then - --print("+++++++++++++function2", match) - return "(anonymous)" - end - return "(anonymous)" + assert(type(line) == "string") + --print(line) + local match = line:match("^%s*function%s+(%w+)") + if match then + --print("+++++++++++++function", match) + return match + end + match = line:match("^%s*local%s+function%s+(%w+)") + if match then + --print("++++++++++++local", match) + return match + end + match = line:match("^%s*local%s+(%w+)%s+=%s+function") + if match then + --print("++++++++++++local func", match) + return match + end + match = line:match("%s*function%s*%(") -- this is an anonymous function + if match then + --print("+++++++++++++function2", match) + return "(anonymous)" + end + return "(anonymous)" end -- Private: @@ -131,38 +131,38 @@ end -- It parses either the file or the string where the function is defined. -- Returns '?' if the line where the function is defined is not found local function GuessFunctionName(info) - --print("guessing function name") - if type(info.source) == "string" and info.source:sub(1,1) == "@" then - local file, err = io_open(info.source:sub(2), "r") - if not file then - print("file not found: "..tostring(err)) -- whoops! - return "?" - end - local line - for i = 1, info.linedefined do - line = file:read("*l") - end - if not line then - print("line not found") -- whoops! - return "?" - end - return ParseLine(line) - else - local line - local lineNumber = 0 - for l in string_gmatch(info.source, "([^\n]+)\n-") do - lineNumber = lineNumber + 1 - if lineNumber == info.linedefined then - line = l - break - end - end - if not line then - print("line not found") -- whoops! - return "?" - end - return ParseLine(line) - end + --print("guessing function name") + if type(info.source) == "string" and info.source:sub(1,1) == "@" then + local file, err = io_open(info.source:sub(2), "r") + if not file then + print("file not found: "..tostring(err)) -- whoops! + return "?" + end + local line + for i = 1, info.linedefined do + line = file:read("*l") + end + if not line then + print("line not found") -- whoops! + return "?" + end + return ParseLine(line) + else + local line + local lineNumber = 0 + for l in string_gmatch(info.source, "([^\n]+)\n-") do + lineNumber = lineNumber + 1 + if lineNumber == info.linedefined then + line = l + break + end + end + if not line then + print("line not found") -- whoops! + return "?" + end + return ParseLine(line) + end end --- @@ -171,44 +171,44 @@ end local Dumper = {} Dumper.new = function(thread) - local t = { lines = {} } - for k,v in pairs(Dumper) do t[k] = v end - - t.dumping_same_thread = (thread == coroutine.running()) - - -- if a thread was supplied, bind it to debug.info and debug.get - -- we also need to skip this additional level we are introducing in the callstack (only if we are running - -- in the same thread we're inspecting) - if type(thread) == "thread" then - t.getinfo = function(level, what) - if t.dumping_same_thread and type(level) == "number" then - level = level + 1 - end - return debug.getinfo(thread, level, what) - end - t.getlocal = function(level, loc) - if t.dumping_same_thread then - level = level + 1 - end - return debug.getlocal(thread, level, loc) - end - else - t.getinfo = debug.getinfo - t.getlocal = debug.getlocal - end - - return t + local t = { lines = {} } + for k,v in pairs(Dumper) do t[k] = v end + + t.dumping_same_thread = (thread == coroutine.running()) + + -- if a thread was supplied, bind it to debug.info and debug.get + -- we also need to skip this additional level we are introducing in the callstack (only if we are running + -- in the same thread we're inspecting) + if type(thread) == "thread" then + t.getinfo = function(level, what) + if t.dumping_same_thread and type(level) == "number" then + level = level + 1 + end + return debug.getinfo(thread, level, what) + end + t.getlocal = function(level, loc) + if t.dumping_same_thread then + level = level + 1 + end + return debug.getlocal(thread, level, loc) + end + else + t.getinfo = debug.getinfo + t.getlocal = debug.getlocal + end + + return t end -- helpers for collecting strings to be used when assembling the final trace function Dumper:add (text) - self.lines[#self.lines + 1] = text + self.lines[#self.lines + 1] = text end function Dumper:add_f (fmt, ...) - self:add(fmt:format(...)) + self:add(fmt:format(...)) end function Dumper:concat_lines () - return table_concat(self.lines) + return table_concat(self.lines) end --- @@ -218,66 +218,66 @@ end -- @param level The stack level where the function is. -- function Dumper:DumpLocals (level) - local prefix = "\t " - local i = 1 - - if self.dumping_same_thread then - level = level + 1 - end - - local name, value = self.getlocal(level, i) - if not name then - return - end - self:add("\tLocal variables:\r\n") - while name do - if type(value) == "number" then - self:add_f("%s%s = number: %g\r\n", prefix, name, value) - elseif type(value) == "boolean" then - self:add_f("%s%s = boolean: %s\r\n", prefix, name, tostring(value)) - elseif type(value) == "string" then - self:add_f("%s%s = string: %q\r\n", prefix, name, value) - elseif type(value) == "userdata" then - self:add_f("%s%s = %s\r\n", prefix, name, safe_tostring(value)) - elseif type(value) == "nil" then - self:add_f("%s%s = nil\r\n", prefix, name) - elseif type(value) == "table" then - if m_known_tables[value] then - self:add_f("%s%s = %s\r\n", prefix, name, m_known_tables[value]) - elseif m_user_known_tables[value] then - self:add_f("%s%s = %s\r\n", prefix, name, m_user_known_tables[value]) - else - local txt = "{" - for k,v in pairs(value) do - txt = txt..safe_tostring(k)..":"..safe_tostring(v) - if #txt > _M.max_tb_output_len then - txt = txt.." (more...)" - break - end - if next(value, k) then txt = txt..", " end - end - self:add_f("%s%s = %s %s\r\n", prefix, name, safe_tostring(value), txt.."}") - end - elseif type(value) == "function" then - local info = self.getinfo(value, "nS") - local fun_name = info.name or m_known_functions[value] or m_user_known_functions[value] - if info.what == "C" then - self:add_f("%s%s = C %s\r\n", prefix, name, (fun_name and ("function: " .. fun_name) or tostring(value))) - else - local source = info.short_src - if source:sub(2,7) == "string" then - source = source:sub(9) -- uno m?s, por el espacio que viene (string "Baragent.Main", por ejemplo) - end - --for k,v in pairs(info) do print(k,v) end - fun_name = fun_name or GuessFunctionName(info) - self:add_f("%s%s = Lua function '%s' (defined at line %d of chunk %s)\r\n", prefix, name, fun_name, info.linedefined, source) - end - elseif type(value) == "thread" then - self:add_f("%sthread %q = %s\r\n", prefix, name, tostring(value)) - end - i = i + 1 - name, value = self.getlocal(level, i) - end + local prefix = "\t " + local i = 1 + + if self.dumping_same_thread then + level = level + 1 + end + + local name, value = self.getlocal(level, i) + if not name then + return + end + self:add("\tLocal variables:\r\n") + while name do + if type(value) == "number" then + self:add_f("%s%s = number: %g\r\n", prefix, name, value) + elseif type(value) == "boolean" then + self:add_f("%s%s = boolean: %s\r\n", prefix, name, tostring(value)) + elseif type(value) == "string" then + self:add_f("%s%s = string: %q\r\n", prefix, name, value) + elseif type(value) == "userdata" then + self:add_f("%s%s = %s\r\n", prefix, name, safe_tostring(value)) + elseif type(value) == "nil" then + self:add_f("%s%s = nil\r\n", prefix, name) + elseif type(value) == "table" then + if m_known_tables[value] then + self:add_f("%s%s = %s\r\n", prefix, name, m_known_tables[value]) + elseif m_user_known_tables[value] then + self:add_f("%s%s = %s\r\n", prefix, name, m_user_known_tables[value]) + else + local txt = "{" + for k,v in pairs(value) do + txt = txt..safe_tostring(k)..":"..safe_tostring(v) + if #txt > _M.max_tb_output_len then + txt = txt.." (more...)" + break + end + if next(value, k) then txt = txt..", " end + end + self:add_f("%s%s = %s %s\r\n", prefix, name, safe_tostring(value), txt.."}") + end + elseif type(value) == "function" then + local info = self.getinfo(value, "nS") + local fun_name = info.name or m_known_functions[value] or m_user_known_functions[value] + if info.what == "C" then + self:add_f("%s%s = C %s\r\n", prefix, name, (fun_name and ("function: " .. fun_name) or tostring(value))) + else + local source = info.short_src + if source:sub(2,7) == "string" then + source = source:sub(9) -- uno m?s, por el espacio que viene (string "Baragent.Main", por ejemplo) + end + --for k,v in pairs(info) do print(k,v) end + fun_name = fun_name or GuessFunctionName(info) + self:add_f("%s%s = Lua function '%s' (defined at line %d of chunk %s)\r\n", prefix, name, fun_name, info.linedefined, source) + end + elseif type(value) == "thread" then + self:add_f("%sthread %q = %s\r\n", prefix, name, tostring(value)) + end + i = i + 1 + name, value = self.getlocal(level, i) + end end @@ -293,119 +293,119 @@ end -- Returns a string with the stack trace and a string with the original error. -- function _M.stacktrace(thread, message, level) - if type(thread) ~= "thread" then - -- shift parameters left - thread, message, level = nil, thread, message - end - - thread = thread or coroutine.running() - - level = level or 1 - - local dumper = Dumper.new(thread) - - local original_error - - if type(message) == "table" then - dumper:add("an error object {\r\n") - local first = true - for k,v in pairs(message) do - if first then - dumper:add(" ") - first = false - else - dumper:add(",\r\n ") - end - dumper:add(safe_tostring(k)) - dumper:add(": ") - dumper:add(safe_tostring(v)) - end - dumper:add("\r\n}") - original_error = dumper:concat_lines() - elseif type(message) == "string" then - dumper:add(message) - original_error = message - end - - dumper:add("\r\n") - dumper:add[[ + if type(thread) ~= "thread" then + -- shift parameters left + thread, message, level = nil, thread, message + end + + thread = thread or coroutine.running() + + level = level or 1 + + local dumper = Dumper.new(thread) + + local original_error + + if type(message) == "table" then + dumper:add("an error object {\r\n") + local first = true + for k,v in pairs(message) do + if first then + dumper:add(" ") + first = false + else + dumper:add(",\r\n ") + end + dumper:add(safe_tostring(k)) + dumper:add(": ") + dumper:add(safe_tostring(v)) + end + dumper:add("\r\n}") + original_error = dumper:concat_lines() + elseif type(message) == "string" then + dumper:add(message) + original_error = message + end + + dumper:add("\r\n") + dumper:add[[ Stack Traceback =============== ]] - --print(error_message) - - local level_to_show = level - if dumper.dumping_same_thread then level = level + 1 end - - local info = dumper.getinfo(level, "nSlf") - while info do - if info.what == "main" then - if string_sub(info.source, 1, 1) == "@" then - dumper:add_f("(%d) main chunk of file '%s' at line %d\r\n", level_to_show, string_sub(info.source, 2), info.currentline) - else - dumper:add_f("(%d) main chunk of %s at line %d\r\n", level_to_show, info.short_src, info.currentline) - end - elseif info.what == "C" then - --print(info.namewhat, info.name) - --for k,v in pairs(info) do print(k,v, type(v)) end - local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name or tostring(info.func) - dumper:add_f("(%d) %s C function '%s'\r\n", level_to_show, info.namewhat, function_name) - --dumper:add_f("%s%s = C %s\r\n", prefix, name, (m_known_functions[value] and ("function: " .. m_known_functions[value]) or tostring(value))) - elseif info.what == "tail" then - --print("tail") - --for k,v in pairs(info) do print(k,v, type(v)) end--print(info.namewhat, info.name) - dumper:add_f("(%d) tail call\r\n", level_to_show) - dumper:DumpLocals(level) - elseif info.what == "Lua" then - local source = info.short_src - local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name - if source:sub(2, 7) == "string" then - source = source:sub(9) - end - local was_guessed = false - if not function_name or function_name == "?" then - --for k,v in pairs(info) do print(k,v, type(v)) end - function_name = GuessFunctionName(info) - was_guessed = true - end - -- test if we have a file name - local function_type = (info.namewhat == "") and "function" or info.namewhat - if info.source and info.source:sub(1, 1) == "@" then - dumper:add_f("(%d) Lua %s '%s' at file '%s:%d'%s\r\n", level_to_show, function_type, function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "") - elseif info.source and info.source:sub(1,1) == '#' then - dumper:add_f("(%d) Lua %s '%s' at template '%s:%d'%s\r\n", level_to_show, function_type, function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "") - else - dumper:add_f("(%d) Lua %s '%s' at line %d of chunk '%s'\r\n", level_to_show, function_type, function_name, info.currentline, source) - end - dumper:DumpLocals(level) - else - dumper:add_f("(%d) unknown frame %s\r\n", level_to_show, info.what) - end - - level = level + 1 - level_to_show = level_to_show + 1 - info = dumper.getinfo(level, "nSlf") - end - - return dumper:concat_lines(), original_error + --print(error_message) + + local level_to_show = level + if dumper.dumping_same_thread then level = level + 1 end + + local info = dumper.getinfo(level, "nSlf") + while info do + if info.what == "main" then + if string_sub(info.source, 1, 1) == "@" then + dumper:add_f("(%d) main chunk of file '%s' at line %d\r\n", level_to_show, string_sub(info.source, 2), info.currentline) + else + dumper:add_f("(%d) main chunk of %s at line %d\r\n", level_to_show, info.short_src, info.currentline) + end + elseif info.what == "C" then + --print(info.namewhat, info.name) + --for k,v in pairs(info) do print(k,v, type(v)) end + local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name or tostring(info.func) + dumper:add_f("(%d) %s C function '%s'\r\n", level_to_show, info.namewhat, function_name) + --dumper:add_f("%s%s = C %s\r\n", prefix, name, (m_known_functions[value] and ("function: " .. m_known_functions[value]) or tostring(value))) + elseif info.what == "tail" then + --print("tail") + --for k,v in pairs(info) do print(k,v, type(v)) end--print(info.namewhat, info.name) + dumper:add_f("(%d) tail call\r\n", level_to_show) + dumper:DumpLocals(level) + elseif info.what == "Lua" then + local source = info.short_src + local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name + if source:sub(2, 7) == "string" then + source = source:sub(9) + end + local was_guessed = false + if not function_name or function_name == "?" then + --for k,v in pairs(info) do print(k,v, type(v)) end + function_name = GuessFunctionName(info) + was_guessed = true + end + -- test if we have a file name + local function_type = (info.namewhat == "") and "function" or info.namewhat + if info.source and info.source:sub(1, 1) == "@" then + dumper:add_f("(%d) Lua %s '%s' at file '%s:%d'%s\r\n", level_to_show, function_type, function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "") + elseif info.source and info.source:sub(1,1) == '#' then + dumper:add_f("(%d) Lua %s '%s' at template '%s:%d'%s\r\n", level_to_show, function_type, function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "") + else + dumper:add_f("(%d) Lua %s '%s' at line %d of chunk '%s'\r\n", level_to_show, function_type, function_name, info.currentline, source) + end + dumper:DumpLocals(level) + else + dumper:add_f("(%d) unknown frame %s\r\n", level_to_show, info.what) + end + + level = level + 1 + level_to_show = level_to_show + 1 + info = dumper.getinfo(level, "nSlf") + end + + return dumper:concat_lines(), original_error end -- -- Adds a table to the list of known tables function _M.add_known_table(tab, description) - if m_known_tables[tab] then - error("Cannot override an already known table") - end - m_user_known_tables[tab] = description + if m_known_tables[tab] then + error("Cannot override an already known table") + end + m_user_known_tables[tab] = description end -- -- Adds a function to the list of known functions function _M.add_known_function(fun, description) - if m_known_functions[fun] then - error("Cannot override an already known function") - end - m_user_known_functions[fun] = description + if m_known_functions[fun] then + error("Cannot override an already known function") + end + m_user_known_functions[fun] = description end return _M diff --git a/src/modules/Eluna/lmarshal.cpp b/src/modules/Eluna/lmarshal.cpp index 67a63af5e4..796c6bb3fa 100644 --- a/src/modules/Eluna/lmarshal.cpp +++ b/src/modules/Eluna/lmarshal.cpp @@ -32,6 +32,7 @@ #include #include #include +#include "ElunaCompat.h" extern "C" { #include "lua.h" @@ -292,8 +293,8 @@ static void mar_encode_value(lua_State *L, mar_Buffer *buf, int val, size_t *idx buf_write(L, (const char*)&tag, MAR_CHR, buf); buf_write(L, (const char*)&rec_buf.head, MAR_I32, buf); - buf_write(L, rec_buf.data, rec_buf.head, buf); - buf_done(L, &rec_buf); + buf_write(L, rec_buf.data, rec_buf.head, buf); + buf_done(L, &rec_buf); } else { luaL_error(L, "attempt to encode userdata (no __persist hook)"); @@ -569,7 +570,7 @@ static const luaL_Reg R[] = {"encode", mar_encode}, {"decode", mar_decode}, {"clone", mar_clone}, - {NULL, NULL} + {NULL, NULL} }; int luaopen_marshal(lua_State *L)