From 85e3cc8621d5cc1a4e64f6d5b2015747a4df4114 Mon Sep 17 00:00:00 2001 From: Sarah Wesker Date: Fri, 12 Jan 2024 10:36:37 -0600 Subject: [PATCH] New event onSpellCheck (#4619) * new event spell check --- data/events/events.xml | 1 + data/events/scripts/player.lua | 8 ++++++++ data/scripts/lib/event_callbacks.lua | 1 + src/events.cpp | 28 ++++++++++++++++++++++++++++ src/events.h | 3 +++ src/luascript.cpp | 13 +++++++++++++ src/luascript.h | 2 ++ src/spells.cpp | 6 ++++++ 8 files changed, 62 insertions(+) diff --git a/data/events/events.xml b/data/events/events.xml index 6af4594efd..8d28bd0312 100644 --- a/data/events/events.xml +++ b/data/events/events.xml @@ -42,6 +42,7 @@ + diff --git a/data/events/scripts/player.lua b/data/events/scripts/player.lua index d2cf4112a4..74c3ce61e1 100644 --- a/data/events/scripts/player.lua +++ b/data/events/scripts/player.lua @@ -304,3 +304,11 @@ function Player:onNetworkMessage(recvByte, msg) handler(self, msg) end + +function Player:onSpellCheck(spell) + local onSpellCheck = EventCallback.onSpellCheck + if onSpellCheck then + return onSpellCheck(self, spell) + end + return true +end diff --git a/data/scripts/lib/event_callbacks.lua b/data/scripts/lib/event_callbacks.lua index e5be9265b9..e9f3bc55d3 100644 --- a/data/scripts/lib/event_callbacks.lua +++ b/data/scripts/lib/event_callbacks.lua @@ -60,6 +60,7 @@ ec.onGainSkillTries = {[3] = 1} ec.onWrapItem = {} ec.onInventoryUpdate = {} ec.onUpdateStorage = {} +ec.onSpellCheck = {} -- Monster ec.onDropLoot = {} ec.onSpawn = {} diff --git a/src/events.cpp b/src/events.cpp index 04c8bf1142..0c2be57a31 100644 --- a/src/events.cpp +++ b/src/events.cpp @@ -122,6 +122,8 @@ bool Events::load() info.playerOnInventoryUpdate = event; } else if (methodName == "onNetworkMessage") { info.playerOnNetworkMessage = event; + } else if (methodName == "onSpellCheck") { + info.playerOnSpellCheck = event; } else { std::cout << "[Warning - Events::load] Unknown player method: " << methodName << std::endl; } @@ -1338,6 +1340,32 @@ void Events::eventPlayerOnNetworkMessage(Player* player, uint8_t recvByte, Netwo scriptInterface.callVoidFunction(3); } +bool Events::eventPlayerOnSpellCheck(Player* player, const Spell* spell) +{ + // Player:onSpellCheck(spell) + if (info.playerOnSpellCheck == -1) { + return true; + } + + if (!scriptInterface.reserveScriptEnv()) { + std::cout << "[Error - Events::eventPlayerOnSpellCheck] Call stack overflow" << std::endl; + return false; + } + + ScriptEnvironment* env = scriptInterface.getScriptEnv(); + env->setScriptId(info.playerOnSpellCheck, &scriptInterface); + + lua_State* L = scriptInterface.getLuaState(); + scriptInterface.pushFunction(info.playerOnSpellCheck); + + LuaScriptInterface::pushUserdata(L, player); + LuaScriptInterface::setMetatable(L, -1, "Player"); + + LuaScriptInterface::pushSpell(L, *spell); + + return scriptInterface.callFunction(2); +} + void Events::eventMonsterOnDropLoot(Monster* monster, Container* corpse) { // Monster:onDropLoot(corpse) diff --git a/src/events.h b/src/events.h index e7cac6c514..a21b37ecbd 100644 --- a/src/events.h +++ b/src/events.h @@ -11,6 +11,7 @@ class ItemType; class NetworkMessage; class Party; +class Spell; class Tile; enum class EventInfoId @@ -68,6 +69,7 @@ class Events int32_t playerOnWrapItem = -1; int32_t playerOnInventoryUpdate = -1; int32_t playerOnNetworkMessage = -1; + int32_t playerOnSpellCheck = -1; // Monster int32_t monsterOnDropLoot = -1; @@ -129,6 +131,7 @@ class Events void eventPlayerOnWrapItem(Player* player, Item* item); void eventPlayerOnInventoryUpdate(Player* player, Item* item, slots_t slot, bool equip); void eventPlayerOnNetworkMessage(Player* player, uint8_t recvByte, NetworkMessage* msg); + bool eventPlayerOnSpellCheck(Player* player, const Spell* spell); // Monster void eventMonsterOnDropLoot(Monster* monster, Container* corpse); diff --git a/src/luascript.cpp b/src/luascript.cpp index 51f5f07955..0d9abccc53 100644 --- a/src/luascript.cpp +++ b/src/luascript.cpp @@ -957,6 +957,19 @@ void LuaScriptInterface::pushInstantSpell(lua_State* L, const InstantSpell& spel setMetatable(L, -1, "Spell"); } +void LuaScriptInterface::pushSpell(lua_State* L, const Spell& spell) +{ + lua_createtable(L, 0, 5); + + setField(L, "name", spell.getName()); + setField(L, "level", spell.getLevel()); + setField(L, "mlevel", spell.getMagicLevel()); + setField(L, "mana", spell.getMana()); + setField(L, "manapercent", spell.getManaPercent()); + + setMetatable(L, -1, "Spell"); +} + void LuaScriptInterface::pushPosition(lua_State* L, const Position& position, int32_t stackpos /* = 0*/) { lua_createtable(L, 0, 4); diff --git a/src/luascript.h b/src/luascript.h index aebf6c26d1..a33293d1ce 100644 --- a/src/luascript.h +++ b/src/luascript.h @@ -23,6 +23,7 @@ class Combat; class Container; class Creature; class Cylinder; +class Spell; class InstantSpell; class Item; class LuaScriptInterface; @@ -354,6 +355,7 @@ class LuaScriptInterface static void pushBoolean(lua_State* L, bool value); static void pushCombatDamage(lua_State* L, const CombatDamage& damage); static void pushInstantSpell(lua_State* L, const InstantSpell& spell); + static void pushSpell(lua_State* L, const Spell& spell); static void pushPosition(lua_State* L, const Position& position, int32_t stackpos = 0); static void pushOutfit(lua_State* L, const Outfit_t& outfit); static void pushOutfit(lua_State* L, const Outfit* outfit); diff --git a/src/spells.cpp b/src/spells.cpp index 84365c191d..4fd1b58151 100644 --- a/src/spells.cpp +++ b/src/spells.cpp @@ -7,6 +7,7 @@ #include "combat.h" #include "configmanager.h" +#include "events.h" #include "game.h" #include "luavariant.h" #include "monsters.h" @@ -14,6 +15,7 @@ extern Game g_game; extern Spells* g_spells; +extern Events* g_events; extern Monsters g_monsters; extern ConfigManager g_config; extern LuaEnvironment g_luaEnvironment; @@ -529,6 +531,10 @@ bool Spell::playerSpellCheck(Player* player) const return false; } + if (!g_events->eventPlayerOnSpellCheck(player, this)) { + return false; + } + if ((aggressive || pzLock) && (range < 1 || (range > 0 && !player->getAttackedCreature())) && player->getSkull() == SKULL_BLACK) { player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE);