diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index faa91bf13..fbfdc8189 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -444,7 +444,7 @@ void Creature::Update(uint32 diff) RegenerateMana(); - m_regenTimer = 2000; + m_regenTimer = REGEN_TIME_FULL; break; } case DEAD_FALLING: diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 0006f266b..66f49eea8 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1242,7 +1242,12 @@ void Player::Update( uint32 p_time ) if (isAlive()) { - RegenerateAll(); + // if no longer casting, set regen power as soon as it is up. + if (!IsUnderLastManaUseEffect()) + SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER); + + if (!m_regenTimer) + RegenerateAll(); } if (m_deathState == JUST_DIED) @@ -1903,36 +1908,33 @@ void Player::RewardRage( uint32 damage, uint32 weaponSpeedHitFactor, bool attack ModifyPower(POWER_RAGE, uint32(addRage*10)); } -void Player::RegenerateAll() +void Player::RegenerateAll(uint32 diff) { - if (m_regenTimer != 0) - return; - uint32 regenDelay = 2000; - // Not in combat or they have regeneration - if( !isInCombat() || HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT) || + if (!isInCombat() || HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT) || HasAuraType(SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT) || IsPolymorphed() ) { - RegenerateHealth(); + RegenerateHealth(diff); if (!isInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) { - Regenerate(POWER_RAGE); + Regenerate(POWER_RAGE, diff); if(getClass() == CLASS_DEATH_KNIGHT) - Regenerate(POWER_RUNIC_POWER); + Regenerate(POWER_RUNIC_POWER, diff); } } - Regenerate( POWER_ENERGY ); + Regenerate(POWER_ENERGY, diff); - Regenerate( POWER_MANA ); + Regenerate(POWER_MANA, diff); - if(getClass() == CLASS_DEATH_KNIGHT) - Regenerate( POWER_RUNE ); + if (getClass() == CLASS_DEATH_KNIGHT) + Regenerate(POWER_RUNE, diff); - m_regenTimer = regenDelay; + m_regenTimer = REGEN_TIME_FULL; } -void Player::Regenerate(Powers power) +// diff contains the time in milliseconds since last regen. +void Player::Regenerate(Powers power, uint32 diff) { uint32 curValue = GetPower(power); uint32 maxValue = GetMaxPower(power); @@ -1971,8 +1973,10 @@ void Player::Regenerate(Powers power) case POWER_RUNE: { for(uint32 i = 0; i < MAX_RUNES; ++i) - if(uint8 cd = GetRuneCooldown(i)) // if we have cooldown, reduce it... - SetRuneCooldown(i, cd - 1); // ... by 2 sec (because update is every 2 sec) + { + if(uint16 cd = GetRuneCooldown(i)) // if we have cooldown, reduce it... + SetRuneCooldown(i, (cd < diff) ? 0 : cd - diff); + } } break; case POWER_FOCUS: case POWER_HAPPINESS: @@ -1990,6 +1994,9 @@ void Player::Regenerate(Powers power) addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f; } + // addvalue computed on a 2sec basis. => update to diff time + addvalue *= float(diff) / REGEN_TIME_FULL; + if (power != POWER_RAGE && power != POWER_RUNIC_POWER) { curValue += uint32(addvalue); @@ -2006,7 +2013,7 @@ void Player::Regenerate(Powers power) SetPower(power, curValue); } -void Player::RegenerateHealth() +void Player::RegenerateHealth(uint32 diff) { uint32 curValue = GetHealth(); uint32 maxValue = GetMaxHealth(); @@ -2043,6 +2050,8 @@ void Player::RegenerateHealth() if(addvalue < 0) addvalue = 0; + addvalue *= (float)diff / REGEN_TIME_FULL; + ModifyHealth(int32(addvalue)); } @@ -19614,7 +19623,7 @@ void Player::ResyncRunes(uint8 count) for(uint32 i = 0; i < count; ++i) { data << uint8(GetCurrentRune(i)); // rune type - data << uint8(255 - (GetRuneCooldown(i) * 51)); // passed cooldown time (0-255) + data << uint8(255 - ((GetRuneCooldown(i) / REGEN_TIME_FULL) * 51)); // passed cooldown time (0-255) } GetSession()->SendPacket(&data); } diff --git a/src/game/Player.h b/src/game/Player.h index fee045180..f9a16aaec 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -269,7 +269,7 @@ struct Areas }; #define MAX_RUNES 6 -#define RUNE_COOLDOWN 5 // 5*2=10 sec +#define RUNE_COOLDOWN 10000 // msec enum RuneType { @@ -282,9 +282,9 @@ enum RuneType struct RuneInfo { - uint8 BaseRune; - uint8 CurrentRune; - uint8 Cooldown; + uint8 BaseRune; + uint8 CurrentRune; + uint16 Cooldown; // msec }; struct Runes @@ -1403,9 +1403,9 @@ class MANGOS_DLL_SPEC Player : public Unit void RewardRage( uint32 damage, uint32 weaponSpeedHitFactor, bool attacker ); void SendPetSkillWipeConfirm(); void CalcRage( uint32 damage,bool attacker ); - void RegenerateAll(); - void Regenerate(Powers power); - void RegenerateHealth(); + void RegenerateAll(uint32 diff = REGEN_TIME_FULL); + void Regenerate(Powers power, uint32 diff); + void RegenerateHealth(uint32 diff); void setRegenTimer(uint32 time) {m_regenTimer = time;} void setWeaponChangeTimer(uint32 time) {m_weaponChangeTimer = time;} @@ -2208,10 +2208,10 @@ class MANGOS_DLL_SPEC Player : public Unit uint8 GetRunesState() const { return m_runes->runeState; } uint8 GetBaseRune(uint8 index) const { return m_runes->runes[index].BaseRune; } uint8 GetCurrentRune(uint8 index) const { return m_runes->runes[index].CurrentRune; } - uint8 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; } + uint16 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; } void SetBaseRune(uint8 index, uint8 baseRune) { m_runes->runes[index].BaseRune = baseRune; } void SetCurrentRune(uint8 index, uint8 currentRune) { m_runes->runes[index].CurrentRune = currentRune; } - void SetRuneCooldown(uint8 index, uint8 cooldown) { m_runes->runes[index].Cooldown = cooldown; m_runes->SetRuneState(index, (cooldown == 0) ? true : false); } + void SetRuneCooldown(uint8 index, uint16 cooldown) { m_runes->runes[index].Cooldown = cooldown; m_runes->SetRuneState(index, (cooldown == 0) ? true : false); } void ConvertRune(uint8 index, uint8 newType); void ResyncRunes(uint8 count); void AddRunePower(uint8 index); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 2c3b22ef0..f917dfd6e 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -5039,6 +5039,15 @@ SpellCastResult Spell::CheckPower() if(m_CastItem) return SPELL_CAST_OK; + // Do precise power regen on spell cast + if (m_powerCost > 0 && m_caster->GetTypeId() == TYPEID_PLAYER) + { + Player* playerCaster = (Player*)m_caster; + uint32 diff = REGEN_TIME_FULL - m_caster->GetRegenTimer(); + if (diff >= REGEN_TIME_PRECISE) + playerCaster->RegenerateAll(diff); + } + // health as power used - need check health amount if(m_spellInfo->powerType == POWER_HEALTH) { diff --git a/src/game/Unit.h b/src/game/Unit.h index 9726aa874..41c037990 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -856,6 +856,10 @@ typedef std::set GuardianPetList; #define ATTACK_DISPLAY_DELAY 200 #define MAX_PLAYER_STEALTH_DETECT_RANGE 45.0f // max distance for detection targets by player +// Regeneration defines +#define REGEN_TIME_FULL 2000 // For this time difference is computed regen value +#define REGEN_TIME_PRECISE 500 // Used in Spell::CheckPower for precise regeneration in spell cast time + struct SpellProcEventEntry; // used only privately class MANGOS_DLL_SPEC Unit : public WorldObject @@ -1423,9 +1427,18 @@ class MANGOS_DLL_SPEC Unit : public WorldObject uint32 SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim); uint32 SpellCriticalHealingBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim); - void SetLastManaUse(uint32 spellCastTime) { m_lastManaUse = spellCastTime; } + void SetLastManaUse(uint32 spellCastTime) + { + if (GetTypeId() == TYPEID_PLAYER && !IsUnderLastManaUseEffect()) + { + RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER); + } + m_lastManaUse = spellCastTime; + } bool IsUnderLastManaUseEffect() const; + uint32 GetRegenTimer() const { return m_regenTimer; } + void SetContestedPvP(Player *attackedPlayer = NULL); void MeleeDamageBonus(Unit *pVictim, uint32 *damage, WeaponAttackType attType, SpellEntry const *spellProto = NULL); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 654a1f652..e3c6ae35b 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8476" + #define REVISION_NR "8477" #endif // __REVISION_NR_H__