diff --git a/config.lua.dist b/config.lua.dist
index b309ecc4bfe..1023fd37d5a 100644
--- a/config.lua.dist
+++ b/config.lua.dist
@@ -285,6 +285,7 @@ houseRentRate = 1.0
houseOwnedByAccount = false
houseBuyLevel = 100
housePurchasedShowPrice = false
+houseLoseAfterInactivity = 30 -- days; 0 = never
onlyInvitedCanMoveHouseItems = true
togglehouseTransferOnRestart = true
@@ -479,6 +480,7 @@ vipBonusSkill = 0
vipAutoLootVipOnly = false
vipStayOnline = false
vipFamiliarTimeCooldownReduction = 0
+vipKeepHouse = false
-- NOTE: set rewardChestCollectEnabled to true to enable the reward collect system
-- NOTE set rewardChestMaxCollectItems max items per collect action
diff --git a/data-canary/scripts/actions/other/exercise_training.lua b/data-canary/scripts/actions/other/exercise_training.lua
index 042e759f9b7..ecf414a8029 100644
--- a/data-canary/scripts/actions/other/exercise_training.lua
+++ b/data-canary/scripts/actions/other/exercise_training.lua
@@ -5,7 +5,7 @@ function exerciseTraining.onUse(player, item, fromPosition, target, toPosition,
local targetId = target:getId()
if target:isItem() and (table.contains(HouseDummies, targetId) or table.contains(FreeDummies, targetId)) then
- if onExerciseTraining[playerId] then
+ if _G.OnExerciseTraining[playerId] then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "This exercise dummy can only be used after a 30 second cooldown.")
LeaveTraining(playerId)
return true
@@ -26,7 +26,7 @@ function exerciseTraining.onUse(player, item, fromPosition, target, toPosition,
if table.contains(HouseDummies, targetId) then
local playersOnDummy = 0
- for _, playerTraining in pairs(onExerciseTraining) do
+ for _, playerTraining in pairs(_G.OnExerciseTraining) do
if playerTraining.dummyPos == targetPos then
playersOnDummy = playersOnDummy + 1
end
@@ -43,10 +43,10 @@ function exerciseTraining.onUse(player, item, fromPosition, target, toPosition,
return true
end
- onExerciseTraining[playerId] = {}
- if not onExerciseTraining[playerId].event then
- onExerciseTraining[playerId].event = addEvent(ExerciseEvent, 0, playerId, targetPos, item.itemid, targetId)
- onExerciseTraining[playerId].dummyPos = targetPos
+ _G.OnExerciseTraining[playerId] = {}
+ if not _G.OnExerciseTraining[playerId].event then
+ _G.OnExerciseTraining[playerId].event = addEvent(ExerciseEvent, 0, playerId, targetPos, item.itemid, targetId)
+ _G.OnExerciseTraining[playerId].dummyPos = targetPos
player:setTraining(true)
player:setStorageValue(Storage.IsTraining, os.time() + 30)
end
diff --git a/data-canary/scripts/creaturescripts/login.lua b/data-canary/scripts/creaturescripts/login.lua
index edcb45ac327..ed0bd894034 100644
--- a/data-canary/scripts/creaturescripts/login.lua
+++ b/data-canary/scripts/creaturescripts/login.lua
@@ -14,7 +14,7 @@ function login.onLogin(player)
end
-- Stamina
- nextUseStaminaTime[player.uid] = 0
+ _G.NextUseStaminaTime[player.uid] = 0
-- Promotion
local vocation = player:getVocation()
@@ -33,9 +33,9 @@ function login.onLogin(player)
player:registerEvent("DropLoot")
player:registerEvent("BossParticipation")
- if onExerciseTraining[player:getId()] then -- onLogin & onLogout
- stopEvent(onExerciseTraining[player:getId()].event)
- onExerciseTraining[player:getId()] = nil
+ if _G.OnExerciseTraining[player:getId()] then -- onLogin & onLogout
+ stopEvent(_G.OnExerciseTraining[player:getId()].event)
+ _G.OnExerciseTraining[player:getId()] = nil
player:setTraining(false)
end
@@ -98,10 +98,10 @@ function login.onLogin(player)
local playerId = player:getId()
-- Stamina
- nextUseStaminaTime[playerId] = 1
+ _G.NextUseStaminaTime[playerId] = 1
-- EXP Stamina
- nextUseXpStamina[playerId] = 1
+ _G.NextUseXpStamina[playerId] = 1
-- Set Client XP Gain Rate --
if configManager.getBoolean(configKeys.XP_DISPLAY_MODE) then
diff --git a/data-canary/scripts/creaturescripts/logout.lua b/data-canary/scripts/creaturescripts/logout.lua
index df1ff64b8ce..598a55878d2 100644
--- a/data-canary/scripts/creaturescripts/logout.lua
+++ b/data-canary/scripts/creaturescripts/logout.lua
@@ -2,13 +2,13 @@ local logout = CreatureEvent("PlayerLogout")
function logout.onLogout(player)
local playerId = player:getId()
- if nextUseStaminaTime[playerId] then
- nextUseStaminaTime[playerId] = nil
+ if _G.NextUseStaminaTime[playerId] then
+ _G.NextUseStaminaTime[playerId] = nil
end
- if onExerciseTraining[playerId] then
- stopEvent(onExerciseTraining[playerId].event)
- onExerciseTraining[playerId] = nil
+ if _G.OnExerciseTraining[playerId] then
+ stopEvent(_G.OnExerciseTraining[playerId].event)
+ _G.OnExerciseTraining[playerId] = nil
player:setTraining(false)
end
return true
diff --git a/data-canary/scripts/movements/tiles.lua b/data-canary/scripts/movements/tiles.lua
index 8deccc1823a..5f0f74e2c80 100644
--- a/data-canary/scripts/movements/tiles.lua
+++ b/data-canary/scripts/movements/tiles.lua
@@ -33,7 +33,7 @@ function tile.onStepIn(creature, item, position, fromPosition)
local depotItem = playerPosition:getTile():getItemByType(ITEM_TYPE_DEPOT)
if depotItem ~= nil then
local depotItems = 0
- for id = 1, configManager.getNumber("depotBoxes") do
+ for id = 1, configManager.getNumber(configKeys.DEPOT_BOXES) do
depotItems = depotItems + player:getDepotChest(id, true):getItemHoldingCount()
end
player:sendTextMessage(MESSAGE_FAILURE, "Your depot contains " .. depotItems .. " item" .. (depotItems > 1 and "s." or ".") .. "\
diff --git a/data-otservbr-global/npc/hireling.lua b/data-otservbr-global/npc/hireling.lua
index 7caf05d9bcd..519ff32773a 100644
--- a/data-otservbr-global/npc/hireling.lua
+++ b/data-otservbr-global/npc/hireling.lua
@@ -7,6 +7,7 @@ function createHirelingType(HirelingName)
end
local npcConfig = {}
+ local enableBankSystem = {}
npcConfig.name = HirelingName
npcConfig.description = HirelingName
@@ -355,6 +356,7 @@ function createHirelingType(HirelingName)
end
npcType.onDisappear = function(npc, creature)
+ enableBankSystem[creature:getId()] = nil
npcHandler:onDisappear(npc, creature)
end
@@ -363,6 +365,7 @@ function createHirelingType(HirelingName)
end
npcType.onCloseChannel = function(npc, creature)
+ enableBankSystem[creature:getId()] = nil
npcHandler:onCloseChannel(npc, creature)
end
@@ -586,7 +589,9 @@ function createHirelingType(HirelingName)
elseif MsgContains(message, "stash") then
if hireling:hasSkill(HIRELING_SKILLS.STEWARD) then
npcHandler:say(GREETINGS.STASH, npc, creature)
+ player:setSpecialContainersAvailable(true)
player:openStash(true)
+ player:sendTextMessage(MESSAGE_FAILURE, "Your supply stash contains " .. player:getStashCount() .. " item" .. (player:getStashCount() > 1 and "s." or "."))
else
sendSkillNotLearned(npc, creature, HIRELING_SKILLS.STEWARD)
end
@@ -614,15 +619,18 @@ function createHirelingType(HirelingName)
npcHandler:setTopic(playerId, TOPIC.SERVICES)
npcHandler:say("Alright then, I will be here.", npc, creature)
end
- elseif npcHandler:getTopic(playerId) >= TOPIC.BANK and npcHandler:getTopic(playerId) < TOPIC.FOOD then
+ elseif npcHandler:getTopic(playerId) == TOPIC.BANK then
+ enableBankSystem[playerId] = true
+ elseif npcHandler:getTopic(playerId) >= TOPIC.FOOD and npcHandler:getTopic(playerId) < TOPIC.GOODS then
+ handleFoodActions(npc, creature, message)
+ end
+ if enableBankSystem[playerId] then
-- Parse bank
npc:parseBank(message, npc, creature, npcHandler)
-- Parse guild bank
npc:parseGuildBank(message, npc, creature, playerId, npcHandler)
-- Normal messages
npc:parseBankMessages(message, npc, creature, npcHandler)
- elseif npcHandler:getTopic(playerId) >= TOPIC.FOOD and npcHandler:getTopic(playerId) < TOPIC.GOODS then
- handleFoodActions(npc, creature, message)
end
return true
end
diff --git a/data-otservbr-global/npc/lynda.lua b/data-otservbr-global/npc/lynda.lua
index 3176a464d70..82a8cf8cc7d 100644
--- a/data-otservbr-global/npc/lynda.lua
+++ b/data-otservbr-global/npc/lynda.lua
@@ -155,6 +155,61 @@ local function creatureSayCallback(npc, creature, type, message)
end
end
+local function tryEngage(npc, creature, message, keywords, parameters, node)
+ local player = Player(creature)
+ local playerStatus = getPlayerMarriageStatus(player:getGuid())
+ local playerSpouse = getPlayerSpouse(player:getGuid())
+ if playerStatus == MARRIED_STATUS then -- check if the player is already married
+ npcHandler:say("You are already married to {" .. player:getName() .. "}.", npc, creature)
+ elseif playerStatus == PROPOSED_STATUS then --check if the player already made a proposal to some1 else
+ npcHandler:say("You already made a wedding proposal to {" .. player:getName() .. "}. You can always remove the proposal by saying {remove} proposal.", npc, creature)
+ else
+ local candidate = getPlayerGUIDByName(message)
+ if candidate == 0 then -- check if there is actually a player called like this
+ npcHandler:say("A player with this name does not exist.", npc, creature)
+ elseif candidate == player:getGuid() then -- if it's himself, cannot marry
+ npcHandler:say("You REALLY want to marry yourself? c'mon, be serious.", npc, creature)
+ else
+ if player:getItemCount(ITEM_WEDDING_RING) == 0 or player:getItemCount(9586) == 0 then -- check for items (wedding ring and outfit box)
+ npcHandler:say("As I said, you need a wedding ring and the wedding outfit box in order to marry.", npc, creature)
+ else
+ local candidateStatus = getPlayerMarriageStatus(candidate)
+ local candidateSpouse = getPlayerSpouse(candidate)
+ if candidateStatus == MARRIED_STATUS then -- if the player you want to marry is already married and to whom
+ npcHandler:say("{" .. getPlayerNameById(candidate) .. "} is already married to {" .. getPlayerNameById(candidateSpouse) .. "}.", npc, creature)
+ elseif candidateStatus == PROPACCEPT_STATUS then -- if the player you want to marry is already going to marry some1 else
+ npcHandler:say("{" .. getPlayerNameById(candidate) .. "} is already engaged to {" .. getPlayerNameById(candidateSpouse) .. "} and they will going to marry soon.", npc, creature)
+ elseif candidateStatus == PROPOSED_STATUS then -- if he/she already made a proposal to some1
+ if candidateSpouse == player:getGuid() then -- if this someone is you.
+ -- if this some1 is not you
+ npcHandler:say("Since both of you are willing to marry, I accept to celebrate your marriage, go prepare yourself, and tell me when you are ready for the {celebration}", npc, creature)
+ player:removeItem(ITEM_WEDDING_RING, 1)
+ player:removeItem(9586, 1) -- wedding outfit box
+ player:addOutfit(329) --Wife
+ player:addOutfit(328) --Husb
+ setPlayerMarriageStatus(player:getGuid(), PROPACCEPT_STATUS)
+ setPlayerMarriageStatus(candidate, PROPACCEPT_STATUS)
+ setPlayerSpouse(player:getGuid(), candidate)
+ local player = Player(getPlayerNameById(candidate))
+ player:addOutfit(329)
+ player:addOutfit(328)
+ else
+ npcHandler:say("{" .. getPlayerNameById(candidate) .. "} already made a wedding proposal to {" .. getPlayerNameById(candidateSpouse) .. "}.", npc, creature)
+ end
+ else -- if the player i want to propose doesn't have other proposal
+ npcHandler:say("Ok, now let's wait and see if {" .. getPlayerNameById(candidate) .. "} accepts your proposal. I'll give you back your wedding ring as soon as {" .. getPlayerNameById(candidate) .. "} accepts your proposal or you {remove} it.", npc, creature)
+ player:removeItem(ITEM_WEDDING_RING, 1)
+ player:removeItem(9586, 1)
+ setPlayerMarriageStatus(player:getGuid(), PROPOSED_STATUS)
+ setPlayerSpouse(player:getGuid(), candidate)
+ end
+ end
+ end
+ end
+ keywordHandler:moveUp(player, 1)
+ return false
+end
+
local function confirmWedding(npc, creature, message, keywords, parameters, node)
local player = Player(creature)
local playerStatus = getPlayerMarriageStatus(player:getGuid())
@@ -199,12 +254,12 @@ local function confirmRemoveEngage(npc, creature, message, keywords, parameters,
setPlayerMarriageStatus(player:getGuid(), 0)
setPlayerSpouse(player:getGuid(), -1)
npcHandler:say(parameters.text, npc, creature)
- keywordHandler:moveUp(parameters.moveup)
+ keywordHandler:moveUp(player, parameters.moveup)
end
node:addChildKeyword({ "yes" }, removeEngage, { moveup = 3, text = "Ok, your marriage proposal to {" .. getPlayerNameById(playerSpouse) .. "} has been removed. Take your wedding ring back." })
else
npcHandler:say("You don't have any pending proposal to be removed.", npc, creature)
- keywordHandler:moveUp(2)
+ keywordHandler:moveUp(player, 2)
end
return true
end
@@ -225,12 +280,12 @@ local function confirmDivorce(npc, creature, message, keywords, parameters, node
setPlayerMarriageStatus(spouse, 0)
setPlayerSpouse(spouse, -1)
npcHandler:say(parameters.text, npc, creature)
- keywordHandler:moveUp(parameters.moveup)
+ keywordHandler:moveUp(player, parameters.moveup)
end
node:addChildKeyword({ "yes" }, divorce, { moveup = 3, text = "Ok, you are now divorced of {" .. getPlayerNameById(playerSpouse) .. "}. Think better next time after marrying someone." })
else
npcHandler:say("You aren't married to get a divorce.", npc, creature)
- keywordHandler:moveUp(2)
+ keywordHandler:moveUp(player, 2)
end
return true
end
diff --git a/data-otservbr-global/scripts/actions/other/exercise_training.lua b/data-otservbr-global/scripts/actions/other/exercise_training.lua
index 1844ab0df8f..e7f67c854be 100644
--- a/data-otservbr-global/scripts/actions/other/exercise_training.lua
+++ b/data-otservbr-global/scripts/actions/other/exercise_training.lua
@@ -16,7 +16,7 @@ function exerciseTraining.onUse(player, item, fromPosition, target, toPosition,
local targetId = target:getId()
if target:isItem() and isDummy(targetId) then
- if onExerciseTraining[playerId] then
+ if _G.OnExerciseTraining[playerId] then
player:sendTextMessage(MESSAGE_FAILURE, "You are already training!")
return true
end
@@ -42,7 +42,7 @@ function exerciseTraining.onUse(player, item, fromPosition, target, toPosition,
return true
end
local playersOnDummy = 0
- for _, playerTraining in pairs(onExerciseTraining) do
+ for _, playerTraining in pairs(_G.OnExerciseTraining) do
if playerTraining.dummyPos == targetPos then
playersOnDummy = playersOnDummy + 1
end
@@ -59,10 +59,10 @@ function exerciseTraining.onUse(player, item, fromPosition, target, toPosition,
return true
end
- onExerciseTraining[playerId] = {}
- if not onExerciseTraining[playerId].event then
- onExerciseTraining[playerId].event = addEvent(ExerciseEvent, 0, playerId, targetPos, item.itemid, targetId)
- onExerciseTraining[playerId].dummyPos = targetPos
+ _G.OnExerciseTraining[playerId] = {}
+ if not _G.OnExerciseTraining[playerId].event then
+ _G.OnExerciseTraining[playerId].event = addEvent(ExerciseEvent, 0, playerId, targetPos, item.itemid, targetId)
+ _G.OnExerciseTraining[playerId].dummyPos = targetPos
player:setTraining(true)
player:setStorageValue(Storage.IsTraining, os.time() + cooldown)
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have started training on an exercise dummy.")
diff --git a/data-otservbr-global/scripts/actions/other/potions.lua b/data-otservbr-global/scripts/actions/other/potions.lua
index 38c323e978e..1cc63639189 100644
--- a/data-otservbr-global/scripts/actions/other/potions.lua
+++ b/data-otservbr-global/scripts/actions/other/potions.lua
@@ -230,10 +230,10 @@ function flaskPotion.onUse(player, item, fromPosition, target, toPosition, isHot
end
-- Delay potion
- if not playerDelayPotion[player:getId()] then
- playerDelayPotion[player:getId()] = 0
+ if not _G.PlayerDelayPotion[player:getId()] then
+ _G.PlayerDelayPotion[player:getId()] = 0
end
- if playerDelayPotion[player:getId()] > systemTime() then
+ if _G.PlayerDelayPotion[player:getId()] > systemTime() then
player:sendTextMessage(MESSAGE_FAILURE, Game.getReturnMessage(RETURNVALUE_YOUAREEXHAUSTED))
return true
end
@@ -284,7 +284,7 @@ function flaskPotion.onUse(player, item, fromPosition, target, toPosition, isHot
player:getPosition():sendSingleSoundEffect(SOUND_EFFECT_TYPE_ITEM_USE_POTION, player:isInGhostMode() and nil or player)
-- Delay potion
- playerDelayPotion[player:getId()] = systemTime() + 500
+ _G.PlayerDelayPotion[player:getId()] = systemTime() + 500
if potion.func then
potion.func(player)
diff --git a/data-otservbr-global/scripts/creaturescripts/others/login.lua b/data-otservbr-global/scripts/creaturescripts/others/login.lua
index 43914430533..27bfddd5ddc 100644
--- a/data-otservbr-global/scripts/creaturescripts/others/login.lua
+++ b/data-otservbr-global/scripts/creaturescripts/others/login.lua
@@ -208,13 +208,13 @@ function playerLogin.onLogin(player)
player:initializeLoyaltySystem()
-- Stamina
- nextUseStaminaTime[playerId] = 1
+ _G.NextUseStaminaTime[playerId] = 1
-- EXP Stamina
- nextUseXpStamina[playerId] = 1
+ _G.NextUseXpStamina[playerId] = 1
-- Concoction Duration
- nextUseConcoctionTime[playerId] = 1
+ _G.NextUseConcoctionTime[playerId] = 1
if player:getAccountType() == ACCOUNT_TYPE_TUTOR then
local msg = [[:: Tutor Rules
@@ -275,10 +275,10 @@ function playerLogin.onLogin(player)
player:getFinalLowLevelBonus()
- if onExerciseTraining[player:getId()] then
+ if _G.OnExerciseTraining[player:getId()] then
-- onLogin & onLogout
- stopEvent(onExerciseTraining[player:getId()].event)
- onExerciseTraining[player:getId()] = nil
+ stopEvent(_G.OnExerciseTraining[player:getId()].event)
+ _G.OnExerciseTraining[player:getId()] = nil
player:setTraining(false)
end
return true
diff --git a/data-otservbr-global/scripts/creaturescripts/others/logout.lua b/data-otservbr-global/scripts/creaturescripts/others/logout.lua
index 314246a981a..ecdb13378d2 100644
--- a/data-otservbr-global/scripts/creaturescripts/others/logout.lua
+++ b/data-otservbr-global/scripts/creaturescripts/others/logout.lua
@@ -2,8 +2,8 @@ local playerLogout = CreatureEvent("PlayerLogout")
function playerLogout.onLogout(player)
local playerId = player:getId()
- if nextUseStaminaTime[playerId] ~= nil then
- nextUseStaminaTime[playerId] = nil
+ if _G.NextUseStaminaTime[playerId] ~= nil then
+ _G.NextUseStaminaTime[playerId] = nil
end
player:saveSpecialStorage()
@@ -22,9 +22,9 @@ function playerLogout.onLogout(player)
end
end
- if onExerciseTraining[playerId] then
- stopEvent(onExerciseTraining[playerId].event)
- onExerciseTraining[playerId] = nil
+ if _G.OnExerciseTraining[playerId] then
+ stopEvent(_G.OnExerciseTraining[playerId].event)
+ _G.OnExerciseTraining[playerId] = nil
player:setTraining(false)
end
diff --git a/data-otservbr-global/scripts/movements/others/tiles.lua b/data-otservbr-global/scripts/movements/others/tiles.lua
index 9773d74d18a..b797f0380a3 100644
--- a/data-otservbr-global/scripts/movements/others/tiles.lua
+++ b/data-otservbr-global/scripts/movements/others/tiles.lua
@@ -33,7 +33,7 @@ function tiles.onStepIn(creature, item, position, fromPosition)
if depotItem ~= nil then
local depotItems = 0
- for id = 1, configManager.getNumber("depotBoxes") do
+ for id = 1, configManager.getNumber(configKeys.DEPOT_BOXES) do
depotItems = depotItems + player:getDepotChest(id, true):getItemHoldingCount()
end
diff --git a/data/events/scripts/player.lua b/data/events/scripts/player.lua
index 333d506919d..39219a06d56 100644
--- a/data/events/scripts/player.lua
+++ b/data/events/scripts/player.lua
@@ -96,7 +96,7 @@ local soulCondition = Condition(CONDITION_SOUL, CONDITIONID_DEFAULT)
soulCondition:setTicks(4 * 60 * 1000)
soulCondition:setParameter(CONDITION_PARAM_SOULGAIN, 1)
-local function useStamina(player)
+local function useStamina(player, isStaminaEnabled)
if not player then
return false
end
@@ -107,12 +107,12 @@ local function useStamina(player)
end
local playerId = player:getId()
- if not playerId or not nextUseStaminaTime[playerId] then
+ if not playerId or not _G.NextUseStaminaTime[playerId] then
return false
end
local currentTime = os.time()
- local timePassed = currentTime - nextUseStaminaTime[playerId]
+ local timePassed = currentTime - _G.NextUseStaminaTime[playerId]
if timePassed <= 0 then
return
end
@@ -123,14 +123,16 @@ local function useStamina(player)
else
staminaMinutes = 0
end
- nextUseStaminaTime[playerId] = currentTime + 120
+ _G.NextUseStaminaTime[playerId] = currentTime + 120
player:removePreyStamina(120)
else
staminaMinutes = staminaMinutes - 1
- nextUseStaminaTime[playerId] = currentTime + 60
+ _G.NextUseStaminaTime[playerId] = currentTime + 60
player:removePreyStamina(60)
end
- player:setStamina(staminaMinutes)
+ if isStaminaEnabled then
+ player:setStamina(staminaMinutes)
+ end
end
local function useStaminaXpBoost(player)
@@ -149,7 +151,7 @@ local function useStaminaXpBoost(player)
end
local currentTime = os.time()
- local timePassed = currentTime - nextUseXpStamina[playerId]
+ local timePassed = currentTime - _G.NextUseXpStamina[playerId]
if timePassed <= 0 then
return
end
@@ -160,10 +162,10 @@ local function useStaminaXpBoost(player)
else
staminaMinutes = 0
end
- nextUseXpStamina[playerId] = currentTime + 120
+ _G.NextUseXpStamina[playerId] = currentTime + 120
else
staminaMinutes = staminaMinutes - 1
- nextUseXpStamina[playerId] = currentTime + 60
+ _G.NextUseXpStamina[playerId] = currentTime + 60
end
player:setExpBoostStamina(staminaMinutes * 60)
end
@@ -174,22 +176,22 @@ local function useConcoctionTime(player)
end
local playerId = player:getId()
- if not playerId or not nextUseConcoctionTime[playerId] then
+ if not playerId or not _G.NextUseConcoctionTime[playerId] then
return false
end
local currentTime = os.time()
- local timePassed = currentTime - nextUseConcoctionTime[playerId]
+ local timePassed = currentTime - _G.NextUseConcoctionTime[playerId]
if timePassed <= 0 then
return false
end
local deduction = 60
if timePassed > 60 then
- nextUseConcoctionTime[playerId] = currentTime + 120
+ _G.NextUseConcoctionTime[playerId] = currentTime + 120
deduction = 120
else
- nextUseConcoctionTime[playerId] = currentTime + 60
+ _G.NextUseConcoctionTime[playerId] = currentTime + 60
end
Concoction.experienceTick(player, deduction)
end
@@ -390,7 +392,7 @@ end
function Player:onMoveCreature(creature, fromPosition, toPosition)
local player = creature:getPlayer()
- if player and onExerciseTraining[player:getId()] and not self:getGroup():hasFlag(PlayerFlag_CanPushAllCreatures) then
+ if player and _G.OnExerciseTraining[player:getId()] and not self:getGroup():hasFlag(PlayerFlag_CanPushAllCreatures) then
self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
return false
end
@@ -514,8 +516,9 @@ function Player:onGainExperience(target, exp, rawExp)
-- Stamina Bonus
local staminaBonusXp = 1
- if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
- useStamina(self)
+ local isStaminaEnabled = configManager.getBoolean(configKeys.STAMINA_SYSTEM)
+ useStamina(self, isStaminaEnabled)
+ if isStaminaEnabled then
staminaBonusXp = self:getFinalBonusStamina()
self:setStaminaXpBoost(staminaBonusXp * 100)
end
diff --git a/data/global.lua b/data/global.lua
index 9fad23e8787..04a8ff78fe9 100644
--- a/data/global.lua
+++ b/data/global.lua
@@ -82,48 +82,31 @@ SCARLETT_MAY_DIE = 0
ropeSpots = { 386, 421, 386, 7762, 12202, 12936, 14238, 17238, 23363, 21965, 21966, 21967, 21968 }
specialRopeSpots = { 12935 }
--- Impact Analyser
-if not GlobalBosses then
- GlobalBosses = {}
+-- Global tables for systems
+if not _G.GlobalBosses then
+ _G.GlobalBosses = {}
end
--- Healing
--- Global table to insert data
-if healingImpact == nil then
- healingImpact = {}
-end
-
--- Damage
--- Global table to insert data
-if damageImpact == nil then
- damageImpact = {}
-end
-
--- Exercise Training
-if onExerciseTraining == nil then
- onExerciseTraining = {}
+if not _G.OnExerciseTraining then
+ _G.OnExerciseTraining = {}
end
-- Stamina
-if nextUseStaminaTime == nil then
- nextUseStaminaTime = {}
-end
-
-if nextUseXpStamina == nil then
- nextUseXpStamina = {}
+if not _G.NextUseStaminaTime then
+ _G.NextUseStaminaTime = {}
end
-if nextUseConcoctionTime == nil then
- nextUseConcoctionTime = {}
+if not _G.NextUseXpStamina then
+ _G.NextUseXpStamina = {}
end
-if lastItemImbuing == nil then
- lastItemImbuing = {}
+if not _G._G.NextUseConcoctionTime then
+ _G._G.NextUseConcoctionTime = {}
end
-- Delay potion
-if not playerDelayPotion then
- playerDelayPotion = {}
+if not _G.PlayerDelayPotion then
+ _G.PlayerDelayPotion = {}
end
table.contains = function(array, value)
diff --git a/data/items/items.xml b/data/items/items.xml
index 5542b35d43f..407f909b6e8 100644
--- a/data/items/items.xml
+++ b/data/items/items.xml
@@ -59786,7 +59786,7 @@
-
+
@@ -59826,7 +59826,7 @@
-
+
-
@@ -59836,7 +59836,7 @@
-
+
-
diff --git a/data/libs/exercise_training.lua b/data/libs/exercise_training.lua
index 74ea2492f46..6981c55ca3b 100644
--- a/data/libs/exercise_training.lua
+++ b/data/libs/exercise_training.lua
@@ -36,9 +36,9 @@ ExerciseWeaponsTable = {
local dummies = Game.getDummies()
function LeaveTraining(playerId)
- if onExerciseTraining[playerId] then
- stopEvent(onExerciseTraining[playerId].event)
- onExerciseTraining[playerId] = nil
+ if _G.OnExerciseTraining[playerId] then
+ stopEvent(_G.OnExerciseTraining[playerId].event)
+ _G.OnExerciseTraining[playerId] = nil
end
local player = Player(playerId)
@@ -120,6 +120,6 @@ function ExerciseEvent(playerId, tilePosition, weaponId, dummyId)
end
local vocation = player:getVocation()
- onExerciseTraining[playerId].event = addEvent(ExerciseEvent, vocation:getBaseAttackSpeed() / configManager.getFloat(configKeys.RATE_EXERCISE_TRAINING_SPEED), playerId, tilePosition, weaponId, dummyId)
+ _G.OnExerciseTraining[playerId].event = addEvent(ExerciseEvent, vocation:getBaseAttackSpeed() / configManager.getFloat(configKeys.RATE_EXERCISE_TRAINING_SPEED), playerId, tilePosition, weaponId, dummyId)
return true
end
diff --git a/data/libs/hazard_lib.lua b/data/libs/hazard_lib.lua
index d10650a81b6..c13f120f740 100644
--- a/data/libs/hazard_lib.lua
+++ b/data/libs/hazard_lib.lua
@@ -88,30 +88,22 @@ function Hazard:getPlayerMaxLevel(player)
local fromStorage = player:getStorageValue(self.storageMax)
return fromStorage <= 0 and 1 or fromStorage
end
- local fromKV = player:kv():scoped(self.name):get("maxLevel")
+ local fromKV = player:kv():scoped(self.name):get("maxLevel") or 1
+
return fromKV <= 0 and 1 or fromKV
end
function Hazard:levelUp(player)
- if self.storageMax and self.storageCurrent then
- local current = self:getPlayerCurrentLevel(player)
- local max = self:getPlayerMaxLevel(player)
- if current == max then
- self:setPlayerMaxLevel(player, max + 1)
- end
- return
- end
-
- local current = player:kv(self.name):get("currentLevel")
- local max = player:kv(self.name):get("maxLevel")
+ local current = self:getPlayerCurrentLevel(player)
+ local max = self:getPlayerMaxLevel(player)
if current == max then
- player:kv(self.name):set("maxLevel", max + 1)
+ self:setPlayerMaxLevel(player, max + 1)
end
end
function Hazard:setPlayerMaxLevel(player, level)
- if level > self.maxLevelLevel then
- level = self.maxLevelLevel
+ if level > self.maxLevel then
+ level = self.maxLevel
end
if self.storageMax then
diff --git a/data/libs/reward_boss/monster.lua b/data/libs/reward_boss/monster.lua
index 028f325bb4c..95df4f4acc5 100644
--- a/data/libs/reward_boss/monster.lua
+++ b/data/libs/reward_boss/monster.lua
@@ -4,11 +4,11 @@ function Monster.setReward(self, enable)
error("Rewards can only be enabled to rewards bosses.")
return false
end
- GlobalBosses[self:getId()] = {}
+ _G.GlobalBosses[self:getId()] = {}
self:registerEvent("BossDeath")
self:registerEvent("BossThink")
else
- GlobalBosses[self:getId()] = nil
+ _G.GlobalBosses[self:getId()] = nil
self:unregisterEvent("BossDeath")
self:unregisterEvent("BossThink")
end
diff --git a/data/libs/reward_boss/player.lua b/data/libs/reward_boss/player.lua
index 2f8887280f4..7a525efa2fd 100644
--- a/data/libs/reward_boss/player.lua
+++ b/data/libs/reward_boss/player.lua
@@ -3,12 +3,12 @@ function Player.getRewardChest(self, autocreate)
end
function Player.inBossFight(self)
- if not next(GlobalBosses) then
+ if not next(_G.GlobalBosses) then
return false
end
local playerGuid = self:getGuid()
- for _, info in pairs(GlobalBosses) do
+ for _, info in pairs(_G.GlobalBosses) do
local stats = info[playerGuid]
if stats and stats.active then
return stats
diff --git a/data/libs/reward_boss/reward_boss.lua b/data/libs/reward_boss/reward_boss.lua
index fb7c75ec5ee..8913d746a84 100644
--- a/data/libs/reward_boss/reward_boss.lua
+++ b/data/libs/reward_boss/reward_boss.lua
@@ -96,14 +96,14 @@ function InsertRewardItems(playerGuid, timestamp, itemList)
end
function GetPlayerStats(bossId, playerGuid, autocreate)
- local ret = GlobalBosses[bossId][playerGuid]
+ local ret = _G.GlobalBosses[bossId][playerGuid]
if not ret and autocreate then
ret = {
bossId = bossId,
damageIn = 0, -- damage taken from the boss
healing = 0, -- healing (other players) done
}
- GlobalBosses[bossId][playerGuid] = ret
+ _G.GlobalBosses[bossId][playerGuid] = ret
return ret
end
return ret
@@ -115,7 +115,7 @@ function ResetAndSetTargetList(creature)
end
local bossId = creature:getId()
- local info = GlobalBosses[bossId]
+ local info = _G.GlobalBosses[bossId]
-- Reset all players' status
for _, player in pairs(info) do
player.active = false
diff --git a/data/scripts/reward_chest/boss_death.lua b/data/scripts/reward_chest/boss_death.lua
index 81a64e0cd84..04bb12b84bc 100644
--- a/data/scripts/reward_chest/boss_death.lua
+++ b/data/scripts/reward_chest/boss_death.lua
@@ -28,7 +28,7 @@ function bossDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUn
local totalDamageOut, totalDamageIn, totalHealing = 0.1, 0.1, 0.1
local scores = {}
- local info = GlobalBosses[bossId]
+ local info = _G.GlobalBosses[bossId]
local damageMap = creature:getDamageMap()
for guid, stats in pairs(info) do
@@ -124,7 +124,7 @@ function bossDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUn
end
end
end
- GlobalBosses[bossId] = nil
+ _G.GlobalBosses[bossId] = nil
end
return true
end
diff --git a/data/scripts/reward_chest/boss_health_change.lua b/data/scripts/reward_chest/boss_health_change.lua
index 75250de64a6..037d6aa567a 100644
--- a/data/scripts/reward_chest/boss_health_change.lua
+++ b/data/scripts/reward_chest/boss_health_change.lua
@@ -1,7 +1,7 @@
local bossParticipation = CreatureEvent("BossParticipation")
function bossParticipation.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
- if not next(GlobalBosses) then
+ if not next(_G.GlobalBosses) then
return primaryDamage, primaryType, secondaryDamage, secondaryType
end
diff --git a/data/scripts/talkactions/gm/teleport_to_active_player.lua b/data/scripts/talkactions/gm/teleport_to_active_player.lua
index 662a007aedf..abb71116a37 100644
--- a/data/scripts/talkactions/gm/teleport_to_active_player.lua
+++ b/data/scripts/talkactions/gm/teleport_to_active_player.lua
@@ -9,7 +9,7 @@ function teleportToCreature.onSay(player, words, param)
for _, targetPlayer in ipairs(players) do
local isGhost = targetPlayer:isInGhostMode()
- local isTraining = onExerciseTraining[targetPlayer:getId()]
+ local isTraining = _G.OnExerciseTraining[targetPlayer:getId()]
local isIdle = targetPlayer:getIdleTime() >= 5 * 60 * 1000
local isActive = not isGhost and not isTraining and not isIdle
if isActive then
diff --git a/data/scripts/talkactions/gm/teleport_to_player.lua b/data/scripts/talkactions/gm/teleport_to_player.lua
index 73eab7b5bec..04bcdf0dc91 100644
--- a/data/scripts/talkactions/gm/teleport_to_player.lua
+++ b/data/scripts/talkactions/gm/teleport_to_player.lua
@@ -18,7 +18,7 @@ function teleportToCreature.onSay(player, words, param)
table.insert(playerList, targetPlayer)
else
local isGhost = targetPlayer:isInGhostMode()
- local isTraining = onExerciseTraining[targetPlayer:getId()]
+ local isTraining = _G.OnExerciseTraining[targetPlayer:getId()]
local isIdle = targetPlayer:getIdleTime() >= 5 * 60 * 1000
local isActive = not isGhost and not isTraining and not isIdle
if isActive then
diff --git a/data/scripts/talkactions/god/create_item.lua b/data/scripts/talkactions/god/create_item.lua
index 4ad618120e0..7a6285ef101 100644
--- a/data/scripts/talkactions/god/create_item.lua
+++ b/data/scripts/talkactions/god/create_item.lua
@@ -1,25 +1,3 @@
-local invalidIds = {
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 10,
- 11,
- 13,
- 14,
- 15,
- 19,
- 21,
- 26,
- 27,
- 28,
- 35,
- 43,
-}
-
local createItem = TalkAction("/i")
function createItem.onSay(player, words, param)
@@ -37,7 +15,7 @@ function createItem.onSay(player, words, param)
end
end
- if table.contains(invalidIds, itemType:getId()) then
+ if itemType:getId() < 100 then
return true
end
@@ -45,7 +23,17 @@ function createItem.onSay(player, words, param)
local count = tonumber(split[2])
if count then
if itemType:isStackable() then
- count = math.min(10000, math.max(1, count))
+ local item = Game.createItem(itemType:getId(), count)
+ if not item then
+ player:sendCancelMessage("Cannot create item")
+ return true
+ end
+
+ local ret = player:addItemEx(item, INDEX_WHEREEVER, FLAG_NOLIMIT)
+ if ret ~= RETURNVALUE_NOERROR then
+ player:sendCancelMessage(ret)
+ end
+ return true
elseif not itemType:isFluidContainer() then
local min = 100
if charges > 0 then
diff --git a/data/scripts/talkactions/player/online.lua b/data/scripts/talkactions/player/online.lua
index be3c988259c..bdedf5b3af0 100644
--- a/data/scripts/talkactions/player/online.lua
+++ b/data/scripts/talkactions/player/online.lua
@@ -16,7 +16,7 @@ function playersOnline.onSay(player, words, param)
for _, targetPlayer in ipairs(players) do
if hasAccess or not targetPlayer:isInGhostMode() then
- if onExerciseTraining[targetPlayer:getId()] then
+ if _G.OnExerciseTraining[targetPlayer:getId()] then
table.insert(onlineList.Training, targetPlayer)
elseif targetPlayer:getIdleTime() >= 5 * 60 * 1000 then
table.insert(onlineList.Idle, targetPlayer)
diff --git a/data/scripts/talkactions/player/server_info.lua b/data/scripts/talkactions/player/server_info.lua
index 5c19c48df7f..136a271f7e4 100644
--- a/data/scripts/talkactions/player/server_info.lua
+++ b/data/scripts/talkactions/player/server_info.lua
@@ -54,10 +54,13 @@ function serverInfo.onSay(player, words, param)
.. configManager.getNumber(configKeys.RATE_SPAWN)
.. "x"
end
+ local loseHouseText = configManager.getNumber(configKeys.HOUSE_LOSE_AFTER_INACTIVITY) > 0 and configManager.getNumber(configKeys.HOUSE_LOSE_AFTER_INACTIVITY) .. " days" or "never"
text = text
.. "\n\nMore Server Info: \n"
.. "\nLevel to buy house: "
.. configManager.getNumber(configKeys.HOUSE_BUY_LEVEL)
+ .. "\nLose house after inactivity: "
+ .. loseHouseText
.. "\nProtection level: "
.. configManager.getNumber(configKeys.PROTECTION_LEVEL)
.. "\nWorldType: "
diff --git a/src/config/config_definitions.hpp b/src/config/config_definitions.hpp
index 417a5348a96..dc7f1caac24 100644
--- a/src/config/config_definitions.hpp
+++ b/src/config/config_definitions.hpp
@@ -10,7 +10,7 @@
#pragma once
// Enum
-enum booleanConfig_t {
+enum ConfigKey_t : uint16_t {
ALLOW_CHANGEOUTFIT,
ONE_PLAYER_ON_ACCOUNT,
AIMBOT_HOTKEY_ENABLED,
@@ -84,17 +84,13 @@ enum booleanConfig_t {
TOGGLE_ATTACK_SPEED_ONFIST,
VIP_SYSTEM_ENABLED,
VIP_AUTOLOOT_VIP_ONLY,
+ VIP_KEEP_HOUSE,
VIP_STAY_ONLINE,
REWARD_CHEST_COLLECT_ENABLED,
TOGGLE_MOUNT_IN_PZ,
TOGGLE_HOUSE_TRANSFER_ON_SERVER_RESTART,
TOGGLE_RECEIVE_REWARD,
TOGGLE_MAINTAIN_MODE,
-
- LAST_BOOLEAN_CONFIG
-};
-
-enum stringConfig_t {
MAP_NAME,
MAP_DOWNLOAD_URL,
MAP_AUTHOR,
@@ -127,11 +123,6 @@ enum stringConfig_t {
TIBIADROME_CONCOCTION_TICK_TYPE,
M_CONST,
MAINTAIN_MODE_MESSAGE,
-
- LAST_STRING_CONFIG
-};
-
-enum integerConfig_t {
SQL_PORT,
MAX_PLAYERS,
PZ_LOCKED,
@@ -145,6 +136,7 @@ enum integerConfig_t {
RATE_KILLING_IN_THE_NAME_OF_POINTS,
HOUSE_PRICE_PER_SQM,
HOUSE_BUY_LEVEL,
+ HOUSE_LOSE_AFTER_INACTIVITY,
MAX_MESSAGEBUFFER,
ACTIONS_DELAY_INTERVAL,
EX_ACTIONS_DELAY_INTERVAL,
@@ -249,53 +241,38 @@ enum integerConfig_t {
PARALLELISM,
BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN,
BOSS_DEFAULT_TIME_TO_DEFEAT,
-
VIP_BONUS_EXP,
VIP_BONUS_LOOT,
VIP_BONUS_SKILL,
VIP_FAMILIAR_TIME_COOLDOWN_REDUCTION,
-
REWARD_CHEST_MAX_COLLECT_ITEMS,
DISCORD_WEBHOOK_DELAY_MS,
-
PVP_MAX_LEVEL_DIFFERENCE,
-
- LAST_INTEGER_CONFIG
-};
-
-enum floatingConfig_t {
BESTIARY_RATE_CHARM_SHOP_PRICE,
-
RATE_HEALTH_REGEN,
RATE_HEALTH_REGEN_SPEED,
RATE_MANA_REGEN,
RATE_MANA_REGEN_SPEED,
RATE_SOUL_REGEN,
RATE_SOUL_REGEN_SPEED,
-
RATE_SPELL_COOLDOWN,
RATE_ATTACK_SPEED,
RATE_OFFLINE_TRAINING_SPEED,
RATE_EXERCISE_TRAINING_SPEED,
-
RATE_MONSTER_HEALTH,
RATE_MONSTER_ATTACK,
RATE_MONSTER_DEFENSE,
RATE_BOSS_HEALTH,
RATE_BOSS_ATTACK,
RATE_BOSS_DEFENSE,
-
RATE_NPC_HEALTH,
RATE_NPC_ATTACK,
RATE_NPC_DEFENSE,
LOYALTY_BONUS_PERCENTAGE_MULTIPLIER,
PARTY_SHARE_LOOT_BOOSTS_DIMINISHING_FACTOR,
-
PVP_RATE_DAMAGE_TAKEN_PER_LEVEL,
PVP_RATE_DAMAGE_REDUCTION_PER_LEVEL,
-
HOUSE_PRICE_RENT_MULTIPLIER,
HOUSE_RENT_RATE,
-
- LAST_FLOATING_CONFIG
+ LOGLEVEL,
};
diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp
index 8f46b9b3f4d..11b1ec90a04 100644
--- a/src/config/configmanager.cpp
+++ b/src/config/configmanager.cpp
@@ -19,62 +19,6 @@
#define lua_strlen lua_rawlen
#endif
-namespace {
-
- std::string getGlobalString(lua_State* L, const char* identifier, const char* defaultValue) {
- lua_getglobal(L, identifier);
- if (!lua_isstring(L, -1)) {
- return defaultValue;
- }
-
- size_t len = lua_strlen(L, -1);
- std::string ret(lua_tostring(L, -1), len);
- lua_pop(L, 1);
- return ret;
- }
-
- int32_t getGlobalNumber(lua_State* L, const char* identifier, const int32_t defaultValue = 0) {
- lua_getglobal(L, identifier);
- if (!lua_isnumber(L, -1)) {
- return defaultValue;
- }
-
- int32_t val = lua_tonumber(L, -1);
- lua_pop(L, 1);
- return val;
- }
-
- bool getGlobalBoolean(lua_State* L, const char* identifier, const bool defaultValue) {
- lua_getglobal(L, identifier);
- if (!lua_isboolean(L, -1)) {
- if (!lua_isstring(L, -1)) {
- return defaultValue;
- }
-
- size_t len = lua_strlen(L, -1);
- std::string ret(lua_tostring(L, -1), len);
- lua_pop(L, 1);
- return booleanString(ret);
- }
-
- int val = lua_toboolean(L, -1);
- lua_pop(L, 1);
- return val != 0;
- }
-
- float getGlobalFloat(lua_State* L, const char* identifier, const float defaultValue = 0.0) {
- lua_getglobal(L, identifier);
- if (!lua_isnumber(L, -1)) {
- return defaultValue;
- }
-
- float val = lua_tonumber(L, -1);
- lua_pop(L, 1);
- return val;
- }
-
-}
-
bool ConfigManager::load() {
lua_State* L = luaL_newstate();
if (!L) {
@@ -90,316 +34,318 @@ bool ConfigManager::load() {
}
#ifndef DEBUG_LOG
- g_logger().setLevel(getGlobalString(L, "logLevel", "info"));
+ g_logger().setLevel(loadStringConfig(L, LOGLEVEL, "logLevel", "info"));
#endif
// Parse config
// Info that must be loaded one time (unless we reset the modules involved)
if (!loaded) {
- boolean[BIND_ONLY_GLOBAL_ADDRESS] = getGlobalBoolean(L, "bindOnlyGlobalAddress", false);
- boolean[OPTIMIZE_DATABASE] = getGlobalBoolean(L, "startupDatabaseOptimization", true);
- boolean[TOGGLE_MAP_CUSTOM] = getGlobalBoolean(L, "toggleMapCustom", true);
- boolean[TOGGLE_MAINTAIN_MODE] = getGlobalBoolean(L, "toggleMaintainMode", false);
- string[MAINTAIN_MODE_MESSAGE] = getGlobalString(L, "maintainModeMessage", "");
-
- string[IP] = getGlobalString(L, "ip", "127.0.0.1");
- string[MAP_NAME] = getGlobalString(L, "mapName", "canary");
- string[MAP_DOWNLOAD_URL] = getGlobalString(L, "mapDownloadUrl", "");
- string[MAP_AUTHOR] = getGlobalString(L, "mapAuthor", "Eduardo Dantas");
-
- string[MAP_CUSTOM_NAME] = getGlobalString(L, "mapCustomName", "");
- string[MAP_CUSTOM_AUTHOR] = getGlobalString(L, "mapCustomAuthor", "OTServBR");
-
- string[HOUSE_RENT_PERIOD] = getGlobalString(L, "houseRentPeriod", "never");
- floating[HOUSE_PRICE_RENT_MULTIPLIER] = getGlobalFloat(L, "housePriceRentMultiplier", 1.0);
- floating[HOUSE_RENT_RATE] = getGlobalFloat(L, "houseRentRate", 1.0);
- string[MYSQL_HOST] = getGlobalString(L, "mysqlHost", "127.0.0.1");
- string[MYSQL_USER] = getGlobalString(L, "mysqlUser", "root");
- string[MYSQL_PASS] = getGlobalString(L, "mysqlPass", "");
- string[MYSQL_DB] = getGlobalString(L, "mysqlDatabase", "canary");
- string[MYSQL_SOCK] = getGlobalString(L, "mysqlSock", "");
-
- string[AUTH_TYPE] = getGlobalString(L, "authType", "password");
- boolean[RESET_SESSIONS_ON_STARTUP] = getGlobalBoolean(L, "resetSessionsOnStartup", false);
-
- integer[SQL_PORT] = getGlobalNumber(L, "mysqlPort", 3306);
- integer[GAME_PORT] = getGlobalNumber(L, "gameProtocolPort", 7172);
- integer[LOGIN_PORT] = getGlobalNumber(L, "loginProtocolPort", 7171);
- integer[STATUS_PORT] = getGlobalNumber(L, "statusProtocolPort", 7171);
-
- integer[MARKET_OFFER_DURATION] = getGlobalNumber(L, "marketOfferDuration", 30 * 24 * 60 * 60);
-
- integer[FREE_DEPOT_LIMIT] = getGlobalNumber(L, "freeDepotLimit", 2000);
- integer[PREMIUM_DEPOT_LIMIT] = getGlobalNumber(L, "premiumDepotLimit", 8000);
- integer[DEPOT_BOXES] = getGlobalNumber(L, "depotBoxes", 20);
- integer[STASH_ITEMS] = getGlobalNumber(L, "stashItemCount", 5000);
-
- boolean[OLD_PROTOCOL] = getGlobalBoolean(L, "allowOldProtocol", true);
+ loadBoolConfig(L, BIND_ONLY_GLOBAL_ADDRESS, "bindOnlyGlobalAddress", false);
+ loadBoolConfig(L, OPTIMIZE_DATABASE, "startupDatabaseOptimization", true);
+ loadBoolConfig(L, TOGGLE_MAP_CUSTOM, "toggleMapCustom", true);
+ loadBoolConfig(L, TOGGLE_MAINTAIN_MODE, "toggleMaintainMode", false);
+ loadStringConfig(L, MAINTAIN_MODE_MESSAGE, "maintainModeMessage", "");
+
+ loadStringConfig(L, IP, "ip", "127.0.0.1");
+ loadStringConfig(L, MAP_NAME, "mapName", "canary");
+ loadStringConfig(L, MAP_DOWNLOAD_URL, "mapDownloadUrl", "");
+ loadStringConfig(L, MAP_AUTHOR, "mapAuthor", "Eduardo Dantas");
+
+ loadStringConfig(L, MAP_CUSTOM_NAME, "mapCustomName", "");
+ loadStringConfig(L, MAP_CUSTOM_AUTHOR, "mapCustomAuthor", "OTServBR");
+
+ loadStringConfig(L, HOUSE_RENT_PERIOD, "houseRentPeriod", "never");
+ loadFloatConfig(L, HOUSE_PRICE_RENT_MULTIPLIER, "housePriceRentMultiplier", 1.0);
+ loadFloatConfig(L, HOUSE_RENT_RATE, "houseRentRate", 1.0);
+ loadStringConfig(L, MYSQL_HOST, "mysqlHost", "127.0.0.1");
+ loadStringConfig(L, MYSQL_USER, "mysqlUser", "root");
+ loadStringConfig(L, MYSQL_PASS, "mysqlPass", "");
+ loadStringConfig(L, MYSQL_DB, "mysqlDatabase", "canary");
+ loadStringConfig(L, MYSQL_SOCK, "mysqlSock", "");
+
+ loadStringConfig(L, AUTH_TYPE, "authType", "password");
+ loadBoolConfig(L, RESET_SESSIONS_ON_STARTUP, "resetSessionsOnStartup", false);
+
+ loadIntConfig(L, SQL_PORT, "mysqlPort", 3306);
+ loadIntConfig(L, GAME_PORT, "gameProtocolPort", 7172);
+ loadIntConfig(L, LOGIN_PORT, "loginProtocolPort", 7171);
+ loadIntConfig(L, STATUS_PORT, "statusProtocolPort", 7171);
+
+ loadIntConfig(L, MARKET_OFFER_DURATION, "marketOfferDuration", 30 * 24 * 60 * 60);
+
+ loadIntConfig(L, FREE_DEPOT_LIMIT, "freeDepotLimit", 2000);
+ loadIntConfig(L, PREMIUM_DEPOT_LIMIT, "premiumDepotLimit", 8000);
+ loadIntConfig(L, DEPOT_BOXES, "depotBoxes", 20);
+ loadIntConfig(L, STASH_ITEMS, "stashItemCount", 5000);
+
+ loadBoolConfig(L, OLD_PROTOCOL, "allowOldProtocol", true);
}
- boolean[ALLOW_CHANGEOUTFIT] = getGlobalBoolean(L, "allowChangeOutfit", true);
- boolean[ONE_PLAYER_ON_ACCOUNT] = getGlobalBoolean(L, "onePlayerOnlinePerAccount", true);
- boolean[AIMBOT_HOTKEY_ENABLED] = getGlobalBoolean(L, "hotkeyAimbotEnabled", true);
- boolean[REMOVE_RUNE_CHARGES] = getGlobalBoolean(L, "removeChargesFromRunes", true);
- boolean[EXPERIENCE_FROM_PLAYERS] = getGlobalBoolean(L, "experienceByKillingPlayers", false);
- boolean[FREE_PREMIUM] = getGlobalBoolean(L, "freePremium", false);
- boolean[REPLACE_KICK_ON_LOGIN] = getGlobalBoolean(L, "replaceKickOnLogin", true);
- boolean[MARKET_PREMIUM] = getGlobalBoolean(L, "premiumToCreateMarketOffer", true);
- boolean[EMOTE_SPELLS] = getGlobalBoolean(L, "emoteSpells", false);
- boolean[STAMINA_SYSTEM] = getGlobalBoolean(L, "staminaSystem", true);
- boolean[WARN_UNSAFE_SCRIPTS] = getGlobalBoolean(L, "warnUnsafeScripts", true);
- boolean[CONVERT_UNSAFE_SCRIPTS] = getGlobalBoolean(L, "convertUnsafeScripts", true);
- boolean[CLASSIC_ATTACK_SPEED] = getGlobalBoolean(L, "classicAttackSpeed", false);
- boolean[TOGGLE_ATTACK_SPEED_ONFIST] = getGlobalBoolean(L, "toggleAttackSpeedOnFist", false);
- integer[MULTIPLIER_ATTACKONFIST] = getGlobalNumber(L, "multiplierSpeedOnFist", 5);
- integer[MAX_SPEED_ATTACKONFIST] = getGlobalNumber(L, "maxSpeedOnFist", 500);
- boolean[SCRIPTS_CONSOLE_LOGS] = getGlobalBoolean(L, "showScriptsLogInConsole", true);
- boolean[STASH_MOVING] = getGlobalBoolean(L, "stashMoving", false);
- boolean[ALLOW_BLOCK_SPAWN] = getGlobalBoolean(L, "allowBlockSpawn", true);
- boolean[REMOVE_WEAPON_AMMO] = getGlobalBoolean(L, "removeWeaponAmmunition", true);
- boolean[REMOVE_WEAPON_CHARGES] = getGlobalBoolean(L, "removeWeaponCharges", true);
- boolean[REMOVE_POTION_CHARGES] = getGlobalBoolean(L, "removeChargesFromPotions", true);
- boolean[GLOBAL_SERVER_SAVE_NOTIFY_MESSAGE] = getGlobalBoolean(L, "globalServerSaveNotifyMessage", true);
- boolean[GLOBAL_SERVER_SAVE_CLEAN_MAP] = getGlobalBoolean(L, "globalServerSaveCleanMap", false);
- boolean[GLOBAL_SERVER_SAVE_CLOSE] = getGlobalBoolean(L, "globalServerSaveClose", false);
- boolean[FORCE_MONSTERTYPE_LOAD] = getGlobalBoolean(L, "forceMonsterTypesOnLoad", true);
- boolean[HOUSE_OWNED_BY_ACCOUNT] = getGlobalBoolean(L, "houseOwnedByAccount", false);
- boolean[CLEAN_PROTECTION_ZONES] = getGlobalBoolean(L, "cleanProtectionZones", false);
- boolean[GLOBAL_SERVER_SAVE_SHUTDOWN] = getGlobalBoolean(L, "globalServerSaveShutdown", true);
- boolean[PUSH_WHEN_ATTACKING] = getGlobalBoolean(L, "pushWhenAttacking", false);
-
- boolean[WEATHER_RAIN] = getGlobalBoolean(L, "weatherRain", false);
- boolean[WEATHER_THUNDER] = getGlobalBoolean(L, "thunderEffect", false);
- boolean[ALL_CONSOLE_LOG] = getGlobalBoolean(L, "allConsoleLog", false);
- boolean[TOGGLE_FREE_QUEST] = getGlobalBoolean(L, "toggleFreeQuest", true);
- boolean[AUTOLOOT] = getGlobalBoolean(L, "autoLoot", false);
- boolean[AUTOBANK] = getGlobalBoolean(L, "autoBank", false);
- boolean[STAMINA_TRAINER] = getGlobalBoolean(L, "staminaTrainer", false);
- boolean[STAMINA_PZ] = getGlobalBoolean(L, "staminaPz", false);
- boolean[SORT_LOOT_BY_CHANCE] = getGlobalBoolean(L, "sortLootByChance", false);
- boolean[TOGGLE_SAVE_INTERVAL] = getGlobalBoolean(L, "toggleSaveInterval", false);
- boolean[TOGGLE_SAVE_INTERVAL_CLEAN_MAP] = getGlobalBoolean(L, "toggleSaveIntervalCleanMap", false);
- boolean[TELEPORT_SUMMONS] = getGlobalBoolean(L, "teleportSummons", false);
- boolean[ALLOW_RELOAD] = getGlobalBoolean(L, "allowReload", false);
-
- boolean[ONLY_PREMIUM_ACCOUNT] = getGlobalBoolean(L, "onlyPremiumAccount", false);
- boolean[RATE_USE_STAGES] = getGlobalBoolean(L, "rateUseStages", false);
- boolean[TOGGLE_IMBUEMENT_SHRINE_STORAGE] = getGlobalBoolean(L, "toggleImbuementShrineStorage", true);
- boolean[TOGGLE_IMBUEMENT_NON_AGGRESSIVE_FIGHT_ONLY] = getGlobalBoolean(L, "toggleImbuementNonAggressiveFightOnly", false);
-
- boolean[TOGGLE_DOWNLOAD_MAP] = getGlobalBoolean(L, "toggleDownloadMap", false);
- boolean[USE_ANY_DATAPACK_FOLDER] = getGlobalBoolean(L, "useAnyDatapackFolder", false);
- boolean[INVENTORY_GLOW] = getGlobalBoolean(L, "inventoryGlowOnFiveBless", false);
- boolean[XP_DISPLAY_MODE] = getGlobalBoolean(L, "experienceDisplayRates", true);
-
- string[DEFAULT_PRIORITY] = getGlobalString(L, "defaultPriority", "high");
- string[SERVER_NAME] = getGlobalString(L, "serverName", "");
- string[SERVER_MOTD] = getGlobalString(L, "serverMotd", "");
- string[OWNER_NAME] = getGlobalString(L, "ownerName", "");
- string[OWNER_EMAIL] = getGlobalString(L, "ownerEmail", "");
- string[URL] = getGlobalString(L, "url", "");
- string[LOCATION] = getGlobalString(L, "location", "");
- string[WORLD_TYPE] = getGlobalString(L, "worldType", "pvp");
- string[STORE_IMAGES_URL] = getGlobalString(L, "coinImagesURL", "");
- string[DISCORD_WEBHOOK_URL] = getGlobalString(L, "discordWebhookURL", "");
- string[SAVE_INTERVAL_TYPE] = getGlobalString(L, "saveIntervalType", "");
- string[GLOBAL_SERVER_SAVE_TIME] = getGlobalString(L, "globalServerSaveTime", "06:00");
- string[DATA_DIRECTORY] = getGlobalString(L, "dataPackDirectory", "data-otservbr-global");
- string[CORE_DIRECTORY] = getGlobalString(L, "coreDirectory", "data");
-
- string[FORGE_FIENDISH_INTERVAL_TYPE] = getGlobalString(L, "forgeFiendishIntervalType", "hour");
- string[FORGE_FIENDISH_INTERVAL_TIME] = getGlobalString(L, "forgeFiendishIntervalTime", "1");
-
- integer[MAX_PLAYERS] = getGlobalNumber(L, "maxPlayers");
- integer[PZ_LOCKED] = getGlobalNumber(L, "pzLocked", 60000);
- integer[DEFAULT_DESPAWNRANGE] = getGlobalNumber(L, "deSpawnRange", 2);
- integer[DEFAULT_DESPAWNRADIUS] = getGlobalNumber(L, "deSpawnRadius", 50);
- integer[RATE_EXPERIENCE] = getGlobalNumber(L, "rateExp", 1);
- integer[RATE_SKILL] = getGlobalNumber(L, "rateSkill", 1);
- integer[RATE_LOOT] = getGlobalNumber(L, "rateLoot", 1);
- integer[RATE_MAGIC] = getGlobalNumber(L, "rateMagic", 1);
- integer[RATE_SPAWN] = getGlobalNumber(L, "rateSpawn", 1);
- integer[RATE_KILLING_IN_THE_NAME_OF_POINTS] = getGlobalNumber(L, "rateKillingInTheNameOfPoints", 1);
-
- integer[HOUSE_PRICE_PER_SQM] = getGlobalNumber(L, "housePriceEachSQM", 1000);
- integer[HOUSE_BUY_LEVEL] = getGlobalNumber(L, "houseBuyLevel", 0);
- boolean[HOUSE_PURSHASED_SHOW_PRICE] = getGlobalBoolean(L, "housePurchasedShowPrice", false);
- boolean[ONLY_INVITED_CAN_MOVE_HOUSE_ITEMS] = getGlobalBoolean(L, "onlyInvitedCanMoveHouseItems", true);
-
- integer[ACTIONS_DELAY_INTERVAL] = getGlobalNumber(L, "timeBetweenActions", 200);
- integer[EX_ACTIONS_DELAY_INTERVAL] = getGlobalNumber(L, "timeBetweenExActions", 1000);
- integer[MAX_MESSAGEBUFFER] = getGlobalNumber(L, "maxMessageBuffer", 4);
- integer[KICK_AFTER_MINUTES] = getGlobalNumber(L, "kickIdlePlayerAfterMinutes", 15);
- integer[PROTECTION_LEVEL] = getGlobalNumber(L, "protectionLevel", 1);
- integer[DEATH_LOSE_PERCENT] = getGlobalNumber(L, "deathLosePercent", -1);
- integer[STATUSQUERY_TIMEOUT] = getGlobalNumber(L, "statusTimeout", 5000);
- integer[FRAG_TIME] = getGlobalNumber(L, "timeToDecreaseFrags", 24 * 60 * 60 * 1000);
- integer[WHITE_SKULL_TIME] = getGlobalNumber(L, "whiteSkullTime", 15 * 60 * 1000);
- integer[STAIRHOP_DELAY] = getGlobalNumber(L, "stairJumpExhaustion", 2000);
- integer[MAX_CONTAINER] = getGlobalNumber(L, "maxContainer", 500);
- integer[MAX_CONTAINER_ITEM] = getGlobalNumber(L, "maxItem", 5000);
- integer[EXP_FROM_PLAYERS_LEVEL_RANGE] = getGlobalNumber(L, "expFromPlayersLevelRange", 75);
- integer[CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES] = getGlobalNumber(L, "checkExpiredMarketOffersEachMinutes", 60);
- integer[MAX_MARKET_OFFERS_AT_A_TIME_PER_PLAYER] = getGlobalNumber(L, "maxMarketOffersAtATimePerPlayer", 100);
- integer[MAX_PACKETS_PER_SECOND] = getGlobalNumber(L, "maxPacketsPerSecond", 25);
- integer[COMPRESSION_LEVEL] = getGlobalNumber(L, "packetCompressionLevel", 6);
- integer[STORE_COIN_PACKET] = getGlobalNumber(L, "coinPacketSize", 25);
- integer[DAY_KILLS_TO_RED] = getGlobalNumber(L, "dayKillsToRedSkull", 3);
- integer[WEEK_KILLS_TO_RED] = getGlobalNumber(L, "weekKillsToRedSkull", 5);
- integer[MONTH_KILLS_TO_RED] = getGlobalNumber(L, "monthKillsToRedSkull", 10);
- integer[RED_SKULL_DURATION] = getGlobalNumber(L, "redSkullDuration", 30);
- integer[BLACK_SKULL_DURATION] = getGlobalNumber(L, "blackSkullDuration", 45);
- integer[ORANGE_SKULL_DURATION] = getGlobalNumber(L, "orangeSkullDuration", 7);
- integer[GLOBAL_SERVER_SAVE_NOTIFY_DURATION] = getGlobalNumber(L, "globalServerSaveNotifyDuration", 5);
-
- integer[PARTY_LIST_MAX_DISTANCE] = getGlobalNumber(L, "partyListMaxDistance", 0);
-
- integer[PUSH_DELAY] = getGlobalNumber(L, "pushDelay", 1000);
- integer[PUSH_DISTANCE_DELAY] = getGlobalNumber(L, "pushDistanceDelay", 1500);
-
- integer[STAMINA_ORANGE_DELAY] = getGlobalNumber(L, "staminaOrangeDelay", 1);
- integer[STAMINA_GREEN_DELAY] = getGlobalNumber(L, "staminaGreenDelay", 5);
- integer[STAMINA_PZ_GAIN] = getGlobalNumber(L, "staminaPzGain", 1);
- integer[STAMINA_TRAINER_DELAY] = getGlobalNumber(L, "staminaTrainerDelay", 5);
- integer[STAMINA_TRAINER_GAIN] = getGlobalNumber(L, "staminaTrainerGain", 1);
- integer[SAVE_INTERVAL_TIME] = getGlobalNumber(L, "saveIntervalTime", 1);
- integer[MAX_ALLOWED_ON_A_DUMMY] = getGlobalNumber(L, "maxAllowedOnADummy", 1);
- integer[FREE_QUEST_STAGE] = getGlobalNumber(L, "freeQuestStage", 1);
- integer[DEPOTCHEST] = getGlobalNumber(L, "depotChest", 4);
- integer[CRITICALCHANCE] = getGlobalNumber(L, "criticalChance", 10);
-
- integer[ADVENTURERSBLESSING_LEVEL] = getGlobalNumber(L, "adventurersBlessingLevel", 21);
- integer[FORGE_MAX_ITEM_TIER] = getGlobalNumber(L, "forgeMaxItemTier", 10);
- integer[FORGE_COST_ONE_SLIVER] = getGlobalNumber(L, "forgeCostOneSliver", 20);
- integer[FORGE_SLIVER_AMOUNT] = getGlobalNumber(L, "forgeSliverAmount", 3);
- integer[FORGE_CORE_COST] = getGlobalNumber(L, "forgeCoreCost", 50);
- integer[FORGE_MAX_DUST] = getGlobalNumber(L, "forgeMaxDust", 225);
- integer[FORGE_FUSION_DUST_COST] = getGlobalNumber(L, "forgeFusionCost", 100);
- integer[FORGE_TRANSFER_DUST_COST] = getGlobalNumber(L, "forgeTransferCost", 100);
- integer[FORGE_BASE_SUCCESS_RATE] = getGlobalNumber(L, "forgeBaseSuccessRate", 50);
- integer[FORGE_BONUS_SUCCESS_RATE] = getGlobalNumber(L, "forgeBonusSuccessRate", 15);
- integer[FORGE_TIER_LOSS_REDUCTION] = getGlobalNumber(L, "forgeTierLossReduction", 50);
- integer[FORGE_AMOUNT_MULTIPLIER] = getGlobalNumber(L, "forgeAmountMultiplier", 3);
- integer[FORGE_MIN_SLIVERS] = getGlobalNumber(L, "forgeMinSlivers", 3);
- integer[FORGE_MAX_SLIVERS] = getGlobalNumber(L, "forgeMaxSlivers", 7);
- integer[FORGE_INFLUENCED_CREATURES_LIMIT] = getGlobalNumber(L, "forgeInfluencedLimit", 300);
- integer[FORGE_FIENDISH_CREATURES_LIMIT] = getGlobalNumber(L, "forgeFiendishLimit", 3);
- integer[DISCORD_WEBHOOK_DELAY_MS] = getGlobalNumber(L, "discordWebhookDelayMs", Webhook::DEFAULT_DELAY_MS);
-
- floating[BESTIARY_RATE_CHARM_SHOP_PRICE] = getGlobalFloat(L, "bestiaryRateCharmShopPrice", 1.0);
- floating[RATE_HEALTH_REGEN] = getGlobalFloat(L, "rateHealthRegen", 1.0);
- floating[RATE_HEALTH_REGEN_SPEED] = getGlobalFloat(L, "rateHealthRegenSpeed", 1.0);
- floating[RATE_MANA_REGEN] = getGlobalFloat(L, "rateManaRegen", 1.0);
- floating[RATE_MANA_REGEN_SPEED] = getGlobalFloat(L, "rateManaRegenSpeed", 1.0);
- floating[RATE_SOUL_REGEN] = getGlobalFloat(L, "rateSoulRegen", 1.0);
- floating[RATE_SOUL_REGEN_SPEED] = getGlobalFloat(L, "rateSoulRegenSpeed", 1.0);
- floating[RATE_SPELL_COOLDOWN] = getGlobalFloat(L, "rateSpellCooldown", 1.0);
- floating[RATE_ATTACK_SPEED] = getGlobalFloat(L, "rateAttackSpeed", 1.0);
- floating[RATE_OFFLINE_TRAINING_SPEED] = getGlobalFloat(L, "rateOfflineTrainingSpeed", 1.0);
- floating[RATE_EXERCISE_TRAINING_SPEED] = getGlobalFloat(L, "rateExerciseTrainingSpeed", 1.0);
-
- floating[RATE_MONSTER_HEALTH] = getGlobalFloat(L, "rateMonsterHealth", 1.0);
- floating[RATE_MONSTER_ATTACK] = getGlobalFloat(L, "rateMonsterAttack", 1.0);
- floating[RATE_MONSTER_DEFENSE] = getGlobalFloat(L, "rateMonsterDefense", 1.0);
- floating[RATE_BOSS_HEALTH] = getGlobalFloat(L, "rateBossHealth", 1.0);
- floating[RATE_BOSS_ATTACK] = getGlobalFloat(L, "rateBossAttack", 1.0);
- floating[RATE_BOSS_DEFENSE] = getGlobalFloat(L, "rateBossDefense", 1.0);
- integer[BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN] = getGlobalNumber(L, "bossDefaultTimeToFightAgain", 20 * 60 * 60);
- integer[BOSS_DEFAULT_TIME_TO_DEFEAT] = getGlobalNumber(L, "bossDefaultTimeToDefeat", 20 * 60);
-
- floating[RATE_NPC_HEALTH] = getGlobalFloat(L, "rateNpcHealth", 1.0);
- floating[RATE_NPC_ATTACK] = getGlobalFloat(L, "rateNpcAttack", 1.0);
- floating[RATE_NPC_DEFENSE] = getGlobalFloat(L, "rateNpcDefense", 1.0);
-
- boolean[PREY_ENABLED] = getGlobalBoolean(L, "preySystemEnabled", true);
- boolean[PREY_FREE_THIRD_SLOT] = getGlobalBoolean(L, "preyFreeThirdSlot", false);
- integer[PREY_REROLL_PRICE_LEVEL] = getGlobalNumber(L, "preyRerollPricePerLevel", 200);
- integer[PREY_SELECTION_LIST_PRICE] = getGlobalNumber(L, "preySelectListPrice", 5);
- integer[PREY_BONUS_TIME] = getGlobalNumber(L, "preyBonusTime", 7200);
- integer[PREY_BONUS_REROLL_PRICE] = getGlobalNumber(L, "preyBonusRerollPrice", 1);
- integer[PREY_FREE_REROLL_TIME] = getGlobalNumber(L, "preyFreeRerollTime", 72000);
-
- boolean[TASK_HUNTING_ENABLED] = getGlobalBoolean(L, "taskHuntingSystemEnabled", true);
- boolean[TASK_HUNTING_FREE_THIRD_SLOT] = getGlobalBoolean(L, "taskHuntingFreeThirdSlot", false);
- integer[TASK_HUNTING_LIMIT_EXHAUST] = getGlobalNumber(L, "taskHuntingLimitedTasksExhaust", 72000);
- integer[TASK_HUNTING_REROLL_PRICE_LEVEL] = getGlobalNumber(L, "taskHuntingRerollPricePerLevel", 200);
- integer[TASK_HUNTING_SELECTION_LIST_PRICE] = getGlobalNumber(L, "taskHuntingSelectListPrice", 5);
- integer[TASK_HUNTING_BONUS_REROLL_PRICE] = getGlobalNumber(L, "taskHuntingBonusRerollPrice", 1);
- integer[TASK_HUNTING_FREE_REROLL_TIME] = getGlobalNumber(L, "taskHuntingFreeRerollTime", 72000);
-
- integer[BESTIARY_KILL_MULTIPLIER] = getGlobalNumber(L, "bestiaryKillMultiplier", 1);
- integer[BOSSTIARY_KILL_MULTIPLIER] = getGlobalNumber(L, "bosstiaryKillMultiplier", 1);
- boolean[BOOSTED_BOSS_SLOT] = getGlobalBoolean(L, "boostedBossSlot", true);
- integer[BOOSTED_BOSS_LOOT_BONUS] = getGlobalNumber(L, "boostedBossLootBonus", 250);
- integer[BOOSTED_BOSS_KILL_BONUS] = getGlobalNumber(L, "boostedBossKillBonus", 3);
-
- integer[FAMILIAR_TIME] = getGlobalNumber(L, "familiarTime", 30);
-
- boolean[TOGGLE_GOLD_POUCH_ALLOW_ANYTHING] = getGlobalBoolean(L, "toggleGoldPouchAllowAnything", false);
- boolean[TOGGLE_GOLD_POUCH_QUICKLOOT_ONLY] = getGlobalBoolean(L, "toggleGoldPouchQuickLootOnly", false);
- boolean[TOGGLE_SERVER_IS_RETRO] = getGlobalBoolean(L, "toggleServerIsRetroPVP", false);
- boolean[TOGGLE_TRAVELS_FREE] = getGlobalBoolean(L, "toggleTravelsFree", false);
- integer[BUY_AOL_COMMAND_FEE] = getGlobalNumber(L, "buyAolCommandFee", 0);
- integer[BUY_BLESS_COMMAND_FEE] = getGlobalNumber(L, "buyBlessCommandFee", 0);
- boolean[TELEPORT_PLAYER_TO_VOCATION_ROOM] = getGlobalBoolean(L, "teleportPlayerToVocationRoom", true);
-
- boolean[TOGGLE_HAZARDSYSTEM] = getGlobalBoolean(L, "toogleHazardSystem", true);
- integer[HAZARD_CRITICAL_INTERVAL] = getGlobalNumber(L, "hazardCriticalInterval", 2000);
- integer[HAZARD_CRITICAL_CHANCE] = getGlobalNumber(L, "hazardCriticalChance", 750);
- integer[HAZARD_CRITICAL_MULTIPLIER] = getGlobalNumber(L, "hazardCriticalMultiplier", 25);
- integer[HAZARD_DAMAGE_MULTIPLIER] = getGlobalNumber(L, "hazardDamageMultiplier", 200);
- integer[HAZARD_DODGE_MULTIPLIER] = getGlobalNumber(L, "hazardDodgeMultiplier", 85);
- integer[HAZARD_PODS_DROP_MULTIPLIER] = getGlobalNumber(L, "hazardPodsDropMultiplier", 87);
- integer[HAZARD_PODS_TIME_TO_DAMAGE] = getGlobalNumber(L, "hazardPodsTimeToDamage", 2000);
- integer[HAZARD_PODS_TIME_TO_SPAWN] = getGlobalNumber(L, "hazardPodsTimeToSpawn", 4000);
- integer[HAZARD_EXP_BONUS_MULTIPLIER] = getGlobalNumber(L, "hazardExpBonusMultiplier", 2);
- integer[HAZARD_LOOT_BONUS_MULTIPLIER] = getGlobalNumber(L, "hazardLootBonusMultiplier", 2);
- integer[HAZARD_PODS_DAMAGE] = getGlobalNumber(L, "hazardPodsDamage", 5);
- integer[HAZARD_SPAWN_PLUNDER_MULTIPLIER] = getGlobalNumber(L, "hazardSpawnPlunderMultiplier", 25);
- integer[LOW_LEVEL_BONUS_EXP] = getGlobalNumber(L, "lowLevelBonusExp", 50);
-
- boolean[LOYALTY_ENABLED] = getGlobalBoolean(L, "loyaltyEnabled", true);
- integer[LOYALTY_POINTS_PER_CREATION_DAY] = getGlobalNumber(L, "loyaltyPointsPerCreationDay", 1);
- integer[LOYALTY_POINTS_PER_PREMIUM_DAY_SPENT] = getGlobalNumber(L, "loyaltyPointsPerPremiumDaySpent", 0);
- integer[LOYALTY_POINTS_PER_PREMIUM_DAY_PURCHASED] = getGlobalNumber(L, "loyaltyPointsPerPremiumDayPurchased", 0);
- floating[LOYALTY_BONUS_PERCENTAGE_MULTIPLIER] = getGlobalFloat(L, "loyaltyBonusPercentageMultiplier", 1.0);
-
- boolean[TOGGLE_WHEELSYSTEM] = getGlobalBoolean(L, "wheelSystemEnabled", true);
- integer[WHEEL_POINTS_PER_LEVEL] = getGlobalNumber(L, "wheelPointsPerLevel", 1);
-
- boolean[PARTY_AUTO_SHARE_EXPERIENCE] = getGlobalBoolean(L, "partyAutoShareExperience", true);
- boolean[PARTY_SHARE_LOOT_BOOSTS] = getGlobalBoolean(L, "partyShareLootBoosts", true);
- floating[PARTY_SHARE_LOOT_BOOSTS_DIMINISHING_FACTOR] = getGlobalFloat(L, "partyShareLootBoostsDimishingFactor", 0.7f);
- integer[TIBIADROME_CONCOCTION_COOLDOWN] = getGlobalNumber(L, "tibiadromeConcoctionCooldown", 24 * 60 * 60);
- integer[TIBIADROME_CONCOCTION_DURATION] = getGlobalNumber(L, "tibiadromeConcoctionDuration", 1 * 60 * 60);
- string[TIBIADROME_CONCOCTION_TICK_TYPE] = getGlobalString(L, "tibiadromeConcoctionTickType", "online");
-
- string[M_CONST] = getGlobalString(L, "memoryConst", "1<<16");
- integer[T_CONST] = getGlobalNumber(L, "temporaryConst", 2);
- integer[PARALLELISM] = getGlobalNumber(L, "parallelism", 2);
+ loadBoolConfig(L, ALLOW_CHANGEOUTFIT, "allowChangeOutfit", true);
+ loadBoolConfig(L, ONE_PLAYER_ON_ACCOUNT, "onePlayerOnlinePerAccount", true);
+ loadBoolConfig(L, AIMBOT_HOTKEY_ENABLED, "hotkeyAimbotEnabled", true);
+ loadBoolConfig(L, REMOVE_RUNE_CHARGES, "removeChargesFromRunes", true);
+ loadBoolConfig(L, EXPERIENCE_FROM_PLAYERS, "experienceByKillingPlayers", false);
+ loadBoolConfig(L, FREE_PREMIUM, "freePremium", false);
+ loadBoolConfig(L, REPLACE_KICK_ON_LOGIN, "replaceKickOnLogin", true);
+ loadBoolConfig(L, MARKET_PREMIUM, "premiumToCreateMarketOffer", true);
+ loadBoolConfig(L, EMOTE_SPELLS, "emoteSpells", false);
+ loadBoolConfig(L, STAMINA_SYSTEM, "staminaSystem", true);
+ loadBoolConfig(L, WARN_UNSAFE_SCRIPTS, "warnUnsafeScripts", true);
+ loadBoolConfig(L, CONVERT_UNSAFE_SCRIPTS, "convertUnsafeScripts", true);
+ loadBoolConfig(L, CLASSIC_ATTACK_SPEED, "classicAttackSpeed", false);
+ loadBoolConfig(L, TOGGLE_ATTACK_SPEED_ONFIST, "toggleAttackSpeedOnFist", false);
+ loadIntConfig(L, MULTIPLIER_ATTACKONFIST, "multiplierSpeedOnFist", 5);
+ loadIntConfig(L, MAX_SPEED_ATTACKONFIST, "maxSpeedOnFist", 500);
+ loadBoolConfig(L, SCRIPTS_CONSOLE_LOGS, "showScriptsLogInConsole", true);
+ loadBoolConfig(L, STASH_MOVING, "stashMoving", false);
+ loadBoolConfig(L, ALLOW_BLOCK_SPAWN, "allowBlockSpawn", true);
+ loadBoolConfig(L, REMOVE_WEAPON_AMMO, "removeWeaponAmmunition", true);
+ loadBoolConfig(L, REMOVE_WEAPON_CHARGES, "removeWeaponCharges", true);
+ loadBoolConfig(L, REMOVE_POTION_CHARGES, "removeChargesFromPotions", true);
+ loadBoolConfig(L, GLOBAL_SERVER_SAVE_NOTIFY_MESSAGE, "globalServerSaveNotifyMessage", true);
+ loadBoolConfig(L, GLOBAL_SERVER_SAVE_CLEAN_MAP, "globalServerSaveCleanMap", false);
+ loadBoolConfig(L, GLOBAL_SERVER_SAVE_CLOSE, "globalServerSaveClose", false);
+ loadBoolConfig(L, FORCE_MONSTERTYPE_LOAD, "forceMonsterTypesOnLoad", true);
+ loadBoolConfig(L, HOUSE_OWNED_BY_ACCOUNT, "houseOwnedByAccount", false);
+ loadBoolConfig(L, CLEAN_PROTECTION_ZONES, "cleanProtectionZones", false);
+ loadBoolConfig(L, GLOBAL_SERVER_SAVE_SHUTDOWN, "globalServerSaveShutdown", true);
+ loadBoolConfig(L, PUSH_WHEN_ATTACKING, "pushWhenAttacking", false);
+
+ loadBoolConfig(L, WEATHER_RAIN, "weatherRain", false);
+ loadBoolConfig(L, WEATHER_THUNDER, "thunderEffect", false);
+ loadBoolConfig(L, ALL_CONSOLE_LOG, "allConsoleLog", false);
+ loadBoolConfig(L, TOGGLE_FREE_QUEST, "toggleFreeQuest", true);
+ loadBoolConfig(L, AUTOLOOT, "autoLoot", false);
+ loadBoolConfig(L, AUTOBANK, "autoBank", false);
+ loadBoolConfig(L, STAMINA_TRAINER, "staminaTrainer", false);
+ loadBoolConfig(L, STAMINA_PZ, "staminaPz", false);
+ loadBoolConfig(L, SORT_LOOT_BY_CHANCE, "sortLootByChance", false);
+ loadBoolConfig(L, TOGGLE_SAVE_INTERVAL, "toggleSaveInterval", false);
+ loadBoolConfig(L, TOGGLE_SAVE_INTERVAL_CLEAN_MAP, "toggleSaveIntervalCleanMap", false);
+ loadBoolConfig(L, TELEPORT_SUMMONS, "teleportSummons", false);
+ loadBoolConfig(L, ALLOW_RELOAD, "allowReload", false);
+
+ loadBoolConfig(L, ONLY_PREMIUM_ACCOUNT, "onlyPremiumAccount", false);
+ loadBoolConfig(L, RATE_USE_STAGES, "rateUseStages", false);
+ loadBoolConfig(L, TOGGLE_IMBUEMENT_SHRINE_STORAGE, "toggleImbuementShrineStorage", true);
+ loadBoolConfig(L, TOGGLE_IMBUEMENT_NON_AGGRESSIVE_FIGHT_ONLY, "toggleImbuementNonAggressiveFightOnly", false);
+
+ loadBoolConfig(L, TOGGLE_DOWNLOAD_MAP, "toggleDownloadMap", false);
+ loadBoolConfig(L, USE_ANY_DATAPACK_FOLDER, "useAnyDatapackFolder", false);
+ loadBoolConfig(L, INVENTORY_GLOW, "inventoryGlowOnFiveBless", false);
+ loadBoolConfig(L, XP_DISPLAY_MODE, "experienceDisplayRates", true);
+
+ loadStringConfig(L, DEFAULT_PRIORITY, "defaultPriority", "high");
+ loadStringConfig(L, SERVER_NAME, "serverName", "");
+ loadStringConfig(L, SERVER_MOTD, "serverMotd", "");
+ loadStringConfig(L, OWNER_NAME, "ownerName", "");
+ loadStringConfig(L, OWNER_EMAIL, "ownerEmail", "");
+ loadStringConfig(L, URL, "url", "");
+ loadStringConfig(L, LOCATION, "location", "");
+ loadStringConfig(L, WORLD_TYPE, "worldType", "pvp");
+ loadStringConfig(L, STORE_IMAGES_URL, "coinImagesURL", "");
+ loadStringConfig(L, DISCORD_WEBHOOK_URL, "discordWebhookURL", "");
+ loadStringConfig(L, SAVE_INTERVAL_TYPE, "saveIntervalType", "");
+ loadStringConfig(L, GLOBAL_SERVER_SAVE_TIME, "globalServerSaveTime", "06:00");
+ loadStringConfig(L, DATA_DIRECTORY, "dataPackDirectory", "data-otservbr-global");
+ loadStringConfig(L, CORE_DIRECTORY, "coreDirectory", "data");
+
+ loadStringConfig(L, FORGE_FIENDISH_INTERVAL_TYPE, "forgeFiendishIntervalType", "hour");
+ loadStringConfig(L, FORGE_FIENDISH_INTERVAL_TIME, "forgeFiendishIntervalTime", "1");
+
+ loadIntConfig(L, MAX_PLAYERS, "maxPlayers", 0);
+ loadIntConfig(L, PZ_LOCKED, "pzLocked", 60000);
+ loadIntConfig(L, DEFAULT_DESPAWNRANGE, "deSpawnRange", 2);
+ loadIntConfig(L, DEFAULT_DESPAWNRADIUS, "deSpawnRadius", 50);
+ loadIntConfig(L, RATE_EXPERIENCE, "rateExp", 1);
+ loadIntConfig(L, RATE_SKILL, "rateSkill", 1);
+ loadIntConfig(L, RATE_LOOT, "rateLoot", 1);
+ loadIntConfig(L, RATE_MAGIC, "rateMagic", 1);
+ loadIntConfig(L, RATE_SPAWN, "rateSpawn", 1);
+ loadIntConfig(L, RATE_KILLING_IN_THE_NAME_OF_POINTS, "rateKillingInTheNameOfPoints", 1);
+
+ loadIntConfig(L, HOUSE_PRICE_PER_SQM, "housePriceEachSQM", 1000);
+ loadIntConfig(L, HOUSE_BUY_LEVEL, "houseBuyLevel", 0);
+ loadIntConfig(L, HOUSE_LOSE_AFTER_INACTIVITY, "houseLoseAfterInactivity", 0);
+ loadBoolConfig(L, HOUSE_PURSHASED_SHOW_PRICE, "housePurchasedShowPrice", false);
+ loadBoolConfig(L, ONLY_INVITED_CAN_MOVE_HOUSE_ITEMS, "onlyInvitedCanMoveHouseItems", true);
+
+ loadIntConfig(L, ACTIONS_DELAY_INTERVAL, "timeBetweenActions", 200);
+ loadIntConfig(L, EX_ACTIONS_DELAY_INTERVAL, "timeBetweenExActions", 1000);
+ loadIntConfig(L, MAX_MESSAGEBUFFER, "maxMessageBuffer", 4);
+ loadIntConfig(L, KICK_AFTER_MINUTES, "kickIdlePlayerAfterMinutes", 15);
+ loadIntConfig(L, PROTECTION_LEVEL, "protectionLevel", 1);
+ loadIntConfig(L, DEATH_LOSE_PERCENT, "deathLosePercent", -1);
+ loadIntConfig(L, STATUSQUERY_TIMEOUT, "statusTimeout", 5000);
+ loadIntConfig(L, FRAG_TIME, "timeToDecreaseFrags", 24 * 60 * 60 * 1000);
+ loadIntConfig(L, WHITE_SKULL_TIME, "whiteSkullTime", 15 * 60 * 1000);
+ loadIntConfig(L, STAIRHOP_DELAY, "stairJumpExhaustion", 2000);
+ loadIntConfig(L, MAX_CONTAINER, "maxContainer", 500);
+ loadIntConfig(L, MAX_CONTAINER_ITEM, "maxItem", 5000);
+ loadIntConfig(L, EXP_FROM_PLAYERS_LEVEL_RANGE, "expFromPlayersLevelRange", 75);
+ loadIntConfig(L, CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES, "checkExpiredMarketOffersEachMinutes", 60);
+ loadIntConfig(L, MAX_MARKET_OFFERS_AT_A_TIME_PER_PLAYER, "maxMarketOffersAtATimePerPlayer", 100);
+ loadIntConfig(L, MAX_PACKETS_PER_SECOND, "maxPacketsPerSecond", 25);
+ loadIntConfig(L, COMPRESSION_LEVEL, "packetCompressionLevel", 6);
+ loadIntConfig(L, STORE_COIN_PACKET, "coinPacketSize", 25);
+ loadIntConfig(L, DAY_KILLS_TO_RED, "dayKillsToRedSkull", 3);
+ loadIntConfig(L, WEEK_KILLS_TO_RED, "weekKillsToRedSkull", 5);
+ loadIntConfig(L, MONTH_KILLS_TO_RED, "monthKillsToRedSkull", 10);
+ loadIntConfig(L, RED_SKULL_DURATION, "redSkullDuration", 30);
+ loadIntConfig(L, BLACK_SKULL_DURATION, "blackSkullDuration", 45);
+ loadIntConfig(L, ORANGE_SKULL_DURATION, "orangeSkullDuration", 7);
+ loadIntConfig(L, GLOBAL_SERVER_SAVE_NOTIFY_DURATION, "globalServerSaveNotifyDuration", 5);
+
+ loadIntConfig(L, PARTY_LIST_MAX_DISTANCE, "partyListMaxDistance", 0);
+
+ loadIntConfig(L, PUSH_DELAY, "pushDelay", 1000);
+ loadIntConfig(L, PUSH_DISTANCE_DELAY, "pushDistanceDelay", 1500);
+
+ loadIntConfig(L, STAMINA_ORANGE_DELAY, "staminaOrangeDelay", 1);
+ loadIntConfig(L, STAMINA_GREEN_DELAY, "staminaGreenDelay", 5);
+ loadIntConfig(L, STAMINA_PZ_GAIN, "staminaPzGain", 1);
+ loadIntConfig(L, STAMINA_TRAINER_DELAY, "staminaTrainerDelay", 5);
+ loadIntConfig(L, STAMINA_TRAINER_GAIN, "staminaTrainerGain", 1);
+ loadIntConfig(L, SAVE_INTERVAL_TIME, "saveIntervalTime", 1);
+ loadIntConfig(L, MAX_ALLOWED_ON_A_DUMMY, "maxAllowedOnADummy", 1);
+ loadIntConfig(L, FREE_QUEST_STAGE, "freeQuestStage", 1);
+ loadIntConfig(L, DEPOTCHEST, "depotChest", 4);
+ loadIntConfig(L, CRITICALCHANCE, "criticalChance", 10);
+
+ loadIntConfig(L, ADVENTURERSBLESSING_LEVEL, "adventurersBlessingLevel", 21);
+ loadIntConfig(L, FORGE_MAX_ITEM_TIER, "forgeMaxItemTier", 10);
+ loadIntConfig(L, FORGE_COST_ONE_SLIVER, "forgeCostOneSliver", 20);
+ loadIntConfig(L, FORGE_SLIVER_AMOUNT, "forgeSliverAmount", 3);
+ loadIntConfig(L, FORGE_CORE_COST, "forgeCoreCost", 50);
+ loadIntConfig(L, FORGE_MAX_DUST, "forgeMaxDust", 225);
+ loadIntConfig(L, FORGE_FUSION_DUST_COST, "forgeFusionCost", 100);
+ loadIntConfig(L, FORGE_TRANSFER_DUST_COST, "forgeTransferCost", 100);
+ loadIntConfig(L, FORGE_BASE_SUCCESS_RATE, "forgeBaseSuccessRate", 50);
+ loadIntConfig(L, FORGE_BONUS_SUCCESS_RATE, "forgeBonusSuccessRate", 15);
+ loadIntConfig(L, FORGE_TIER_LOSS_REDUCTION, "forgeTierLossReduction", 50);
+ loadIntConfig(L, FORGE_AMOUNT_MULTIPLIER, "forgeAmountMultiplier", 3);
+ loadIntConfig(L, FORGE_MIN_SLIVERS, "forgeMinSlivers", 3);
+ loadIntConfig(L, FORGE_MAX_SLIVERS, "forgeMaxSlivers", 7);
+ loadIntConfig(L, FORGE_INFLUENCED_CREATURES_LIMIT, "forgeInfluencedLimit", 300);
+ loadIntConfig(L, FORGE_FIENDISH_CREATURES_LIMIT, "forgeFiendishLimit", 3);
+ loadIntConfig(L, DISCORD_WEBHOOK_DELAY_MS, "discordWebhookDelayMs", Webhook::DEFAULT_DELAY_MS);
+
+ loadFloatConfig(L, BESTIARY_RATE_CHARM_SHOP_PRICE, "bestiaryRateCharmShopPrice", 1.0);
+ loadFloatConfig(L, RATE_HEALTH_REGEN, "rateHealthRegen", 1.0);
+ loadFloatConfig(L, RATE_HEALTH_REGEN_SPEED, "rateHealthRegenSpeed", 1.0);
+ loadFloatConfig(L, RATE_MANA_REGEN, "rateManaRegen", 1.0);
+ loadFloatConfig(L, RATE_MANA_REGEN_SPEED, "rateManaRegenSpeed", 1.0);
+ loadFloatConfig(L, RATE_SOUL_REGEN, "rateSoulRegen", 1.0);
+ loadFloatConfig(L, RATE_SOUL_REGEN_SPEED, "rateSoulRegenSpeed", 1.0);
+ loadFloatConfig(L, RATE_SPELL_COOLDOWN, "rateSpellCooldown", 1.0);
+ loadFloatConfig(L, RATE_ATTACK_SPEED, "rateAttackSpeed", 1.0);
+ loadFloatConfig(L, RATE_OFFLINE_TRAINING_SPEED, "rateOfflineTrainingSpeed", 1.0);
+ loadFloatConfig(L, RATE_EXERCISE_TRAINING_SPEED, "rateExerciseTrainingSpeed", 1.0);
+
+ loadFloatConfig(L, RATE_MONSTER_HEALTH, "rateMonsterHealth", 1.0);
+ loadFloatConfig(L, RATE_MONSTER_ATTACK, "rateMonsterAttack", 1.0);
+ loadFloatConfig(L, RATE_MONSTER_DEFENSE, "rateMonsterDefense", 1.0);
+ loadFloatConfig(L, RATE_BOSS_HEALTH, "rateBossHealth", 1.0);
+ loadFloatConfig(L, RATE_BOSS_ATTACK, "rateBossAttack", 1.0);
+ loadFloatConfig(L, RATE_BOSS_DEFENSE, "rateBossDefense", 1.0);
+ loadIntConfig(L, BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN, "bossDefaultTimeToFightAgain", 20 * 60 * 60);
+ loadIntConfig(L, BOSS_DEFAULT_TIME_TO_DEFEAT, "bossDefaultTimeToDefeat", 20 * 60);
+
+ loadFloatConfig(L, RATE_NPC_HEALTH, "rateNpcHealth", 1.0);
+ loadFloatConfig(L, RATE_NPC_ATTACK, "rateNpcAttack", 1.0);
+ loadFloatConfig(L, RATE_NPC_DEFENSE, "rateNpcDefense", 1.0);
+
+ loadBoolConfig(L, PREY_ENABLED, "preySystemEnabled", true);
+ loadBoolConfig(L, PREY_FREE_THIRD_SLOT, "preyFreeThirdSlot", false);
+ loadIntConfig(L, PREY_REROLL_PRICE_LEVEL, "preyRerollPricePerLevel", 200);
+ loadIntConfig(L, PREY_SELECTION_LIST_PRICE, "preySelectListPrice", 5);
+ loadIntConfig(L, PREY_BONUS_TIME, "preyBonusTime", 7200);
+ loadIntConfig(L, PREY_BONUS_REROLL_PRICE, "preyBonusRerollPrice", 1);
+ loadIntConfig(L, PREY_FREE_REROLL_TIME, "preyFreeRerollTime", 72000);
+
+ loadBoolConfig(L, TASK_HUNTING_ENABLED, "taskHuntingSystemEnabled", true);
+ loadBoolConfig(L, TASK_HUNTING_FREE_THIRD_SLOT, "taskHuntingFreeThirdSlot", false);
+ loadIntConfig(L, TASK_HUNTING_LIMIT_EXHAUST, "taskHuntingLimitedTasksExhaust", 72000);
+ loadIntConfig(L, TASK_HUNTING_REROLL_PRICE_LEVEL, "taskHuntingRerollPricePerLevel", 200);
+ loadIntConfig(L, TASK_HUNTING_SELECTION_LIST_PRICE, "taskHuntingSelectListPrice", 5);
+ loadIntConfig(L, TASK_HUNTING_BONUS_REROLL_PRICE, "taskHuntingBonusRerollPrice", 1);
+ loadIntConfig(L, TASK_HUNTING_FREE_REROLL_TIME, "taskHuntingFreeRerollTime", 72000);
+
+ loadIntConfig(L, BESTIARY_KILL_MULTIPLIER, "bestiaryKillMultiplier", 1);
+ loadIntConfig(L, BOSSTIARY_KILL_MULTIPLIER, "bosstiaryKillMultiplier", 1);
+ loadBoolConfig(L, BOOSTED_BOSS_SLOT, "boostedBossSlot", true);
+ loadIntConfig(L, BOOSTED_BOSS_LOOT_BONUS, "boostedBossLootBonus", 250);
+ loadIntConfig(L, BOOSTED_BOSS_KILL_BONUS, "boostedBossKillBonus", 3);
+
+ loadIntConfig(L, FAMILIAR_TIME, "familiarTime", 30);
+
+ loadBoolConfig(L, TOGGLE_GOLD_POUCH_ALLOW_ANYTHING, "toggleGoldPouchAllowAnything", false);
+ loadBoolConfig(L, TOGGLE_GOLD_POUCH_QUICKLOOT_ONLY, "toggleGoldPouchQuickLootOnly", false);
+ loadBoolConfig(L, TOGGLE_SERVER_IS_RETRO, "toggleServerIsRetroPVP", false);
+ loadBoolConfig(L, TOGGLE_TRAVELS_FREE, "toggleTravelsFree", false);
+ loadIntConfig(L, BUY_AOL_COMMAND_FEE, "buyAolCommandFee", 0);
+ loadIntConfig(L, BUY_BLESS_COMMAND_FEE, "buyBlessCommandFee", 0);
+ loadBoolConfig(L, TELEPORT_PLAYER_TO_VOCATION_ROOM, "teleportPlayerToVocationRoom", true);
+
+ loadBoolConfig(L, TOGGLE_HAZARDSYSTEM, "toogleHazardSystem", true);
+ loadIntConfig(L, HAZARD_CRITICAL_INTERVAL, "hazardCriticalInterval", 2000);
+ loadIntConfig(L, HAZARD_CRITICAL_CHANCE, "hazardCriticalChance", 750);
+ loadIntConfig(L, HAZARD_CRITICAL_MULTIPLIER, "hazardCriticalMultiplier", 25);
+ loadIntConfig(L, HAZARD_DAMAGE_MULTIPLIER, "hazardDamageMultiplier", 200);
+ loadIntConfig(L, HAZARD_DODGE_MULTIPLIER, "hazardDodgeMultiplier", 85);
+ loadIntConfig(L, HAZARD_PODS_DROP_MULTIPLIER, "hazardPodsDropMultiplier", 87);
+ loadIntConfig(L, HAZARD_PODS_TIME_TO_DAMAGE, "hazardPodsTimeToDamage", 2000);
+ loadIntConfig(L, HAZARD_PODS_TIME_TO_SPAWN, "hazardPodsTimeToSpawn", 4000);
+ loadIntConfig(L, HAZARD_EXP_BONUS_MULTIPLIER, "hazardExpBonusMultiplier", 2);
+ loadIntConfig(L, HAZARD_LOOT_BONUS_MULTIPLIER, "hazardLootBonusMultiplier", 2);
+ loadIntConfig(L, HAZARD_PODS_DAMAGE, "hazardPodsDamage", 5);
+ loadIntConfig(L, HAZARD_SPAWN_PLUNDER_MULTIPLIER, "hazardSpawnPlunderMultiplier", 25);
+ loadIntConfig(L, LOW_LEVEL_BONUS_EXP, "lowLevelBonusExp", 50);
+
+ loadBoolConfig(L, LOYALTY_ENABLED, "loyaltyEnabled", true);
+ loadIntConfig(L, LOYALTY_POINTS_PER_CREATION_DAY, "loyaltyPointsPerCreationDay", 1);
+ loadIntConfig(L, LOYALTY_POINTS_PER_PREMIUM_DAY_SPENT, "loyaltyPointsPerPremiumDaySpent", 0);
+ loadIntConfig(L, LOYALTY_POINTS_PER_PREMIUM_DAY_PURCHASED, "loyaltyPointsPerPremiumDayPurchased", 0);
+ loadFloatConfig(L, LOYALTY_BONUS_PERCENTAGE_MULTIPLIER, "loyaltyBonusPercentageMultiplier", 1.0);
+
+ loadBoolConfig(L, TOGGLE_WHEELSYSTEM, "wheelSystemEnabled", true);
+ loadIntConfig(L, WHEEL_POINTS_PER_LEVEL, "wheelPointsPerLevel", 1);
+
+ loadBoolConfig(L, PARTY_AUTO_SHARE_EXPERIENCE, "partyAutoShareExperience", true);
+ loadBoolConfig(L, PARTY_SHARE_LOOT_BOOSTS, "partyShareLootBoosts", true);
+ loadFloatConfig(L, PARTY_SHARE_LOOT_BOOSTS_DIMINISHING_FACTOR, "partyShareLootBoostsDimishingFactor", 0.7f);
+ loadIntConfig(L, TIBIADROME_CONCOCTION_COOLDOWN, "tibiadromeConcoctionCooldown", 24 * 60 * 60);
+ loadIntConfig(L, TIBIADROME_CONCOCTION_DURATION, "tibiadromeConcoctionDuration", 1 * 60 * 60);
+ loadStringConfig(L, TIBIADROME_CONCOCTION_TICK_TYPE, "tibiadromeConcoctionTickType", "online");
+
+ loadStringConfig(L, M_CONST, "memoryConst", "1<<16");
+ loadIntConfig(L, T_CONST, "temporaryConst", 2);
+ loadIntConfig(L, PARALLELISM, "parallelism", 2);
// Vip System
- boolean[VIP_SYSTEM_ENABLED] = getGlobalBoolean(L, "vipSystemEnabled", false);
- integer[VIP_BONUS_EXP] = getGlobalNumber(L, "vipBonusExp", 0);
- integer[VIP_BONUS_LOOT] = getGlobalNumber(L, "vipBonusLoot", 0);
- integer[VIP_BONUS_SKILL] = getGlobalNumber(L, "vipBonusSkill", 0);
- boolean[VIP_AUTOLOOT_VIP_ONLY] = getGlobalBoolean(L, "vipAutoLootVipOnly", false);
- boolean[VIP_STAY_ONLINE] = getGlobalBoolean(L, "vipStayOnline", false);
- integer[VIP_FAMILIAR_TIME_COOLDOWN_REDUCTION] = getGlobalNumber(L, "vipFamiliarTimeCooldownReduction", 0);
-
- boolean[REWARD_CHEST_COLLECT_ENABLED] = getGlobalBoolean(L, "rewardChestCollectEnabled", true);
- integer[REWARD_CHEST_MAX_COLLECT_ITEMS] = getGlobalNumber(L, "rewardChestMaxCollectItems", 200);
+ loadBoolConfig(L, VIP_SYSTEM_ENABLED, "vipSystemEnabled", false);
+ loadIntConfig(L, VIP_BONUS_EXP, "vipBonusExp", 0);
+ loadIntConfig(L, VIP_BONUS_LOOT, "vipBonusLoot", 0);
+ loadIntConfig(L, VIP_BONUS_SKILL, "vipBonusSkill", 0);
+ loadBoolConfig(L, VIP_AUTOLOOT_VIP_ONLY, "vipAutoLootVipOnly", false);
+ loadBoolConfig(L, VIP_KEEP_HOUSE, "vipKeepHouse", false);
+ loadBoolConfig(L, VIP_STAY_ONLINE, "vipStayOnline", false);
+ loadIntConfig(L, VIP_FAMILIAR_TIME_COOLDOWN_REDUCTION, "vipFamiliarTimeCooldownReduction", 0);
+
+ loadBoolConfig(L, REWARD_CHEST_COLLECT_ENABLED, "rewardChestCollectEnabled", true);
+ loadIntConfig(L, REWARD_CHEST_MAX_COLLECT_ITEMS, "rewardChestMaxCollectItems", 200);
// PVP System
- floating[PVP_RATE_DAMAGE_TAKEN_PER_LEVEL] = getGlobalFloat(L, "pvpRateDamageTakenPerLevel", 0.0);
- floating[PVP_RATE_DAMAGE_REDUCTION_PER_LEVEL] = getGlobalFloat(L, "pvpRateDamageReductionPerLevel", 0.0);
- integer[PVP_MAX_LEVEL_DIFFERENCE] = getGlobalNumber(L, "pvpMaxLevelDifference", 0);
+ loadFloatConfig(L, PVP_RATE_DAMAGE_TAKEN_PER_LEVEL, "pvpRateDamageTakenPerLevel", 0.0);
+ loadFloatConfig(L, PVP_RATE_DAMAGE_REDUCTION_PER_LEVEL, "pvpRateDamageReductionPerLevel", 0.0);
+ loadIntConfig(L, PVP_MAX_LEVEL_DIFFERENCE, "pvpMaxLevelDifference", 0);
- boolean[TOGGLE_MOUNT_IN_PZ] = getGlobalBoolean(L, "toggleMountInProtectionZone", false);
+ loadBoolConfig(L, TOGGLE_MOUNT_IN_PZ, "toggleMountInProtectionZone", false);
- boolean[TOGGLE_HOUSE_TRANSFER_ON_SERVER_RESTART] = getGlobalBoolean(L, "togglehouseTransferOnRestart", false);
+ loadBoolConfig(L, TOGGLE_HOUSE_TRANSFER_ON_SERVER_RESTART, "togglehouseTransferOnRestart", false);
- boolean[TOGGLE_RECEIVE_REWARD] = getGlobalBoolean(L, "toggleReceiveReward", false);
+ loadBoolConfig(L, TOGGLE_RECEIVE_REWARD, "toggleReceiveReward", false);
loaded = true;
lua_close(L);
@@ -407,51 +353,86 @@ bool ConfigManager::load() {
}
bool ConfigManager::reload() {
- bool result = load();
+ const bool result = load();
if (transformToSHA1(getString(SERVER_MOTD)) != g_game().getMotdHash()) {
g_game().incrementMotdNum();
}
return result;
}
-static std::string dummyStr;
+std::string ConfigManager::loadStringConfig(lua_State* L, const ConfigKey_t &key, const char* identifier, const std::string &defaultValue) {
+ std::string value = defaultValue;
+ lua_getglobal(L, identifier);
+ if (lua_isstring(L, -1)) {
+ value = lua_tostring(L, -1);
+ }
+ configs[key] = value;
+ lua_pop(L, 1);
+ return value;
+}
-const std::string &ConfigManager::getString(stringConfig_t what) const {
- if (what >= LAST_STRING_CONFIG) {
- g_logger().warn("[ConfigManager::getString] - Accessing invalid index: {}", fmt::underlying(what));
- return dummyStr;
+int32_t ConfigManager::loadIntConfig(lua_State* L, const ConfigKey_t &key, const char* identifier, const int32_t &defaultValue) {
+ int32_t value = defaultValue;
+ lua_getglobal(L, identifier);
+ if (lua_isnumber(L, -1)) {
+ value = static_cast(lua_tointeger(L, -1));
}
- return string[what];
+ configs[key] = value;
+ lua_pop(L, 1);
+ return value;
}
-int32_t ConfigManager::getNumber(integerConfig_t what) const {
- if (what >= LAST_INTEGER_CONFIG) {
- g_logger().warn("[ConfigManager::getNumber] - Accessing invalid index: {}", fmt::underlying(what));
- return 0;
+bool ConfigManager::loadBoolConfig(lua_State* L, const ConfigKey_t &key, const char* identifier, const bool &defaultValue) {
+ bool value = defaultValue;
+ lua_getglobal(L, identifier);
+ if (lua_isboolean(L, -1)) {
+ value = static_cast(lua_toboolean(L, -1));
}
- return integer[what];
+ configs[key] = value;
+ lua_pop(L, 1);
+ return value;
}
-int16_t ConfigManager::getShortNumber(integerConfig_t what) const {
- if (what >= LAST_INTEGER_CONFIG) {
- g_logger().warn("[ConfigManager::getShortNumber] - Accessing invalid index: {}", fmt::underlying(what));
- return 0;
+float ConfigManager::loadFloatConfig(lua_State* L, const ConfigKey_t &key, const char* identifier, const float &defaultValue) {
+ float value = defaultValue;
+ lua_getglobal(L, identifier);
+ if (lua_isnumber(L, -1)) {
+ value = static_cast(lua_tonumber(L, -1));
}
- return integer[what];
+ configs[key] = value;
+ lua_pop(L, 1);
+ return value;
}
-bool ConfigManager::getBoolean(booleanConfig_t what) const {
- if (what >= LAST_BOOLEAN_CONFIG) {
- g_logger().warn("[ConfigManager::getBoolean] - Accessing invalid index: {}", fmt::underlying(what));
- return false;
+const std::string &ConfigManager::getString(const ConfigKey_t &key) const {
+ static const std::string dummyStr;
+ if (configs.contains(key) && std::holds_alternative(configs.at(key))) {
+ return std::get(configs.at(key));
+ }
+ g_logger().warn("[ConfigManager::getString] - Accessing invalid or wrong type index: {}", fmt::underlying(key));
+ return dummyStr;
+}
+
+int32_t ConfigManager::getNumber(const ConfigKey_t &key) const {
+ if (configs.contains(key) && std::holds_alternative(configs.at(key))) {
+ return std::get(configs.at(key));
+ }
+ g_logger().warn("[ConfigManager::getNumber] - Accessing invalid or wrong type index: {}", fmt::underlying(key));
+ return 0;
+}
+
+bool ConfigManager::getBoolean(const ConfigKey_t &key) const {
+ if (configs.contains(key) && std::holds_alternative(configs.at(key))) {
+ return std::get(configs.at(key));
}
- return boolean[what];
+ g_logger().warn("[ConfigManager::getBoolean] - Accessing invalid or wrong type index: {}", fmt::underlying(key));
+ return false;
}
-float ConfigManager::getFloat(floatingConfig_t what) const {
- if (what >= LAST_FLOATING_CONFIG) {
- g_logger().warn("[ConfigManager::getFLoat] - Accessing invalid index: {}", fmt::underlying(what));
- return 0;
+float ConfigManager::getFloat(const ConfigKey_t &key) const {
+ if (configs.contains(key) && std::holds_alternative(configs.at(key))) {
+ return std::get(configs.at(key));
}
- return floating[what];
+ g_logger().warn("[ConfigManager::getFloat] - Accessing invalid or wrong type index: {}", fmt::underlying(key));
+ return 0.0f;
}
diff --git a/src/config/configmanager.hpp b/src/config/configmanager.hpp
index 21e42f9e768..39d88a046f2 100644
--- a/src/config/configmanager.hpp
+++ b/src/config/configmanager.hpp
@@ -12,6 +12,8 @@
#include "declarations.hpp"
#include "lib/di/container.hpp"
+using ConfigValue = std::variant;
+
class ConfigManager {
public:
ConfigManager() = default;
@@ -27,28 +29,27 @@ class ConfigManager {
bool load();
bool reload();
- const std::string &getString(stringConfig_t what) const;
- int32_t getNumber(integerConfig_t what) const;
- int16_t getShortNumber(integerConfig_t what) const;
- bool getBoolean(booleanConfig_t what) const;
- float getFloat(floatingConfig_t what) const;
-
const std::string &setConfigFileLua(const std::string &what) {
configFileLua = { what };
return configFileLua;
};
- const std::string &getConfigFileLua() const {
+ [[nodiscard]] const std::string &getConfigFileLua() const {
return configFileLua;
};
-private:
- std::string configFileLua = { "config.lua" };
+ [[nodiscard]] const std::string &getString(const ConfigKey_t &key) const;
+ [[nodiscard]] int32_t getNumber(const ConfigKey_t &key) const;
+ [[nodiscard]] bool getBoolean(const ConfigKey_t &key) const;
+ [[nodiscard]] float getFloat(const ConfigKey_t &key) const;
- std::string string[LAST_STRING_CONFIG] = {};
- int32_t integer[LAST_INTEGER_CONFIG] = {};
- bool boolean[LAST_BOOLEAN_CONFIG] = {};
- float floating[LAST_FLOATING_CONFIG] = {};
+private:
+ phmap::flat_hash_map configs;
+ std::string loadStringConfig(lua_State* L, const ConfigKey_t &key, const char* identifier, const std::string &defaultValue);
+ int32_t loadIntConfig(lua_State* L, const ConfigKey_t &key, const char* identifier, const int32_t &defaultValue);
+ bool loadBoolConfig(lua_State* L, const ConfigKey_t &key, const char* identifier, const bool &defaultValue);
+ float loadFloatConfig(lua_State* L, const ConfigKey_t &key, const char* identifier, const float &defaultValue);
+ std::string configFileLua = { "config.lua" };
bool loaded = false;
};
diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp
index 9a80ad55ce3..2a646be071c 100644
--- a/src/creatures/combat/combat.cpp
+++ b/src/creatures/combat/combat.cpp
@@ -297,19 +297,20 @@ ReturnValue Combat::canDoCombat(std::shared_ptr attacker, std::shared_
return RETURNVALUE_NOERROR;
}
+ auto targetPlayer = target ? target->getPlayer() : nullptr;
if (target) {
std::shared_ptr tile = target->getTile();
if (tile->hasProperty(CONST_PROP_BLOCKPROJECTILE)) {
return RETURNVALUE_NOTENOUGHROOM;
}
if (tile->hasFlag(TILESTATE_PROTECTIONZONE)) {
- return RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE;
+ auto permittedOnPz = targetPlayer ? targetPlayer->hasPermittedConditionInPZ() : false;
+ return permittedOnPz ? RETURNVALUE_NOERROR : RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE;
}
}
if (attacker) {
const std::shared_ptr attackerMaster = attacker->getMaster();
- auto targetPlayer = target ? target->getPlayer() : nullptr;
if (targetPlayer) {
if (targetPlayer->hasFlag(PlayerFlags_t::CannotBeAttacked)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER;
diff --git a/src/creatures/creature.cpp b/src/creatures/creature.cpp
index 46804d6b51b..4d9894772f0 100644
--- a/src/creatures/creature.cpp
+++ b/src/creatures/creature.cpp
@@ -754,7 +754,7 @@ bool Creature::dropCorpse(std::shared_ptr lastHitCreature, std::shared
auto monster = getMonster();
if (monster && !monster->isRewardBoss()) {
std::ostringstream lootMessage;
- lootMessage << "Loot of " << getNameDescription() << ": " << corpse->getContainer()->getContentDescription(player->getProtocolVersion() < 1200);
+ lootMessage << "Loot of " << getNameDescription() << ": " << corpse->getContainer()->getContentDescription(player->getProtocolVersion() < 1200) << ".";
auto suffix = corpse->getContainer()->getAttribute(ItemAttribute_t::LOOTMESSAGE_SUFFIX);
if (!suffix.empty()) {
lootMessage << suffix;
diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp
index b2660933a27..0446addb0c6 100644
--- a/src/creatures/monsters/monster.cpp
+++ b/src/creatures/monsters/monster.cpp
@@ -773,7 +773,9 @@ void Monster::onThink(uint32_t interval) {
}
} else if (!targetList.empty()) {
const bool attackedCreatureIsDisconnected = attackedCreature && attackedCreature->getPlayer() && attackedCreature->getPlayer()->isDisconnected();
- if (!attackedCreature || attackedCreatureIsDisconnected) {
+ const bool attackedCreatureIsUnattackable = attackedCreature && !canUseAttack(getPosition(), attackedCreature);
+ const bool attackedCreatureIsUnreachable = targetDistance <= 1 && attackedCreature && followCreature && !hasFollowPath;
+ if (!attackedCreature || attackedCreatureIsDisconnected || attackedCreatureIsUnattackable || attackedCreatureIsUnreachable) {
if (!followCreature || !hasFollowPath || attackedCreatureIsDisconnected) {
searchTarget(TARGETSEARCH_NEAREST);
} else if (attackedCreature && isFleeing() && !canUseAttack(getPosition(), attackedCreature)) {
diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp
index 9002feea81f..f63d3799918 100644
--- a/src/creatures/players/player.cpp
+++ b/src/creatures/players/player.cpp
@@ -6722,6 +6722,10 @@ std::pair>, std::mapisStoreItem()) {
+ continue;
+ }
+
const ItemType &itemType = Item::items[item->getID()];
if (itemType.wareId == 0) {
continue;
@@ -7712,3 +7716,24 @@ std::shared_ptr Player::getLootPouch() {
return container;
}
+
+bool Player::hasPermittedConditionInPZ() const {
+ static const std::unordered_set allowedConditions = {
+ CONDITION_ENERGY,
+ CONDITION_FIRE,
+ CONDITION_POISON,
+ CONDITION_BLEEDING,
+ CONDITION_CURSED,
+ CONDITION_DAZZLED
+ };
+
+ bool hasPermittedCondition = false;
+ for (auto condition : allowedConditions) {
+ if (getCondition(condition)) {
+ hasPermittedCondition = true;
+ break;
+ }
+ }
+
+ return hasPermittedCondition;
+}
diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp
index 5000f1ccf6e..9757717e675 100644
--- a/src/creatures/players/player.hpp
+++ b/src/creatures/players/player.hpp
@@ -344,6 +344,10 @@ class Player final : public Creature, public Cylinder, public Bankable {
operatingSystem = clientos;
}
+ bool isOldProtocol() {
+ return client && client->oldProtocol;
+ }
+
uint32_t getProtocolVersion() const {
if (!client) {
return 0;
@@ -2544,6 +2548,8 @@ class Player final : public Creature, public Cylinder, public Bankable {
std::shared_ptr getLootPouch();
+ bool hasPermittedConditionInPZ() const;
+
private:
friend class PlayerLock;
std::mutex mutex;
diff --git a/src/game/game.cpp b/src/game/game.cpp
index 0ff4a08e6e3..8b2489c3df6 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -1625,6 +1625,10 @@ ReturnValue Game::checkMoveItemToCylinder(std::shared_ptr player, std::s
isValidMoveItem = true;
}
+ if (item->getID() == ITEM_GOLD_POUCH) {
+ isValidMoveItem = true;
+ }
+
if (!isValidMoveItem) {
return RETURNVALUE_NOTPOSSIBLE;
}
@@ -4214,6 +4218,8 @@ void Game::playerStashWithdraw(uint32_t playerId, uint16_t itemId, uint32_t coun
if (player->isDepotSearchOpenOnItem(itemId)) {
player->requestDepotSearchItem(itemId, 0);
}
+
+ player->sendOpenStash(true);
}
void Game::playerSeekInContainer(uint32_t playerId, uint8_t containerId, uint16_t index, uint8_t containerCategory) {
diff --git a/src/game/scheduling/dispatcher.cpp b/src/game/scheduling/dispatcher.cpp
index a24ef770466..fff897def89 100644
--- a/src/game/scheduling/dispatcher.cpp
+++ b/src/game/scheduling/dispatcher.cpp
@@ -21,13 +21,13 @@ Dispatcher &Dispatcher::getInstance() {
}
void Dispatcher::init() {
- updateClock();
+ UPDATE_OTSYS_TIME();
threadPool.addLoad([this] {
std::unique_lock asyncLock(dummyMutex);
while (!threadPool.getIoContext().stopped()) {
- updateClock();
+ UPDATE_OTSYS_TIME();
executeEvents();
executeScheduledEvents();
@@ -104,7 +104,7 @@ void Dispatcher::executeScheduledEvents() {
auto it = scheduledTasks.begin();
while (it != scheduledTasks.end()) {
const auto &task = *it;
- if (task->getTime() > Task::TIME_NOW) {
+ if (task->getTime() > OTSYS_TIME()) {
break;
}
@@ -168,17 +168,17 @@ void Dispatcher::mergeEvents() {
checkPendingTasks();
}
-std::chrono::nanoseconds Dispatcher::timeUntilNextScheduledTask() const {
- static constexpr auto CHRONO_NANO_0 = std::chrono::nanoseconds(0);
- static constexpr auto CHRONO_MILI_MAX = std::chrono::milliseconds::max();
+std::chrono::milliseconds Dispatcher::timeUntilNextScheduledTask() const {
+ constexpr auto CHRONO_0 = std::chrono::milliseconds(0);
+ constexpr auto CHRONO_MILI_MAX = std::chrono::milliseconds::max();
if (scheduledTasks.empty()) {
return CHRONO_MILI_MAX;
}
const auto &task = *scheduledTasks.begin();
- const auto timeRemaining = task->getTime() - Task::TIME_NOW;
- return std::max(timeRemaining, CHRONO_NANO_0);
+ const auto timeRemaining = std::chrono::milliseconds(task->getTime() - OTSYS_TIME());
+ return std::max(timeRemaining, CHRONO_0);
}
void Dispatcher::addEvent(std::function &&f, std::string_view context, uint32_t expiresAfterMs) {
diff --git a/src/game/scheduling/dispatcher.hpp b/src/game/scheduling/dispatcher.hpp
index 9d0a5c51750..1c5f72658c1 100644
--- a/src/game/scheduling/dispatcher.hpp
+++ b/src/game/scheduling/dispatcher.hpp
@@ -32,7 +32,7 @@ enum class DispatcherType : uint8_t {
struct DispatcherContext {
bool isOn() const {
- return Task::TIME_NOW != SYSTEM_TIME_ZERO;
+ return OTSYS_TIME() != 0;
}
bool isGroup(const TaskGroup _group) const {
@@ -134,11 +134,6 @@ class Dispatcher {
private:
thread_local static DispatcherContext dispacherContext;
- // Update Time Cache
- static void updateClock() {
- Task::TIME_NOW = std::chrono::system_clock::now();
- }
-
const auto &getThreadTask() const {
return threads[ThreadPool::getThreadId()];
}
@@ -159,7 +154,7 @@ class Dispatcher {
inline void executeSerialEvents(std::vector &tasks);
inline void executeParallelEvents(std::vector &tasks, const uint8_t groupId);
- inline std::chrono::nanoseconds timeUntilNextScheduledTask() const;
+ inline std::chrono::milliseconds timeUntilNextScheduledTask() const;
inline void checkPendingTasks() {
hasPendingTasks = false;
diff --git a/src/game/scheduling/task.cpp b/src/game/scheduling/task.cpp
index c9e6157ab9e..28418a4a169 100644
--- a/src/game/scheduling/task.cpp
+++ b/src/game/scheduling/task.cpp
@@ -10,8 +10,6 @@
#include "pch.hpp"
#include "task.hpp"
#include "lib/logging/log_with_spd_log.hpp"
-
-std::chrono::system_clock::time_point Task::TIME_NOW = SYSTEM_TIME_ZERO;
std::atomic_uint_fast64_t Task::LAST_EVENT_ID = 0;
bool Task::execute() const {
diff --git a/src/game/scheduling/task.hpp b/src/game/scheduling/task.hpp
index f42602242c5..18dfd5d39de 100644
--- a/src/game/scheduling/task.hpp
+++ b/src/game/scheduling/task.hpp
@@ -11,19 +11,15 @@
#include "utils/tools.hpp"
#include
-static constexpr auto SYSTEM_TIME_ZERO = std::chrono::system_clock::time_point(std::chrono::milliseconds(0));
-
class Task {
public:
- static std::chrono::system_clock::time_point TIME_NOW;
-
Task(uint32_t expiresAfterMs, std::function &&f, std::string_view context) :
- func(std::move(f)), context(context), utime(TIME_NOW), expiration(expiresAfterMs > 0 ? TIME_NOW + std::chrono::milliseconds(expiresAfterMs) : SYSTEM_TIME_ZERO) {
+ func(std::move(f)), context(context), utime(OTSYS_TIME()), expiration(expiresAfterMs > 0 ? OTSYS_TIME() + expiresAfterMs : 0) {
assert(!this->context.empty() && "Context cannot be empty!");
}
Task(std::function &&f, std::string_view context, uint32_t delay, bool cycle = false, bool log = true) :
- func(std::move(f)), context(context), utime(TIME_NOW + std::chrono::milliseconds(delay)), delay(delay), cycle(cycle), log(log) {
+ func(std::move(f)), context(context), utime(OTSYS_TIME() + delay), delay(delay), cycle(cycle), log(log) {
assert(!this->context.empty() && "Context cannot be empty!");
}
@@ -54,7 +50,7 @@ class Task {
}
bool hasExpired() const {
- return expiration != SYSTEM_TIME_ZERO && expiration < TIME_NOW;
+ return expiration != 0 && expiration < OTSYS_TIME();
}
bool isCycle() const {
@@ -75,7 +71,7 @@ class Task {
static std::atomic_uint_fast64_t LAST_EVENT_ID;
void updateTime() {
- utime = TIME_NOW + std::chrono::milliseconds(delay);
+ utime = OTSYS_TIME() + delay;
}
bool hasTraceableContext() const {
@@ -117,8 +113,8 @@ class Task {
std::function func = nullptr;
std::string_view context;
- std::chrono::system_clock::time_point utime = SYSTEM_TIME_ZERO;
- std::chrono::system_clock::time_point expiration = SYSTEM_TIME_ZERO;
+ int64_t utime = 0;
+ int64_t expiration = 0;
uint64_t id = 0;
uint32_t delay = 0;
diff --git a/src/lua/functions/core/game/config_functions.cpp b/src/lua/functions/core/game/config_functions.cpp
index bdeaa226fc1..dae41773882 100644
--- a/src/lua/functions/core/game/config_functions.cpp
+++ b/src/lua/functions/core/game/config_functions.cpp
@@ -14,264 +14,44 @@
void ConfigFunctions::init(lua_State* L) {
registerTable(L, "configManager");
- registerMethod(L, "configManager", "getString", ConfigFunctions::luaConfigManagerGetString);
- registerMethod(L, "configManager", "getNumber", ConfigFunctions::luaConfigManagerGetNumber);
- registerMethod(L, "configManager", "getBoolean", ConfigFunctions::luaConfigManagerGetBoolean);
- registerMethod(L, "configManager", "getFloat", ConfigFunctions::luaConfigManagerGetFloat);
-
-#define registerEnumIn(L, tableName, value) \
- do { \
- std::string enumName = #value; \
- registerVariable(L, tableName, enumName.substr(enumName.find_last_of(':') + 1), value); \
+ registerMethod(L, "configManager", "getString", luaConfigManagerGetString);
+ registerMethod(L, "configManager", "getNumber", luaConfigManagerGetNumber);
+ registerMethod(L, "configManager", "getBoolean", luaConfigManagerGetBoolean);
+ registerMethod(L, "configManager", "getFloat", luaConfigManagerGetFloat);
+
+#define registerMagicEnumIn(L, tableName, enumValue) \
+ do { \
+ auto number = magic_enum::enum_integer(enumValue); \
+ auto name = magic_enum::enum_name(enumValue).data(); \
+ registerVariable(L, tableName, name, value); \
} while (0)
registerTable(L, "configKeys");
- registerEnumIn(L, "configKeys", ALLOW_CHANGEOUTFIT);
- registerEnumIn(L, "configKeys", ONE_PLAYER_ON_ACCOUNT);
- registerEnumIn(L, "configKeys", AIMBOT_HOTKEY_ENABLED);
- registerEnumIn(L, "configKeys", REMOVE_RUNE_CHARGES);
- registerEnumIn(L, "configKeys", EXPERIENCE_FROM_PLAYERS);
- registerEnumIn(L, "configKeys", FREE_PREMIUM);
- registerEnumIn(L, "configKeys", REPLACE_KICK_ON_LOGIN);
- registerEnumIn(L, "configKeys", BIND_ONLY_GLOBAL_ADDRESS);
- registerEnumIn(L, "configKeys", OPTIMIZE_DATABASE);
- registerEnumIn(L, "configKeys", MARKET_PREMIUM);
- registerEnumIn(L, "configKeys", EMOTE_SPELLS);
- registerEnumIn(L, "configKeys", STAMINA_SYSTEM);
- registerEnumIn(L, "configKeys", WARN_UNSAFE_SCRIPTS);
- registerEnumIn(L, "configKeys", CONVERT_UNSAFE_SCRIPTS);
- registerEnumIn(L, "configKeys", ALLOW_BLOCK_SPAWN);
- registerEnumIn(L, "configKeys", CLASSIC_ATTACK_SPEED);
- registerEnumIn(L, "configKeys", REMOVE_WEAPON_AMMO);
- registerEnumIn(L, "configKeys", REMOVE_WEAPON_CHARGES);
- registerEnumIn(L, "configKeys", REMOVE_POTION_CHARGES);
- registerEnumIn(L, "configKeys", WEATHER_RAIN);
- registerEnumIn(L, "configKeys", ALLOW_RELOAD);
- registerEnumIn(L, "configKeys", WEATHER_THUNDER);
- registerEnumIn(L, "configKeys", TOGGLE_FREE_QUEST);
- registerEnumIn(L, "configKeys", FREE_QUEST_STAGE);
- registerEnumIn(L, "configKeys", ALL_CONSOLE_LOG);
- registerEnumIn(L, "configKeys", GLOBAL_SERVER_SAVE_NOTIFY_MESSAGE);
- registerEnumIn(L, "configKeys", GLOBAL_SERVER_SAVE_NOTIFY_DURATION);
- registerEnumIn(L, "configKeys", XP_DISPLAY_MODE);
- registerEnumIn(L, "configKeys", GLOBAL_SERVER_SAVE_CLEAN_MAP);
- registerEnumIn(L, "configKeys", GLOBAL_SERVER_SAVE_CLOSE);
- registerEnumIn(L, "configKeys", GLOBAL_SERVER_SAVE_SHUTDOWN);
- registerEnumIn(L, "configKeys", MAP_NAME);
- registerEnumIn(L, "configKeys", TOGGLE_MAP_CUSTOM);
- registerEnumIn(L, "configKeys", MAP_CUSTOM_NAME);
- registerEnumIn(L, "configKeys", HOUSE_RENT_PERIOD);
- registerEnumIn(L, "configKeys", SERVER_NAME);
- registerEnumIn(L, "configKeys", SERVER_MOTD);
- registerEnumIn(L, "configKeys", OWNER_NAME);
- registerEnumIn(L, "configKeys", OWNER_EMAIL);
- registerEnumIn(L, "configKeys", URL);
- registerEnumIn(L, "configKeys", LOCATION);
- registerEnumIn(L, "configKeys", IP);
- registerEnumIn(L, "configKeys", WORLD_TYPE);
- registerEnumIn(L, "configKeys", MYSQL_HOST);
- registerEnumIn(L, "configKeys", MYSQL_USER);
- registerEnumIn(L, "configKeys", MYSQL_PASS);
- registerEnumIn(L, "configKeys", MYSQL_DB);
- registerEnumIn(L, "configKeys", MYSQL_SOCK);
- registerEnumIn(L, "configKeys", DEFAULT_PRIORITY);
- registerEnumIn(L, "configKeys", MAP_AUTHOR);
- registerEnumIn(L, "configKeys", STORE_IMAGES_URL);
- registerEnumIn(L, "configKeys", PARTY_LIST_MAX_DISTANCE);
- registerEnumIn(L, "configKeys", SQL_PORT);
- registerEnumIn(L, "configKeys", MAX_PLAYERS);
- registerEnumIn(L, "configKeys", PZ_LOCKED);
- registerEnumIn(L, "configKeys", DEFAULT_DESPAWNRANGE);
- registerEnumIn(L, "configKeys", PREY_ENABLED);
- registerEnumIn(L, "configKeys", PREY_FREE_THIRD_SLOT);
- registerEnumIn(L, "configKeys", PREY_REROLL_PRICE_LEVEL);
- registerEnumIn(L, "configKeys", PREY_BONUS_TIME);
- registerEnumIn(L, "configKeys", PREY_BONUS_REROLL_PRICE);
- registerEnumIn(L, "configKeys", PREY_FREE_REROLL_TIME);
- registerEnumIn(L, "configKeys", TASK_HUNTING_ENABLED);
- registerEnumIn(L, "configKeys", TASK_HUNTING_FREE_THIRD_SLOT);
- registerEnumIn(L, "configKeys", TASK_HUNTING_LIMIT_EXHAUST);
- registerEnumIn(L, "configKeys", TASK_HUNTING_REROLL_PRICE_LEVEL);
- registerEnumIn(L, "configKeys", TASK_HUNTING_SELECTION_LIST_PRICE);
- registerEnumIn(L, "configKeys", TASK_HUNTING_BONUS_REROLL_PRICE);
- registerEnumIn(L, "configKeys", TASK_HUNTING_FREE_REROLL_TIME);
- registerEnumIn(L, "configKeys", DEFAULT_DESPAWNRADIUS);
- registerEnumIn(L, "configKeys", RATE_EXPERIENCE);
- registerEnumIn(L, "configKeys", RATE_SKILL);
- registerEnumIn(L, "configKeys", RATE_LOOT);
- registerEnumIn(L, "configKeys", RATE_MAGIC);
- registerEnumIn(L, "configKeys", RATE_SPAWN);
- registerEnumIn(L, "configKeys", RATE_KILLING_IN_THE_NAME_OF_POINTS);
- registerEnumIn(L, "configKeys", HOUSE_PRICE_PER_SQM);
- registerEnumIn(L, "configKeys", HOUSE_BUY_LEVEL);
- registerEnumIn(L, "configKeys", MAX_MESSAGEBUFFER);
- registerEnumIn(L, "configKeys", ACTIONS_DELAY_INTERVAL);
- registerEnumIn(L, "configKeys", EX_ACTIONS_DELAY_INTERVAL);
- registerEnumIn(L, "configKeys", KICK_AFTER_MINUTES);
- registerEnumIn(L, "configKeys", PROTECTION_LEVEL);
- registerEnumIn(L, "configKeys", DEATH_LOSE_PERCENT);
- registerEnumIn(L, "configKeys", STATUSQUERY_TIMEOUT);
- registerEnumIn(L, "configKeys", FRAG_TIME);
- registerEnumIn(L, "configKeys", WHITE_SKULL_TIME);
- registerEnumIn(L, "configKeys", GAME_PORT);
- registerEnumIn(L, "configKeys", LOGIN_PORT);
- registerEnumIn(L, "configKeys", STATUS_PORT);
- registerEnumIn(L, "configKeys", STAIRHOP_DELAY);
- registerEnumIn(L, "configKeys", MARKET_OFFER_DURATION);
- registerEnumIn(L, "configKeys", CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES);
- registerEnumIn(L, "configKeys", MAX_MARKET_OFFERS_AT_A_TIME_PER_PLAYER);
- registerEnumIn(L, "configKeys", EXP_FROM_PLAYERS_LEVEL_RANGE);
- registerEnumIn(L, "configKeys", MAX_PACKETS_PER_SECOND);
- registerEnumIn(L, "configKeys", STORE_COIN_PACKET);
- registerEnumIn(L, "configKeys", DAY_KILLS_TO_RED);
- registerEnumIn(L, "configKeys", WEEK_KILLS_TO_RED);
- registerEnumIn(L, "configKeys", MONTH_KILLS_TO_RED);
- registerEnumIn(L, "configKeys", RED_SKULL_DURATION);
- registerEnumIn(L, "configKeys", BLACK_SKULL_DURATION);
- registerEnumIn(L, "configKeys", ORANGE_SKULL_DURATION);
- registerEnumIn(L, "configKeys", RATE_MONSTER_HEALTH);
- registerEnumIn(L, "configKeys", RATE_MONSTER_ATTACK);
- registerEnumIn(L, "configKeys", RATE_MONSTER_DEFENSE);
- registerEnumIn(L, "configKeys", RATE_BOSS_HEALTH);
- registerEnumIn(L, "configKeys", RATE_BOSS_ATTACK);
- registerEnumIn(L, "configKeys", RATE_BOSS_DEFENSE);
- registerEnumIn(L, "configKeys", BOSS_DEFAULT_TIME_TO_FIGHT_AGAIN);
- registerEnumIn(L, "configKeys", BOSS_DEFAULT_TIME_TO_DEFEAT);
- registerEnumIn(L, "configKeys", RATE_NPC_HEALTH);
- registerEnumIn(L, "configKeys", RATE_NPC_ATTACK);
- registerEnumIn(L, "configKeys", RATE_NPC_DEFENSE);
-
- registerEnumIn(L, "configKeys", RATE_HEALTH_REGEN);
- registerEnumIn(L, "configKeys", RATE_HEALTH_REGEN_SPEED);
- registerEnumIn(L, "configKeys", RATE_MANA_REGEN);
- registerEnumIn(L, "configKeys", RATE_MANA_REGEN_SPEED);
- registerEnumIn(L, "configKeys", RATE_SOUL_REGEN);
- registerEnumIn(L, "configKeys", RATE_SOUL_REGEN_SPEED);
-
- registerEnumIn(L, "configKeys", RATE_SPELL_COOLDOWN);
- registerEnumIn(L, "configKeys", RATE_ATTACK_SPEED);
- registerEnumIn(L, "configKeys", RATE_OFFLINE_TRAINING_SPEED);
- registerEnumIn(L, "configKeys", RATE_EXERCISE_TRAINING_SPEED);
-
- registerEnumIn(L, "configKeys", STAMINA_TRAINER);
- registerEnumIn(L, "configKeys", STAMINA_PZ);
- registerEnumIn(L, "configKeys", STAMINA_ORANGE_DELAY);
- registerEnumIn(L, "configKeys", STAMINA_GREEN_DELAY);
- registerEnumIn(L, "configKeys", STAMINA_TRAINER_DELAY);
- registerEnumIn(L, "configKeys", STAMINA_PZ_GAIN);
- registerEnumIn(L, "configKeys", STAMINA_TRAINER_GAIN);
- registerEnumIn(L, "configKeys", SORT_LOOT_BY_CHANCE);
- registerEnumIn(L, "configKeys", MAX_ALLOWED_ON_A_DUMMY);
-
- registerEnumIn(L, "configKeys", PUSH_WHEN_ATTACKING);
- registerEnumIn(L, "configKeys", TOGGLE_SAVE_INTERVAL);
- registerEnumIn(L, "configKeys", SAVE_INTERVAL_TYPE);
- registerEnumIn(L, "configKeys", TOGGLE_SAVE_INTERVAL_CLEAN_MAP);
- registerEnumIn(L, "configKeys", SAVE_INTERVAL_TIME);
- registerEnumIn(L, "configKeys", RATE_USE_STAGES);
- registerEnumIn(L, "configKeys", TOGGLE_IMBUEMENT_SHRINE_STORAGE);
- registerEnumIn(L, "configKeys", TOGGLE_IMBUEMENT_NON_AGGRESSIVE_FIGHT_ONLY);
- registerEnumIn(L, "configKeys", GLOBAL_SERVER_SAVE_TIME);
- registerEnumIn(L, "configKeys", DATA_DIRECTORY);
- registerEnumIn(L, "configKeys", CORE_DIRECTORY);
-
- registerEnumIn(L, "configKeys", FORGE_COST_ONE_SLIVER);
- registerEnumIn(L, "configKeys", FORGE_SLIVER_AMOUNT);
- registerEnumIn(L, "configKeys", FORGE_CORE_COST);
- registerEnumIn(L, "configKeys", FORGE_MAX_DUST);
- registerEnumIn(L, "configKeys", FORGE_FUSION_DUST_COST);
- registerEnumIn(L, "configKeys", FORGE_TRANSFER_DUST_COST);
- registerEnumIn(L, "configKeys", FORGE_BASE_SUCCESS_RATE);
- registerEnumIn(L, "configKeys", FORGE_BONUS_SUCCESS_RATE);
- registerEnumIn(L, "configKeys", FORGE_TIER_LOSS_REDUCTION);
- registerEnumIn(L, "configKeys", FORGE_AMOUNT_MULTIPLIER);
- registerEnumIn(L, "configKeys", FORGE_INFLUENCED_CREATURES_LIMIT);
-
- registerEnumIn(L, "configKeys", BESTIARY_KILL_MULTIPLIER);
- registerEnumIn(L, "configKeys", BOSSTIARY_KILL_MULTIPLIER);
- registerEnumIn(L, "configKeys", BOOSTED_BOSS_SLOT);
- registerEnumIn(L, "configKeys", BOOSTED_BOSS_LOOT_BONUS);
- registerEnumIn(L, "configKeys", BOOSTED_BOSS_KILL_BONUS);
- registerEnumIn(L, "configKeys", BESTIARY_RATE_CHARM_SHOP_PRICE);
-
- registerEnumIn(L, "configKeys", FAMILIAR_TIME);
-
- registerEnumIn(L, "configKeys", TOGGLE_GOLD_POUCH_ALLOW_ANYTHING);
- registerEnumIn(L, "configKeys", TOGGLE_SERVER_IS_RETRO);
- registerEnumIn(L, "configKeys", TOGGLE_TRAVELS_FREE);
- registerEnumIn(L, "configKeys", BUY_AOL_COMMAND_FEE);
- registerEnumIn(L, "configKeys", BUY_BLESS_COMMAND_FEE);
- registerEnumIn(L, "configKeys", TELEPORT_PLAYER_TO_VOCATION_ROOM);
-
- registerEnumIn(L, "configKeys", HAZARD_SPAWN_PLUNDER_MULTIPLIER);
- registerEnumIn(L, "configKeys", HAZARD_CRITICAL_INTERVAL);
- registerEnumIn(L, "configKeys", HAZARD_CRITICAL_CHANCE);
- registerEnumIn(L, "configKeys", HAZARD_CRITICAL_MULTIPLIER);
- registerEnumIn(L, "configKeys", HAZARD_DAMAGE_MULTIPLIER);
- registerEnumIn(L, "configKeys", HAZARD_DODGE_MULTIPLIER);
- registerEnumIn(L, "configKeys", HAZARD_PODS_DROP_MULTIPLIER);
- registerEnumIn(L, "configKeys", HAZARD_PODS_TIME_TO_DAMAGE);
- registerEnumIn(L, "configKeys", HAZARD_PODS_TIME_TO_SPAWN);
- registerEnumIn(L, "configKeys", HAZARD_EXP_BONUS_MULTIPLIER);
- registerEnumIn(L, "configKeys", HAZARD_LOOT_BONUS_MULTIPLIER);
- registerEnumIn(L, "configKeys", HAZARD_PODS_DAMAGE);
- registerEnumIn(L, "configKeys", TOGGLE_HAZARDSYSTEM);
- registerEnumIn(L, "configKeys", LOW_LEVEL_BONUS_EXP);
-
- registerEnumIn(L, "configKeys", LOYALTY_ENABLED);
- registerEnumIn(L, "configKeys", LOYALTY_POINTS_PER_CREATION_DAY);
- registerEnumIn(L, "configKeys", LOYALTY_POINTS_PER_PREMIUM_DAY_SPENT);
- registerEnumIn(L, "configKeys", LOYALTY_POINTS_PER_PREMIUM_DAY_PURCHASED);
- registerEnumIn(L, "configKeys", LOYALTY_BONUS_PERCENTAGE_MULTIPLIER);
-
- registerEnumIn(L, "configKeys", PARTY_SHARE_LOOT_BOOSTS);
- registerEnumIn(L, "configKeys", PARTY_SHARE_LOOT_BOOSTS_DIMINISHING_FACTOR);
- registerEnumIn(L, "configKeys", TIBIADROME_CONCOCTION_COOLDOWN);
- registerEnumIn(L, "configKeys", TIBIADROME_CONCOCTION_DURATION);
- registerEnumIn(L, "configKeys", TIBIADROME_CONCOCTION_TICK_TYPE);
-
- registerEnumIn(L, "configKeys", AUTH_TYPE);
- registerEnumIn(L, "configKeys", RESET_SESSIONS_ON_STARTUP);
-
- registerEnumIn(L, "configKeys", TOGGLE_ATTACK_SPEED_ONFIST);
- registerEnumIn(L, "configKeys", MULTIPLIER_ATTACKONFIST);
- registerEnumIn(L, "configKeys", MAX_SPEED_ATTACKONFIST);
-
- registerEnumIn(L, "configKeys", M_CONST);
- registerEnumIn(L, "configKeys", T_CONST);
- registerEnumIn(L, "configKeys", PARALLELISM);
-
- registerEnumIn(L, "configKeys", AUTOLOOT);
-
- registerEnumIn(L, "configKeys", VIP_SYSTEM_ENABLED);
- registerEnumIn(L, "configKeys", VIP_BONUS_EXP);
- registerEnumIn(L, "configKeys", VIP_BONUS_LOOT);
- registerEnumIn(L, "configKeys", VIP_BONUS_SKILL);
- registerEnumIn(L, "configKeys", VIP_AUTOLOOT_VIP_ONLY);
- registerEnumIn(L, "configKeys", VIP_STAY_ONLINE);
- registerEnumIn(L, "configKeys", VIP_FAMILIAR_TIME_COOLDOWN_REDUCTION);
-
- registerEnumIn(L, "configKeys", TOGGLE_HOUSE_TRANSFER_ON_SERVER_RESTART);
-
- registerEnumIn(L, "configKeys", TOGGLE_RECEIVE_REWARD);
-#undef registerEnumIn
+ for (auto value : magic_enum::enum_values()) {
+ auto enumName = magic_enum::enum_name(value).data();
+ if (enumName) {
+ registerMagicEnumIn(L, "configKeys", value);
+ g_logger().debug("Registering ConfigManager enum name '{}' value '{}' to lua", enumName, fmt::underlying(value));
+ }
+ }
+#undef registerMagicEnumIn
}
int ConfigFunctions::luaConfigManagerGetString(lua_State* L) {
- pushString(L, g_configManager().getString(getNumber(L, -1)));
+ pushString(L, g_configManager().getString(getNumber(L, -1)));
return 1;
}
int ConfigFunctions::luaConfigManagerGetNumber(lua_State* L) {
- lua_pushnumber(L, g_configManager().getNumber(getNumber(L, -1)));
+ lua_pushnumber(L, g_configManager().getNumber(getNumber(L, -1)));
return 1;
}
int ConfigFunctions::luaConfigManagerGetBoolean(lua_State* L) {
- pushBoolean(L, g_configManager().getBoolean(getNumber(L, -1)));
+ pushBoolean(L, g_configManager().getBoolean(getNumber(L, -1)));
return 1;
}
int ConfigFunctions::luaConfigManagerGetFloat(lua_State* L) {
- lua_pushnumber(L, g_configManager().getFloat(getNumber(L, -1)));
+ lua_pushnumber(L, g_configManager().getFloat(getNumber(L, -1)));
return 1;
}
diff --git a/src/lua/functions/core/game/lua_enums.cpp b/src/lua/functions/core/game/lua_enums.cpp
index f462aaae26a..5d566920c7b 100644
--- a/src/lua/functions/core/game/lua_enums.cpp
+++ b/src/lua/functions/core/game/lua_enums.cpp
@@ -18,7 +18,7 @@
#include "declarations.hpp"
#include "game/functions/game_reload.hpp"
-#define registerEnumClass(luaState, enumClassType) \
+#define registerMagicEnum(luaState, enumClassType) \
{ \
auto number = magic_enum::enum_integer(enumClassType); \
auto name = magic_enum::enum_name(enumClassType).data(); \
@@ -26,7 +26,7 @@
} \
void(0)
-#define registerEnumClassNamespace(luaState, luaNamespace, enumClassType) \
+#define registerMagicEnumNamespace(luaState, luaNamespace, enumClassType) \
{ \
auto number = magic_enum::enum_integer(enumClassType); \
auto name = std::string(luaNamespace) + magic_enum::enum_name(enumClassType).data(); \
@@ -277,7 +277,7 @@ void LuaEnums::initCombatEnums(lua_State* L) {
void LuaEnums::initCombatParamEnums(lua_State* L) {
for (auto value : magic_enum::enum_values()) {
- registerEnumClass(L, value);
+ registerMagicEnum(L, value);
}
}
@@ -443,7 +443,7 @@ void LuaEnums::initConditionParamEnums(lua_State* L) {
void LuaEnums::initAttributeConditionSubIdEnums(lua_State* L) {
std::string luaNamespace = "AttrSubId_";
for (auto value : magic_enum::enum_values()) {
- registerEnumClassNamespace(L, luaNamespace, value);
+ registerMagicEnumNamespace(L, luaNamespace, value);
}
}
@@ -849,7 +849,7 @@ void LuaEnums::initItemTypeEnums(lua_State* L) {
void LuaEnums::initFluidEnums(lua_State* L) {
for (auto value : magic_enum::enum_values()) {
- registerEnumClass(L, value);
+ registerMagicEnum(L, value);
}
}
@@ -920,22 +920,22 @@ void LuaEnums::initItemIdEnums(lua_State* L) {
void LuaEnums::initPlayerFlagEnums(lua_State* L) {
for (auto value : magic_enum::enum_values()) {
- registerEnumClass(L, value);
+ registerMagicEnum(L, value);
}
}
void LuaEnums::initCreatureIconEnums(lua_State* L) {
std::string luaNamespace = "CreatureIconCategory_";
for (auto value : magic_enum::enum_values()) {
- registerEnumClassNamespace(L, luaNamespace, value);
+ registerMagicEnumNamespace(L, luaNamespace, value);
}
luaNamespace = "CreatureIconModifications_";
for (auto value : magic_enum::enum_values()) {
- registerEnumClassNamespace(L, luaNamespace, value);
+ registerMagicEnumNamespace(L, luaNamespace, value);
}
luaNamespace = "CreatureIconQuests_";
for (auto value : magic_enum::enum_values()) {
- registerEnumClassNamespace(L, luaNamespace, value);
+ registerMagicEnumNamespace(L, luaNamespace, value);
}
}
@@ -1205,7 +1205,7 @@ void LuaEnums::initReturnValueEnums(lua_State* L) {
// Reload
void LuaEnums::initReloadTypeEnums(lua_State* L) {
for (auto value : magic_enum::enum_values()) {
- registerEnumClass(L, value);
+ registerMagicEnum(L, value);
}
}
@@ -1231,7 +1231,7 @@ void LuaEnums::initCreaturesEventEnums(lua_State* L) {
void LuaEnums::initForgeEnums(lua_State* L) {
for (auto value : magic_enum::enum_values()) {
- registerEnumClass(L, value);
+ registerMagicEnum(L, value);
}
}
@@ -1245,7 +1245,7 @@ void LuaEnums::initWebhookEnums(lua_State* L) {
void LuaEnums::initBosstiaryEnums(lua_State* L) {
for (auto value : magic_enum::enum_values()) {
- registerEnumClass(L, value);
+ registerMagicEnum(L, value);
}
}
@@ -1769,30 +1769,30 @@ void LuaEnums::initSoundEnums(lua_State* L) {
void LuaEnums::initWheelEnums(lua_State* L) {
std::string wheelNamespace = "WHEEL_INSTANT_";
for (auto value : magic_enum::enum_values()) {
- registerEnumClassNamespace(L, wheelNamespace, value);
+ registerMagicEnumNamespace(L, wheelNamespace, value);
}
wheelNamespace = "WHEEL_STAGE_";
for (auto value : magic_enum::enum_values()) {
- registerEnumClassNamespace(L, wheelNamespace, value);
+ registerMagicEnumNamespace(L, wheelNamespace, value);
}
wheelNamespace = "WHEEL_GRADE_";
for (auto value : magic_enum::enum_values()) {
- registerEnumClassNamespace(L, wheelNamespace, value);
+ registerMagicEnumNamespace(L, wheelNamespace, value);
}
wheelNamespace = "WHEEL_AVATAR_SKILL_";
for (auto value : magic_enum::enum_values()) {
- registerEnumClassNamespace(L, wheelNamespace, value);
+ registerMagicEnumNamespace(L, wheelNamespace, value);
}
wheelNamespace = "WHEEL_STAT_";
for (auto value : magic_enum::enum_values()) {
- registerEnumClassNamespace(L, wheelNamespace, value);
+ registerMagicEnumNamespace(L, wheelNamespace, value);
}
wheelNamespace = "WHEEL_BOOST_";
for (auto value : magic_enum::enum_values()) {
- registerEnumClassNamespace(L, wheelNamespace, value);
+ registerMagicEnumNamespace(L, wheelNamespace, value);
}
}
diff --git a/src/map/house/house.cpp b/src/map/house/house.cpp
index 20af6ee4042..828753b8c56 100644
--- a/src/map/house/house.cpp
+++ b/src/map/house/house.cpp
@@ -752,11 +752,6 @@ void Houses::payHouses(RentPeriod_t rentPeriod) const {
continue;
}
- const uint32_t rent = house->getRent();
- if (rent == 0 || house->getPaidUntil() > currentTime) {
- continue;
- }
-
const uint32_t ownerId = house->getOwner();
const auto &town = g_game().map.towns.getTown(house->getTownId());
if (!town) {
@@ -770,6 +765,27 @@ void Houses::payHouses(RentPeriod_t rentPeriod) const {
continue;
}
+ // Player hasn't logged in for a while, reset house owner
+ auto daysToReset = g_configManager().getNumber(HOUSE_LOSE_AFTER_INACTIVITY);
+ if (daysToReset > 0) {
+ auto daysSinceLastLogin = (currentTime - player->getLastLoginSaved()) / (60 * 60 * 24);
+ bool vipKeep = g_configManager().getBoolean(VIP_KEEP_HOUSE) && player->isVip();
+ bool activityKeep = daysSinceLastLogin < daysToReset;
+ if (vipKeep && !activityKeep) {
+ g_logger().info("Player {} has not logged in for {} days, but is a VIP, so the house will not be reset.", player->getName(), daysToReset);
+ } else if (!vipKeep && !activityKeep) {
+ g_logger().info("Player {} has not logged in for {} days, so the house will be reset.", player->getName(), daysToReset);
+ house->setOwner(0, true, player);
+ g_saveManager().savePlayer(player);
+ continue;
+ }
+ }
+
+ const uint32_t rent = house->getRent();
+ if (rent == 0 || house->getPaidUntil() > currentTime) {
+ continue;
+ }
+
if (player->getBankBalance() >= rent) {
g_game().removeMoney(player, rent, 0, true);
diff --git a/src/pch.hpp b/src/pch.hpp
index 0f5775b73d3..04f692a0bf1 100644
--- a/src/pch.hpp
+++ b/src/pch.hpp
@@ -95,7 +95,18 @@
#include "lua/global/shared_object.hpp"
-// Magic Enum
+/**
+ * @brief Magic Enum is a C++ library that facilitates easy conversion between enums and strings.
+ * By default, the range of supported enum values is from -128 to 128. We need extends that range.
+ *
+ * @def MAGIC_ENUM_RANGE_MIN
+ * @note Sets the lower limit of the enum value range to -500.
+ *
+ * @def MAGIC_ENUM_RANGE_MAX
+ * @note Sets the upper limit of the enum value range to 500.
+ */
+#define MAGIC_ENUM_RANGE_MIN -500
+#define MAGIC_ENUM_RANGE_MAX 500
#include
// Memory Mapped File
diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp
index dc6cea87b90..b9e6e673c10 100644
--- a/src/server/network/protocol/protocolgame.cpp
+++ b/src/server/network/protocol/protocolgame.cpp
@@ -469,6 +469,8 @@ void ProtocolGame::login(const std::string &name, uint32_t accountId, OperatingS
writeToOutputBuffer(opcodeMessage);
}
+ g_logger().debug("Player logging in in version '{}' and oldProtocol '{}'", getVersion(), oldProtocol);
+
// dispatcher thread
std::shared_ptr foundPlayer = g_game().getPlayerUniqueLogin(name);
if (!foundPlayer) {
@@ -734,6 +736,11 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) {
std::shared_ptr foundPlayer = g_game().getPlayerUniqueLogin(characterName);
if (foundPlayer && foundPlayer->client) {
+ if (foundPlayer->getProtocolVersion() != getVersion() && foundPlayer->isOldProtocol() != oldProtocol) {
+ disconnectClient(fmt::format("You are already logged in using protocol '{}'. Please log out from the other session to connect here.", foundPlayer->getProtocolVersion()));
+ return;
+ }
+
foundPlayer->client->disconnectClient("You are already connected through another client. Please use only one client at a time!");
}
@@ -6899,7 +6906,10 @@ void ProtocolGame::sendPreyData(const std::unique_ptr &slot) {
}
if (oldProtocol) {
- msg.add(static_cast(std::max(std::max(static_cast(((slot->freeRerollTimeStamp - OTSYS_TIME()) / 1000)), 0), 0)));
+ auto currentTime = OTSYS_TIME();
+ auto timeDiffMs = (slot->freeRerollTimeStamp > currentTime) ? (slot->freeRerollTimeStamp - currentTime) : 0;
+ auto timeDiffMinutes = timeDiffMs / 60000;
+ msg.add(timeDiffMinutes ? timeDiffMinutes : 0);
} else {
msg.add(std::max(static_cast(((slot->freeRerollTimeStamp - OTSYS_TIME()) / 1000)), 0));
msg.addByte(static_cast(slot->option));
diff --git a/src/server/network/protocol/protocollogin.cpp b/src/server/network/protocol/protocollogin.cpp
index 1f0a3b57ad9..4c905f58fcb 100644
--- a/src/server/network/protocol/protocollogin.cpp
+++ b/src/server/network/protocol/protocollogin.cpp
@@ -77,7 +77,7 @@ void ProtocolLogin::getCharacterList(const std::string &accountDescriptor, const
output->addString(g_configManager().getString(SERVER_NAME));
output->addString(g_configManager().getString(IP));
- output->add(g_configManager().getShortNumber(GAME_PORT));
+ output->add(g_configManager().getNumber(GAME_PORT));
output->addByte(0);
diff --git a/src/server/network/protocol/protocolstatus.cpp b/src/server/network/protocol/protocolstatus.cpp
index f07e5e85d18..40dcffa646b 100644
--- a/src/server/network/protocol/protocolstatus.cpp
+++ b/src/server/network/protocol/protocolstatus.cpp
@@ -82,7 +82,7 @@ void ProtocolStatus::sendStatusString() {
uint64_t uptime = (OTSYS_TIME() - ProtocolStatus::start) / 1000;
serverinfo.append_attribute("uptime") = std::to_string(uptime).c_str();
serverinfo.append_attribute("ip") = g_configManager().getString(IP).c_str();
- serverinfo.append_attribute("servername") = g_configManager().getString(stringConfig_t::SERVER_NAME).c_str();
+ serverinfo.append_attribute("servername") = g_configManager().getString(ConfigKey_t::SERVER_NAME).c_str();
serverinfo.append_attribute("port") = std::to_string(g_configManager().getNumber(LOGIN_PORT)).c_str();
serverinfo.append_attribute("location") = g_configManager().getString(LOCATION).c_str();
serverinfo.append_attribute("url") = g_configManager().getString(URL).c_str();
@@ -154,7 +154,7 @@ void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string &charact
if (requestedInfo & REQUEST_BASIC_SERVER_INFO) {
output->addByte(0x10);
- output->addString(g_configManager().getString(stringConfig_t::SERVER_NAME));
+ output->addString(g_configManager().getString(ConfigKey_t::SERVER_NAME));
output->addString(g_configManager().getString(IP));
output->addString(std::to_string(g_configManager().getNumber(LOGIN_PORT)));
}
diff --git a/src/utils/tools.cpp b/src/utils/tools.cpp
index a4b9f8d31db..ce42c04ad50 100644
--- a/src/utils/tools.cpp
+++ b/src/utils/tools.cpp
@@ -1454,8 +1454,13 @@ const char* getReturnMessage(ReturnValue value) {
}
}
+int64_t OTSYSTIME = 0;
+void UPDATE_OTSYS_TIME() {
+ OTSYSTIME = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count();
+}
+
int64_t OTSYS_TIME() {
- return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count();
+ return OTSYSTIME;
}
SpellGroup_t stringToSpellGroup(const std::string &value) {
diff --git a/src/utils/tools.hpp b/src/utils/tools.hpp
index 099f77afc67..580a962c9e4 100644
--- a/src/utils/tools.hpp
+++ b/src/utils/tools.hpp
@@ -135,6 +135,7 @@ bool isCaskItem(uint16_t itemId);
std::string getObjectCategoryName(ObjectCategory_t category);
int64_t OTSYS_TIME();
+void UPDATE_OTSYS_TIME();
SpellGroup_t stringToSpellGroup(const std::string &value);