From 0a2d6a686892a0aba80dfae72d6614297f5ca698 Mon Sep 17 00:00:00 2001 From: TracentEden <92269743+TracentEden@users.noreply.github.com> Date: Fri, 10 May 2024 23:52:56 +0300 Subject: [PATCH] Add getfishers command to get all recent fishers Co-authored-by: xkoredev --- scripts/commands/getfishers.lua | 43 +++++++++++++++++++++++++++++++++ src/map/lua/luautils.cpp | 40 ++++++++++++++++++++++++++++++ src/map/lua/luautils.h | 3 ++- src/map/utils/fishingutils.cpp | 2 ++ 4 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 scripts/commands/getfishers.lua diff --git a/scripts/commands/getfishers.lua b/scripts/commands/getfishers.lua new file mode 100644 index 00000000000..c395514fe03 --- /dev/null +++ b/scripts/commands/getfishers.lua @@ -0,0 +1,43 @@ +----------------------------------- +-- func: getfishers +-- desc: Returns a list of all players who have recently fished. +-- The default period to look back is 5 minutes but command +-- accepts parameter between 1 and 60 minutes +----------------------------------- +local commandObj = {} + +commandObj.cmdprops = +{ + permission = 1, + parameters = 'i' +} + +local function error(player, msg) + player:printToPlayer(msg) + player:printToPlayer('!getfishers ') +end + +commandObj.onTrigger = function(player, minutes) + -- default look back period is 5 minutes + if minutes == nil then + minutes = 5 + elseif minutes < 1 or minutes > 60 then + error(player, 'The specified look back period must be between 1 and 60 minutes.') + return + end + + local fishers = GetRecentFishers(minutes) + + if #fishers == 0 then + player:printToPlayer(string.format('No active fishers in past %i minutes.', minutes), xi.msg.channel.SYSTEM_3) + return + end + + player:printToPlayer(string.format('Active fishers in past %i minutes:', minutes), xi.msg.channel.SYSTEM_3) + for _, fisher in pairs(fishers) do + player:printToPlayer(string.format('Name: %s, Zone: %s, JobLevel: %d, Skill: %d', + fisher.playerName, fisher.zoneName, fisher.jobLevel, fisher.skill), xi.msg.channel.SYSTEM_3) + end +end + +return commandObj diff --git a/src/map/lua/luautils.cpp b/src/map/lua/luautils.cpp index 052791ccc9a..106aaf332d7 100644 --- a/src/map/lua/luautils.cpp +++ b/src/map/lua/luautils.cpp @@ -214,6 +214,7 @@ namespace luautils lua.set_function("GetMobRespawnTime", &luautils::GetMobRespawnTime); lua.set_function("DisallowRespawn", &luautils::DisallowRespawn); lua.set_function("UpdateNMSpawnPoint", &luautils::UpdateNMSpawnPoint); + lua.set_function("GetRecentFishers", &luautils::GetRecentFishers); lua.set_function("NearLocation", &luautils::NearLocation); lua.set_function("GetFurthestValidPosition", &luautils::GetFurthestValidPosition); lua.set_function("Terminate", &luautils::Terminate); @@ -5082,6 +5083,45 @@ namespace luautils return 0; } + /************************************************************************ + * Gets a list of players that have fished in the last specified mins * + * where the specified param is between 1 and 60 mins * + ************************************************************************/ + + sol::table GetRecentFishers(uint16 minutes) + { + // limit the lookback time to prevent huge queries + uint16 lookbackTime = std::clamp(minutes, 1, 60); + + sol::table fishers = lua.create_table(); + const char* Query = "SELECT cv.charid, c.charname, stats.mlvl, z.name, COALESCE(cs.value, 0) / 10 as skill " + "FROM char_vars cv " + "LEFT JOIN chars c ON c.charid = cv.charid " + "LEFT JOIN char_skills cs ON cs.charid = cv.charid AND cs.skillid = 48 " + "INNER JOIN char_stats stats ON stats.charid = c.charid " + "INNER JOIN zone_settings z ON z.zoneid = c.pos_zone " + "WHERE " + "varname = '[Fish]LastCastTime' AND " + "FROM_UNIXTIME(cv.value) > NOW() - INTERVAL %u MINUTE " + "ORDER BY z.name, z.name, stats.mlvl, skill"; + + if (_sql->Query(Query, lookbackTime) != SQL_ERROR && _sql->NumRows() != 0) + { + while (_sql->NextRow() == SQL_SUCCESS) + { + auto fisher = lua.create_table(); + auto charId = _sql->GetUIntData(0); + fisher["playerName"] = _sql->GetStringData(1); + fisher["jobLevel"] = _sql->GetUIntData(2); + fisher["zoneName"] = _sql->GetStringData(3); + fisher["skill"] = _sql->GetUIntData(4); + fishers[charId] = fisher; + } + } + + return fishers; + } + std::string GetServerMessage(uint8 language) { TracyZoneScoped; diff --git a/src/map/lua/luautils.h b/src/map/lua/luautils.h index 9ba5bdb9219..6f2b7fe266c 100644 --- a/src/map/lua/luautils.h +++ b/src/map/lua/luautils.h @@ -328,7 +328,8 @@ namespace luautils void DisallowRespawn(uint32 mobid, bool allowRespawn); void UpdateNMSpawnPoint(uint32 mobid); - std::string GetServerMessage(uint8 language); // Get the message to be delivered to player on first zone in of a session + std::string GetServerMessage(uint8 language); // Get the message to be delivered to player on first zone in of a session + auto GetRecentFishers(uint16 minutes) -> sol::table; // returns a list of recently active fishers (that fished in the last specified minutes) int32 OnAdditionalEffect(CBattleEntity* PAttacker, CBattleEntity* PDefender, actionTarget_t* Action, int32 damage); // for mobs with additional effects int32 OnSpikesDamage(CBattleEntity* PDefender, CBattleEntity* PAttacker, actionTarget_t* Action, int32 damage); // for mobs with spikes diff --git a/src/map/utils/fishingutils.cpp b/src/map/utils/fishingutils.cpp index d23262f5c29..3b67b167c9f 100644 --- a/src/map/utils/fishingutils.cpp +++ b/src/map/utils/fishingutils.cpp @@ -1950,6 +1950,8 @@ namespace fishingutils } else { + auto secs = std::chrono::duration_cast(server_clock::now().time_since_epoch()); + PChar->setCharVar("[Fish]LastCastTime", secs.count()); PChar->lastCastTime = vanaTime; PChar->nextFishTime = PChar->lastCastTime + 5; }