diff --git a/data-canary/monster/demons/fury.lua b/data-canary/monster/demons/fury.lua
index cdaad15cf8f..3835050ce67 100644
--- a/data-canary/monster/demons/fury.lua
+++ b/data-canary/monster/demons/fury.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Fury")
local monster = {}
monster.description = "a fury"
-monster.experience = 3600
+monster.experience = 4000
monster.outfit = {
lookType = 149,
lookHead = 94,
diff --git a/data-canary/scripts/actions/tools/crowbar.lua b/data-canary/scripts/actions/tools/crowbar.lua
deleted file mode 100644
index 3be211f70ea..00000000000
--- a/data-canary/scripts/actions/tools/crowbar.lua
+++ /dev/null
@@ -1,8 +0,0 @@
-local crowbar = Action()
-
-function crowbar.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- return ActionsLib.useCrowbar(player, item, fromPosition, target, toPosition, isHotkey) or ActionsLib.destroyItem(player, target, toPosition)
-end
-
-crowbar:id(3304)
-crowbar:register()
diff --git a/data-canary/scripts/actions/tools/machete.lua b/data-canary/scripts/actions/tools/machete.lua
deleted file mode 100644
index 290ba5d2a7d..00000000000
--- a/data-canary/scripts/actions/tools/machete.lua
+++ /dev/null
@@ -1,8 +0,0 @@
-local machete = Action()
-
-function machete.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- return ActionsLib.useMachete(player, item, fromPosition, target, toPosition, isHotkey) or ActionsLib.destroyItem(player, target, toPosition)
-end
-
-machete:id(3308, 3330)
-machete:register()
diff --git a/data-canary/scripts/actions/tools/pick.lua b/data-canary/scripts/actions/tools/pick.lua
deleted file mode 100644
index 37cbc136948..00000000000
--- a/data-canary/scripts/actions/tools/pick.lua
+++ /dev/null
@@ -1,8 +0,0 @@
-local pick = Action()
-
-function pick.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- return ActionsLib.usePick(player, item, fromPosition, target, toPosition, isHotkey)
-end
-
-pick:id(3456)
-pick:register()
diff --git a/data-canary/scripts/actions/tools/rope.lua b/data-canary/scripts/actions/tools/rope.lua
deleted file mode 100644
index f557cf3202e..00000000000
--- a/data-canary/scripts/actions/tools/rope.lua
+++ /dev/null
@@ -1,8 +0,0 @@
-local rope = Action()
-
-function rope.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- return ActionsLib.useRope(player, item, fromPosition, target, toPosition, isHotkey)
-end
-
-rope:id(646, 3003)
-rope:register()
diff --git a/data-canary/scripts/actions/tools/scythe.lua b/data-canary/scripts/actions/tools/scythe.lua
deleted file mode 100644
index 5a29085d188..00000000000
--- a/data-canary/scripts/actions/tools/scythe.lua
+++ /dev/null
@@ -1,8 +0,0 @@
-local scythe = Action()
-
-function scythe.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- return ActionsLib.useScythe(player, item, fromPosition, target, toPosition, isHotkey)
-end
-
-scythe:id(3453)
-scythe:register()
diff --git a/data-canary/scripts/actions/tools/shovel.lua b/data-canary/scripts/actions/tools/shovel.lua
deleted file mode 100644
index 1edf67e4a72..00000000000
--- a/data-canary/scripts/actions/tools/shovel.lua
+++ /dev/null
@@ -1,8 +0,0 @@
-local shovel = Action()
-
-function shovel.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- return ActionsLib.useShovel(player, item, fromPosition, target, toPosition, isHotkey)
-end
-
-shovel:id(3457, 5710)
-shovel:register()
diff --git a/data-canary/scripts/actions/tools/spoon.lua b/data-canary/scripts/actions/tools/spoon.lua
deleted file mode 100644
index f885f6d195f..00000000000
--- a/data-canary/scripts/actions/tools/spoon.lua
+++ /dev/null
@@ -1,8 +0,0 @@
-local spoon = Action()
-
-function spoon.onUse(player, item, fromPosition, target, toPosition, isHotkey)
- return ActionsLib.useSpoon(player, item, fromPosition, target, toPosition, isHotkey)
-end
-
-spoon:id(3468, 20189)
-spoon:register()
diff --git a/data-otservbr-global/monster/demons/hellfire_fighter.lua b/data-otservbr-global/monster/demons/hellfire_fighter.lua
index 446234df576..6a90b5af06d 100644
--- a/data-otservbr-global/monster/demons/hellfire_fighter.lua
+++ b/data-otservbr-global/monster/demons/hellfire_fighter.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Hellfire Fighter")
local monster = {}
monster.description = "a hellfire fighter"
-monster.experience = 3120
+monster.experience = 3400
monster.outfit = {
lookType = 243,
lookHead = 0,
diff --git a/data-otservbr-global/monster/demons/hellflayer.lua b/data-otservbr-global/monster/demons/hellflayer.lua
index 93e9db81e1e..1e54dca6f57 100644
--- a/data-otservbr-global/monster/demons/hellflayer.lua
+++ b/data-otservbr-global/monster/demons/hellflayer.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Hellflayer")
local monster = {}
monster.description = "a hellflayer"
-monster.experience = 11000
+monster.experience = 11720
monster.outfit = {
lookType = 856,
lookHead = 0,
diff --git a/data-otservbr-global/monster/demons/juggernaut.lua b/data-otservbr-global/monster/demons/juggernaut.lua
index bab7fcf5dad..8f783924ef2 100644
--- a/data-otservbr-global/monster/demons/juggernaut.lua
+++ b/data-otservbr-global/monster/demons/juggernaut.lua
@@ -28,8 +28,8 @@ monster.Bestiary = {
Oramond Dungeon, Grounds of Destruction and Halls of Ascension.",
}
-monster.health = 20000
-monster.maxHealth = 20000
+monster.health = 18000
+monster.maxHealth = 18000
monster.race = "blood"
monster.corpse = 6335
monster.speed = 170
diff --git a/data-otservbr-global/monster/demons/plaguesmith.lua b/data-otservbr-global/monster/demons/plaguesmith.lua
index 6fbc96b533d..e919f78cf09 100644
--- a/data-otservbr-global/monster/demons/plaguesmith.lua
+++ b/data-otservbr-global/monster/demons/plaguesmith.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Plaguesmith")
local monster = {}
monster.description = "a plaguesmith"
-monster.experience = 3555
+monster.experience = 3800
monster.outfit = {
lookType = 247,
lookHead = 0,
diff --git a/data-otservbr-global/monster/magicals/nightmare.lua b/data-otservbr-global/monster/magicals/nightmare.lua
index b5c93d2b87b..00929effa57 100644
--- a/data-otservbr-global/monster/magicals/nightmare.lua
+++ b/data-otservbr-global/monster/magicals/nightmare.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Nightmare")
local monster = {}
monster.description = "a nightmare"
-monster.experience = 1666
+monster.experience = 1800
monster.outfit = {
lookType = 245,
lookHead = 0,
diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ferumbras_mortal_shell.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ferumbras_mortal_shell.lua
index ca11ccb542a..90b3124369a 100644
--- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ferumbras_mortal_shell.lua
+++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ferumbras_mortal_shell.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Ferumbras Mortal Shell")
local monster = {}
monster.description = "Ferumbras Mortal Shell"
-monster.experience = 100000
+monster.experience = 500000
monster.outfit = {
lookType = 229,
lookHead = 0,
diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/mazoran.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/mazoran.lua
index 9bc02481292..0e0822e3d72 100644
--- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/mazoran.lua
+++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/mazoran.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Mazoran")
local monster = {}
monster.description = "Mazoran"
-monster.experience = 50000
+monster.experience = 250000
monster.outfit = {
lookType = 842,
lookHead = 77,
diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/plagirath.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/plagirath.lua
index b86ac1a47bd..625f10cf7fc 100644
--- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/plagirath.lua
+++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/plagirath.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Plagirath")
local monster = {}
monster.description = "Plagirath"
-monster.experience = 50000
+monster.experience = 250000
monster.outfit = {
lookType = 862,
lookHead = 84,
diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ragiaz.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ragiaz.lua
index e9f97824c97..9701dc7d0f9 100644
--- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ragiaz.lua
+++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/ragiaz.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Ragiaz")
local monster = {}
monster.description = "Ragiaz"
-monster.experience = 50000
+monster.experience = 250000
monster.outfit = {
lookType = 862,
lookHead = 76,
diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/razzagorn.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/razzagorn.lua
index 07d2a55b07b..67d218c5ee0 100644
--- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/razzagorn.lua
+++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/razzagorn.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Razzagorn")
local monster = {}
monster.description = "Razzagorn"
-monster.experience = 50000
+monster.experience = 250000
monster.outfit = {
lookType = 842,
lookHead = 78,
diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/shulgrax.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/shulgrax.lua
index 69eae8f369b..c0de2c0c362 100644
--- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/shulgrax.lua
+++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/shulgrax.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Shulgrax")
local monster = {}
monster.description = "Shulgrax"
-monster.experience = 21000
+monster.experience = 250000
monster.outfit = {
lookType = 842,
lookHead = 0,
diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/tarbaz.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/tarbaz.lua
index 16fd12f63e8..583167460e1 100644
--- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/tarbaz.lua
+++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/tarbaz.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Tarbaz")
local monster = {}
monster.description = "Tarbaz"
-monster.experience = 55000
+monster.experience = 250000
monster.outfit = {
lookType = 842,
lookHead = 0,
diff --git a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh.lua b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh.lua
index f3bbd04efd4..5a441ff10f1 100644
--- a/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh.lua
+++ b/data-otservbr-global/monster/quests/ferumbras_ascendant/bosses/zamulosh.lua
@@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Zamulosh")
local monster = {}
monster.description = "Zamulosh"
-monster.experience = 50000
+monster.experience = 250000
monster.outfit = {
lookType = 862,
lookHead = 16,
diff --git a/data-otservbr-global/monster/undeads/blightwalker.lua b/data-otservbr-global/monster/undeads/blightwalker.lua
index 2edb1712a80..28706adeb50 100644
--- a/data-otservbr-global/monster/undeads/blightwalker.lua
+++ b/data-otservbr-global/monster/undeads/blightwalker.lua
@@ -26,8 +26,8 @@ monster.Bestiary = {
Locations = "Pits of Inferno, Edron (In the Vats during The Inquisition Quest), Roshamuul Prison, Grounds of Undeath.",
}
-monster.health = 8900
-monster.maxHealth = 8900
+monster.health = 8100
+monster.maxHealth = 8100
monster.race = "undead"
monster.corpse = 6353
monster.speed = 175
diff --git a/data-otservbr-global/monster/undeads/hand_of_cursed_fate.lua b/data-otservbr-global/monster/undeads/hand_of_cursed_fate.lua
index be6f79fc666..b1f76414dd4 100644
--- a/data-otservbr-global/monster/undeads/hand_of_cursed_fate.lua
+++ b/data-otservbr-global/monster/undeads/hand_of_cursed_fate.lua
@@ -26,8 +26,8 @@ monster.Bestiary = {
Locations = "Pits of Inferno, The Battlefield, The Arcanum, The Blood Halls and The Crystal Caves.",
}
-monster.health = 7500
-monster.maxHealth = 7500
+monster.health = 6600
+monster.maxHealth = 6600
monster.race = "blood"
monster.corpse = 6311
monster.speed = 130
diff --git a/data-otservbr-global/monster/undeads/undead_dragon.lua b/data-otservbr-global/monster/undeads/undead_dragon.lua
index 0dc1652d85f..2ab63af8b77 100644
--- a/data-otservbr-global/monster/undeads/undead_dragon.lua
+++ b/data-otservbr-global/monster/undeads/undead_dragon.lua
@@ -133,7 +133,7 @@ monster.elements = {
{ type = COMBAT_LIFEDRAIN, percent = 0 },
{ type = COMBAT_MANADRAIN, percent = 0 },
{ type = COMBAT_DROWNDAMAGE, percent = 100 },
- { type = COMBAT_ICEDAMAGE, percent = 50 },
+ { type = COMBAT_ICEDAMAGE, percent = 90 },
{ type = COMBAT_HOLYDAMAGE, percent = -25 },
{ type = COMBAT_DEATHDAMAGE, percent = 100 },
}
diff --git a/data-otservbr-global/npc/gnomadness.lua b/data-otservbr-global/npc/gnomadness.lua
index 5723d22ee2a..1c866a160ae 100644
--- a/data-otservbr-global/npc/gnomadness.lua
+++ b/data-otservbr-global/npc/gnomadness.lua
@@ -83,12 +83,13 @@ local function creatureSayCallback(npc, creature, type, message)
end
if hazard:setPlayerCurrentLevel(player, desiredLevel) then
npcHandler:say("Your hazard level has been set to " .. desiredLevel .. ". Good luck!", npc, creature)
- if desiredLevel >= hazard.maxLevel and not player:kv():scoped("primal-ordeal"):get("received-prize") then
- player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Congratulations you received the Noxious Ripptor mount.")
+ if desiredLevel >= 6 and not player:kv():scoped("primal-ordeal"):get("received-prize") then
player:addMount(202)
- npcHandler:say("You've achived the maximum hazard level. As a reward, you've received the Noxious Ripptor mount and a primal bag.", npc, creature)
+ player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Congratulations you received the Noxious Ripptor mount.")
+ player:addAchievement("Ripp-Ripp Hooray!")
player:addItem(PRIMAL_BAG, 1)
player:kv():scoped("primal-ordeal"):set("received-prize", true)
+ npcHandler:say("You've achieved the necessary hazard level. As a reward, you've received the Noxious Ripptor mount and a primal bag.", npc, creature)
end
else
npcHandler:say("You can't set your hazard level higher than your maximum unlocked level.", npc, creature)
diff --git a/data/items/items.xml b/data/items/items.xml
index 5e464330019..b1a1c6b003f 100644
--- a/data/items/items.xml
+++ b/data/items/items.xml
@@ -1252,7 +1252,6 @@
-
-
@@ -1327,7 +1326,6 @@
-
-
@@ -1386,7 +1384,6 @@
-
-
@@ -1401,7 +1398,6 @@
-
-
@@ -1490,7 +1486,6 @@
-
-
@@ -1565,7 +1560,6 @@
-
-
@@ -1624,7 +1618,6 @@
-
-
@@ -1639,7 +1632,6 @@
-
-
@@ -2267,7 +2259,6 @@
-
-
@@ -2342,7 +2333,6 @@
-
-
@@ -2401,7 +2391,6 @@
-
-
@@ -2416,7 +2405,6 @@
-
-
@@ -2488,7 +2476,6 @@
-
-
@@ -2567,7 +2554,6 @@
-
-
@@ -2626,7 +2612,6 @@
-
-
@@ -2641,7 +2626,6 @@
-
-
@@ -8266,7 +8250,6 @@
-
-
@@ -8280,7 +8263,6 @@
-
-
@@ -8316,7 +8298,6 @@
-
-
@@ -8397,7 +8378,6 @@
-
-
@@ -8438,7 +8418,6 @@
-
-
@@ -8460,7 +8439,6 @@
-
-
@@ -8499,7 +8477,6 @@
-
-
@@ -8607,7 +8584,6 @@
-
-
@@ -8700,7 +8676,6 @@
-
-
@@ -8771,7 +8746,6 @@
-
-
@@ -8793,7 +8767,6 @@
-
-
@@ -8816,7 +8789,6 @@
-
-
@@ -8963,7 +8935,6 @@
-
-
@@ -8977,7 +8948,6 @@
-
-
@@ -8998,7 +8968,6 @@
-
-
@@ -9073,7 +9042,6 @@
-
-
@@ -9217,7 +9185,6 @@
-
-
@@ -9259,7 +9226,6 @@
-
-
@@ -9281,7 +9247,6 @@
-
-
@@ -9338,7 +9303,6 @@
-
-
@@ -9416,7 +9380,6 @@
-
-
@@ -9460,7 +9423,6 @@
-
-
@@ -9520,7 +9482,6 @@
-
-
@@ -9567,7 +9528,6 @@
-
-
@@ -9579,7 +9539,6 @@
-
-
@@ -10826,7 +10785,6 @@
-
-
@@ -15646,7 +15604,6 @@
-
-
@@ -17988,7 +17945,6 @@
-
-
@@ -18116,7 +18072,6 @@
-
-
@@ -19368,7 +19323,6 @@
-
-
@@ -19391,7 +19345,6 @@
-
-
@@ -19427,7 +19380,6 @@
-
-
@@ -19507,7 +19459,6 @@
-
-
@@ -19593,7 +19544,6 @@
-
-
@@ -19615,7 +19565,6 @@
-
-
@@ -19673,7 +19622,6 @@
-
-
@@ -19695,7 +19643,6 @@
-
-
@@ -19738,7 +19685,6 @@
-
-
@@ -19761,7 +19707,6 @@
-
-
@@ -19783,7 +19728,6 @@
-
-
@@ -19886,7 +19830,6 @@
-
-
@@ -19909,7 +19852,6 @@
-
-
@@ -20084,7 +20026,6 @@
-
-
@@ -20105,7 +20046,6 @@
-
-
@@ -20119,7 +20059,6 @@
-
-
@@ -20140,7 +20079,6 @@
-
-
@@ -20155,7 +20093,6 @@
-
-
@@ -20171,7 +20108,6 @@
-
-
@@ -20321,7 +20257,6 @@
-
-
@@ -20363,7 +20298,6 @@
-
-
@@ -20420,7 +20354,6 @@
-
-
@@ -20434,7 +20367,6 @@
-
-
@@ -20476,7 +20408,6 @@
-
-
@@ -20498,7 +20429,6 @@
-
-
@@ -20513,7 +20443,6 @@
-
-
@@ -21455,7 +21384,6 @@
-
-
@@ -21478,7 +21406,6 @@
-
-
@@ -21502,7 +21429,6 @@
-
-
@@ -21525,7 +21451,6 @@
-
-
@@ -21547,7 +21472,6 @@
-
-
@@ -21571,7 +21495,6 @@
-
-
@@ -21595,7 +21518,6 @@
-
-
@@ -21610,7 +21532,6 @@
-
-
@@ -21633,7 +21554,6 @@
-
-
@@ -21648,7 +21568,6 @@
-
-
@@ -22372,7 +22291,6 @@
-
-
@@ -22428,7 +22346,6 @@
-
-
@@ -22483,7 +22400,6 @@
-
-
@@ -25284,7 +25200,6 @@
-
-
@@ -25372,7 +25287,6 @@
-
-
@@ -25395,7 +25309,6 @@
-
-
@@ -27222,7 +27135,6 @@
-
-
@@ -27237,7 +27149,6 @@
-
-
@@ -27273,7 +27184,6 @@
-
-
@@ -27295,7 +27205,6 @@
-
-
@@ -27375,7 +27284,6 @@
-
-
@@ -28880,7 +28788,6 @@
-
-
@@ -30740,7 +30647,6 @@
-
-
@@ -30883,7 +30789,6 @@
-
-
@@ -31909,7 +31814,6 @@
-
-
@@ -32299,7 +32203,6 @@
-
-
@@ -32656,7 +32559,6 @@
-
-
@@ -32673,7 +32575,6 @@
-
-
@@ -32935,7 +32836,6 @@
-
-
@@ -34607,7 +34507,6 @@
-
-
@@ -34631,7 +34530,6 @@
-
-
@@ -36065,7 +35963,6 @@
-
-
@@ -39421,7 +39318,6 @@
-
-
@@ -39486,7 +39382,6 @@
-
-
@@ -39628,7 +39523,6 @@
-
-
@@ -39958,7 +39852,6 @@
-
-
@@ -39980,7 +39873,6 @@
-
-
@@ -40003,7 +39895,6 @@
-
-
@@ -40078,7 +39969,6 @@
-
-
@@ -40100,7 +39990,6 @@
-
-
@@ -40123,7 +40012,6 @@
-
-
@@ -40198,7 +40086,6 @@
-
-
@@ -40220,7 +40107,6 @@
-
-
@@ -40243,7 +40129,6 @@
-
-
@@ -40260,7 +40145,6 @@
-
-
@@ -40284,7 +40168,6 @@
-
-
@@ -40309,7 +40192,6 @@
-
-
@@ -40326,7 +40208,6 @@
-
-
@@ -40350,7 +40231,6 @@
-
-
@@ -40375,7 +40255,6 @@
-
-
@@ -41958,7 +41837,6 @@
-
-
@@ -41994,7 +41872,6 @@
-
-
@@ -42026,7 +41903,6 @@
-
-
@@ -42044,7 +41920,6 @@
-
-
@@ -42062,7 +41937,6 @@
-
@@ -44339,7 +44213,6 @@ Awarded by TibiaMisterios.com.br"/>
-
-
@@ -44353,7 +44226,6 @@ Awarded by TibiaMisterios.com.br"/>
-
@@ -45198,7 +45070,6 @@ Awarded by TibiaMisterios.com.br"/>
-
-
@@ -45692,7 +45563,6 @@ Awarded by TibiaMisterios.com.br"/>
-
-
@@ -45716,7 +45586,6 @@ Awarded by TibiaMisterios.com.br"/>
-
-
@@ -51748,7 +51617,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -51789,7 +51657,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -51830,7 +51697,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -51853,7 +51719,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -51876,7 +51741,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -54205,7 +54069,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -54310,7 +54173,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -54334,7 +54196,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -55254,7 +55115,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -55472,7 +55332,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -55516,7 +55375,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -57319,7 +57177,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -59171,7 +59028,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -59312,7 +59168,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -61759,7 +61614,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -64025,7 +63879,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -64077,7 +63930,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -64129,7 +63981,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -64157,7 +64008,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -64185,7 +64035,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -64602,7 +64451,6 @@ hands of its owner. Granted by TibiaRoyal.com"/>
-
-
@@ -65927,7 +65775,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
-
@@ -65999,7 +65846,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
-
@@ -67397,7 +67243,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
-
@@ -67422,7 +67267,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
-
@@ -67446,7 +67290,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
-
@@ -67495,7 +67338,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
-
@@ -67520,7 +67362,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
-
@@ -67566,7 +67407,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
-
@@ -67593,7 +67433,6 @@ former students at the Noodles Academy. Awarded by TibiaLabs.com"/>
-
-
@@ -71644,7 +71483,6 @@ Granted by TibiaGoals.com"/>
-
-
@@ -75313,7 +75151,6 @@ Granted by TibiaGoals.com"/>
-
-
@@ -75338,7 +75175,6 @@ Granted by TibiaGoals.com"/>
-
-
@@ -75363,7 +75199,6 @@ Granted by TibiaGoals.com"/>
-
-
@@ -75388,7 +75223,6 @@ Granted by TibiaGoals.com"/>
-
-
@@ -75413,7 +75247,6 @@ Granted by TibiaGoals.com"/>
-
-
@@ -75438,7 +75271,6 @@ Granted by TibiaGoals.com"/>
-
-
@@ -75481,7 +75313,6 @@ Granted by TibiaGoals.com"/>
-
-
@@ -75509,7 +75340,6 @@ Granted by TibiaGoals.com"/>
-
-
@@ -75537,7 +75367,6 @@ Granted by TibiaGoals.com"/>
-
-
@@ -75565,7 +75394,6 @@ Granted by TibiaGoals.com"/>
-
-
diff --git a/data/modules/scripts/gamestore/init.lua b/data/modules/scripts/gamestore/init.lua
index 4fa9daea28b..a927715cd93 100644
--- a/data/modules/scripts/gamestore/init.lua
+++ b/data/modules/scripts/gamestore/init.lua
@@ -1739,8 +1739,8 @@ function GameStore.processExpBoostPuchase(player)
player:setStoreXpBoost(50)
player:setExpBoostStamina(currentExpBoostTime + 3600)
- if player:getStorageValue(GameStore.Storages.expBoostCount) == -1 or expBoostCount == 6 then
- player:setStorageValue(GameStore.Storages.expBoostCount, 1)
+ if expBoostCount == -1 or expBoostCount == 6 then
+ expBoostCount = 1
end
player:setStorageValue(GameStore.Storages.expBoostCount, expBoostCount + 1)
diff --git a/data-otservbr-global/scripts/actions/tools/crowbar.lua b/data/scripts/actions/tools/crowbar.lua
similarity index 100%
rename from data-otservbr-global/scripts/actions/tools/crowbar.lua
rename to data/scripts/actions/tools/crowbar.lua
diff --git a/data-otservbr-global/scripts/actions/tools/machete.lua b/data/scripts/actions/tools/machete.lua
similarity index 100%
rename from data-otservbr-global/scripts/actions/tools/machete.lua
rename to data/scripts/actions/tools/machete.lua
diff --git a/data-otservbr-global/scripts/actions/tools/pick.lua b/data/scripts/actions/tools/pick.lua
similarity index 100%
rename from data-otservbr-global/scripts/actions/tools/pick.lua
rename to data/scripts/actions/tools/pick.lua
diff --git a/data-otservbr-global/scripts/actions/tools/rope.lua b/data/scripts/actions/tools/rope.lua
similarity index 100%
rename from data-otservbr-global/scripts/actions/tools/rope.lua
rename to data/scripts/actions/tools/rope.lua
diff --git a/data-otservbr-global/scripts/actions/tools/scythe.lua b/data/scripts/actions/tools/scythe.lua
similarity index 100%
rename from data-otservbr-global/scripts/actions/tools/scythe.lua
rename to data/scripts/actions/tools/scythe.lua
diff --git a/data-otservbr-global/scripts/actions/tools/shovel.lua b/data/scripts/actions/tools/shovel.lua
similarity index 100%
rename from data-otservbr-global/scripts/actions/tools/shovel.lua
rename to data/scripts/actions/tools/shovel.lua
diff --git a/data-otservbr-global/scripts/actions/tools/spoon.lua b/data/scripts/actions/tools/spoon.lua
similarity index 100%
rename from data-otservbr-global/scripts/actions/tools/spoon.lua
rename to data/scripts/actions/tools/spoon.lua
diff --git a/data/scripts/globalevents/global_server_save.lua b/data/scripts/globalevents/global_server_save.lua
index 00eaebbc3c3..c68c3dedc88 100644
--- a/data/scripts/globalevents/global_server_save.lua
+++ b/data/scripts/globalevents/global_server_save.lua
@@ -5,7 +5,8 @@ local function ServerSave()
if configManager.getBoolean(configKeys.GLOBAL_SERVER_SAVE_CLOSE) then
Game.setGameState(GAME_STATE_CLOSED)
- elseif configManager.getBoolean(configKeys.GLOBAL_SERVER_SAVE_SHUTDOWN) then
+ end
+ if configManager.getBoolean(configKeys.GLOBAL_SERVER_SAVE_SHUTDOWN) then
Game.setGameState(GAME_STATE_SHUTDOWN)
end
diff --git a/data/scripts/lib/register_achievements.lua b/data/scripts/lib/register_achievements.lua
index 11d238d8bcf..18a2d6e41ef 100644
--- a/data/scripts/lib/register_achievements.lua
+++ b/data/scripts/lib/register_achievements.lua
@@ -526,6 +526,7 @@ ACHIEVEMENTS = {
[531] = { name = "First Achievement", grade = 1, points = 1, secret = true, description = "Congratulations to your very first achievement! ... Well, not really. But imagine, it is. Because at this point during your journey into Tibia's past, achievements have been introduced." },
[532] = { name = "Sharp Dressed", grade = 1, points = 2, description = "Just everyone will be crazy about you if you are wearing this formal dress. They will come running, promise!" },
[533] = { name = "Engine Driver", grade = 1, points = 3, description = "This glooth-driven locomotive will bring you to any party in the blink of an eye." },
+ [540] = { name = "Ripp-Ripp Hooray!", grade = 1, points = 3, description = "Don't get carried away by your success. Get carried away by your Ripptor." },
}
--[[
diff --git a/src/creatures/players/achievement/player_achievement.cpp b/src/creatures/players/achievement/player_achievement.cpp
index 18e2db3d3f2..2db53dbe776 100644
--- a/src/creatures/players/achievement/player_achievement.cpp
+++ b/src/creatures/players/achievement/player_achievement.cpp
@@ -16,18 +16,7 @@
#include "kv/kv.hpp"
PlayerAchievement::PlayerAchievement(Player &player) :
- m_player(player) {
- auto unlockedAchievements = getUnlockedKV()->keys();
- for (const auto &achievementName : unlockedAchievements) {
- const Achievement &achievement = g_game().getAchievementByName(achievementName);
- if (achievement.id == 0) {
- g_logger().error("[{}] - Achievement {} not found.", __FUNCTION__, achievementName);
- continue;
- }
-
- m_achievementsUnlocked.push_back({ achievement.id, getUnlockedKV()->get(achievementName)->getNumber() });
- }
-}
+ m_player(player) { }
bool PlayerAchievement::add(uint16_t id, bool message /* = true*/, uint32_t timestamp /* = 0*/) {
if (isUnlocked(id)) {
@@ -108,6 +97,22 @@ std::vector> PlayerAchievement::getUnlockedAchieve
return m_achievementsUnlocked;
}
+void PlayerAchievement::loadUnlockedAchievements() {
+ const auto &unlockedAchievements = getUnlockedKV()->keys();
+ g_logger().debug("[{}] - Loading unlocked achievements: {}", __FUNCTION__, unlockedAchievements.size());
+ for (const auto &achievementName : unlockedAchievements) {
+ const Achievement &achievement = g_game().getAchievementByName(achievementName);
+ if (achievement.id == 0) {
+ g_logger().error("[{}] - Achievement {} not found.", __FUNCTION__, achievementName);
+ continue;
+ }
+
+ g_logger().debug("[{}] - Achievement {} found for player {}.", __FUNCTION__, achievementName, m_player.getName());
+
+ m_achievementsUnlocked.push_back({ achievement.id, getUnlockedKV()->get(achievementName)->getNumber() });
+ }
+}
+
void PlayerAchievement::sendUnlockedSecretAchievements() {
std::vector> m_achievementsUnlocked;
uint16_t unlockedSecret = 0;
diff --git a/src/creatures/players/achievement/player_achievement.hpp b/src/creatures/players/achievement/player_achievement.hpp
index 8959ce429ca..7d141c96a16 100644
--- a/src/creatures/players/achievement/player_achievement.hpp
+++ b/src/creatures/players/achievement/player_achievement.hpp
@@ -36,6 +36,7 @@ class PlayerAchievement {
void addPoints(uint16_t toAddPoints);
void removePoints(uint16_t toRemovePoints);
std::vector> getUnlockedAchievements() const;
+ void loadUnlockedAchievements();
void sendUnlockedSecretAchievements();
const std::shared_ptr &getUnlockedKV();
diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp
index 6dd304e90ba..874089e5602 100644
--- a/src/creatures/players/player.cpp
+++ b/src/creatures/players/player.cpp
@@ -3246,11 +3246,7 @@ ReturnValue Player::queryAdd(int32_t index, const std::shared_ptr &thing,
}
}
} else if (slotPosition & SLOTP_TWO_HAND) {
- if (inventory[CONST_SLOT_LEFT] && inventory[CONST_SLOT_LEFT] != item) {
- ret = RETURNVALUE_BOTHHANDSNEEDTOBEFREE;
- } else {
- ret = RETURNVALUE_NOERROR;
- }
+ ret = RETURNVALUE_CANNOTBEDRESSED;
} else if (inventory[CONST_SLOT_LEFT]) {
std::shared_ptr
- leftItem = inventory[CONST_SLOT_LEFT];
WeaponType_t type = item->getWeaponType(), leftType = leftItem->getWeaponType();
@@ -3273,11 +3269,19 @@ ReturnValue Player::queryAdd(int32_t index, const std::shared_ptr &thing,
}
case CONST_SLOT_LEFT: {
- if (slotPosition & SLOTP_LEFT) {
+ if (item->isQuiver()) {
+ ret = RETURNVALUE_CANNOTBEDRESSED;
+ } else if (slotPosition & SLOTP_LEFT) {
WeaponType_t type = item->getWeaponType();
if (type == WEAPON_NONE || type == WEAPON_SHIELD || type == WEAPON_AMMO) {
ret = RETURNVALUE_CANNOTBEDRESSED;
- } else if (inventory[CONST_SLOT_RIGHT] && (slotPosition & SLOTP_TWO_HAND)) {
+ } else {
+ ret = RETURNVALUE_NOERROR;
+ }
+ } else if (slotPosition & SLOTP_TWO_HAND) {
+ if (inventory[CONST_SLOT_RIGHT]) {
+ WeaponType_t type = item->getWeaponType();
+ // Allow equip bow when quiver is in SLOT_RIGHT
if (type == WEAPON_DISTANCE && inventory[CONST_SLOT_RIGHT]->isQuiver()) {
ret = RETURNVALUE_NOERROR;
} else {
@@ -3286,12 +3290,6 @@ ReturnValue Player::queryAdd(int32_t index, const std::shared_ptr &thing,
} else {
ret = RETURNVALUE_NOERROR;
}
- } else if (slotPosition & SLOTP_TWO_HAND) {
- if (inventory[CONST_SLOT_RIGHT] && inventory[CONST_SLOT_RIGHT] != item) {
- ret = RETURNVALUE_BOTHHANDSNEEDTOBEFREE;
- } else {
- ret = RETURNVALUE_NOERROR;
- }
} else if (inventory[CONST_SLOT_RIGHT]) {
std::shared_ptr
- rightItem = inventory[CONST_SLOT_RIGHT];
WeaponType_t type = item->getWeaponType(), rightType = rightItem->getWeaponType();
diff --git a/src/creatures/players/wheel/player_wheel.cpp b/src/creatures/players/wheel/player_wheel.cpp
index b2fa39960e1..77a15f7cbf7 100644
--- a/src/creatures/players/wheel/player_wheel.cpp
+++ b/src/creatures/players/wheel/player_wheel.cpp
@@ -32,6 +32,47 @@ const static std::vector wheelGemBasicSlot1Allowed = {
WheelGemBasicModifier_t::Vocation_Health_IceResistance,
WheelGemBasicModifier_t::Vocation_Health_EnergyResistance,
WheelGemBasicModifier_t::Vocation_Health_EarthResistance,
+ WheelGemBasicModifier_t::Vocation_Mana_FireResistance,
+ WheelGemBasicModifier_t::Vocation_Mana_EnergyResistance,
+ WheelGemBasicModifier_t::Vocation_Mana_Earth_Resistance,
+ WheelGemBasicModifier_t::Vocation_Mana_Ice_Resistance,
+ WheelGemBasicModifier_t::Vocation_Capacity_FireResistance,
+ WheelGemBasicModifier_t::Vocation_Capacity_EnergyResistance,
+ WheelGemBasicModifier_t::Vocation_Capacity_EarthResistance,
+ WheelGemBasicModifier_t::Vocation_Capacity_IceResistance,
+};
+
+const static std::vector wheelGemBasicSlot2Allowed = {
+ WheelGemBasicModifier_t::General_FireResistance,
+ WheelGemBasicModifier_t::General_IceResistance,
+ WheelGemBasicModifier_t::General_EnergyResistance,
+ WheelGemBasicModifier_t::General_EarthResistance,
+ WheelGemBasicModifier_t::General_PhysicalResistance,
+ WheelGemBasicModifier_t::General_HolyResistance,
+ WheelGemBasicModifier_t::General_HolyResistance_DeathWeakness,
+ WheelGemBasicModifier_t::General_DeathResistance_HolyWeakness,
+ WheelGemBasicModifier_t::General_FireResistance_EarthResistance,
+ WheelGemBasicModifier_t::General_FireResistance_IceResistance,
+ WheelGemBasicModifier_t::General_FireResistance_EnergyResistance,
+ WheelGemBasicModifier_t::General_EarthResistance_IceResistance,
+ WheelGemBasicModifier_t::General_EarthResistance_EnergyResistance,
+ WheelGemBasicModifier_t::General_IceResistance_EnergyResistance,
+ WheelGemBasicModifier_t::General_FireResistance_EarthWeakness,
+ WheelGemBasicModifier_t::General_FireResistance_IceWeakness,
+ WheelGemBasicModifier_t::General_FireResistance_EnergyWeakness,
+ WheelGemBasicModifier_t::General_EarthResistance_FireWeakness,
+ WheelGemBasicModifier_t::General_EarthResistance_IceWeakness,
+ WheelGemBasicModifier_t::General_EarthResistance_EnergyWeakness,
+ WheelGemBasicModifier_t::General_IceResistance_EarthWeakness,
+ WheelGemBasicModifier_t::General_IceResistance_FireWeakness,
+ WheelGemBasicModifier_t::General_IceResistance_EnergyWeakness,
+ WheelGemBasicModifier_t::General_EnergyResistance_EarthWeakness,
+ WheelGemBasicModifier_t::General_EnergyResistance_IceWeakness,
+ WheelGemBasicModifier_t::General_EnergyResistance_FireWeakness,
+ WheelGemBasicModifier_t::General_ManaDrainResistance,
+ WheelGemBasicModifier_t::General_LifeDrainResistance,
+ WheelGemBasicModifier_t::General_ManaDrainResistance_LifeDrainResistance,
+ WheelGemBasicModifier_t::General_MitigationMultiplier,
};
// To avoid conflict in other files that might use a function with the same name
@@ -835,7 +876,7 @@ void PlayerWheel::revealGem(WheelGemQuality_t quality) {
gem.basicModifier2 = {};
gem.supremeModifier = {};
if (quality >= WheelGemQuality_t::Regular) {
- gem.basicModifier2 = static_cast(uniform_random(0, magic_enum::enum_count() - 1));
+ gem.basicModifier2 = selectBasicModifier2(gem.basicModifier1);
}
if (quality >= WheelGemQuality_t::Greater && !supremeModifiers.empty()) {
gem.supremeModifier = supremeModifiers[uniform_random(0, supremeModifiers.size() - 1)];
@@ -3106,3 +3147,11 @@ float PlayerWheel::calculateMitigation() const {
mitigation += (mitigation * (float)getMitigationMultiplier()) / 100.f;
return mitigation;
}
+
+WheelGemBasicModifier_t PlayerWheel::selectBasicModifier2(WheelGemBasicModifier_t modifier1) const {
+ WheelGemBasicModifier_t modifier = modifier1;
+ while (modifier == modifier1) {
+ modifier = wheelGemBasicSlot2Allowed[uniform_random(0, wheelGemBasicSlot2Allowed.size() - 1)];
+ }
+ return modifier;
+}
diff --git a/src/creatures/players/wheel/player_wheel.hpp b/src/creatures/players/wheel/player_wheel.hpp
index 3ede17c339d..303063beb9b 100644
--- a/src/creatures/players/wheel/player_wheel.hpp
+++ b/src/creatures/players/wheel/player_wheel.hpp
@@ -454,6 +454,8 @@ class PlayerWheel {
}
}
+ WheelGemBasicModifier_t selectBasicModifier2(WheelGemBasicModifier_t modifier1) const;
+
private:
friend class Player;
// Reference to the player
diff --git a/src/game/bank/bank.cpp b/src/game/bank/bank.cpp
index 5f8db90fd1a..30345e0495b 100644
--- a/src/game/bank/bank.cpp
+++ b/src/game/bank/bank.cpp
@@ -97,16 +97,17 @@ bool Bank::transferTo(const std::shared_ptr destination, uint64_t amount)
g_logger().error("Bank::transferTo: destinationBankable is nullptr");
return false;
}
- if (destinationBankable->getPlayer() != nullptr) {
- auto player = destinationBankable->getPlayer();
- auto name = asLowerCaseString(player->getName());
+
+ auto destinationPlayer = destinationBankable->getPlayer();
+ if (destinationPlayer != nullptr) {
+ auto name = asLowerCaseString(destinationPlayer->getName());
replaceString(name, " ", "");
if (deniedNames.contains(name)) {
g_logger().warn("Bank::transferTo: denied name: {}", name);
return false;
}
- if (player->getTown()->getID() < minTownId) {
- g_logger().warn("Bank::transferTo: denied town: {}", player->getTown()->getID());
+ if (destinationPlayer->getTown()->getID() < minTownId) {
+ g_logger().warn("Bank::transferTo: denied town: {}", destinationPlayer->getTown()->getID());
return false;
}
}
@@ -114,8 +115,15 @@ bool Bank::transferTo(const std::shared_ptr destination, uint64_t amount)
if (!(debit(amount) && destination->credit(amount))) {
return false;
}
- g_metrics().addCounter("balance_increase", amount, { { "player", destination->getBankable()->getPlayer()->getName() }, { "context", "bank_transfer" } });
- g_metrics().addCounter("balance_decrease", amount, { { "player", getBankable()->getPlayer()->getName() }, { "context", "bank_transfer" } });
+
+ if (destinationPlayer) {
+ g_metrics().addCounter("balance_increase", amount, { { "player", destinationPlayer->getName() }, { "context", "bank_transfer" } });
+ }
+
+ if (bankable->getPlayer()) {
+ g_metrics().addCounter("balance_decrease", amount, { { "player", bankable->getPlayer()->getName() }, { "context", "bank_transfer" } });
+ }
+
return true;
}
@@ -151,6 +159,8 @@ bool Bank::deposit(const std::shared_ptr destination, uint64_t amount) {
if (!g_game().removeMoney(bankable->getPlayer(), amount)) {
return false;
}
- g_metrics().addCounter("balance_increase", amount, { { "player", bankable->getPlayer()->getName() }, { "context", "bank_deposit" } });
+ if (bankable->getPlayer() != nullptr) {
+ g_metrics().addCounter("balance_decrease", amount, { { "player", bankable->getPlayer()->getName() }, { "context", "bank_deposit" } });
+ }
return destination->credit(amount);
}
diff --git a/src/game/game.cpp b/src/game/game.cpp
index ae170a37be2..53e887c9096 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -2581,7 +2581,15 @@ std::shared_ptr
- Game::transformItem(std::shared_ptr
- item, uint16_t n
uint16_t itemId = item->getID();
int32_t count = item->getSubType();
- if (curType.id != newType.id) {
+ auto decaying = item->getDecaying();
+ // If the item is decaying, we need to transform it to the new item
+ if (decaying > DECAYING_FALSE && item->getDuration() <= 1) {
+ g_logger().debug("Decay duration old type {}, transformEquipTo {}, transformDeEquipTo {}", curType.decayTo, curType.transformEquipTo, curType.transformDeEquipTo);
+ g_logger().debug("Decay duration new type, decayTo {}, transformEquipTo {}, transformDeEquipTo {}", newType.decayTo, newType.transformEquipTo, newType.transformDeEquipTo);
+ if (newType.decayTo) {
+ itemId = newType.decayTo;
+ }
+ } else if (curType.id != newType.id) {
if (newType.group != curType.group) {
item->setDefaultSubtype();
}
diff --git a/src/io/functions/iologindata_load_player.cpp b/src/io/functions/iologindata_load_player.cpp
index bd61b2456bb..d4a4f33774d 100644
--- a/src/io/functions/iologindata_load_player.cpp
+++ b/src/io/functions/iologindata_load_player.cpp
@@ -10,6 +10,7 @@
#include "pch.hpp"
#include "creatures/players/wheel/player_wheel.hpp"
+#include "creatures/players/achievement/player_achievement.hpp"
#include "io/functions/iologindata_load_player.hpp"
#include "game/game.hpp"
#include "enums/object_category.hpp"
@@ -887,6 +888,8 @@ void IOLoginDataLoad::loadPlayerInitializeSystem(std::shared_ptr player)
player->wheel()->loadDBPlayerSlotPointsOnLogin();
player->wheel()->initializePlayerData();
+ player->achiev()->loadUnlockedAchievements();
+
player->initializePrey();
player->initializeTaskHunting();
}
diff --git a/src/io/functions/iologindata_save_player.hpp b/src/io/functions/iologindata_save_player.hpp
index 5bc2ea9ce02..bbd44105de6 100644
--- a/src/io/functions/iologindata_save_player.hpp
+++ b/src/io/functions/iologindata_save_player.hpp
@@ -26,7 +26,7 @@ class IOLoginDataSave : public IOLoginData {
static bool savePlayerTaskHuntingClass(std::shared_ptr player);
static bool savePlayerForgeHistory(std::shared_ptr player);
static bool savePlayerBosstiary(std::shared_ptr player);
- static bool savePlayerStorage(std::shared_ptr palyer);
+ static bool savePlayerStorage(std::shared_ptr player);
protected:
using ItemBlockList = std::list>>;
diff --git a/src/io/io_wheel.cpp b/src/io/io_wheel.cpp
index 6e7c2b02b0f..e8ad30a5d80 100644
--- a/src/io/io_wheel.cpp
+++ b/src/io/io_wheel.cpp
@@ -416,7 +416,7 @@ void IOWheel::slotGreen200(const std::shared_ptr &player, uint16_t point
// SLOT_GREEN_TOP_150 = 2
void IOWheel::slotGreenTop150(const std::shared_ptr &player, uint16_t points, uint8_t, PlayerWheelMethodsBonusData &bonusData) const {
bonusData.mitigation += MITIGATION_INCREASE * points;
- if (isMaxPointAddedToSlot(player, points, WheelSlots_t::SLOT_GREEN_BOTTOM_150)) {
+ if (isMaxPointAddedToSlot(player, points, WheelSlots_t::SLOT_GREEN_TOP_150)) {
bonusData.leech.manaLeech += MANA_LEECH_INCREASE;
}
}
@@ -522,7 +522,7 @@ void IOWheel::slotGreenTop75(const std::shared_ptr &player, uint16_t poi
} else {
bonusData.stats.mana += 6 * points;
}
- if (isMaxPointAddedToSlot(player, points, WheelSlots_t::SLOT_GREEN_TOP_100)) {
+ if (isMaxPointAddedToSlot(player, points, WheelSlots_t::SLOT_GREEN_TOP_75)) {
bonusData.leech.lifeLeech += HEALTH_LEECH_INCREASE;
}
}
@@ -566,7 +566,7 @@ void IOWheel::slotRedBottom150(const std::shared_ptr &player, uint16_t p
} else {
bonusData.stats.health += 1 * points;
}
- if (isMaxPointAddedToSlot(player, points, WheelSlots_t::SLOT_RED_TOP_150)) {
+ if (isMaxPointAddedToSlot(player, points, WheelSlots_t::SLOT_RED_BOTTOM_150)) {
bonusData.leech.manaLeech += MANA_LEECH_INCREASE;
}
}
@@ -760,7 +760,7 @@ void IOWheel::slotBlueTop150(const std::shared_ptr &player, uint16_t poi
} else {
bonusData.stats.capacity += 2 * points;
}
- if (isMaxPointAddedToSlot(player, points, WheelSlots_t::SLOT_BLUE_BOTTOM_150)) {
+ if (isMaxPointAddedToSlot(player, points, WheelSlots_t::SLOT_BLUE_TOP_150)) {
bonusData.leech.lifeLeech += HEALTH_LEECH_INCREASE;
}
}
@@ -796,7 +796,7 @@ void IOWheel::slotBlueBottom75(const std::shared_ptr &player, uint16_t p
// SLOT_PURPLE_BOTTOM_75 = 28
void IOWheel::slotPurpleBottom75(const std::shared_ptr &player, uint16_t points, uint8_t, PlayerWheelMethodsBonusData &bonusData) const {
bonusData.mitigation += MITIGATION_INCREASE * points;
- if (isMaxPointAddedToSlot(player, points, WheelSlots_t::SLOT_PURPLE_BOTTOM_100)) {
+ if (isMaxPointAddedToSlot(player, points, WheelSlots_t::SLOT_PURPLE_BOTTOM_75)) {
bonusData.leech.manaLeech += MANA_LEECH_INCREASE;
}
}
@@ -898,7 +898,7 @@ void IOWheel::slotPurpleBottom150(const std::shared_ptr &player, uint16_
} else {
bonusData.stats.mana += 6 * points;
}
- if (isMaxPointAddedToSlot(player, points, WheelSlots_t::SLOT_PURPLE_TOP_150)) {
+ if (isMaxPointAddedToSlot(player, points, WheelSlots_t::SLOT_PURPLE_BOTTOM_150)) {
bonusData.leech.lifeLeech += HEALTH_LEECH_INCREASE;
}
}
diff --git a/src/io/iomarket.cpp b/src/io/iomarket.cpp
index ac79ef4c541..ca1bdb209d2 100644
--- a/src/io/iomarket.cpp
+++ b/src/io/iomarket.cpp
@@ -55,6 +55,7 @@ MarketOfferList IOMarket::getActiveOffers(MarketAction_t action) {
} while (result->next());
return offerList;
}
+
MarketOfferList IOMarket::getActiveOffers(MarketAction_t action, uint16_t itemId, uint8_t tier) {
MarketOfferList offerList;
diff --git a/src/items/functions/item/item_parse.cpp b/src/items/functions/item/item_parse.cpp
index e25954cf8c1..5bb10307e9d 100644
--- a/src/items/functions/item/item_parse.cpp
+++ b/src/items/functions/item/item_parse.cpp
@@ -1026,7 +1026,7 @@ void ItemParse::createAndRegisterScript(ItemType &itemType, pugi::xml_node attri
auto stringKey = asLowerCaseString(subKeyAttribute.as_string());
if (stringKey == "slot") {
auto slotName = asLowerCaseString(subValueAttribute.as_string());
- if (moveevent && slotName != "two-handed" && (moveevent->getEventType() == MOVE_EVENT_EQUIP || moveevent->getEventType() == MOVE_EVENT_DEEQUIP)) {
+ if (moveevent && (moveevent->getEventType() == MOVE_EVENT_EQUIP || moveevent->getEventType() == MOVE_EVENT_DEEQUIP)) {
if (slotName == "head") {
moveevent->setSlot(SLOTP_HEAD);
} else if (slotName == "necklace") {
@@ -1049,6 +1049,8 @@ void ItemParse::createAndRegisterScript(ItemType &itemType, pugi::xml_node attri
moveevent->setSlot(SLOTP_RING);
} else if (slotName == "ammo") {
moveevent->setSlot(SLOTP_AMMO);
+ } else if (slotName == "two-handed") {
+ moveevent->setSlot(SLOTP_TWO_HAND);
} else {
g_logger().warn("[{}] unknown slot type '{}'", __FUNCTION__, slotName);
}
@@ -1164,13 +1166,14 @@ void ItemParse::createAndRegisterScript(ItemType &itemType, pugi::xml_node attri
g_logger().warn("[{}] - wandtype '{}' does not exist", __FUNCTION__, elementName);
}
} else if (stringKey == "chain" && weapon) {
- if (auto value = subValueAttribute.as_double()) {
- weapon->setChainSkillValue(value);
- g_logger().trace("Found chain skill value '{}' for weapon: {}", value, itemType.name);
+ auto doubleValue = subValueAttribute.as_double();
+ if (doubleValue > 0) {
+ weapon->setChainSkillValue(doubleValue);
+ g_logger().trace("Found chain skill value '{}' for weapon: {}", doubleValue, itemType.name);
}
- if (subValueAttribute.as_bool() == false) {
+ if (doubleValue < 0.1 && subValueAttribute.as_bool() == false) {
weapon->setDisabledChain();
- g_logger().warn("Chain disabled for weapon: {}", itemType.name);
+ g_logger().trace("Chain disabled for weapon: {}", itemType.name);
}
}
}
diff --git a/src/items/weapons/weapons.cpp b/src/items/weapons/weapons.cpp
index aa90fda6c2d..6c0d56d882e 100644
--- a/src/items/weapons/weapons.cpp
+++ b/src/items/weapons/weapons.cpp
@@ -224,7 +224,6 @@ void Weapon::internalUseWeapon(std::shared_ptr player, std::shared_ptr player, std::shared_ptrdoCombatChain(player, target, params.aggressive);
+ g_logger().debug("Weapon::internalUseWeapon - Chain callback executed.");
} else {
Combat::doCombatHealth(player, target, damage, params);
}
@@ -888,17 +888,26 @@ int32_t WeaponWand::getWeaponDamage(std::shared_ptr player, std::shared_
}
// If chain system is enabled, calculates magic-based damage
- int32_t attackSkill;
- int32_t attackValue;
- float attackFactor;
- [[maybe_unused]] int16_t elementAttack;
+ int32_t attackSkill = 0;
+ int32_t attackValue = 0;
+ float attackFactor = 0.0;
+ [[maybe_unused]] int16_t elementAttack = 0;
[[maybe_unused]] CombatDamage combatDamage;
calculateSkillFormula(player, attackSkill, attackValue, attackFactor, elementAttack, combatDamage);
auto magLevel = player->getMagicLevel();
auto level = player->getLevel();
- double min = (level / 5.0) + (magLevel + attackValue) / 3.0;
- double max = (level / 5.0) + (magLevel + attackValue);
+
+ // Check if level is greater than zero before performing division
+ auto levelDivision = level > 0 ? level / 5.0 : 0.0;
+
+ auto totalAttackValue = magLevel + attackValue;
+
+ // Check if magLevel is greater than zero before performing division
+ auto magicLevelDivision = totalAttackValue > 0 ? totalAttackValue / 3.0 : 0.0;
+
+ double min = levelDivision + magicLevelDivision;
+ double max = levelDivision + totalAttackValue;
// Returns the calculated maximum damage or a random value between the calculated minimum and maximum
return maxDamage ? -max : -normal_random(min, max);
diff --git a/src/lua/creature/movement.cpp b/src/lua/creature/movement.cpp
index 076d2b90216..0af09476ed8 100644
--- a/src/lua/creature/movement.cpp
+++ b/src/lua/creature/movement.cpp
@@ -530,6 +530,7 @@ uint32_t MoveEvent::EquipItem(const std::shared_ptr moveEvent, std::s
}
if (player->isItemAbilityEnabled(slot)) {
+ g_logger().debug("[{}] item ability is already enabled", __FUNCTION__);
return 1;
}
diff --git a/src/server/network/connection/connection.cpp b/src/server/network/connection/connection.cpp
index 7d9de916263..41789b88387 100644
--- a/src/server/network/connection/connection.cpp
+++ b/src/server/network/connection/connection.cpp
@@ -175,7 +175,9 @@ void Connection::parseHeader(const std::error_code &error) {
readTimer.cancel();
if (error) {
- g_logger().debug("[Connection::parseHeader] - Read error: {}", error.message());
+ if (error != asio::error::operation_aborted && error != asio::error::eof && error != asio::error::connection_reset) {
+ g_logger().debug("[Connection::parseHeader] - Read error: {}", error.message());
+ }
close(FORCE_CLOSE);
return;
} else if (connectionState == CONNECTION_STATE_CLOSED) {
diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp
index 43fa9046cbb..5398155067e 100644
--- a/src/server/network/protocol/protocolgame.cpp
+++ b/src/server/network/protocol/protocolgame.cpp
@@ -3949,6 +3949,10 @@ void ProtocolGame::sendStats() {
}
void ProtocolGame::sendBasicData() {
+ if (!player) {
+ return;
+ }
+
NetworkMessage msg;
msg.addByte(0x9F);
if (player->isPremium() || player->isVip()) {
@@ -5921,7 +5925,12 @@ void ProtocolGame::sendRestingStatus(uint8_t protection) {
msg.addByte(0xA9);
msg.addByte(protection); // 1 / 0
- int32_t dailyStreak = static_cast(player->kv()->scoped("daily-reward")->get("streak")->getNumber());
+ uint8_t dailyStreak = 0;
+ auto dailyRewardKV = player->kv()->scoped("daily-reward")->get("streak");
+ if (dailyRewardKV && dailyRewardKV.has_value()) {
+ dailyStreak = static_cast(dailyRewardKV->getNumber());
+ }
+
msg.addByte(dailyStreak < 2 ? 0 : 1);
if (dailyStreak < 2) {
msg.addString("Resting Area (no active bonus)", "ProtocolGame::sendRestingStatus - Resting Area (no active bonus)");
@@ -6105,6 +6114,10 @@ void ProtocolGame::sendPartyCreatureShowStatus(std::shared_ptr target,
}
void ProtocolGame::sendPartyPlayerVocation(std::shared_ptr target) {
+ if (!target) {
+ return;
+ }
+
uint32_t cid = target->getID();
if (!knownCreatureSet.contains(cid)) {
sendPartyCreatureUpdate(target);
@@ -6124,7 +6137,7 @@ void ProtocolGame::sendPartyPlayerVocation(std::shared_ptr target) {
}
void ProtocolGame::sendPlayerVocation(std::shared_ptr target) {
- if (!player || oldProtocol) {
+ if (!player || !target || oldProtocol) {
return;
}
@@ -8618,7 +8631,7 @@ void ProtocolGame::sendMonsterPodiumWindow(std::shared_ptr
- podium, const P
}
void ProtocolGame::parseSetMonsterPodium(NetworkMessage &msg) const {
- if (oldProtocol) {
+ if (!player || oldProtocol) {
return;
}