illarion-content/lte/activity_tracker.lua
2026-04-22 13:40:35 +02:00

341 lines
12 KiB
Lua
Raw Permalink Blame History

--[[
Illarion Server
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
You should have received a copy of the GNU Affero General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
]]
-- Activity Tracker, effect id 84
local common = require("base.common")
local factions = require("base.factions")
local gems = require("base.gems")
local testing = require("base.testing")
local M = {}
M.reputationTrackerQuestID = 393
M.rankTrackerQuestID = factions.rankTrackerQuestID
M.diamondQuestID = 452
local reputationTrackerQuestID = M.reputationTrackerQuestID
local rankTrackerQuestID = M.rankTrackerQuestID
M.monthQuestIDs = {
Elos = 377,
Tanos = 378,
Zhas = 379,
Ushos = 380,
Siros = 381,
Ronas = 382,
Bras = 383,
Eldas = 384,
Irmas = 385,
Malas = 386,
Findos = 387,
Olos = 388,
Adras = 389,
Naras = 390,
Chos = 391,
Mas = 392
}
local monthQuestIDs = M.monthQuestIDs
local function isActive(effect)
local foundResetRestTime, lastResetRestTime = effect:findValue("lastResetRestTime")
local currentTime = world:getTime("unix")
local difference = currentTime - lastResetRestTime
if not foundResetRestTime or difference > 300 then --checks if player was active within the last 5 minutes
return false
end
return true
end
local function isInteracting(effect)
local foundLastInteractionTime, lastInteractionTime = effect:findValue("lastInteractionTime")
local foundLastInteractionSkip, lastInteractionSkip = effect:findValue("firstInteractionSkip")
local foundLastRealmInteractionTime, lastRealmInteractionTime = effect:findValue("lastRealmInteractionTime")
local currentTime = world:getTime("unix")
local difference = currentTime - lastInteractionTime
local differenceRealm = currentTime - lastRealmInteractionTime
if not foundLastInteractionTime or difference > 300 then --checks if player was speaking/emoting near other players within the last 5 minutes
return false, false
end
if foundLastInteractionSkip and lastInteractionSkip == 1 then
effect:addValue("firstInteractionSkip", 0) -- First interaction gets skipped for both parties in an attempt to help ensure actual dialogue is happening
return false, false
end
if foundLastRealmInteractionTime and differenceRealm <= 300 then
return true, true
end
return true, false
end
local function saveAndResetValues(effect, user, lastSessionMonth, lastSessionYear)
local currentYear = world:getTime("year")
local foundActiveTime, sessionActiveTime = effect:findValue("sessionActiveTime")
local foundInteractionTime, sessionInteractionTime = effect:findValue("sessionInteractionTime")
local foundRankTime, sessionRankTime = effect:findValue("sessionRankTime")
if not foundInteractionTime then
sessionInteractionTime = 0
end
if not foundActiveTime then
sessionActiveTime = 0
end
if not foundRankTime then
sessionRankTime = 0
end
local monthName = common.Month_To_String(lastSessionMonth)
local questIDtoUse = monthQuestIDs[monthName] -- The activity is tracked over an in game year, this checks what month to use based on when the data was recorded
local preExistingValue = 0
local currentMonth = world:getTime("month")
if currentYear == lastSessionYear or (currentYear > lastSessionYear and lastSessionMonth > currentMonth) then -- Checks if the data is too outdated (if a player has not logged in for 4+ IRL months)
preExistingValue = user:getQuestProgress(questIDtoUse)
end
user:setQuestProgress(questIDtoUse, preExistingValue + sessionActiveTime)
preExistingValue = user:getQuestProgress(reputationTrackerQuestID)
local preExistingRankValue = user:getQuestProgress(rankTrackerQuestID)
user:setQuestProgress(reputationTrackerQuestID, preExistingValue + sessionInteractionTime)
user:setQuestProgress(rankTrackerQuestID, preExistingRankValue + sessionRankTime)
effect:addValue("sessionActiveTime", 0)
effect:addValue("sessionInteractionTime", 0)
effect:addValue("sessionRankTime", 0)
effect:addValue("sessionMonth", currentMonth)
effect:addValue("sessionYear", currentYear)
effect:addValue("sessionCalls", 0)
M[user.id] = {}
end
function M.addEffect(effect, user)
M.callEffect(effect, user)
end
local function updateRank(effect, user)
if not M[user.id] then
M[user.id] = {}
end
if not M[user.id].questRankStatus then -- We save it here as checking the quest progress each time would result in some lag
M[user.id].questRankStatus = user:getQuestProgress(M.rankTrackerQuestID) -- pre existing rank points
end
local foundRankTime, sessionRankTime = effect:findValue("sessionRankTime") --Current sessions rank points
if not foundRankTime then
return
end
local totalRankTime = sessionRankTime + M[user.id].questRankStatus
if factions.convertTicksToRankNumber(M[user.id].questRankStatus) < factions.convertTicksToRankNumber(totalRankTime) then
factions.sendRankUpmessage(user, totalRankTime)
M[user.id].questRankStatus = totalRankTime
user:setQuestProgress(M.rankTrackerQuestID, totalRankTime)
effect:addValue("sessionRankTime", 0)
end
local foundInteractionTime, sessionInteractionTime = effect:findValue("sessionInteractionTime") --Current sessions interaction points
if not foundInteractionTime then
return
end
if not M[user.id].questDiamondStatus then -- We save it here as checking the quest progress each time would result in some lag
M[user.id].questDiamondStatus = user:getQuestProgress(M.diamondQuestID) -- pre existing diamong quest status
end
if not M[user.id].questInteractionStatus then -- We save it here as checking the quest progress each time would result in some lag
M[user.id].questInteractionStatus = user:getQuestProgress(M.reputationTrackerQuestID) -- pre existing interaction points
end
local totalInteractionTime = M[user.id].questInteractionStatus + sessionInteractionTime
if totalInteractionTime >= 1200 + 1200*M[user.id].questDiamondStatus then -- 100 hours of RP for each diamond
local gemData = gems.getMagicGemData(1, user.name)
common.CreateItem(user, 3520, 1, 333, gemData)
log("[Gems] "..user.name.."("..user.id..") just received a magical diamond gem for accumulating "..(100 + 100*M[user.id].questDiamondStatus).." hours of roleplayed time.")
local newStatus = M[user.id].questDiamondStatus + 1
user:setQuestProgress(M.diamondQuestID, newStatus)
M[user.id].questDiamondStatus = newStatus
user:inform("Wie neugierig! Du hast gerade einen magischen Diamanten in deiner Tasche gefunden! K<>nnte es das Werk der G<>tter sein, vielleicht Zhambra oder Adron, die dich f<>r deine sozialen Errungenschaften preisen?", "How curious! You just found a magical diamond in your pocket! Could it be the works of the gods, perhaps Zhambra or Adron praising you for your social feats?")
end
end
local function drinkEffectProcced(user)
local foundEffect, myEffect = user.effects:find(404)
if not foundEffect then
return false
end
local foundCurrentInfluence, currentInfluence = myEffect:findValue("influence")
if not foundCurrentInfluence then
return false
end
if math.random() <= currentInfluence/100 then --Divided by 100 because it is stored at an integer representing the percentage chance, between 5-10% based on drink rarity
return true
end
return false
end
function M.callEffect(effect, user)
local potionToxinReduction = 0
local foundCalls, sessionCalls = effect:findValue("sessionCalls")
if not foundCalls then
sessionCalls = 0
end
local foundActiveTime, sessionActiveTime = effect:findValue("sessionActiveTime")
local foundInteractionTime, sessionInteractionTime = effect:findValue("sessionInteractionTime")
local foundRankTime, sessionRankTime = effect:findValue("sessionRankTime")
if not foundActiveTime then
sessionActiveTime = 0
end
if not foundInteractionTime then
sessionInteractionTime = 0
end
if not foundRankTime then
sessionRankTime = 0
end
local foundMonth, sessionMonth = effect:findValue("sessionMonth")
local foundYear, sessionYear = effect:findValue("sessionYear")
local currentMonth = world:getTime("month")
local currentYear = world:getTime("year")
if not foundYear then
sessionYear = currentYear
effect:addValue("sessionYear", currentYear)
end
if not foundMonth then
sessionMonth = currentMonth
effect:addValue("sessionMonth", currentMonth)
end
if sessionMonth ~= currentMonth or currentYear ~= sessionYear then --a month swap happened in the last 5 minutes the character was online
saveAndResetValues(effect, user, sessionMonth, sessionYear)
end
if sessionCalls >= 1 then
if isActive(effect) then
potionToxinReduction = potionToxinReduction + 1
effect:addValue("sessionActiveTime", sessionActiveTime + 1)
end
local interacting, withFellowCitizen = isInteracting(effect)
local increase = 1
if drinkEffectProcced(user) then
increase = 2
end
if interacting then
potionToxinReduction = potionToxinReduction + 1
effect:addValue("sessionInteractionTime", sessionInteractionTime + increase)
if withFellowCitizen then
effect:addValue("sessionRankTime", sessionRankTime + increase)
end
end
end
local oldValue = user:getQuestProgress(690)
if potionToxinReduction > 0 and oldValue > 0 then
user:setQuestProgress(690, math.max(user:getQuestProgress(690)-1, user:getQuestProgress(690)-potionToxinReduction))
if testing.active then
user:inform("Potion toxins reduced from "..oldValue.." to "..user:getQuestProgress(690))
end
end
updateRank(effect, user) --If the last sessionRankTime addition ranked you up, this gives an inform and updates the quest status early to save it while reseting sessionRankTime
effect:addValue("sessionCalls", sessionCalls + 1)
effect.nextCalled = 3000 --Called once every five minutes
return true
end
function M.removeEffect(effect, user)
end
function M.loadEffect(effect, user)
local foundMonth, sessionMonth = effect:findValue("sessionMonth")
local foundYear, sessionYear = effect:findValue("sessionYear")
if not foundYear or not foundMonth then --Should never be the case as calling the effect will set these values before a load ever happens
debug("Something unexpected has happened!")
return
end
saveAndResetValues(effect, user, sessionMonth, sessionYear)
effect.nextCalled = 10
end
return M