From b61cd9d4227220dd46c408a11f55c6217d8ba7eb Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Tue, 12 Mar 2024 19:28:29 -0300 Subject: [PATCH 01/16] fix: null pointers check (#2422) --- src/io/iomarket.cpp | 1 + src/server/network/connection/connection.cpp | 4 +++- src/server/network/protocol/protocolgame.cpp | 19 ++++++++++++++++--- 3 files changed, 20 insertions(+), 4 deletions(-) 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/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; } From c6895eb063d564a479e4a42e4c1d15f241f9aa9e Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Tue, 12 Mar 2024 19:32:53 -0300 Subject: [PATCH 02/16] fix: loop related to decay items with duration (#2419) Fixes a loop related to decay item with duration Resolves #1074 --- src/game/game.cpp | 10 +++++++++- src/lua/creature/movement.cpp | 11 ++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) 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/lua/creature/movement.cpp b/src/lua/creature/movement.cpp index 076d2b90216..862c1902788 100644 --- a/src/lua/creature/movement.cpp +++ b/src/lua/creature/movement.cpp @@ -524,17 +524,18 @@ uint32_t MoveEvent::EquipItem(const std::shared_ptr moveEvent, std::s return 1; } - const ItemType &it = Item::items[item->getID()]; - if (it.transformEquipTo != 0) { - g_game().transformItem(item, it.transformEquipTo); - } - if (player->isItemAbilityEnabled(slot)) { + g_logger().debug("[{}] item ability is already enabled", __FUNCTION__); return 1; } player->setItemAbility(slot, true); + const ItemType &it = Item::items[item->getID()]; + if (it.transformEquipTo != 0) { + g_game().transformItem(item, it.transformEquipTo); + } + for (uint8_t slotid = 0; slotid < item->getImbuementSlot(); slotid++) { player->updateImbuementTrackerStats(); ImbuementInfo imbuementInfo; From beb74ab40c4503d9209374f5b1cd22ee4960d465 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Tue, 12 Mar 2024 19:34:53 -0300 Subject: [PATCH 03/16] fix: move loading of achievements to player login (#2420) Fixes achievement loading bug. In some scenarios, the "kv_store" may not have been read yet and therefore in the constructor it will still be nil. --- .../achievement/player_achievement.cpp | 29 +++++++++++-------- .../achievement/player_achievement.hpp | 1 + src/io/functions/iologindata_load_player.cpp | 3 ++ 3 files changed, 21 insertions(+), 12 deletions(-) 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/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(); } From d2a5b8f889ea5d4dfcba384a93e2a1bdc536441f Mon Sep 17 00:00:00 2001 From: Aerwix Date: Wed, 13 Mar 2024 07:51:53 -0600 Subject: [PATCH 04/16] feat: monster balancing from cipsoft (#2427) --- data-canary/monster/demons/fury.lua | 2 +- data-otservbr-global/monster/demons/hellfire_fighter.lua | 2 +- data-otservbr-global/monster/demons/hellflayer.lua | 2 +- data-otservbr-global/monster/demons/juggernaut.lua | 4 ++-- data-otservbr-global/monster/demons/plaguesmith.lua | 2 +- data-otservbr-global/monster/magicals/nightmare.lua | 2 +- .../ferumbras_ascendant/bosses/ferumbras_mortal_shell.lua | 2 +- .../monster/quests/ferumbras_ascendant/bosses/mazoran.lua | 2 +- .../monster/quests/ferumbras_ascendant/bosses/plagirath.lua | 2 +- .../monster/quests/ferumbras_ascendant/bosses/ragiaz.lua | 2 +- .../monster/quests/ferumbras_ascendant/bosses/razzagorn.lua | 2 +- .../monster/quests/ferumbras_ascendant/bosses/shulgrax.lua | 2 +- .../monster/quests/ferumbras_ascendant/bosses/tarbaz.lua | 2 +- .../monster/quests/ferumbras_ascendant/bosses/zamulosh.lua | 2 +- data-otservbr-global/monster/undeads/blightwalker.lua | 4 ++-- data-otservbr-global/monster/undeads/hand_of_cursed_fate.lua | 4 ++-- data-otservbr-global/monster/undeads/undead_dragon.lua | 2 +- 17 files changed, 20 insertions(+), 20 deletions(-) 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-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 }, } From f2eb82ea440aa8a53df0524d7010e84e41596b96 Mon Sep 17 00:00:00 2001 From: Luan Luciano Date: Thu, 14 Mar 2024 12:36:06 -0300 Subject: [PATCH 05/16] fix: typo in savePlayerStorage function (#2435) --- src/io/functions/iologindata_save_player.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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>>; From 7d18c431046fa5e841508ee7836eb4ecbf068faf Mon Sep 17 00:00:00 2001 From: Marco Date: Thu, 14 Mar 2024 12:37:39 -0300 Subject: [PATCH 06/16] refactor: move tools to data path (#2434) --- data-canary/scripts/actions/tools/crowbar.lua | 8 -------- data-canary/scripts/actions/tools/machete.lua | 8 -------- data-canary/scripts/actions/tools/pick.lua | 8 -------- data-canary/scripts/actions/tools/rope.lua | 8 -------- data-canary/scripts/actions/tools/scythe.lua | 8 -------- data-canary/scripts/actions/tools/shovel.lua | 8 -------- data-canary/scripts/actions/tools/spoon.lua | 8 -------- .../scripts/actions/tools/crowbar.lua | 0 .../scripts/actions/tools/machete.lua | 0 .../scripts/actions/tools/pick.lua | 0 .../scripts/actions/tools/rope.lua | 0 .../scripts/actions/tools/scythe.lua | 0 .../scripts/actions/tools/shovel.lua | 0 .../scripts/actions/tools/spoon.lua | 0 14 files changed, 56 deletions(-) delete mode 100644 data-canary/scripts/actions/tools/crowbar.lua delete mode 100644 data-canary/scripts/actions/tools/machete.lua delete mode 100644 data-canary/scripts/actions/tools/pick.lua delete mode 100644 data-canary/scripts/actions/tools/rope.lua delete mode 100644 data-canary/scripts/actions/tools/scythe.lua delete mode 100644 data-canary/scripts/actions/tools/shovel.lua delete mode 100644 data-canary/scripts/actions/tools/spoon.lua rename {data-otservbr-global => data}/scripts/actions/tools/crowbar.lua (100%) rename {data-otservbr-global => data}/scripts/actions/tools/machete.lua (100%) rename {data-otservbr-global => data}/scripts/actions/tools/pick.lua (100%) rename {data-otservbr-global => data}/scripts/actions/tools/rope.lua (100%) rename {data-otservbr-global => data}/scripts/actions/tools/scythe.lua (100%) rename {data-otservbr-global => data}/scripts/actions/tools/shovel.lua (100%) rename {data-otservbr-global => data}/scripts/actions/tools/spoon.lua (100%) 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/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 From cba26d7909dd1922a10cc3ef151ff0b33aa1d230 Mon Sep 17 00:00:00 2001 From: sebbesiren <35768829+sebbesiren@users.noreply.github.com> Date: Thu, 14 Mar 2024 20:15:49 +0100 Subject: [PATCH 07/16] fix: two-handed being equipped in right hand on unequip (#2436) Equipping a two-handed weapon using keybind and then unequipping it placed the two-handed weapon in right hand. The change makes the right hand not a possible slot for a two-handed weapon which forces it to be placed in backpack similar to other equipment. --- src/creatures/players/player.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) 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(); From 93b378608f58134436bd2297047a8d40a2b035e5 Mon Sep 17 00:00:00 2001 From: Dvineone Date: Thu, 14 Mar 2024 15:49:55 -0500 Subject: [PATCH 08/16] fix: added check for type 'two-handed' (#2410) Warnings when starting the server. --- src/items/functions/item/item_parse.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/items/functions/item/item_parse.cpp b/src/items/functions/item/item_parse.cpp index e25954cf8c1..e4195c0aefb 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); } From 50da833a802cdaf98fcc836cf65dc4655850ff6c Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Thu, 14 Mar 2024 18:47:58 -0300 Subject: [PATCH 09/16] fix: skill duplication on equip item (#2439) Revert send mistake from: https://github.com/opentibiabr/canary/commit/c6895eb063d564a479e4a42e4c1d15f241f9aa9e --- src/lua/creature/movement.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lua/creature/movement.cpp b/src/lua/creature/movement.cpp index 862c1902788..0af09476ed8 100644 --- a/src/lua/creature/movement.cpp +++ b/src/lua/creature/movement.cpp @@ -524,6 +524,11 @@ uint32_t MoveEvent::EquipItem(const std::shared_ptr moveEvent, std::s return 1; } + const ItemType &it = Item::items[item->getID()]; + if (it.transformEquipTo != 0) { + g_game().transformItem(item, it.transformEquipTo); + } + if (player->isItemAbilityEnabled(slot)) { g_logger().debug("[{}] item ability is already enabled", __FUNCTION__); return 1; @@ -531,11 +536,6 @@ uint32_t MoveEvent::EquipItem(const std::shared_ptr moveEvent, std::s player->setItemAbility(slot, true); - const ItemType &it = Item::items[item->getID()]; - if (it.transformEquipTo != 0) { - g_game().transformItem(item, it.transformEquipTo); - } - for (uint8_t slotid = 0; slotid < item->getImbuementSlot(); slotid++) { player->updateImbuementTrackerStats(); ImbuementInfo imbuementInfo; From af7126a27f676cbb4a6d18d89a02b7703b63fe76 Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Sat, 16 Mar 2024 00:21:24 -0300 Subject: [PATCH 10/16] fix: hazard mount and achievement (#2431) --- data-otservbr-global/npc/gnomadness.lua | 7 ++++--- data/scripts/lib/register_achievements.lua | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) 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/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." }, } --[[ From d643fba748b329076159ec3f5f98f3c631ec4b67 Mon Sep 17 00:00:00 2001 From: Luan Santos Date: Sun, 17 Mar 2024 13:12:27 -0700 Subject: [PATCH 11/16] fix: check if bankable is valid player before emitting metric (#2453) --- src/game/bank/bank.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) 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); } From e9e99675c65a25325f8f9ff43daae4a7beac4f49 Mon Sep 17 00:00:00 2001 From: Elson Costa Date: Mon, 18 Mar 2024 14:45:11 -0300 Subject: [PATCH 12/16] fix: global server save and expBoostCount improvements (#2449) --- data/modules/scripts/gamestore/init.lua | 4 ++-- data/scripts/globalevents/global_server_save.lua | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) 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/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 From bb886a46e15f440c70adce79a91519d14cc16829 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Mon, 18 Mar 2024 18:21:53 -0300 Subject: [PATCH 13/16] fix: sonar bugs related to uninitialized variable (#2462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Initialized variables • Guaranteed that there is no division by 0, avoiding crash --- src/items/weapons/weapons.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) 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); From 034695599a75c030d393c324338f52281afc9059 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Mon, 18 Mar 2024 18:23:38 -0300 Subject: [PATCH 14/16] fix: two-handed weapons attributes (#2461) Resolves #2442 Co-authored-by: Lpcordovilll <162099109+lpcordovilll@users.noreply.github.com> --- data/items/items.xml | 172 ------------------------------------------- 1 file changed, 172 deletions(-) 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"/> - From 39d0d840db934d678f02cafcdc65ab1ef8596224 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Mon, 18 Mar 2024 18:29:50 -0300 Subject: [PATCH 15/16] fix: wheel bugs (#2417) Added some missing wheel modifiers. Fixed some wrong wheel slots. --- src/creatures/players/wheel/player_wheel.cpp | 51 +++++++++++++++++++- src/creatures/players/wheel/player_wheel.hpp | 2 + src/io/io_wheel.cpp | 12 ++--- 3 files changed, 58 insertions(+), 7 deletions(-) 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/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; } } From 4a661ef2c1a5333e189dbdeb15483f9dba44ab55 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Mon, 18 Mar 2024 20:36:46 -0300 Subject: [PATCH 16/16] fix: register weapon with chain attribute (#2421) Log moved to trace and fixed a minor error in the deactivation logic. --- src/items/functions/item/item_parse.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/items/functions/item/item_parse.cpp b/src/items/functions/item/item_parse.cpp index e4195c0aefb..5bb10307e9d 100644 --- a/src/items/functions/item/item_parse.cpp +++ b/src/items/functions/item/item_parse.cpp @@ -1166,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); } } }