From ba6ad33ff6351cb386d616a9b6197e691cc2fe00 Mon Sep 17 00:00:00 2001 From: Pedro Cruz Date: Mon, 18 Nov 2024 15:08:12 -0300 Subject: [PATCH 1/5] fix: wheel spells bonuses (#3122) This fixes the issue that some spells was sharing bonuses between all other spells --- src/creatures/combat/spells.cpp | 3 --- src/creatures/combat/spells.hpp | 6 +++--- src/io/io_wheel.cpp | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/creatures/combat/spells.cpp b/src/creatures/combat/spells.cpp index 327d97f3284..f522eac86a6 100644 --- a/src/creatures/combat/spells.cpp +++ b/src/creatures/combat/spells.cpp @@ -23,9 +23,6 @@ #include "lua/scripts/scripts.hpp" #include "lib/di/container.hpp" -std::array(WheelSpellBoost_t::TOTAL_COUNT)> wheelOfDestinyRegularBoost = { 0 }; -std::array(WheelSpellBoost_t::TOTAL_COUNT)> wheelOfDestinyUpgradedBoost = { 0 }; - Spells::Spells() = default; Spells::~Spells() = default; diff --git a/src/creatures/combat/spells.hpp b/src/creatures/combat/spells.hpp index 5d9edb70dd6..56ff1a330de 100644 --- a/src/creatures/combat/spells.hpp +++ b/src/creatures/combat/spells.hpp @@ -10,9 +10,7 @@ #pragma once #include "lua/creature/actions.hpp" - -enum class WheelSpellBoost_t : uint8_t; -enum class WheelSpellGrade_t : uint8_t; +#include "creatures/players/wheel/wheel_definitions.hpp" class InstantSpell; class RuneSpell; @@ -256,6 +254,8 @@ class Spell : public BaseSpell { bool pzLocked = false; bool whellOfDestinyUpgraded = false; + std::array(WheelSpellBoost_t::TOTAL_COUNT)> wheelOfDestinyRegularBoost = { 0 }; + std::array(WheelSpellBoost_t::TOTAL_COUNT)> wheelOfDestinyUpgradedBoost = { 0 }; private: uint32_t mana = 0; diff --git a/src/io/io_wheel.cpp b/src/io/io_wheel.cpp index 2e1b57c79bc..cfcf6593010 100644 --- a/src/io/io_wheel.cpp +++ b/src/io/io_wheel.cpp @@ -58,7 +58,7 @@ namespace InternalPlayerWheel { return; } - auto spell = g_spells().getInstantSpellByName(name); + const auto &spell = g_spells().getInstantSpellByName(name); if (spell) { g_logger().trace("[{}] registering instant spell with name {}", __FUNCTION__, spell->getName()); // Increase data @@ -127,7 +127,7 @@ bool IOWheel::initializeGlobalData(bool reload /* = false*/) { // Register spells for druid for (const auto &data : getWheelBonusData().spells.druid) { for (size_t i = 1; i < 3; ++i) { - const auto grade = data.grade[i]; + const auto &grade = data.grade[i]; InternalPlayerWheel::registerWheelSpellTable(grade, data.name, static_cast(i)); } } From 3bdad994189c8d956515e031b3094864bd1b84f0 Mon Sep 17 00:00:00 2001 From: murilo09 <78226931+murilo09@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:50:17 -0300 Subject: [PATCH 2/5] fix: blessings calculations (#3126) Wrong blessing calculations --- src/creatures/players/player.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index d838f8b96a0..a2cf64bc809 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -3517,7 +3517,7 @@ void Player::death(const std::shared_ptr &lastHitCreature) { } // Level loss - auto expLoss = static_cast(std::ceil((experience * deathLossPercent) / 100.)); + auto expLoss = static_cast(std::ceil(experience * deathLossPercent)); g_logger().debug("[{}] - experience lost {}", __FUNCTION__, expLoss); g_events().eventPlayerOnLoseExperience(static_self_cast(), expLoss); @@ -6323,9 +6323,9 @@ double Player::getLostPercent() const { g_logger().debug("[{}] - after promotion {}", __FUNCTION__, percentReduction); } - g_logger().debug("[{}] - total lost percent {}", __FUNCTION__, lossPercent - (lossPercent * percentReduction)); + g_logger().debug("[{}] - total lost percent {}", __FUNCTION__, (lossPercent * (1 - percentReduction)) / 100.); - return lossPercent - (lossPercent * percentReduction); + return (lossPercent * (1 - percentReduction)) / 100.; } [[nodiscard]] const std::string &Player::getGuildNick() const { From 93448b8d65fc699e4c4ca0ca7e4f6c5d8345c305 Mon Sep 17 00:00:00 2001 From: Pedro Cruz Date: Mon, 18 Nov 2024 20:01:42 -0300 Subject: [PATCH 3/5] fix: wands and rods chain damage (#3128) This fixes the damage when chain system enabled for wands and rods. Fixes #2472 --- src/items/weapons/weapons.cpp | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/src/items/weapons/weapons.cpp b/src/items/weapons/weapons.cpp index 4eb84d246c6..2ec09945f36 100644 --- a/src/items/weapons/weapons.cpp +++ b/src/items/weapons/weapons.cpp @@ -942,35 +942,7 @@ void WeaponWand::configureWeapon(const ItemType &it) { } int32_t WeaponWand::getWeaponDamage(const std::shared_ptr &player, const std::shared_ptr &, const std::shared_ptr &, bool maxDamage /* = false*/) const { - if (!g_configManager().getBoolean(TOGGLE_CHAIN_SYSTEM)) { - // Returns maximum damage or a random value between minChange and maxChange - return maxDamage ? -maxChange : -normal_random(minChange, maxChange); - } - - // If chain system is enabled, calculates magic-based damage - 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); - - const auto magLevel = player->getMagicLevel(); - const auto level = player->getLevel(); - - // Check if level is greater than zero before performing division - const auto levelDivision = level > 0 ? level / 5.0 : 0.0; - - const auto totalAttackValue = magLevel + attackValue; - - // Check if magLevel is greater than zero before performing division - const auto magicLevelDivision = totalAttackValue > 0 ? totalAttackValue / 3.0 : 0.0; - - const double min = levelDivision + magicLevelDivision; - const 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); + return maxDamage ? -maxChange : -normal_random(minChange, maxChange); } int16_t WeaponWand::getElementDamageValue() const { From 46553572781b032382f876f048f234da30679505 Mon Sep 17 00:00:00 2001 From: Pedro Cruz Date: Mon, 18 Nov 2024 20:44:59 -0300 Subject: [PATCH 4/5] fix: ebb and flow boat summons teleport (#3125) This fixes the ebb and flow boat teleport that was not teleporting player summons Fixes #2943 --- data-otservbr-global/lib/quests/soul_war.lua | 6 +- .../globalevent-ebb_and_flow_change_maps.lua | 64 ++++++++++++------- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/data-otservbr-global/lib/quests/soul_war.lua b/data-otservbr-global/lib/quests/soul_war.lua index f5b2d75f5ba..a6058bc4715 100644 --- a/data-otservbr-global/lib/quests/soul_war.lua +++ b/data-otservbr-global/lib/quests/soul_war.lua @@ -1455,7 +1455,7 @@ function Player:getSoulWarZoneMonster() return zoneMonsterName end -function Player:isInBoatSpot() +function Creature:isInBoatSpot() -- Get ebb and flow zone and check if player is in zone local zone = SoulWarQuest.ebbAndFlow.getZone() local tile = Tile(self:getPosition()) @@ -1464,11 +1464,11 @@ function Player:isInBoatSpot() groundId = tile:getGround():getId() end if zone and zone:isInZone(self:getPosition()) and tile and groundId == SoulWarQuest.ebbAndFlow.boatId then - logger.trace("Player {} is in boat spot", self:getName()) + logger.trace("Creature {} is in boat spot", self:getName()) return true end - logger.trace("Player {} is not in boat spot", self:getName()) + logger.trace("Creature {} is not in boat spot", self:getName()) return false end diff --git a/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua b/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua index 91273ac4cbd..e5166038db2 100644 --- a/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua +++ b/data-otservbr-global/scripts/quests/soul_war/globalevent-ebb_and_flow_change_maps.lua @@ -18,17 +18,25 @@ local function updateWaterPoolsSize() end local function loadMapEmpty() - if SoulWarQuest.ebbAndFlow.getZone():countPlayers() > 0 then - local players = SoulWarQuest.ebbAndFlow.getZone():getPlayers() - for _, player in ipairs(players) do - if player:getPosition().z == 8 then - if player:isInBoatSpot() then - local teleportPosition = player:getPosition() - teleportPosition.z = 9 - player:teleportTo(teleportPosition) - logger.trace("Teleporting player to down.") + local playersInZone = SoulWarQuest.ebbAndFlow.getZone():countPlayers() + local monstersInZone = SoulWarQuest.ebbAndFlow.getZone():countMonsters() + if playersInZone > 0 or monstersInZone > 0 then + local creatures = SoulWarQuest.ebbAndFlow.getZone():getCreatures() + for _, creature in ipairs(creatures) do + local creatureMaster = creature:getMaster() + local player = creature:getPlayer() + if creature:isPlayer() or (creature:isMonster() and creatureMaster and creatureMaster:getPlayer()) then + if creature:getPosition().z == 8 then + if creature:isInBoatSpot() then + local teleportPosition = creature:getPosition() + teleportPosition.z = 9 + creature:teleportTo(teleportPosition) + logger.trace("Teleporting player to down.") + end + if player then + player:sendCreatureAppear() + end end - player:sendCreatureAppear() end end end @@ -72,22 +80,30 @@ local function findNearestRoomPosition(playerPosition) end local function loadMapInundate() - if SoulWarQuest.ebbAndFlow.getZone():countPlayers() > 0 then - local players = SoulWarQuest.ebbAndFlow.getZone():getPlayers() - for _, player in ipairs(players) do - local playerPosition = player:getPosition() - if playerPosition.z == 9 then - if player:isInBoatSpot() then - local nearestCenterPosition = findNearestRoomPosition(playerPosition) - player:teleportTo(nearestCenterPosition) - logger.trace("Teleporting player to the near center position room and updating tile.") - else - player:teleportTo(SoulWarQuest.ebbAndFlow.waitPosition) - logger.trace("Teleporting player to wait position and updating tile.") + local playersInZone = SoulWarQuest.ebbAndFlow.getZone():countPlayers() + local monstersInZone = SoulWarQuest.ebbAndFlow.getZone():countMonsters() + if playersInZone > 0 or monstersInZone > 0 then + local creatures = SoulWarQuest.ebbAndFlow.getZone():getCreatures() + for _, creature in ipairs(creatures) do + local creatureMaster = creature:getMaster() + local player = creature:getPlayer() + if creature:isPlayer() or (creature:isMonster() and creatureMaster and creatureMaster:getPlayer()) then + local creaturePosition = creature:getPosition() + if creaturePosition.z == 9 then + if creature:isInBoatSpot() then + local nearestCenterPosition = findNearestRoomPosition(creaturePosition) + creature:teleportTo(nearestCenterPosition) + logger.trace("Teleporting player to the near center position room and updating tile.") + else + creature:teleportTo(SoulWarQuest.ebbAndFlow.waitPosition) + logger.trace("Teleporting player to wait position and updating tile.") + end + creaturePosition:sendMagicEffect(CONST_ME_TELEPORT) + end + if player then + player:sendCreatureAppear() end - playerPosition:sendMagicEffect(CONST_ME_TELEPORT) end - player:sendCreatureAppear() end end From 5072de83e91d4937070998c206217a087913e20f Mon Sep 17 00:00:00 2001 From: Pedro Cruz Date: Mon, 18 Nov 2024 20:49:34 -0300 Subject: [PATCH 5/5] fix: xp rates display (#3123) This fixes the display xp rates with low level bonus and boost xp. --- src/creatures/players/player.cpp | 8 ++++++++ src/creatures/players/player.hpp | 2 ++ src/server/network/protocol/protocolgame.cpp | 8 ++++---- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index a2cf64bc809..3ef1d64e982 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -2739,6 +2739,10 @@ uint16_t Player::getGrindingXpBoost() const { return grindingXpBoost; } +uint16_t Player::getDisplayGrindingXpBoost() const { + return std::clamp(grindingXpBoost * (baseXpGain / 100), 0, std::numeric_limits::max()); +} + void Player::setGrindingXpBoost(uint16_t value) { grindingXpBoost = std::min(std::numeric_limits::max(), value); } @@ -2747,6 +2751,10 @@ uint16_t Player::getXpBoostPercent() const { return xpBoostPercent; } +uint16_t Player::getDisplayXpBoostPercent() const { + return std::clamp(xpBoostPercent * (baseXpGain / 100), 0, std::numeric_limits::max()); +} + void Player::setXpBoostPercent(uint16_t percent) { xpBoostPercent = percent; } diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp index 03f248cfa2f..6ab3be4ca7a 100644 --- a/src/creatures/players/player.hpp +++ b/src/creatures/players/player.hpp @@ -972,8 +972,10 @@ class Player final : public Creature, public Cylinder, public Bankable { uint16_t getVoucherXpBoost() const; void setVoucherXpBoost(uint16_t value); uint16_t getGrindingXpBoost() const; + uint16_t getDisplayGrindingXpBoost() const; void setGrindingXpBoost(uint16_t value); uint16_t getXpBoostPercent() const; + uint16_t getDisplayXpBoostPercent() const; void setXpBoostPercent(uint16_t percent); uint16_t getStaminaXpBoost() const; void setStaminaXpBoost(uint16_t value); diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 727c1cc0097..38f7600310e 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -3480,8 +3480,8 @@ void ProtocolGame::sendCyclopediaCharacterGeneralStats() { msg.add(player->getLevel()); msg.addByte(player->getLevelPercent()); msg.add(player->getBaseXpGain()); // BaseXPGainRate - msg.add(player->getGrindingXpBoost()); // LowLevelBonus - msg.add(player->getXpBoostPercent()); // XPBoost + msg.add(player->getDisplayGrindingXpBoost()); // LowLevelBonus + msg.add(player->getDisplayXpBoostPercent()); // XPBoost msg.add(player->getStaminaXpBoost()); // StaminaMultiplier(100=x1.0) msg.add(player->getXpBoostTime()); // xpBoostRemainingTime msg.addByte(player->getXpBoostTime() > 0 ? 0x00 : 0x01); // canBuyXpBoost @@ -7840,8 +7840,8 @@ void ProtocolGame::AddPlayerStats(NetworkMessage &msg) { msg.add(player->getVoucherXpBoost()); // xp voucher } - msg.add(player->getGrindingXpBoost()); // low level bonus - msg.add(player->getXpBoostPercent()); // xp boost + msg.add(player->getDisplayGrindingXpBoost()); // low level bonus + msg.add(player->getDisplayXpBoostPercent()); // xp boost msg.add(player->getStaminaXpBoost()); // stamina multiplier (100 = 1.0x) if (!oldProtocol) {