From 5cf7de6aa722120a8a7899f397415fd6055eefb0 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Mon, 27 Apr 2020 14:39:07 +0200 Subject: [PATCH] Core/Units: make health regeneration functions for players and creatures virtual --- .../game/Entities/Creature/Creature.cpp | 21 +++++++------------ src/server/game/Entities/Creature/Creature.h | 3 +-- src/server/game/Entities/Player/Player.cpp | 4 ++++ src/server/game/Entities/Player/Player.h | 2 +- src/server/game/Entities/Unit/Unit.cpp | 11 +++++++++- src/server/game/Entities/Unit/Unit.h | 5 ++++- 6 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index ea6c0f70fc..fb8a073bdf 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -212,7 +212,6 @@ m_formation(nullptr), m_triggerJustAppeared(true), m_respawnCompatibilityMode(fa DisableReputationGain = false; - _healthRegenerationTimer = UNIT_HEALTH_REGENERATION_INTERVAL; m_SightDistance = sWorld->getFloatConfig(CONFIG_SIGHT_MONSTER); m_CombatDistance = 0;//MELEE_RANGE; @@ -773,19 +772,6 @@ void Creature::Update(uint32 diff) if (!IsAlive()) break; - _healthRegenerationTimer -= diff; - if (_healthRegenerationTimer <= 0) - { - bool isInCombat = IsInCombat() && (!GetVictim() || // if IsInCombat() is true and this has no victim - !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself() || // or the victim/owner/charmer is not a player - !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()->IsGameMaster()); // or the victim/owner/charmer is not a GameMaster - - if (!IsInEvadeMode() && (!isInCombat || IsPolymorphed() || CanNotReachTarget())) // regenerate health if not in combat or if polymorphed - RegenerateHealth(); - - _healthRegenerationTimer += UNIT_HEALTH_REGENERATION_INTERVAL; - } - if (HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER)) Regenerate(GetPowerType(), diff); @@ -815,6 +801,13 @@ void Creature::RegenerateHealth() if (!isRegeneratingHealth()) return; + bool isInCombat = IsInCombat() && (!GetVictim() || // if IsInCombat() is true and this has no victim + !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself() || // or the victim/owner/charmer is not a player + !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()->IsGameMaster()); // or the victim/owner/charmer is not a GameMaster + + if (IsInEvadeMode() || (isInCombat && !IsPolymorphed() && !CanNotReachTarget())) // regenerate health if not in combat or if polymorphed + return; + uint32 curValue = GetHealth(); uint32 maxValue = GetMaxHealth(); diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index b95f3c0b2c..f848152d1a 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -320,7 +320,6 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma static float _GetDamageMod(int32 Rank); - int32 _healthRegenerationTimer; float m_SightDistance; float m_CombatDistance; @@ -371,7 +370,7 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma uint32 m_combatPulseDelay; // (secs) how often the creature puts the entire zone in combat (only works in dungeons) ReactStates m_reactState; // for AI, not charmInfo - void RegenerateHealth(); + void RegenerateHealth() override; MovementGeneratorType m_defaultMovementType; ObjectGuid::LowType m_spawnId; ///< For new or temporary creatures is 0 for saved it is lowguid uint8 m_equipmentId; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 2d59108b27..32f58b2e44 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1883,6 +1883,10 @@ void Player::RegenerateAll(uint32 diff) void Player::RegenerateHealth() { + // Do not regenerate health when in combat, when not polymorphed or when any regeneration aura allows it + if (IsInCombat() && !IsPolymorphed() && !m_baseHealthRegen && !HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT) && !HasAuraType(SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT)) + return; + uint32 curValue = GetHealth(); uint32 maxValue = GetMaxHealth(); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index d534dac7bf..d95989810a 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1515,7 +1515,7 @@ class TC_GAME_API Player : public Unit, public GridObject void SendTalentWipeConfirm(ObjectGuid guid) const; void ResetPetTalents(); void RegenerateAll(uint32 diff); - void RegenerateHealth(); + void RegenerateHealth() override; void SetRegenerationTimer(uint32 time) { _regenerationTimer = time;} void setWeaponChangeTimer(uint32 time) { m_weaponChangeTimer = time;} diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 82d59c45c9..2b18072506 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -416,7 +416,8 @@ Unit::Unit(bool isWorldObject) : for (uint8 i = 0; i < MAX_POWERS_PER_CLASS; ++i) _powerFraction[i] = 0; - _regenerationTimer = 0; + _regenerationTimer = GetRegenerationInterval(); + _healthRegenerationTimer = UNIT_HEALTH_REGENERATION_INTERVAL; _oldFactionId = 0; _isWalkingBeforeCharm = false; @@ -554,6 +555,14 @@ void Unit::Update(uint32 p_time) _regenerationTimer -= (GetRegenerationInterval() - p_time); else _regenerationTimer += p_time; + + // Update Health Regeneration + _healthRegenerationTimer -= p_time; + if (_healthRegenerationTimer <= 0) + { + RegenerateHealth(); + _healthRegenerationTimer += UNIT_HEALTH_REGENERATION_INTERVAL; + } } bool Unit::haveOffhandWeapon() const diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 90a886f206..998059ceb2 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1057,7 +1057,7 @@ class TC_GAME_API Unit : public WorldObject void ClearUnitState(uint32 f) { m_state &= ~f; } bool CanFreeMove() const; - virtual void UpdatePowerRegeneration(Powers powerType) { } + virtual void UpdatePowerRegeneration(Powers /*powerType*/) { } uint32 HasUnitTypeMask(uint32 mask) const { return mask & m_unitTypeMask; } void AddUnitTypeMask(uint32 mask) { m_unitTypeMask |= mask; } @@ -1124,6 +1124,8 @@ class TC_GAME_API Unit : public WorldObject int32 ModifyPowerPct(Powers power, float pct, bool apply = true); float GetPowerRegen(Powers powerType, bool isInCombat) const; + virtual void RegenerateHealth() { } + uint32 GetAttackTime(WeaponAttackType att) const; void SetAttackTime(WeaponAttackType att, uint32 val) { SetFloatValue(UNIT_FIELD_BASEATTACKTIME+att, val*m_modAttackSpeedPct[att]); } void ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply); @@ -2006,6 +2008,7 @@ class TC_GAME_API Unit : public WorldObject uint32 _powerBarId; float _powerFraction[MAX_POWERS_PER_CLASS]; int32 _regenerationTimer; + int32 _healthRegenerationTimer; bool IsAlwaysVisibleFor(WorldObject const* seer) const override; bool IsAlwaysDetectableFor(WorldObject const* seer) const override;