Core/Units: updated power regeneration handling to get closer to the master version of it
This commit is contained in:
1 parent
e8588fd5ba
commit
f9425284ca
10 files changed
+290
-236
No files matched your search
@@ -1332,6 +1332,59 @@ EmotesTextSoundEntry const* DBCManager::FindTextSoundEmoteFor(uint32 emote, uint
|
||||
return itr != sEmotesTextSoundMap.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
/*static*/ float DBCManager::GetBasePowerRegen(Powers powerType, bool isInCombat, uint32 powerBarId)
|
||||
{
|
||||
if (powerType != POWER_ALTERNATE_POWER)
|
||||
{
|
||||
switch (powerType)
|
||||
{
|
||||
case POWER_RAGE: return isInCombat ? 0.f : -12.5f;
|
||||
case POWER_FOCUS: return 5.f;
|
||||
case POWER_RUNIC_POWER: return isInCombat ? 0.f : -12.5f;
|
||||
case POWER_ENERGY: return 10.f;
|
||||
case POWER_HOLY_POWER: return isInCombat ? 0.f : -0.1f;
|
||||
case POWER_RUNE: return 0.1f;
|
||||
default:
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UnitPowerBarEntry const* powerBar = sUnitPowerBarStore.LookupEntry(powerBarId);
|
||||
if (!powerBar)
|
||||
return 0.f;
|
||||
|
||||
return isInCombat ? powerBar->RegenerationCombat : powerBar->RegenerationPeace;
|
||||
}
|
||||
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
/*static*/ bool DBCManager::IsPowerTypeAffectedByHaste(Powers powerType)
|
||||
{
|
||||
switch (powerType)
|
||||
{
|
||||
case POWER_ENERGY:
|
||||
case POWER_FOCUS:
|
||||
case POWER_RUNE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*static*/ float DBCManager::GetGtOCTRegenMPPerSpirit(uint8 classId, uint8 level)
|
||||
{
|
||||
level = std::min<uint8>(level, GT_MAX_LEVEL);
|
||||
GtRegenMPPerSptEntry const* gt = sGtRegenMPPerSptStore.LookupEntry((classId - 1) * GT_MAX_LEVEL + level - 1);
|
||||
if (gt == nullptr)
|
||||
return 0.0f;
|
||||
|
||||
return gt->ratio;
|
||||
}
|
||||
|
||||
bool DBCManager::IsInArea(uint32 objectAreaId, uint32 areaId)
|
||||
{
|
||||
do
|
||||
|
||||
@@ -238,7 +238,7 @@ public:
|
||||
static uint32 GetLiquidFlags(uint32 liquidType);
|
||||
static uint32 GetDefaultMapLight(uint32 mapId);
|
||||
PvPDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 level);
|
||||
PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundBracketId id);
|
||||
PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundBracketId id);
|
||||
CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender);
|
||||
CharSectionsEntry const* GetCharSectionEntry(uint8 race, CharSectionType genType, uint8 gender, uint8 type, uint8 color);
|
||||
uint32 GetPowerIndexByClass(Powers power, uint32 classId);
|
||||
@@ -248,7 +248,10 @@ public:
|
||||
std::vector<SkillLineAbilityEntry const*> const* GetSkillLineAbilitiesBySkill(uint32 skillId) const;
|
||||
SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_);
|
||||
ResponseCodes ValidateName(std::wstring const& name, LocaleConstant locale);
|
||||
EmotesTextSoundEntry const* FindTextSoundEmoteFor(uint32 emote, uint32 race, uint32 gender);
|
||||
EmotesTextSoundEntry const* FindTextSoundEmoteFor(uint32 emote, uint32 race, uint32 gender);
|
||||
static float GetBasePowerRegen(Powers powerType, bool isInCombat, uint32 powerBarId = 0);
|
||||
static bool IsPowerTypeAffectedByHaste(Powers powerType);
|
||||
static float GetGtOCTRegenMPPerSpirit(uint8 classId, uint8 level);
|
||||
};
|
||||
|
||||
#define sDBCManager DBCManager::Instance()
|
||||
|
||||
@@ -1428,6 +1428,7 @@ void Creature::UpdateLevelDependantStats()
|
||||
Powers powerType = CalculateDisplayPowerType();
|
||||
SetCreateMana(stats->BaseMana);
|
||||
SetStatPctModifier(UnitMods(UNIT_MOD_POWER_START + AsUnderlyingType(powerType)), BASE_PCT, cInfo->ModMana * cInfo->ModManaExtra);
|
||||
RegisterPowerTypes();
|
||||
SetPowerType(powerType);
|
||||
|
||||
switch (getClass())
|
||||
|
||||
@@ -178,7 +178,6 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
|
||||
uint32 GetPowerIndex(Powers power) const override;
|
||||
void UpdateAttackPowerAndDamage(bool ranged = false) override;
|
||||
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const override;
|
||||
void UpdatePowerRegeneration(Powers powerType) override;
|
||||
|
||||
void SetCanDualWield(bool value) override;
|
||||
int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; }
|
||||
|
||||
@@ -451,6 +451,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, createInfo->Class);
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, createInfo->Gender);
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, powertype);
|
||||
RegisterPowerTypes();
|
||||
InitDisplayIds();
|
||||
if (sWorld->getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || sWorld->getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP)
|
||||
{
|
||||
@@ -4929,25 +4930,6 @@ float Player::GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float Player::OCTRegenMPPerSpirit() const
|
||||
{
|
||||
uint8 level = getLevel();
|
||||
uint32 pclass = getClass();
|
||||
|
||||
if (level > GT_MAX_LEVEL)
|
||||
level = GT_MAX_LEVEL;
|
||||
|
||||
// GtOCTRegenMPEntry const* baseRatio = sGtOCTRegenMPStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1);
|
||||
GtRegenMPPerSptEntry const* moreRatio = sGtRegenMPPerSptStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1);
|
||||
if (moreRatio == nullptr)
|
||||
return 0.0f;
|
||||
|
||||
// Formula get from PaperDollFrame script
|
||||
float spirit = GetStat(STAT_SPIRIT);
|
||||
float regen = spirit * moreRatio->ratio;
|
||||
return regen;
|
||||
}
|
||||
|
||||
void Player::ApplyRatingMod(CombatRating combatRating, int32 value, bool apply)
|
||||
{
|
||||
// explicit affected values
|
||||
@@ -4959,16 +4941,16 @@ void Player::ApplyRatingMod(CombatRating combatRating, int32 value, bool apply)
|
||||
ApplyAttackTimePercentMod(BASE_ATTACK, (m_baseRatingValue[combatRating] + (apply ? value : -value)) * GetRatingMultiplier(combatRating), true);
|
||||
ApplyAttackTimePercentMod(OFF_ATTACK, m_baseRatingValue[combatRating] * GetRatingMultiplier(combatRating), false);
|
||||
ApplyAttackTimePercentMod(OFF_ATTACK, (m_baseRatingValue[combatRating] + (apply ? value : -value)) * GetRatingMultiplier(combatRating), true);
|
||||
ApplyHasteRegenMod(BASE_ATTACK, m_baseRatingValue[combatRating] * GetRatingMultiplier(combatRating), false);
|
||||
ApplyHasteRegenMod(BASE_ATTACK, (m_baseRatingValue[combatRating] + (apply ? value : -value)) * GetRatingMultiplier(combatRating), true);
|
||||
|
||||
// Haste Rating affects all three haste types so we only have to apply it once here
|
||||
ApplyHasteRegenMod(m_baseRatingValue[combatRating] * GetRatingMultiplier(combatRating), false);
|
||||
ApplyHasteRegenMod((m_baseRatingValue[combatRating] + (apply ? value : -value)) * GetRatingMultiplier(combatRating), true);
|
||||
break;
|
||||
}
|
||||
case CR_HASTE_RANGED:
|
||||
{
|
||||
ApplyAttackTimePercentMod(RANGED_ATTACK, m_baseRatingValue[combatRating] * GetRatingMultiplier(combatRating), false);
|
||||
ApplyAttackTimePercentMod(RANGED_ATTACK, (m_baseRatingValue[combatRating] + (apply ? value : -value)) * GetRatingMultiplier(combatRating), true);
|
||||
ApplyHasteRegenMod(RANGED_ATTACK, m_baseRatingValue[combatRating] * GetRatingMultiplier(combatRating), false);
|
||||
ApplyHasteRegenMod(RANGED_ATTACK, (m_baseRatingValue[combatRating] + (apply ? value : -value)) * GetRatingMultiplier(combatRating), true);
|
||||
break;
|
||||
}
|
||||
case CR_HASTE_SPELL:
|
||||
@@ -16973,6 +16955,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
|
||||
//mails are loaded only when needed ;-) - when player in game click on mailbox.
|
||||
//_LoadMail();
|
||||
|
||||
RegisterPowerTypes();
|
||||
UpdateDisplayPower();
|
||||
_LoadTalents(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TALENTS));
|
||||
_LoadSpells(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SPELLS));
|
||||
|
||||
@@ -1793,7 +1793,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
float GetMeleeCritFromAgility() const;
|
||||
void GetDodgeFromAgility(float &diminishing, float &nondiminishing) const;
|
||||
float GetSpellCritFromIntellect() const;
|
||||
float OCTRegenMPPerSpirit() const;
|
||||
float GetRatingMultiplier(CombatRating cr) const;
|
||||
float GetRatingBonusValue(CombatRating cr) const;
|
||||
|
||||
@@ -1819,7 +1818,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
void UpdateExpertise(WeaponAttackType attType);
|
||||
void ApplyManaRegenBonus(int32 amount, bool apply);
|
||||
void ApplyHealthRegenBonus(int32 amount, bool apply);
|
||||
void UpdatePowerRegeneration(Powers powerType) override;
|
||||
uint32 GetRuneTimer(uint8 index) const { return m_runeGraceCooldown[index]; }
|
||||
void SetRuneTimer(uint8 index, uint32 timer) { m_runeGraceCooldown[index] = timer; }
|
||||
uint32 GetLastRuneGraceTimer(uint8 index) const { return m_lastRuneGraceTimers[index]; }
|
||||
|
||||
@@ -119,6 +119,140 @@ int32 Unit::GetCreatePowerValue(Powers power) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Unit::UpdatePowerRegeneration(Powers powerType)
|
||||
{
|
||||
uint32 powerIndex = GetPowerIndex(powerType);
|
||||
if ((powerIndex == MAX_POWERS || powerIndex >= MAX_POWERS_PER_CLASS) && powerType != POWER_RUNE)
|
||||
return;
|
||||
|
||||
// Runes are not officially considered a power type for the class so we gotta bypass the rules this way
|
||||
if (powerType == POWER_RUNE && (!IsPlayer() || getClass() != CLASS_DEATH_KNIGHT))
|
||||
return;
|
||||
|
||||
float powerRegenMod = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, powerType) / 5.f;
|
||||
float powerRegenModPct = GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, powerType);
|
||||
|
||||
switch (powerType)
|
||||
{
|
||||
case POWER_MANA:
|
||||
{
|
||||
// Get base of Mana Pool in sBaseMPGameTable
|
||||
uint32 basemana = 0, basehp = 0;
|
||||
if (IsPlayer())
|
||||
sObjectMgr->GetPlayerClassLevelInfo(getClass(), getLevel(), basemana, basehp);
|
||||
else
|
||||
basemana = GetCreateMana(); // this should also get replaced by the base mana game table in the future.
|
||||
|
||||
// BaseRegen = 5% of Base Mana per five seconds
|
||||
float baseRegen = basemana / 100.f;
|
||||
// SPELL_AURA_MOD_POWER_REGEN flat bonus
|
||||
baseRegen += powerRegenMod;
|
||||
|
||||
// SpiritRegen = Spirit * GTRegenMpPerSpt * Sqrt(INT) * 5
|
||||
float spiritRegen = GetStat(STAT_SPIRIT) * DBCManager::GetGtOCTRegenMPPerSpirit(getClass(), getLevel());
|
||||
if (GetStat(STAT_INTELLECT) > 0.0f)
|
||||
spiritRegen *= std::sqrt(GetStat(STAT_INTELLECT));
|
||||
|
||||
// SPELL_AURA_MOD_POWER_REGEN_PERCENT pct bonus
|
||||
baseRegen *= powerRegenModPct;
|
||||
spiritRegen *= powerRegenModPct;
|
||||
|
||||
// SPELL_AURA_MOD_MANA_REGEN_INTERRUPT allow some of the spirit regeneration to bypass the combat restriction
|
||||
int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT);
|
||||
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + powerIndex, baseRegen + CalculatePct(spiritRegen, modManaRegenInterrupt));
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + powerIndex, baseRegen + spiritRegen);
|
||||
break;
|
||||
}
|
||||
case POWER_RUNE:
|
||||
{
|
||||
float baseRegen = DBCManager::GetBasePowerRegen(powerType, false, 0);
|
||||
|
||||
// Hase Regen
|
||||
if (DBCManager::IsPowerTypeAffectedByHaste(powerType) && IsPlayer())
|
||||
{
|
||||
float hasteRegen = GetFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN);
|
||||
if (G3D::fuzzyNe(hasteRegen, 0.0f))
|
||||
baseRegen /= hasteRegen;
|
||||
}
|
||||
|
||||
baseRegen += powerRegenMod;
|
||||
|
||||
if (IsPlayer())
|
||||
for (uint8 i = 0; i < NUM_RUNE_TYPES; ++i)
|
||||
SetFloatValue(PLAYER_RUNE_REGEN_1 + i, baseRegen);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// Base Regen
|
||||
float peaceRegen = DBCManager::GetBasePowerRegen(powerType, false, 0);
|
||||
float combatRegen = DBCManager::GetBasePowerRegen(powerType, true, 0);
|
||||
|
||||
// Hase Regen
|
||||
if (DBCManager::IsPowerTypeAffectedByHaste(powerType) && IsPlayer())
|
||||
{
|
||||
float hasteRegen = GetFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN);
|
||||
if (G3D::fuzzyNe(hasteRegen, 0.0f))
|
||||
{
|
||||
peaceRegen /= hasteRegen;
|
||||
combatRegen /= hasteRegen;
|
||||
}
|
||||
}
|
||||
|
||||
peaceRegen *= powerRegenModPct;
|
||||
combatRegen *= powerRegenModPct;
|
||||
|
||||
// Subtract the base value to get the proper offset
|
||||
peaceRegen -= DBCManager::GetBasePowerRegen(powerType, false, 0);
|
||||
combatRegen -= DBCManager::GetBasePowerRegen(powerType, true, 0);
|
||||
|
||||
peaceRegen += powerRegenMod;
|
||||
combatRegen += powerRegenMod;
|
||||
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + powerIndex, combatRegen);
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + powerIndex, peaceRegen);
|
||||
}
|
||||
|
||||
/*
|
||||
case POWER_FOCUS:
|
||||
case POWER_ENERGY:
|
||||
{
|
||||
// Energy and Focus regeneration is always consistent in and out of combat
|
||||
float baseRegen = DBCManager::GetBasePowerRegen(powerType, false, 0);
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + powerIndex, baseRegen * powerRegenModPct - baseRegen + powerRegenMod);
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + powerIndex, baseRegen * powerRegenModPct - baseRegen + powerRegenMod);
|
||||
break;
|
||||
}
|
||||
case POWER_RUNIC_POWER:
|
||||
case POWER_RAGE:
|
||||
// Butchery and Anger Management
|
||||
SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + powerIndex, powerRegenMod);
|
||||
break;
|
||||
case POWER_RUNE:
|
||||
{
|
||||
// Formular: base cooldown / (1 - haste)
|
||||
float regeneration = 0.1f;
|
||||
float haste = GetFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN);
|
||||
if (haste != 0.f)
|
||||
regeneration /= haste;
|
||||
|
||||
for (int8 i = 0; i < NUM_RUNE_TYPES; i++)
|
||||
{
|
||||
float mod = 0.f;
|
||||
for (AuraEffect const* effect : GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN))
|
||||
if (effect->GetMiscValue() == int32(powerType) && effect->GetMiscValueB() == i)
|
||||
mod += effect->GetAmount();
|
||||
|
||||
SetFloatValue(PLAYER_RUNE_REGEN_1 + i, regeneration + mod);
|
||||
}
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*#######################################
|
||||
######## ########
|
||||
######## PLAYERS STAT SYSTEM ########
|
||||
@@ -817,76 +951,6 @@ void Player::ApplyHealthRegenBonus(int32 amount, bool apply)
|
||||
_ModifyUInt32(apply, m_baseHealthRegen, amount);
|
||||
}
|
||||
|
||||
void Player::UpdatePowerRegeneration(Powers powerType)
|
||||
{
|
||||
uint32 powerIndex = GetPowerIndex(powerType);
|
||||
if (powerIndex == MAX_POWERS && powerType != POWER_RUNE)
|
||||
return;
|
||||
|
||||
float powerRegenMod = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, powerType) / 5.f;
|
||||
float powerRegenModPct = GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, powerType);
|
||||
|
||||
switch (powerType)
|
||||
{
|
||||
case POWER_MANA:
|
||||
{
|
||||
// Mana regen from spirit
|
||||
float spirit_regen = OCTRegenMPPerSpirit();
|
||||
// Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen
|
||||
spirit_regen *= powerRegenModPct;
|
||||
|
||||
// SpiritRegen(SPI, INT, LEVEL) = (0.001 + (SPI x sqrt(INT) x BASE_REGEN[LEVEL])) x 5
|
||||
if (GetStat(STAT_INTELLECT) > 0.0f)
|
||||
spirit_regen *= std::sqrt(GetStat(STAT_INTELLECT));
|
||||
|
||||
// CombatRegen = 5% of Base Mana per five seconds
|
||||
float base_regen = CalculatePct(GetCreateMana(), 1) + powerRegenMod;
|
||||
|
||||
// Set regen rate in cast state apply only on spirit based regen
|
||||
int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT);
|
||||
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + powerIndex, base_regen + CalculatePct(spirit_regen, modManaRegenInterrupt));
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + powerIndex, spirit_regen + base_regen);
|
||||
break;
|
||||
}
|
||||
case POWER_FOCUS:
|
||||
case POWER_ENERGY:
|
||||
{
|
||||
// Energy and Focus regeneration is always consistent in and out of combat
|
||||
float baseRegen = Unit::GetBasePowerRegen(0, powerType, false);
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + powerIndex, baseRegen * powerRegenModPct - baseRegen + powerRegenMod);
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER + powerIndex, baseRegen * powerRegenModPct - baseRegen + powerRegenMod);
|
||||
break;
|
||||
}
|
||||
case POWER_RUNIC_POWER:
|
||||
case POWER_RAGE:
|
||||
// Butchery and Anger Management
|
||||
SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + powerIndex, powerRegenMod);
|
||||
break;
|
||||
case POWER_RUNE:
|
||||
{
|
||||
// Formular: base cooldown / (1 - haste)
|
||||
float regeneration = 0.1f;
|
||||
float haste = GetFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN);
|
||||
if (haste != 0.f)
|
||||
regeneration /= haste;
|
||||
|
||||
for (int8 i = 0; i < NUM_RUNE_TYPES; i++)
|
||||
{
|
||||
float mod = 0.f;
|
||||
for (AuraEffect const* effect : GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN))
|
||||
if (effect->GetMiscValue() == int32(powerType) && effect->GetMiscValueB() == i)
|
||||
mod += effect->GetAmount();
|
||||
|
||||
SetFloatValue(PLAYER_RUNE_REGEN_1 + i, regeneration + mod);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::_ApplyAllStatBonuses()
|
||||
{
|
||||
SetCanModifyStats(false);
|
||||
@@ -983,37 +1047,6 @@ void Creature::UpdateMaxPower(Powers power)
|
||||
SetMaxPower(power, uint32(std::lroundf(value)));
|
||||
}
|
||||
|
||||
void Creature::UpdatePowerRegeneration(Powers powerType)
|
||||
{
|
||||
float powerRegenMod = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, powerType) / 5.f;
|
||||
float powerRegenModPct = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, powerType);
|
||||
|
||||
switch (powerType)
|
||||
{
|
||||
case POWER_MANA:
|
||||
// Regeneration for controlled units
|
||||
if (!GetCharmerGUID().IsEmpty() || !GetOwnerGUID().IsEmpty())
|
||||
{
|
||||
float spiritRegen = (GetStat(STAT_SPIRIT) / 5.f + 17.f);
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, spiritRegen + powerRegenMod);
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, powerRegenMod);
|
||||
}
|
||||
else // Default creature regeneration value.
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, 8.714059f + powerRegenMod); // Most common value in sniffs. Todo: research
|
||||
break;
|
||||
case POWER_ENERGY:
|
||||
case POWER_FOCUS:
|
||||
{
|
||||
float regenerationRate = CalculatePct<float>(10, powerRegenModPct) + powerRegenMod;
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, regenerationRate);
|
||||
SetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, regenerationRate);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::UpdateAttackPowerAndDamage(bool ranged)
|
||||
{
|
||||
UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER;
|
||||
|
||||
@@ -368,11 +368,12 @@ Unit::Unit(bool isWorldObject) :
|
||||
|
||||
_powerBarId = 0;
|
||||
|
||||
_powerFraction.fill(0.0f);
|
||||
|
||||
_powerUpdateTimer = GetPowerUpdateInterval();
|
||||
_healthRegenerationTimer = UNIT_HEALTH_REGENERATION_INTERVAL;
|
||||
|
||||
_powerFraction.fill(0.0f);
|
||||
_usedPowerTypes.fill(MAX_POWERS);
|
||||
|
||||
_oldFactionId = 0;
|
||||
_isWalkingBeforeCharm = false;
|
||||
}
|
||||
@@ -5205,12 +5206,19 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType
|
||||
SendAttackStateUpdate(&dmgInfo);
|
||||
}
|
||||
|
||||
void Unit::SetPowerType(Powers new_powertype)
|
||||
void Unit::SetPowerType(Powers power)
|
||||
{
|
||||
if (GetPowerType() == new_powertype)
|
||||
if (GetPowerType() == power)
|
||||
return;
|
||||
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, new_powertype);
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, power);
|
||||
|
||||
// Creatures can swap out their power type at index 0 so we do keep track of the new power type here
|
||||
if (IsCreature())
|
||||
{
|
||||
_usedPowerTypes[GetPowerIndex(power)] = power;
|
||||
UpdatePowerRegeneration(power);
|
||||
}
|
||||
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
@@ -5228,10 +5236,10 @@ void Unit::SetPowerType(Powers new_powertype)
|
||||
}
|
||||
|
||||
// Update max power
|
||||
UpdateMaxPower(new_powertype);
|
||||
UpdateMaxPower(power);
|
||||
|
||||
// Update current power
|
||||
switch (new_powertype)
|
||||
switch (power)
|
||||
{
|
||||
case POWER_MANA: // Keep the same (druid form switching...)
|
||||
case POWER_ENERGY:
|
||||
@@ -5240,7 +5248,7 @@ void Unit::SetPowerType(Powers new_powertype)
|
||||
SetPower(POWER_RAGE, 0);
|
||||
break;
|
||||
case POWER_FOCUS: // Make it full
|
||||
SetFullPower(new_powertype);
|
||||
SetFullPower(power);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -8218,39 +8226,12 @@ int32 Unit::ModifyPower(Powers power, int32 dVal, bool withPowerUpdate /*= true*
|
||||
return gain;
|
||||
}
|
||||
|
||||
/*static */ float Unit::GetBasePowerRegen(uint32 powerBarId, Powers powerType, bool isInCombat)
|
||||
{
|
||||
if (powerType != POWER_ALTERNATE_POWER)
|
||||
{
|
||||
switch (powerType)
|
||||
{
|
||||
case POWER_RAGE: return isInCombat ? 0.f : -12.5f;
|
||||
case POWER_FOCUS: return 5.f;
|
||||
case POWER_RUNIC_POWER: return isInCombat ? 0.f : -12.5f;
|
||||
case POWER_ENERGY: return 10.f;
|
||||
case POWER_HOLY_POWER: return isInCombat ? 0.f : -0.1f;
|
||||
default:
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UnitPowerBarEntry const* powerBar = sUnitPowerBarStore.LookupEntry(powerBarId);
|
||||
if (!powerBar)
|
||||
return 0.f;
|
||||
|
||||
return isInCombat ? powerBar->RegenerationCombat : powerBar->RegenerationPeace;
|
||||
}
|
||||
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
// Based on client function
|
||||
float Unit::GetPowerRegen(Powers powerType, bool isInCombat) const
|
||||
{
|
||||
uint32 powerSlot = MAX_POWERS;
|
||||
float totalRegeneration = 0.f;
|
||||
double result = GetBasePowerRegen(_powerBarId, powerType, isInCombat); // base power regen
|
||||
double result = DBCManager::GetBasePowerRegen(powerType, isInCombat, _powerBarId);
|
||||
float combatRegeneration = result;
|
||||
|
||||
powerSlot = GetPowerIndex(powerType);
|
||||
@@ -8263,10 +8244,10 @@ float Unit::GetPowerRegen(Powers powerType, bool isInCombat) const
|
||||
else
|
||||
totalRegeneration = result;
|
||||
|
||||
if (IsPlayer() && (powerType == POWER_ENERGY || powerType == POWER_FOCUS))
|
||||
if (IsPlayer() && DBCManager::IsPowerTypeAffectedByHaste(powerType))
|
||||
{
|
||||
float hasteRegen = GetFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN);
|
||||
if (hasteRegen != 0.f)
|
||||
if (G3D::fuzzyNe(hasteRegen, 0.f))
|
||||
result = totalRegeneration / hasteRegen;
|
||||
}
|
||||
|
||||
@@ -9480,6 +9461,18 @@ void Unit::Regenerate(Powers powerType, uint32 diff)
|
||||
UpdateUInt32Value(UNIT_FIELD_POWER1 + powerIndex, curValue);
|
||||
}
|
||||
|
||||
void Unit::RegisterPowerTypes()
|
||||
{
|
||||
for (uint8 i = POWER_MANA; i < MAX_POWERS; ++i)
|
||||
{
|
||||
uint32 powerIndex = GetPowerIndex(Powers(i));
|
||||
if (powerIndex == MAX_POWERS || powerIndex == MAX_POWERS_PER_CLASS)
|
||||
continue;
|
||||
|
||||
_usedPowerTypes[powerIndex] = static_cast<Powers>(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::AIUpdateTick(uint32 diff)
|
||||
{
|
||||
if (UnitAI* ai = GetAI())
|
||||
@@ -10652,32 +10645,31 @@ void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply
|
||||
m_attackTimer[att] = uint32(GetAttackTime(att) * m_modAttackSpeedPct[att] * remainingTimePct);
|
||||
}
|
||||
|
||||
void Unit::ApplyHasteRegenMod(WeaponAttackType att, float val, bool apply)
|
||||
void Unit::ApplyHasteRegenMod(float val, bool apply)
|
||||
{
|
||||
if (GetTypeId() != TYPEID_PLAYER)
|
||||
if (!IsPlayer())
|
||||
return;
|
||||
|
||||
float amount = GetFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN);
|
||||
|
||||
if (val > 0.f)
|
||||
{
|
||||
if (att == BASE_ATTACK && getClass() != CLASS_HUNTER)
|
||||
ApplyPercentModFloatVar(amount, val, !apply);
|
||||
else if (att == RANGED_ATTACK && getClass() == CLASS_HUNTER)
|
||||
ApplyPercentModFloatVar(amount, val, !apply);
|
||||
}
|
||||
ApplyPercentModFloatVar(amount, val, !apply);
|
||||
else
|
||||
{
|
||||
if (att == BASE_ATTACK && getClass() != CLASS_HUNTER)
|
||||
ApplyPercentModFloatVar(amount, -val, apply);
|
||||
else if (att == RANGED_ATTACK && getClass() == CLASS_HUNTER)
|
||||
ApplyPercentModFloatVar(amount, -val, apply);
|
||||
}
|
||||
ApplyPercentModFloatVar(amount, -val, apply);
|
||||
|
||||
SetFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN, amount);
|
||||
|
||||
if (getClass() == CLASS_DEATH_KNIGHT)
|
||||
ToPlayer()->UpdatePowerRegeneration(POWER_RUNE);
|
||||
for (Powers powerType : GetUsedPowerTypes())
|
||||
{
|
||||
if (powerType == MAX_POWERS || GetPowerIndex(powerType) == MAX_POWERS)
|
||||
continue;
|
||||
|
||||
if (DBCManager::IsPowerTypeAffectedByHaste(powerType))
|
||||
UpdatePowerRegeneration(powerType);
|
||||
}
|
||||
|
||||
if (IsPlayer() && getClass() == CLASS_DEATH_KNIGHT)
|
||||
UpdatePowerRegeneration(POWER_RUNE);
|
||||
}
|
||||
|
||||
void Unit::ApplyCastTimePercentMod(float val, bool apply, bool withCastHaste /*= true*/, bool withCastSpeed /*= true*/)
|
||||
|
||||
@@ -876,8 +876,6 @@ class TC_GAME_API Unit : public WorldObject
|
||||
void ClearUnitState(uint32 f) { m_state &= ~f; }
|
||||
bool CanFreeMove() const;
|
||||
|
||||
virtual void UpdatePowerRegeneration(Powers /*powerType*/) { }
|
||||
|
||||
uint32 HasUnitTypeMask(uint32 mask) const { return mask & m_unitTypeMask; }
|
||||
void AddUnitTypeMask(uint32 mask) { m_unitTypeMask |= mask; }
|
||||
bool IsSummon() const { return (m_unitTypeMask & UNIT_MASK_SUMMON) != 0; }
|
||||
@@ -938,12 +936,13 @@ class TC_GAME_API Unit : public WorldObject
|
||||
void SetMaxPower(Powers power, int32 val);
|
||||
void SetPowerBarID(uint32 id) { _powerBarId = id; }
|
||||
void Regenerate(Powers powerType, uint32 diff);
|
||||
void UpdatePowerRegeneration(Powers powerType);
|
||||
void RegisterPowerTypes();
|
||||
|
||||
inline void SetFullPower(Powers power) { SetPower(power, GetMaxPower(power)); }
|
||||
|
||||
// returns the change in power
|
||||
int32 ModifyPower(Powers power, int32 val, bool withPowerUpdate = true);
|
||||
static float GetBasePowerRegen(uint32 powerBarId, Powers powerType, bool isInCombat);
|
||||
float GetPowerRegen(Powers powerType, bool isInCombat) const;
|
||||
|
||||
virtual void RegenerateHealth() { }
|
||||
@@ -951,7 +950,7 @@ class TC_GAME_API Unit : public WorldObject
|
||||
uint32 GetAttackTime(WeaponAttackType att) const;
|
||||
void SetAttackTime(WeaponAttackType att, uint32 val) { SetFloatValue(UNIT_FIELD_BASEATTACKTIME + AsUnderlyingType(att), val * m_modAttackSpeedPct[att]); }
|
||||
void ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply);
|
||||
void ApplyHasteRegenMod(WeaponAttackType att, float val, bool apply);
|
||||
void ApplyHasteRegenMod(float val, bool apply);
|
||||
void ApplyCastTimePercentMod(float val, bool apply, bool withCastHaste = true, bool withCastSpeed = true);
|
||||
|
||||
SheathState GetSheath() const { return SheathState(GetByteValue(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_SHEATH_STATE)); }
|
||||
@@ -1846,10 +1845,17 @@ class TC_GAME_API Unit : public WorldObject
|
||||
|
||||
uint32 m_unitTypeMask;
|
||||
LiquidTypeEntry const* _lastLiquid;
|
||||
|
||||
uint32 _powerBarId;
|
||||
std::array<float, MAX_POWERS_PER_CLASS> _powerFraction;
|
||||
int32 _powerUpdateTimer;
|
||||
int32 _healthRegenerationTimer;
|
||||
std::array<float, MAX_POWERS_PER_CLASS> _powerFraction;
|
||||
std::array<Powers, MAX_POWERS_PER_CLASS> _usedPowerTypes;
|
||||
public:
|
||||
// Returns an array that contains information about which power type is used at which power index. MAX_POWERS implies that a power at given index is not used.
|
||||
std::array<Powers, MAX_POWERS_PER_CLASS> const& GetUsedPowerTypes() const { return _usedPowerTypes; }
|
||||
|
||||
protected:
|
||||
|
||||
bool IsAlwaysVisibleFor(WorldObject const* seer) const override;
|
||||
bool IsAlwaysDetectableFor(WorldObject const* seer) const override;
|
||||
|
||||
@@ -200,7 +200,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
|
||||
&AuraEffect::HandleAuraModIncreaseHealthPercent, //133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT
|
||||
&AuraEffect::HandleAuraModRegenInterrupt, //134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT
|
||||
&AuraEffect::HandleModHealingDone, //135 SPELL_AURA_MOD_HEALING_DONE
|
||||
&AuraEffect::HandleModHealingDonePercent, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT
|
||||
&AuraEffect::HandleModHealingDonePercent, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT
|
||||
&AuraEffect::HandleModTotalPercentStat, //137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE
|
||||
&AuraEffect::HandleModMeleeSpeedPct, //138 SPELL_AURA_MOD_MELEE_HASTE
|
||||
&AuraEffect::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION
|
||||
@@ -2197,7 +2197,7 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode,
|
||||
{
|
||||
if (caster->HasAura(52648)) // Glyph of the Penguin
|
||||
model_id = 26452;
|
||||
else if (caster->HasAura(57927)) // Glyph of the Monkey
|
||||
else if (caster->HasAura(57927)) // Glyph of the Monkey
|
||||
model_id = 21362;
|
||||
}
|
||||
}
|
||||
@@ -2316,7 +2316,7 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (auto& pair : target->GetThreatManager().GetThreatenedByMeList())
|
||||
pair.second->ScaleThreat(0.0f);
|
||||
|
||||
@@ -3344,7 +3344,7 @@ void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const* aurApp, uint
|
||||
target->GetThreatManager().EvaluateSuppressed();
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
// do not remove unit flag if there are more than this auraEffect of that kind on unit
|
||||
if (target->HasAuraType(GetAuraType()))
|
||||
return;
|
||||
@@ -4108,12 +4108,6 @@ void AuraEffect::HandleModMeleeRangedSpeedPct(AuraApplication const* aurApp, uin
|
||||
target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), apply);
|
||||
target->ApplyAttackTimePercentMod(OFF_ATTACK, (float)GetAmount(), apply);
|
||||
target->ApplyAttackTimePercentMod(RANGED_ATTACK, (float)GetAmount(), apply);
|
||||
|
||||
if (GetAuraType() != SPELL_AURA_MOD_MELEE_RANGED_HASTE_2 && GetAuraType() != SPELL_AURA_MOD_RANGED_HASTE_2)
|
||||
{
|
||||
target->ApplyHasteRegenMod(BASE_ATTACK, (float)GetAmount(), apply);
|
||||
target->ApplyHasteRegenMod(RANGED_ATTACK, (float)GetAmount(), apply);
|
||||
}
|
||||
}
|
||||
|
||||
void AuraEffect::HandleModCombatSpeedPct(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
@@ -4122,7 +4116,7 @@ void AuraEffect::HandleModCombatSpeedPct(AuraApplication const* aurApp, uint8 mo
|
||||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MELEE_SLOW);
|
||||
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, GetAuraType());
|
||||
if (abs(spellGroupVal) >= abs(GetAmount()))
|
||||
return;
|
||||
|
||||
@@ -4132,16 +4126,16 @@ void AuraEffect::HandleModCombatSpeedPct(AuraApplication const* aurApp, uint8 mo
|
||||
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(spellGroupVal), !apply);
|
||||
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply);
|
||||
target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(spellGroupVal), !apply);
|
||||
|
||||
target->ApplyHasteRegenMod(float(spellGroupVal), !apply);
|
||||
}
|
||||
|
||||
target->ApplyCastTimePercentMod(float(GetAmount()), apply);
|
||||
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
|
||||
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply);
|
||||
target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(GetAmount()), apply);
|
||||
if (GetAuraType() != SPELL_AURA_MOD_MELEE_RANGED_HASTE_2 && GetAuraType() != SPELL_AURA_MOD_RANGED_HASTE_2)
|
||||
{
|
||||
target->ApplyHasteRegenMod(BASE_ATTACK, (float)GetAmount(), apply);
|
||||
target->ApplyHasteRegenMod(RANGED_ATTACK, (float)GetAmount(), apply);
|
||||
}
|
||||
|
||||
target->ApplyHasteRegenMod((float)GetAmount(), apply);
|
||||
}
|
||||
|
||||
void AuraEffect::HandleModAttackSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
@@ -4152,8 +4146,6 @@ void AuraEffect::HandleModAttackSpeed(AuraApplication const* aurApp, uint8 mode,
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
|
||||
if (GetAuraType() != SPELL_AURA_MOD_MELEE_RANGED_HASTE_2 && GetAuraType() != SPELL_AURA_MOD_RANGED_HASTE_2)
|
||||
target->ApplyHasteRegenMod(BASE_ATTACK, (float)GetAmount(), apply);
|
||||
target->UpdateDamagePhysical(BASE_ATTACK);
|
||||
}
|
||||
|
||||
@@ -4163,35 +4155,26 @@ void AuraEffect::HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mod
|
||||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
bool applyRegenPct = GetAuraType() != SPELL_AURA_MOD_MELEE_HASTE_3 && GetAuraType() != SPELL_AURA_MOD_RANGED_HASTE_2;
|
||||
|
||||
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, GetAuraType());
|
||||
if (abs(spellGroupVal) >= abs(GetAmount()))
|
||||
bool applyHasteRegenMod = GetAuraType() == SPELL_AURA_MOD_MELEE_HASTE;
|
||||
|
||||
if (std::abs(spellGroupVal) >= std::abs(GetAmount()))
|
||||
return;
|
||||
|
||||
if (spellGroupVal)
|
||||
{
|
||||
if (target->GetTypeId() == TYPEID_PLAYER && applyRegenPct && GetBase()->HasEffectType(SPELL_AURA_MOD_MELEE_HASTE_3))
|
||||
target->ApplyHasteRegenMod(BASE_ATTACK, (float)GetAmount(), !apply);
|
||||
else
|
||||
{
|
||||
target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), !apply);
|
||||
target->ApplyAttackTimePercentMod(OFF_ATTACK, (float)GetAmount(), !apply);
|
||||
if (applyRegenPct)
|
||||
target->ApplyHasteRegenMod(BASE_ATTACK, (float)GetAmount(), !apply);
|
||||
}
|
||||
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(spellGroupVal), !apply);
|
||||
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply);
|
||||
|
||||
if (applyHasteRegenMod)
|
||||
target->ApplyHasteRegenMod(float(spellGroupVal), !apply);
|
||||
}
|
||||
|
||||
// Auras that only increase regeneration
|
||||
if (target->GetTypeId() == TYPEID_PLAYER && applyRegenPct && GetBase()->HasEffectType(SPELL_AURA_MOD_MELEE_HASTE_3))
|
||||
target->ApplyHasteRegenMod(BASE_ATTACK, (float)GetAmount(), apply);
|
||||
else
|
||||
{
|
||||
target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), apply);
|
||||
target->ApplyAttackTimePercentMod(OFF_ATTACK, (float)GetAmount(), apply);
|
||||
if (applyRegenPct)
|
||||
target->ApplyHasteRegenMod(BASE_ATTACK, (float)GetAmount(), apply);
|
||||
}
|
||||
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
|
||||
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply);
|
||||
|
||||
if (applyHasteRegenMod)
|
||||
target->ApplyHasteRegenMod(float(GetAmount()), apply);
|
||||
}
|
||||
|
||||
void AuraEffect::HandleAuraModRangedHaste(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
@@ -4201,19 +4184,22 @@ void AuraEffect::HandleAuraModRangedHaste(AuraApplication const* aurApp, uint8 m
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, GetAuraType());
|
||||
if (abs(spellGroupVal) >= abs(GetAmount()))
|
||||
bool applyHasteRegenMod = GetAuraType() == SPELL_AURA_MOD_RANGED_HASTE;
|
||||
|
||||
if (std::abs(spellGroupVal) >= std::abs(GetAmount()))
|
||||
return;
|
||||
|
||||
if (spellGroupVal)
|
||||
{
|
||||
target->ApplyAttackTimePercentMod(RANGED_ATTACK, (float)GetAmount(), !apply);
|
||||
if (GetAuraType() != SPELL_AURA_MOD_MELEE_RANGED_HASTE_2 && GetAuraType() != SPELL_AURA_MOD_RANGED_HASTE_2)
|
||||
target->ApplyHasteRegenMod(RANGED_ATTACK, (float)GetAmount(), !apply);
|
||||
}
|
||||
target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(spellGroupVal), !apply);
|
||||
|
||||
target->ApplyAttackTimePercentMod(RANGED_ATTACK, (float)GetAmount(), apply);
|
||||
if (GetAuraType() != SPELL_AURA_MOD_MELEE_RANGED_HASTE_2 && GetAuraType() != SPELL_AURA_MOD_RANGED_HASTE_2)
|
||||
target->ApplyHasteRegenMod(RANGED_ATTACK, (float)GetAmount(), apply);
|
||||
if (applyHasteRegenMod)
|
||||
target->ApplyHasteRegenMod(float(spellGroupVal), !apply);
|
||||
}
|
||||
target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(GetAmount()), apply);
|
||||
|
||||
if (applyHasteRegenMod)
|
||||
target->ApplyHasteRegenMod(float(GetAmount()), apply);
|
||||
}
|
||||
|
||||
/********************************/
|
||||
|
||||
Reference in new issue
Block a user