From e68858ba958584f35fbf8a96f55fd0f2a81a46a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rey=20Alem=C3=A1n?= Date: Fri, 21 Apr 2023 22:07:20 -0600 Subject: [PATCH] bestiary tracker --- data/creaturescripts/scripts/login.lua | 5 ++ data/global.lua | 9 +++ data/lib/core/game.lua | 6 ++ data/lib/core/player.lua | 76 +++++++++++++++++++ data/lib/core/storages.lua | 1 + .../creaturescripts/bestiary_kills.lua | 4 + data/scripts/network/bestiary_tracker.lua | 11 +++ 7 files changed, 112 insertions(+) create mode 100644 data/scripts/network/bestiary_tracker.lua diff --git a/data/creaturescripts/scripts/login.lua b/data/creaturescripts/scripts/login.lua index cf2c35f794..cc50a62f9f 100644 --- a/data/creaturescripts/scripts/login.lua +++ b/data/creaturescripts/scripts/login.lua @@ -22,6 +22,11 @@ function onLogin(player) player:setVocation(vocation:getDemotion()) end + local trackedBestiary = player:getTrackedBestiary(true) + if #trackedBestiary > 0 then + player:sendBestiaryTracker() + end + -- Events player:registerEvent("PlayerDeath") player:registerEvent("DropLoot") diff --git a/data/global.lua b/data/global.lua index bf1e6e1b2d..4f02daa94f 100644 --- a/data/global.lua +++ b/data/global.lua @@ -112,6 +112,15 @@ table.contains = function(array, value) return false end +table.indexOf = function(array, value) + for i, targetColumn in pairs(array) do + if targetColumn == value then + return i + end + end + return nil +end + string.split = function(str, sep) local res = {} for v in str:gmatch("([^" .. sep .. "]+)") do diff --git a/data/lib/core/game.lua b/data/lib/core/game.lua index 4ce9e9c891..d633fad5d7 100644 --- a/data/lib/core/game.lua +++ b/data/lib/core/game.lua @@ -177,3 +177,9 @@ do return false end end + +do + local trackedBestiary = {} + + function Game.getTrackedBestiary() return trackedBestiary end +end diff --git a/data/lib/core/player.lua b/data/lib/core/player.lua index 5c7b70ff4d..31adb519e5 100644 --- a/data/lib/core/player.lua +++ b/data/lib/core/player.lua @@ -534,3 +534,79 @@ function Player.sendBestiaryMilestoneReached(self, raceId) msg:delete() return true end + +function Player.getMaxTrackedBestiary(self) + return 50 -- client sided +end + +function Player.setTrackedBestiary(self, raceId, checked) + local trackedBestiary = self:getTrackedBestiary() + if checked and #trackedBestiary >= self:getMaxTrackedBestiary() then + self:sendTextMessage(MESSAGE_STATUS_WARNING, "You have reached the maximum number of trackable creatures.\nYou have to remove one of your currently tracked creatures before you can add another one.") + return false + end + + local index = table.indexOf(trackedBestiary, raceId) + if not checked then + if index ~= nil then table.remove(trackedBestiary, index) end + else + if index == nil then table.insert(trackedBestiary, raceId) end + end + + for k = 1, self:getMaxTrackedBestiary() do + self:setStorageValue(PlayerStorageKeys.bestiaryTrackerBase + k, -1) + end + + for k = 1, #trackedBestiary do + self:setStorageValue(PlayerStorageKeys.bestiaryTrackerBase + k, trackedBestiary[k]) + end + + Game.getTrackedBestiary()[self:getId()] = trackedBestiary + + return true +end + +function Player.getTrackedBestiary(self, isLogin) + if isLogin == nil then isLogin = false end + if not isLogin then + return Game.getTrackedBestiary()[self:getId()] + end + + local trackedBestiary = {} + for k = 1, self:getMaxTrackedBestiary() do + local raceId = self:getStorageValue(PlayerStorageKeys.bestiaryTrackerBase + k) + if raceId > 0 then + table.insert(trackedBestiary, raceId) + end + end + + Game.getTrackedBestiary()[self:getId()] = trackedBestiary + + return trackedBestiary +end + +function Player.sendBestiaryTracker(self) + local msg = NetworkMessage() + msg:addByte(0xB9) + + local trackedBestiary = self:getTrackedBestiary() + msg:addByte(#trackedBestiary) + + for _, raceId in ipairs(trackedBestiary) do + msg:addU16(raceId) + + local kills = self:getBestiaryKills(raceId) + msg:addU32(kills) + + local monsterType = MonsterType(raceId) + local info = monsterType and monsterType:getBestiaryInfo() or {prowess = 1, expertise = 2, mastery = 3} + msg:addU16(info.prowess) + msg:addU16(info.expertise) + msg:addU16(info.mastery) + msg:addByte(kills >= info.mastery and 0x01 or 0x00) + end + + msg:sendToPlayer(self) + msg:delete() + return true +end diff --git a/data/lib/core/storages.lua b/data/lib/core/storages.lua index 2ccd844969..0d66b5b1d6 100644 --- a/data/lib/core/storages.lua +++ b/data/lib/core/storages.lua @@ -39,4 +39,5 @@ PlayerStorageKeys = { achievementsCounter = 20000, bestiaryKillsBase = 400000, + bestiaryTrackerBase = 500000, } diff --git a/data/scripts/creaturescripts/bestiary_kills.lua b/data/scripts/creaturescripts/bestiary_kills.lua index cba9b68c25..2ab41d7ecc 100644 --- a/data/scripts/creaturescripts/bestiary_kills.lua +++ b/data/scripts/creaturescripts/bestiary_kills.lua @@ -36,6 +36,10 @@ function creatureEvent.onKill(player, target) for _, killer in pairs(getKillersForBestiary(monster)) do killer:addBestiaryKills(raceId) + local trackedBestiary = killer:getTrackedBestiary() + if #trackedBestiary > 0 and table.contains(trackedBestiary, raceId) then + killer:sendBestiaryTracker() + end end return true end diff --git a/data/scripts/network/bestiary_tracker.lua b/data/scripts/network/bestiary_tracker.lua new file mode 100644 index 0000000000..5ca5bc2132 --- /dev/null +++ b/data/scripts/network/bestiary_tracker.lua @@ -0,0 +1,11 @@ +local handler = PacketHandler(0x2A) + +function handler.onReceive(player, msg) + local raceId = msg:getU16() + local checked = msg:getByte() == 1 + if player:setTrackedBestiary(raceId, checked) then + player:sendBestiaryTracker() + end +end + +handler:register()