From b51a32c3df4cc18d41ab200c5552d847f0e0db6c Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Tue, 2 Apr 2024 12:52:11 -0300 Subject: [PATCH 1/4] Created playerOnWalk EventCallback. Created talkaction to spam "AFK" message to support players (gm & god). --- data/scripts/eventcallbacks/README.md | 1 + data/scripts/talkactions/gm/afk.lua | 79 +++++++++++++++++++++ src/creatures/players/player.cpp | 2 + src/lua/callbacks/callbacks_definitions.hpp | 1 + src/lua/callbacks/event_callback.cpp | 23 ++++++ src/lua/callbacks/event_callback.hpp | 1 + 6 files changed, 107 insertions(+) create mode 100644 data/scripts/talkactions/gm/afk.lua diff --git a/data/scripts/eventcallbacks/README.md b/data/scripts/eventcallbacks/README.md index bdafcb41b33..601653574bd 100644 --- a/data/scripts/eventcallbacks/README.md +++ b/data/scripts/eventcallbacks/README.md @@ -47,6 +47,7 @@ Event callbacks are available for several categories of game entities, such as ` - `(void)` `playerOnCombat` - `(void)` `playerOnInventoryUpdate` - `(bool)` `playerOnRotateItem` +- `(void)` `playerOnWalk` - `(void)` `monsterOnDropLoot` - `(void)` `monsterPostDropLoot` - `(void)` `monsterOnSpawn` diff --git a/data/scripts/talkactions/gm/afk.lua b/data/scripts/talkactions/gm/afk.lua new file mode 100644 index 00000000000..4285ec9b111 --- /dev/null +++ b/data/scripts/talkactions/gm/afk.lua @@ -0,0 +1,79 @@ +local afk = TalkAction("/afk") + +playersAFKs = {} + +local function checkIsAFK(id) + for index, item in pairs(playersAFKs) do + if id == item.id then + return { afk = true, index = index } + end + end + return { afk = false } +end + +function afk.onSay(player, words, param) + if param == "" then + player:sendCancelMessage("You need to specify on/off param.") + return true + end + + local id, position = player:getId(), player:getPosition() + local isAfk = checkIsAFK(id) + if param == "on" then + if isAfk.afk then + player:sendCancelMessage("You already is AFK!") + return true + end + + table.insert(playersAFKs, { id = id, position = position }) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are now AFK!") + position:sendMagicEffect(CONST_ME_REDSMOKE) + local spectators = Game.getSpectators(position, false, true, 8, 8, 8, 8) + if #spectators > 0 then + for _, spectator in ipairs(spectators) do + spectator:say("AFK !", TALKTYPE_MONSTER_SAY, false, spectator, position) + end + end + elseif param == "off" then + if isAfk.afk then + table.remove(playersAFKs, isAfk.index) + end + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are no longer AFK!") + position:sendMagicEffect(CONST_ME_REDSMOKE) + end + + return true +end + +afk:separator(" ") +afk:groupType("gamemaster") +afk:register() + +------------------ AFK Effect Message ------------------ +local afkEffect = GlobalEvent("GodAfkEffect") +function afkEffect.onThink(interval) + for _, player in ipairs(playersAFKs) do + local spectators = Game.getSpectators(player.position, false, true, 8, 8, 8, 8) + if #spectators > 0 then + for _, spectator in ipairs(spectators) do + spectator:say("AFK !", TALKTYPE_MONSTER_SAY, false, spectator, player.position) + end + end + end + return true +end + +afkEffect:interval(5000) +afkEffect:register() + +------------------ Stop AFK Message when moves ------------------ +local callback = EventCallback() +function callback.playerOnWalk(player, creature, creaturePos, toPos) + local isAfk = checkIsAFK(player:getId()) + if isAfk.afk then + table.remove(playersAFKs, isAfk.index) + end + return true +end + +callback:register() diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 75e5b5ef2af..77f1b2377e1 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -1926,6 +1926,8 @@ void Player::onWalk(Direction &dir) { Creature::onWalk(dir); setNextActionTask(nullptr); setNextAction(OTSYS_TIME() + getStepDuration(dir)); + + g_callbacks().executeCallback(EventCallback_t::playerOnWalk, &EventCallback::playerOnWalk, getPlayer(), dir); } void Player::onCreatureMove(const std::shared_ptr &creature, const std::shared_ptr &newTile, const Position &newPos, const std::shared_ptr &oldTile, const Position &oldPos, bool teleport) { diff --git a/src/lua/callbacks/callbacks_definitions.hpp b/src/lua/callbacks/callbacks_definitions.hpp index 521a2c4cda7..3b8016f5f5b 100644 --- a/src/lua/callbacks/callbacks_definitions.hpp +++ b/src/lua/callbacks/callbacks_definitions.hpp @@ -56,6 +56,7 @@ enum class EventCallback_t : uint16_t { playerOnCombat, playerOnInventoryUpdate, playerOnRotateItem, + playerOnWalk, // Monster monsterOnDropLoot, monsterPostDropLoot, diff --git a/src/lua/callbacks/event_callback.cpp b/src/lua/callbacks/event_callback.cpp index 51c03131fa9..d2b88c30f3a 100644 --- a/src/lua/callbacks/event_callback.cpp +++ b/src/lua/callbacks/event_callback.cpp @@ -985,6 +985,29 @@ bool EventCallback::playerOnRotateItem(std::shared_ptr player, std::shar return getScriptInterface()->callFunction(3); } +void EventCallback::playerOnWalk(std::shared_ptr player, Direction &dir) const { + if (!getScriptInterface()->reserveScriptEnv()) { + g_logger().error("[EventCallback::eventOnWalk - " + "Player {}] " + "Call stack overflow. Too many lua script calls being nested.", + player->getName()); + return; + } + + ScriptEnvironment* scriptEnvironment = getScriptInterface()->getScriptEnv(); + scriptEnvironment->setScriptId(getScriptId(), getScriptInterface()); + + lua_State* L = getScriptInterface()->getLuaState(); + getScriptInterface()->pushFunction(getScriptId()); + + LuaScriptInterface::pushUserdata(L, player); + LuaScriptInterface::setMetatable(L, -1, "Player"); + + lua_pushnumber(L, dir); + + getScriptInterface()->callVoidFunction(2); +} + void EventCallback::playerOnStorageUpdate(std::shared_ptr player, const uint32_t key, const int32_t value, int32_t oldValue, uint64_t currentTime) const { if (!getScriptInterface()->reserveScriptEnv()) { g_logger().error("[EventCallback::eventOnStorageUpdate - " diff --git a/src/lua/callbacks/event_callback.hpp b/src/lua/callbacks/event_callback.hpp index d9dc4a9b110..9141235a028 100644 --- a/src/lua/callbacks/event_callback.hpp +++ b/src/lua/callbacks/event_callback.hpp @@ -116,6 +116,7 @@ class EventCallback : public Script { void playerOnCombat(std::shared_ptr player, std::shared_ptr target, std::shared_ptr item, CombatDamage &damage) const; void playerOnInventoryUpdate(std::shared_ptr player, std::shared_ptr item, Slots_t slot, bool equip) const; bool playerOnRotateItem(std::shared_ptr player, std::shared_ptr item, const Position &position) const; + void playerOnWalk(std::shared_ptr player, Direction &dir) const; // Monster void monsterOnDropLoot(std::shared_ptr monster, std::shared_ptr corpse) const; From 4e39524c4cf2a209d56b4986bfe3cea64dfe2a68 Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Tue, 2 Apr 2024 14:10:25 -0300 Subject: [PATCH 2/4] Check ghost mode. --- data/scripts/talkactions/gm/afk.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data/scripts/talkactions/gm/afk.lua b/data/scripts/talkactions/gm/afk.lua index 4285ec9b111..de10845191d 100644 --- a/data/scripts/talkactions/gm/afk.lua +++ b/data/scripts/talkactions/gm/afk.lua @@ -26,6 +26,9 @@ function afk.onSay(player, words, param) end table.insert(playersAFKs, { id = id, position = position }) + if player:isInGhostMode() then + player:setGhostMode(false) + end player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are now AFK!") position:sendMagicEffect(CONST_ME_REDSMOKE) local spectators = Game.getSpectators(position, false, true, 8, 8, 8, 8) From 2514df348315eb24c101da1052df9c02ada7106a Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Tue, 2 Apr 2024 17:47:28 -0300 Subject: [PATCH 3/4] fix typos. --- data/scripts/talkactions/gm/afk.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/scripts/talkactions/gm/afk.lua b/data/scripts/talkactions/gm/afk.lua index de10845191d..a01a324195a 100644 --- a/data/scripts/talkactions/gm/afk.lua +++ b/data/scripts/talkactions/gm/afk.lua @@ -21,7 +21,7 @@ function afk.onSay(player, words, param) local isAfk = checkIsAFK(id) if param == "on" then if isAfk.afk then - player:sendCancelMessage("You already is AFK!") + player:sendCancelMessage("You are already AFK!") return true end @@ -75,6 +75,7 @@ function callback.playerOnWalk(player, creature, creaturePos, toPos) local isAfk = checkIsAFK(player:getId()) if isAfk.afk then table.remove(playersAFKs, isAfk.index) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are no longer AFK!") end return true end From 4ba32fbc8a102ed6d8e9c0922ebca041ce5cb9c1 Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Sun, 7 Apr 2024 21:40:34 -0300 Subject: [PATCH 4/4] afk script: some improvements and added remove message when player logout. --- data/scripts/talkactions/gm/afk.lua | 45 ++++++++++++++++++----------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/data/scripts/talkactions/gm/afk.lua b/data/scripts/talkactions/gm/afk.lua index a01a324195a..6167a2b6068 100644 --- a/data/scripts/talkactions/gm/afk.lua +++ b/data/scripts/talkactions/gm/afk.lua @@ -11,13 +11,22 @@ local function checkIsAFK(id) return { afk = false } end +local function showAfkMessage(playerPosition) + local spectators = Game.getSpectators(playerPosition, false, true, 8, 8, 8, 8) + if #spectators > 0 then + for _, spectator in ipairs(spectators) do + spectator:say("AFK !", TALKTYPE_MONSTER_SAY, false, spectator, playerPosition) + end + end +end + function afk.onSay(player, words, param) if param == "" then player:sendCancelMessage("You need to specify on/off param.") return true end - local id, position = player:getId(), player:getPosition() + local id, playerPosition = player:getId(), player:getPosition() local isAfk = checkIsAFK(id) if param == "on" then if isAfk.afk then @@ -25,24 +34,19 @@ function afk.onSay(player, words, param) return true end - table.insert(playersAFKs, { id = id, position = position }) + table.insert(playersAFKs, { id = id, position = playerPosition }) if player:isInGhostMode() then player:setGhostMode(false) end player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are now AFK!") - position:sendMagicEffect(CONST_ME_REDSMOKE) - local spectators = Game.getSpectators(position, false, true, 8, 8, 8, 8) - if #spectators > 0 then - for _, spectator in ipairs(spectators) do - spectator:say("AFK !", TALKTYPE_MONSTER_SAY, false, spectator, position) - end - end + playerPosition:sendMagicEffect(CONST_ME_REDSMOKE) + showAfkMessage(playerPosition) elseif param == "off" then if isAfk.afk then table.remove(playersAFKs, isAfk.index) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are no longer AFK!") + playerPosition:sendMagicEffect(CONST_ME_REDSMOKE) end - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are no longer AFK!") - position:sendMagicEffect(CONST_ME_REDSMOKE) end return true @@ -56,12 +60,7 @@ afk:register() local afkEffect = GlobalEvent("GodAfkEffect") function afkEffect.onThink(interval) for _, player in ipairs(playersAFKs) do - local spectators = Game.getSpectators(player.position, false, true, 8, 8, 8, 8) - if #spectators > 0 then - for _, spectator in ipairs(spectators) do - spectator:say("AFK !", TALKTYPE_MONSTER_SAY, false, spectator, player.position) - end - end + showAfkMessage(player.position) end return true end @@ -81,3 +80,15 @@ function callback.playerOnWalk(player, creature, creaturePos, toPos) end callback:register() + +------------------ Player Logout ------------------ +local godAfkLogout = CreatureEvent("GodAfkLogout") +function godAfkLogout.onLogout(player) + local isAfk = checkIsAFK(player:getId()) + if isAfk.afk then + table.remove(playersAFKs, isAfk.index) + end + return true +end + +godAfkLogout:register()