Skip to content

Commit

Permalink
fix: wrong calculation from elemental damage for weapons
Browse files Browse the repository at this point in the history
  • Loading branch information
dudantas committed Dec 21, 2024
1 parent 34b6fa8 commit 1b088d9
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 10 deletions.
17 changes: 17 additions & 0 deletions src/creatures/monsters/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "lua/callbacks/event_callback.hpp"
#include "lua/callbacks/events_callbacks.hpp"
#include "map/spectators.hpp"
#include "items/weapons/weapons.hpp"

int32_t Monster::despawnRange;
int32_t Monster::despawnRadius;
Expand Down Expand Up @@ -2660,3 +2661,19 @@ void Monster::onExecuteAsyncTasks() {
updateIdleStatus();
}
}

std::map<CombatType_t, int32_t> Monster::calculateElementalDamage(CombatType_t weaponElement, int32_t baseDamage
) const {
std::map<CombatType_t, int32_t> damageByElement;
// Start with the base damage assigned to the weapon's element type
int32_t elementDamage = baseDamage;
// Check the monster's resistance/weakness for the element type
auto it = mType->info.elementMap.find(weaponElement);
if (it != mType->info.elementMap.end()) {
int32_t elementMod = it->second; // Monster's resistance or weakness
elementDamage = static_cast<int32_t>(std::round(elementDamage * ((100 - elementMod) / 100.0)));
}
// Add the calculated damage to the result map
damageByElement[weaponElement] = elementDamage;
return damageByElement;
}
5 changes: 5 additions & 0 deletions src/creatures/monsters/monster.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,11 @@ class Monster final : public Creature {

void setDead(bool isDead);

std::map<CombatType_t, int32_t> calculateElementalDamage(
CombatType_t weaponElement,
int32_t baseDamage
) const;

protected:
void onExecuteAsyncTasks() override;

Expand Down
67 changes: 57 additions & 10 deletions src/items/weapons/weapons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,26 @@ void Weapon::internalUseWeapon(const std::shared_ptr<Player> &player, const std:
damage.origin = ORIGIN_MELEE;
}

// Define the primary and secondary damage types
damage.primary.type = params.combatType;
damage.primary.value = (getWeaponDamage(player, target, item) * damageModifier) / 100;
damage.secondary.type = getElementType();

// Cleave damage
// Step 1: Calculate total damage
const int32_t totalDamage = (getWeaponDamage(player, target, item) * damageModifier) / 100;
if (damage.secondary.type != COMBAT_NONE) {
// Step 2: Use the helper function to distribute the damage
auto [physicalDamage, elementalDamage] = calculateDamageDistribution(target, totalDamage);
// Step 3: Assign the calculated values to the damage object
damage.primary.value = physicalDamage;
damage.secondary.value = elementalDamage;
} else {
// Step 2: Assign the total damage to the primary value
damage.primary.value = totalDamage;
damage.secondary.value = 0;
}

// Apply cleave adjustments if applicable
uint16_t damagePercent = 100;
if (cleavePercent != 0) {
damage.extension = true;
Expand All @@ -271,16 +286,11 @@ void Weapon::internalUseWeapon(const std::shared_ptr<Player> &player, const std:
damage.exString += ", ";
}
damage.exString += "cleave damage";
damage.primary.value = (damage.primary.value * damagePercent) / 100;
damage.secondary.value = (damage.secondary.value * damagePercent) / 100;
}

if (damage.secondary.type == COMBAT_NONE) {
damage.primary.value = (getWeaponDamage(player, target, item) * damageModifier / 100) * damagePercent / 100;
damage.secondary.value = 0;
} else {
damage.primary.value = (getWeaponDamage(player, target, item) * damageModifier / 100) * damagePercent / 100;
damage.secondary.value = (getElementDamage(player, target, item) * damageModifier / 100) * damagePercent / 100;
}

// Handle chain system
if (g_configManager().getBoolean(TOGGLE_CHAIN_SYSTEM) && params.chainCallback) {
m_combat->doCombatChain(player, target, params.aggressive);
g_logger().debug("Weapon::internalUseWeapon - Chain callback executed.");
Expand Down Expand Up @@ -484,6 +494,43 @@ std::shared_ptr<Combat> Weapon::getCombat() {
return m_combat;
}

std::pair<int32_t, int32_t> Weapon::calculateDamageDistribution(
const std::shared_ptr<Creature> &target,
int32_t totalDamage
) const {
// Default damage distribution percentages
constexpr float DEFAULT_ELEMENTAL_PERCENTAGE = 0.666f; // 2/3 elemental damage
constexpr float DEFAULT_PHYSICAL_PERCENTAGE = 1.0f - DEFAULT_ELEMENTAL_PERCENTAGE;
// Initialize damage percentages
float elementalPercentage = DEFAULT_ELEMENTAL_PERCENTAGE;
float physicalPercentage = DEFAULT_PHYSICAL_PERCENTAGE;
// Check if the target is a player
const auto &targetPlayer = target ? target->getPlayer() : nullptr;
if (targetPlayer) {
// Players have no weaknesses, damage is split 50/50
elementalPercentage = 0.5f;
physicalPercentage = 0.5f;
}
// Calculate base physical and elemental damage
int32_t physicalDamage = static_cast<int32_t>(totalDamage * physicalPercentage);
int32_t elementalDamage = static_cast<int32_t>(totalDamage * elementalPercentage);
// Apply resistance/weakness modifiers for monsters only
if (!targetPlayer && target) {
const auto &targetMonster = target->getMonster();
// Use the Monster::calculateElementalDamage function
if (targetMonster) {
auto elementType = getElementType();
auto elementDamageMap = targetMonster->calculateElementalDamage(elementType, elementalDamage);

Check failure on line 523 in src/items/weapons/weapons.cpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

invalid use of incomplete type ‘using element_type = class Monster’ {aka ‘class Monster’}

Check failure on line 523 in src/items/weapons/weapons.cpp

View workflow job for this annotation

GitHub Actions / ubuntu-24.04-linux-debug

invalid use of incomplete type ‘using std::__shared_ptr_access<Monster, __gnu_cxx::_S_atomic, false, false>::element_type = class Monster’ {aka ‘class Monster’}
auto it = elementDamageMap.find(elementType);
if (it != elementDamageMap.end()) {
elementalDamage = it->second; // Update elemental damage with calculated value
}
}
}
// Return the calculated damage distribution
return {physicalDamage, elementalDamage};
}

WeaponMelee::WeaponMelee() {
// Add combat type and blocked attributes to the weapon
params.blockedByArmor = true;
Expand Down Expand Up @@ -629,7 +676,7 @@ int32_t WeaponMelee::getWeaponDamage(const std::shared_ptr<Player> &player, cons
return -maxValue;
}

return -normal_random(minValue, (maxValue * static_cast<int32_t>(player->getVocation()->meleeDamageMultiplier)));
return -normal_random(minValue, maxValue);
}

WeaponDistance::WeaponDistance() {
Expand Down
4 changes: 4 additions & 0 deletions src/items/weapons/weapons.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ class Weapon {
std::shared_ptr<Combat> getCombat();

bool calculateSkillFormula(const std::shared_ptr<Player> &player, int32_t &attackSkill, int32_t &attackValue, float &attackFactor, int16_t &elementAttack, CombatDamage &damage, bool useCharges = false) const;
std::pair<int32_t, int32_t> calculateDamageDistribution(
const std::shared_ptr<Creature> &target,
int32_t totalDamage
) const;

LuaScriptInterface* getScriptInterface() const;
bool loadScriptId();
Expand Down

0 comments on commit 1b088d9

Please sign in to comment.