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-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/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/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/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 14c0044ee66..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); } 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; }