diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index f5163f17c..53c796e07 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -215,13 +215,13 @@ bool TemporaryThreatModifierEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) return true; } -Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(), m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0), m_lootRecipientGroup(0), +Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(), m_groupLootTimer(0), lootingGroupLowGUID(0), m_lootRecipientGroup(0), m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_wanderDistance(0.0f), m_boundaryCheckTime(2500), m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), _lastDamagedTime(nullptr), m_cannotReachTarget(false), m_cannotReachTimer(0), - _isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0) + _isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0), _playerDamageReq(0), _damagedByPlayer(false) { m_regenTimer = CREATURE_REGEN_INTERVAL; m_valuesCount = UNIT_END; @@ -526,7 +526,7 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele uint32 previousHealth = GetHealth(); uint32 previousMaxHealth = GetMaxHealth(); - uint32 previousPlayerDamageReq = m_PlayerDamageReq; + uint32 previousPlayerDamageReq = _playerDamageReq; SelectLevel(changelevel); if (previousHealth > 0) @@ -535,11 +535,11 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele if (previousMaxHealth && previousMaxHealth > GetMaxHealth()) { - m_PlayerDamageReq = (uint32)(previousPlayerDamageReq * GetMaxHealth() / previousMaxHealth); + _playerDamageReq = (uint32)(previousPlayerDamageReq * GetMaxHealth() / previousMaxHealth); } else { - m_PlayerDamageReq = previousPlayerDamageReq; + _playerDamageReq = previousPlayerDamageReq; } } @@ -3573,3 +3573,30 @@ void Creature::ModifyThreatPercentTemp(Unit* victim, int32 percent, Milliseconds m_Events.AddEvent(pEvent, m_Events.CalculateTime(duration.count())); } } + +bool Creature::IsDamageEnoughForLootingAndReward() const +{ + return (m_creatureInfo->flags_extra & CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ) || (_playerDamageReq == 0 && _damagedByPlayer); +} + +void Creature::LowerPlayerDamageReq(uint32 unDamage, bool damagedByPlayer /*= true*/) +{ + if (_playerDamageReq) + _playerDamageReq > unDamage ? _playerDamageReq -= unDamage : _playerDamageReq = 0; + + if (!_damagedByPlayer) + { + _damagedByPlayer = damagedByPlayer; + } +} + +void Creature::ResetPlayerDamageReq() +{ + _playerDamageReq = GetHealth() / 2; + _damagedByPlayer = false; +} + +uint32 Creature::GetPlayerDamageReq() const +{ + return _playerDamageReq; +} diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 8355ce428..4f2f3eccf 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -341,14 +341,10 @@ public: void SetDisableReputationGain(bool disable) { DisableReputationGain = disable; } [[nodiscard]] bool IsReputationGainDisabled() const { return DisableReputationGain; } - [[nodiscard]] bool IsDamageEnoughForLootingAndReward() const { return (m_creatureInfo->flags_extra & CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ) || (m_PlayerDamageReq == 0); } - void LowerPlayerDamageReq(uint32 unDamage) - { - if (m_PlayerDamageReq) - m_PlayerDamageReq > unDamage ? m_PlayerDamageReq -= unDamage : m_PlayerDamageReq = 0; - } - void ResetPlayerDamageReq() { m_PlayerDamageReq = GetHealth() / 2; } - uint32 m_PlayerDamageReq; + [[nodiscard]] bool IsDamageEnoughForLootingAndReward() const; + void LowerPlayerDamageReq(uint32 unDamage, bool damagedByPlayer = true); + void ResetPlayerDamageReq(); + [[nodiscard]] uint32 GetPlayerDamageReq() const; [[nodiscard]] uint32 GetOriginalEntry() const { return m_originalEntry; } void SetOriginalEntry(uint32 entry) { m_originalEntry = entry; } @@ -470,6 +466,8 @@ private: uint32 m_assistanceTimer; + uint32 _playerDamageReq; + bool _damagedByPlayer; }; class AssistDelayEvent : public BasicEvent diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index da4a0af99..20f45c8df 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -999,7 +999,11 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage victim->ToCreature()->SetLootRecipient(attacker); if (!attacker || attacker->IsControlledByPlayer() || attacker->IsCreatedByPlayer()) - victim->ToCreature()->LowerPlayerDamageReq(health < damage ? health : damage); + { + uint32 unDamage = health < damage ? health : damage; + bool damagedByPlayer = unDamage && attacker && attacker->m_movedByPlayer != nullptr; + victim->ToCreature()->LowerPlayerDamageReq(unDamage, damagedByPlayer); + } } if (health <= damage) diff --git a/src/server/game/Miscellaneous/Formulas.cpp b/src/server/game/Miscellaneous/Formulas.cpp index 3ffb2c3dd..788fc5967 100644 --- a/src/server/game/Miscellaneous/Formulas.cpp +++ b/src/server/game/Miscellaneous/Formulas.cpp @@ -124,9 +124,9 @@ uint32 Acore::XP::Gain(Player* player, Unit* unit, bool isBattleGround /*= false } // if players dealt less than 50% of the damage and were credited anyway (due to CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ), scale XP gained appropriately (linear scaling) - if (creature && creature->m_PlayerDamageReq) + if (creature && creature->GetPlayerDamageReq()) { - xpMod *= 1.0f - 2.0f * creature->m_PlayerDamageReq / creature->GetMaxHealth(); + xpMod *= 1.0f - 2.0f * creature->GetPlayerDamageReq() / creature->GetMaxHealth(); } gain = uint32(gain * xpMod);