From cdbe16fabea9fe140fb59b510118104b3be1bc9f Mon Sep 17 00:00:00 2001 From: ariel- Date: Mon, 23 Jan 2017 22:03:24 -0300 Subject: Core/Scripts: implemented Gnomish Harm Prevention Belt Updates #18542 (cherry picked from commit 2db3e86d9bf200e5049e553160bc47b7bacac621) --- src/server/scripts/Spells/spell_item.cpp | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'src/server/scripts') diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 9836318f066..7461e52e1b4 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -1100,6 +1100,46 @@ class spell_item_gnomish_death_ray : public SpellScriptLoader } }; +// Item 10721: Gnomish Harm Prevention Belt +// 13234 - Harm Prevention Belt +enum HarmPreventionBelt +{ + SPELL_FORCEFIELD_COLLAPSE = 13235 +}; + +class spell_item_harm_prevention_belt : public SpellScriptLoader +{ +public: + spell_item_harm_prevention_belt() : SpellScriptLoader("spell_item_harm_prevention_belt") { } + + class spell_item_harm_prevention_belt_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_harm_prevention_belt_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_FORCEFIELD_COLLAPSE)) + return false; + return true; + } + + void HandleProc(ProcEventInfo& /*eventInfo*/) + { + GetTarget()->CastSpell((Unit*)nullptr, SPELL_FORCEFIELD_COLLAPSE, true); + } + + void Register() override + { + OnProc += AuraProcFn(spell_item_harm_prevention_belt_AuraScript::HandleProc); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_harm_prevention_belt_AuraScript(); + } +}; + enum Heartpierce { SPELL_INVIGORATION_MANA = 71881, @@ -4839,6 +4879,7 @@ void AddSC_item_spell_scripts() new spell_item_flask_of_the_north(); new spell_item_frozen_shadoweave(); new spell_item_gnomish_death_ray(); + new spell_item_harm_prevention_belt(); new spell_item_heartpierce("spell_item_heartpierce"); new spell_item_heartpierce("spell_item_heartpierce_hero"); new spell_item_crystal_spire_of_karabor(); -- cgit v1.2.3 From ebc06b1d0401be69066986e18d0e926170c58023 Mon Sep 17 00:00:00 2001 From: ariel- Date: Mon, 27 Feb 2017 14:20:32 -0300 Subject: Core/Auras: reworked multiplicative AuraEffects calculation - Splitted containers for flat modifiers and pct modifiers, as they now have different handling - Amount is now multiplied only on apply; on unapply, iterate through auras and reset the counter - Fixes many cases of rounding error due to applying/unapplying of small factors - Allows amounts to be zeroed (ie with an AuraEffect of amount -100) - Do a partial revert of 6dc37a9add631888fe5fbcd43d19c2b07bed8a57, auras should update amounts only for items allowed (ie no more giving crit to a sword while having an axe in the other hand and being Poleaxe spec'd) - SPELL_AURA_MOD_SCALE now scales additively, rather than multiplicatively (checked in sniffs) Closes #18687 (cherry picked from commit c69a7d1223b2ce108a221e5cc70f76cd80ae6675) --- src/common/Utilities/Util.h | 7 - src/server/game/Entities/Creature/Creature.cpp | 20 +- src/server/game/Entities/Creature/Creature.h | 2 +- .../game/Entities/Creature/TemporarySummon.h | 1 + src/server/game/Entities/Pet/Pet.cpp | 12 +- src/server/game/Entities/Player/Player.cpp | 310 +++++++++++++------ src/server/game/Entities/Player/Player.h | 29 +- src/server/game/Entities/Unit/StatSystem.cpp | 124 ++++---- src/server/game/Entities/Unit/Unit.cpp | 289 +++++++++++++++--- src/server/game/Entities/Unit/Unit.h | 49 ++- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 327 +++++++++++++-------- src/server/game/Spells/Auras/SpellAuraEffects.h | 1 + src/server/game/Spells/SpellEffects.cpp | 2 +- .../scripts/Northrend/Naxxramas/boss_kelthuzad.cpp | 18 +- src/server/scripts/Spells/spell_pet.cpp | 2 +- 15 files changed, 809 insertions(+), 384 deletions(-) (limited to 'src/server/scripts') diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index 20520cb2068..a18fd16ad15 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -63,13 +63,6 @@ TC_COMMON_API std::string secsToTimeString(uint64 timeInSecs, bool shortText = f TC_COMMON_API uint32 TimeStringToSecs(const std::string& timestring); TC_COMMON_API std::string TimeToTimestampStr(time_t t); -inline void ApplyPercentModFloatVar(float& var, float val, bool apply) -{ - if (val == -100.0f) // prevent set var to zero - val = -99.99f; - var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val)); -} - // Percentage calculation template inline T CalculatePct(T base, U pct) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 748e1ac26ee..4af0dda1212 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -536,12 +536,12 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, UpdateLevelDependantStats(); // We still re-initialize level dependant stats on entry update SetMeleeDamageSchool(SpellSchools(cInfo->dmgschool)); - SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_HOLY])); - SetModifierValue(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FIRE])); - SetModifierValue(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_NATURE])); - SetModifierValue(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FROST])); - SetModifierValue(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_SHADOW])); - SetModifierValue(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_ARCANE])); + SetStatFlatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_HOLY])); + SetStatFlatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FIRE])); + SetStatFlatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_NATURE])); + SetStatFlatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FROST])); + SetStatFlatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_SHADOW])); + SetStatFlatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_ARCANE])); SetCanModifyStats(true); UpdateAllStats(); @@ -1409,7 +1409,7 @@ void Creature::UpdateLevelDependantStats() break; } - SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health); + SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)health); // damage float basedamage = stats->GenerateBaseDamage(cInfo); @@ -1426,11 +1426,11 @@ void Creature::UpdateLevelDependantStats() SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, weaponBaseMinDamage); SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, weaponBaseMaxDamage); - SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower); - SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower); + SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower); + SetStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower); float armor = (float)stats->GenerateArmor(cInfo); /// @todo Why is this treated as uint32 when it's a float? - SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, armor); + SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, armor); } float Creature::_GetHealthMod(int32 Rank) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index afd07d44053..1be3e00e39a 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -155,7 +155,7 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma void UpdateMaxPower(Powers power) override; uint32 GetPowerIndex(Powers power) const override; void UpdateAttackPowerAndDamage(bool ranged = false) override; - void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) override; + void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const override; void SetCanDualWield(bool value) override; int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; } diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h index 056fe78c99d..c91af442cef 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.h +++ b/src/server/game/Entities/Creature/TemporarySummon.h @@ -120,6 +120,7 @@ class TC_GAME_API Guardian : public Minion void UpdateDamagePhysical(WeaponAttackType attType) override; int32 GetBonusDamage() const { return m_bonusSpellDamage; } + float GetBonusStatFromOwner(Stats stat) const { return m_statFromOwner[stat]; } void SetBonusDamage(int32 damage); protected: int32 m_bonusSpellDamage; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 7563289b480..2c0c36e908d 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -794,7 +794,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); - SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel*50)); + SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50)); SetBaseAttackTime(BASE_ATTACK, BASE_ATTACK_TIME); SetBaseAttackTime(OFF_ATTACK, BASE_ATTACK_TIME); @@ -819,7 +819,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) // Hunters pet should not inherit resistances from creature_template, they have separate auras for that if (!IsHunterPet()) for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) - SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i])); + SetStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i])); // Health, Mana or Power, Armor PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(creature_ID, petlevel); @@ -829,7 +829,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) SetCreateMana(pInfo->mana); if (pInfo->armor > 0) - SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor)); + SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor)); for (uint8 stat = 0; stat < MAX_STATS; ++stat) SetCreateStat(Stats(stat), float(pInfo->stats[stat])); @@ -875,7 +875,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4))); - //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower)); + //SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower)); break; } case HUNTER_PET: @@ -963,8 +963,8 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel))); - SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(GetOwner()->GetArmor()) * 0.35f); // Bonus Armor (35% of player armor) - SetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(GetOwner()->GetStat(STAT_STAMINA)) * 0.3f); // Bonus Stamina (30% of player stamina) + SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(GetOwner()->GetArmor()) * 0.35f); // Bonus Armor (35% of player armor) + SetStatFlatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(GetOwner()->GetStat(STAT_STAMINA)) * 0.3f); // Bonus Stamina (30% of player stamina) if (!HasAura(58877))//prevent apply twice for the 2 wolves AddAura(58877, this);//Spirit Hunt, passive, Spirit Wolves' attacks heal them and their master for 150% of damage done. break; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index daeaf3d8877..580f21843d0 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -269,8 +269,8 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this) for (uint8 i = 0; i < BASEMOD_END; ++i) { - m_auraBaseMod[i][FLAT_MOD] = 0.0f; - m_auraBaseMod[i][PCT_MOD] = 1.0f; + m_auraBaseFlatMod[i] = 0.0f; + m_auraBasePctMod[i] = 1.0f; } for (uint8 i = 0; i < MAX_COMBAT_RATING; i++) @@ -4952,20 +4952,104 @@ void Player::LeaveLFGChannel() } } -void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply) +void Player::HandleBaseModFlatValue(BaseModGroup modGroup, float amount, bool apply) { - if (modGroup >= BASEMOD_END || modType >= MOD_END) + if (modGroup >= BASEMOD_END) { TC_LOG_ERROR("spells", "Player::HandleBaseModValue: Invalid BaseModGroup/BaseModType (%u/%u) for player '%s' (%s)", - modGroup, modType, GetName().c_str(), GetGUID().ToString().c_str()); + modGroup, FLAT_MOD, GetName().c_str(), GetGUID().ToString().c_str()); + return; + } + + m_auraBaseFlatMod[modGroup] += apply ? amount : -amount; + UpdateBaseModGroup(modGroup); +} + +void Player::ApplyBaseModPctValue(BaseModGroup modGroup, float pct) +{ + if (modGroup >= BASEMOD_END) + { + TC_LOG_ERROR("spells", "Player::HandleBaseModValue: Invalid BaseModGroup/BaseModType (%u/%u) for player '%s' (%s)", + modGroup, FLAT_MOD, GetName().c_str(), GetGUID().ToString().c_str()); + return; + } + + AddPct(m_auraBasePctMod[modGroup], pct); + UpdateBaseModGroup(modGroup); +} + +void Player::SetBaseModFlatValue(BaseModGroup modGroup, float val) +{ + if (m_auraBaseFlatMod[modGroup] == val) + return; + + m_auraBaseFlatMod[modGroup] = val; + UpdateBaseModGroup(modGroup); +} + +void Player::SetBaseModPctValue(BaseModGroup modGroup, float val) +{ + if (m_auraBasePctMod[modGroup] == val) + return; + + m_auraBasePctMod[modGroup] = val; + UpdateBaseModGroup(modGroup); +} + +void Player::UpdateDamageDoneMods(WeaponAttackType attackType) +{ + Unit::UpdateDamageDoneMods(attackType); + + UnitMods unitMod; + switch (attackType) + { + case BASE_ATTACK: + unitMod = UNIT_MOD_DAMAGE_MAINHAND; + break; + case OFF_ATTACK: + unitMod = UNIT_MOD_DAMAGE_OFFHAND; + break; + case RANGED_ATTACK: + unitMod = UNIT_MOD_DAMAGE_RANGED; + break; + default: + ABORT(); + break; + } + + float amount = 0.0f; + Item* item = GetWeaponForAttack(attackType, true); + if (!item) return; + + for (uint8 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot) + { + SpellItemEnchantmentEntry const* enchantmentEntry = sSpellItemEnchantmentStore.LookupEntry(item->GetEnchantmentId(EnchantmentSlot(slot))); + if (!enchantmentEntry) + continue; + + for (uint8 i = 0; i < MAX_ITEM_ENCHANTMENT_EFFECTS; ++i) + { + switch (enchantmentEntry->Effect[i]) + { + case ITEM_ENCHANTMENT_TYPE_DAMAGE: + amount += enchantmentEntry->EffectScalingPoints[i]; + break; + case ITEM_ENCHANTMENT_TYPE_TOTEM: + if (getClass() == CLASS_SHAMAN) + amount += enchantmentEntry->EffectScalingPoints[i] * item->GetTemplate()->GetDelay() / 1000.0f; + break; + default: + break; + } + } } - if (modType == FLAT_MOD) - m_auraBaseMod[modGroup][modType] += apply ? amount : -amount; - else // PCT_MOD - ApplyPercentModFloatVar(m_auraBaseMod[modGroup][modType], amount, apply); + HandleStatFlatModifier(unitMod, TOTAL_VALUE, amount, true); +} +void Player::UpdateBaseModGroup(BaseModGroup modGroup) +{ if (!CanModifyStats()) return; @@ -4987,10 +5071,7 @@ float Player::GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const return 0.0f; } - if (modType == PCT_MOD && m_auraBaseMod[modGroup][PCT_MOD] <= 0.0f) - return 0.0f; - - return m_auraBaseMod[modGroup][modType]; + return (modType == FLAT_MOD ? m_auraBaseFlatMod[modGroup] : m_auraBasePctMod[modGroup]); } float Player::GetTotalBaseModValue(BaseModGroup modGroup) const @@ -5002,10 +5083,7 @@ float Player::GetTotalBaseModValue(BaseModGroup modGroup) const return 0.0f; } - if (m_auraBaseMod[modGroup][PCT_MOD] <= 0.0f) - return 0.0f; - - return m_auraBaseMod[modGroup][FLAT_MOD] * m_auraBaseMod[modGroup][PCT_MOD]; + return m_auraBaseFlatMod[modGroup] * m_auraBasePctMod[modGroup]; } void Player::GetDodgeFromAgility(float &/*diminishing*/, float &/*nondiminishing*/) const @@ -5053,7 +5131,7 @@ void Player::GetDodgeFromAgility(float &/*diminishing*/, float &/*nondiminishing // return; ///// @todo research if talents/effects that increase total agility by x% should increase non-diminishing part - //float base_agility = GetCreateStat(STAT_AGILITY) * m_auraModifiersGroup[UNIT_MOD_STAT_START + STAT_AGILITY][BASE_PCT]; + //float base_agility = GetCreateStat(STAT_AGILITY) * GetPctModifierValue(UnitMods(UNIT_MOD_STAT_START + STAT_AGILITY), BASE_PCT); //float bonus_agility = GetStat(STAT_AGILITY) - base_agility; //// calculate diminishing (green in char screen) and non-diminishing (white) contribution @@ -5312,7 +5390,7 @@ void Player::UpdateRating(CombatRating cr) void Player::UpdateAllRatings() { - for (int cr = 0; cr < MAX_COMBAT_RATING; ++cr) + for (uint8 cr = 0; cr < MAX_COMBAT_RATING; ++cr) UpdateRating(CombatRating(cr)); } @@ -7419,7 +7497,13 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemA _ApplyItemBonuses(item, slot, apply); ApplyItemEquipSpell(item, apply); if (updateItemAuras) + { ApplyItemDependentAuras(item, apply); + + WeaponAttackType const attackType = Player::GetAttackBySlot(slot, item->GetTemplate()->GetInventoryType()); + if (attackType != MAX_ATTACK) + UpdateWeaponDependentAuras(attackType); + } ApplyArtifactPowers(item, apply); ApplyAzeritePowers(item, apply); ApplyEnchantment(item, apply); @@ -7452,22 +7536,22 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply) switch (statType) { case ITEM_MOD_MANA: - HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply); break; case ITEM_MOD_HEALTH: // modify HP - HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply); break; case ITEM_MOD_AGILITY: // modify agility - HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_AGILITY); break; case ITEM_MOD_STRENGTH: //modify strength - HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_STRENGTH); break; case ITEM_MOD_INTELLECT: //modify intellect - HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_INTELLECT); break; // case ITEM_MOD_SPIRIT: //modify spirit // HandleStatModifier(UNIT_MOD_STAT_SPIRIT, BASE_VALUE, float(val), apply); @@ -7477,8 +7561,8 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply) { if (GtStaminaMultByILvl const* staminaMult = sStaminaMultByILvlGameTable.GetRow(itemLevel)) val = int32(val * GetIlvlStatMultiplier(staminaMult, proto->GetInventoryType())); - HandleStatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_STAMINA, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_PCT_EXCLUDE_CREATE)), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_STAMINA); break; } case ITEM_MOD_DEFENSE_SKILL_RATING: @@ -7570,11 +7654,11 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply) ApplyRatingMod(CR_EXPERTISE, int32(val * combatRatingMultiplier), apply); break; case ITEM_MOD_ATTACK_POWER: - HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply); - HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); break; case ITEM_MOD_RANGED_ATTACK_POWER: - HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); break; case ITEM_MOD_VERSATILITY: ApplyRatingMod(CR_VERSATILITY_DAMAGE_DONE, int32(val * combatRatingMultiplier), apply); @@ -7600,25 +7684,25 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply) ApplyRatingMod(CR_MASTERY, int32(val * combatRatingMultiplier), apply); break; case ITEM_MOD_EXTRA_ARMOR: - HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(val), apply); break; case ITEM_MOD_FIRE_RESISTANCE: - HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(val), apply); break; case ITEM_MOD_FROST_RESISTANCE: - HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(val), apply); break; case ITEM_MOD_HOLY_RESISTANCE: - HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(val), apply); break; case ITEM_MOD_SHADOW_RESISTANCE: - HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(val), apply); break; case ITEM_MOD_NATURE_RESISTANCE: - HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(val), apply); break; case ITEM_MOD_ARCANE_RESISTANCE: - HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(val), apply); break; case ITEM_MOD_PVP_POWER: ApplyRatingMod(CR_PVP_POWER, int32(val), apply); @@ -7654,36 +7738,36 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply) ApplyRatingMod(CR_UNUSED_12, int32(val), apply); break; case ITEM_MOD_AGI_STR_INT: - HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); - HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply); - HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply); - ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply); - ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_AGILITY); + UpdateStatBuffMod(STAT_STRENGTH); + UpdateStatBuffMod(STAT_INTELLECT); break; case ITEM_MOD_AGI_STR: - HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); - HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply); - ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_AGILITY); + UpdateStatBuffMod(STAT_STRENGTH); break; case ITEM_MOD_AGI_INT: - HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); - HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply); - ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_AGILITY); + UpdateStatBuffMod(STAT_INTELLECT); break; case ITEM_MOD_STR_INT: - HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply); - HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply); - ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply); - ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply); + HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply); + UpdateStatBuffMod(STAT_STRENGTH); + UpdateStatBuffMod(STAT_INTELLECT); break; } } if (uint32 armor = item->GetArmor(this)) - HandleStatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(armor), apply); + HandleStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(armor), apply); WeaponAttackType attType = BASE_ATTACK; @@ -7775,6 +7859,49 @@ void Player::ApplyItemObtainSpells(Item* item, bool apply) } } +// this one rechecks weapon auras and stores them in BaseModGroup container +// needed for things like axe specialization applying only to axe weapons in case of dual-wield +void Player::UpdateWeaponDependentCritAuras(WeaponAttackType attackType) +{ + BaseModGroup modGroup; + switch (attackType) + { + case BASE_ATTACK: + modGroup = CRIT_PERCENTAGE; + break; + case OFF_ATTACK: + modGroup = OFFHAND_CRIT_PERCENTAGE; + break; + case RANGED_ATTACK: + modGroup = RANGED_CRIT_PERCENTAGE; + break; + default: + ABORT(); + break; + } + + float amount = 0.0f; + amount += GetTotalAuraModifier(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT, std::bind(&Unit::CheckAttackFitToAuraRequirement, this, attackType, std::placeholders::_1)); + + // these auras don't have item requirement (only Combat Expertise in 3.3.5a) + amount += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + + SetBaseModFlatValue(modGroup, amount); +} + +void Player::UpdateAllWeaponDependentCritAuras() +{ + for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i) + UpdateWeaponDependentCritAuras(WeaponAttackType(i)); +} + +void Player::UpdateWeaponDependentAuras(WeaponAttackType attackType) +{ + UpdateWeaponDependentCritAuras(attackType); + UpdateDamageDoneMods(attackType); + UpdateDamagePctDoneMods(attackType); +} + void Player::ApplyItemDependentAuras(Item* item, bool apply) { if (apply) @@ -8427,6 +8554,10 @@ void Player::_ApplyAllItemMods() ApplyItemDependentAuras(m_items[i], true); _ApplyItemBonuses(m_items[i], i, true); + + WeaponAttackType const attackType = Player::GetAttackBySlot(i, m_items[i]->GetTemplate()->GetInventoryType()); + if (attackType != MAX_ATTACK) + UpdateWeaponDependentAuras(attackType); } } @@ -10094,7 +10225,7 @@ Item* Player::GetChildItemByGuid(ObjectGuid guid) const return nullptr; } -uint8 Player::GetAttackBySlot(uint8 slot, InventoryType inventoryType) +WeaponAttackType Player::GetAttackBySlot(uint8 slot, InventoryType inventoryType) { switch (slot) { @@ -14124,16 +14255,12 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool // processed in Player::CastItemCombatSpell break; case ITEM_ENCHANTMENT_TYPE_DAMAGE: - if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND) - { - if (item->GetTemplate()->GetInventoryType() != INVTYPE_RANGED && item->GetTemplate()->GetInventoryType() != INVTYPE_RANGEDRIGHT) - HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(enchant_amount), apply); - else - HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(enchant_amount), apply); - } - else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND) - HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(enchant_amount), apply); + { + WeaponAttackType const attackType = Player::GetAttackBySlot(item->GetSlot(), item->GetTemplate()->GetInventoryType()); + if (attackType != MAX_ATTACK) + UpdateDamageDoneMods(attackType); break; + } case ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL: if (enchant_spell_id) { @@ -14163,7 +14290,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool enchant_amount = uint32(pEnchant->EffectScalingPoints[s] * GetSpellScalingColumnForClass(spellScaling, scalingClass)); } enchant_amount = std::max(enchant_amount, 1u); - HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply); + HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply); break; case ITEM_ENCHANTMENT_TYPE_STAT: { @@ -14193,26 +14320,26 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool { case ITEM_MOD_MANA: TC_LOG_DEBUG("entities.player.items", "+ %u MANA", enchant_amount); - HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply); + HandleStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply); break; case ITEM_MOD_HEALTH: TC_LOG_DEBUG("entities.player.items", "+ %u HEALTH", enchant_amount); - HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply); + HandleStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply); break; case ITEM_MOD_AGILITY: TC_LOG_DEBUG("entities.player.items", "+ %u AGILITY", enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_AGILITY, (float)enchant_amount, apply); + HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply); + UpdateStatBuffMod(STAT_AGILITY); break; case ITEM_MOD_STRENGTH: TC_LOG_DEBUG("entities.player.items", "+ %u STRENGTH", enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_STRENGTH, (float)enchant_amount, apply); + HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply); + UpdateStatBuffMod(STAT_STRENGTH); break; case ITEM_MOD_INTELLECT: TC_LOG_DEBUG("entities.player.items", "+ %u INTELLECT", enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_INTELLECT, (float)enchant_amount, apply); + HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply); + UpdateStatBuffMod(STAT_INTELLECT); break; // case ITEM_MOD_SPIRIT: // TC_LOG_DEBUG("entities.player.items", "+ %u SPIRIT", enchant_amount); @@ -14221,8 +14348,8 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool // break; case ITEM_MOD_STAMINA: TC_LOG_DEBUG("entities.player.items", "+ %u STAMINA", enchant_amount); - HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply); - ApplyStatBuffMod(STAT_STAMINA, (float)enchant_amount, apply); + HandleStatFlatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply); + UpdateStatBuffMod(STAT_STAMINA); break; case ITEM_MOD_DEFENSE_SKILL_RATING: ApplyRatingMod(CR_DEFENSE_SKILL, enchant_amount, apply); @@ -14330,12 +14457,12 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool TC_LOG_DEBUG("entities.player.items", "+ %u EXPERTISE", enchant_amount); break; case ITEM_MOD_ATTACK_POWER: - HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply); - HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); + HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply); + HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); TC_LOG_DEBUG("entities.player.items", "+ %u ATTACK_POWER", enchant_amount); break; case ITEM_MOD_RANGED_ATTACK_POWER: - HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); + HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); TC_LOG_DEBUG("entities.player.items", "+ %u RANGED_ATTACK_POWER", enchant_amount); break; case ITEM_MOD_MANA_REGENERATION: @@ -14359,7 +14486,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool TC_LOG_DEBUG("entities.player.items", "+ %u SPELL_PENETRATION", enchant_amount); break; case ITEM_MOD_BLOCK_VALUE: - HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(enchant_amount), apply); + HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(enchant_amount), apply); TC_LOG_DEBUG("entities.player.items", "+ %u BLOCK_VALUE", enchant_amount); break; case ITEM_MOD_MASTERY_RATING: @@ -14379,20 +14506,9 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool } case ITEM_ENCHANTMENT_TYPE_TOTEM: // Shaman Rockbiter Weapon { - if (getClass() == CLASS_SHAMAN) - { - float addValue; - if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND) - { - addValue = float(enchant_amount * item->GetTemplate()->GetDelay() / 1000.0f); - HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, addValue, apply); - } - else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND) - { - addValue = float(enchant_amount * item->GetTemplate()->GetDelay() / 1000.0f); - HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, addValue, apply); - } - } + WeaponAttackType const attackType = Player::GetAttackBySlot(item->GetSlot(), item->GetTemplate()->GetInventoryType()); + if (attackType != MAX_ATTACK) + UpdateDamageDoneMods(attackType); break; } case ITEM_ENCHANTMENT_TYPE_USE_SPELL: diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 476aa0d7492..554c9090212 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1128,8 +1128,8 @@ class TC_GAME_API Player : public Unit, public GridObject Item* GetWeaponForAttack(WeaponAttackType attackType, bool useable = false) const; Item* GetShield(bool useable = false) const; Item* GetChildItemByGuid(ObjectGuid guid) const; - static uint8 GetAttackBySlot(uint8 slot, InventoryType inventoryType); // MAX_ATTACK if not weapon slot - std::vector &GetItemUpdateQueue() { return m_itemUpdateQueue; } + static WeaponAttackType GetAttackBySlot(uint8 slot, InventoryType inventoryType); // MAX_ATTACK if not weapon slot + std::vector& GetItemUpdateQueue() { return m_itemUpdateQueue; } static bool IsInventoryPos(uint16 pos) { return IsInventoryPos(pos >> 8, pos & 255); } static bool IsInventoryPos(uint8 bag, uint8 slot); static bool IsEquipmentPos(uint16 pos) { return IsEquipmentPos(pos >> 8, pos & 255); } @@ -1771,6 +1771,7 @@ class TC_GAME_API Player : public Unit, public GridObject void ApplyModDamageDonePos(SpellSchools school, int32 mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDonePos, school), mod, apply); } void ApplyModDamageDoneNeg(SpellSchools school, int32 mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDoneNeg, school), mod, apply); } void ApplyModDamageDonePercent(SpellSchools school, float pct, bool apply) { ApplyPercentModUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDonePercent, school), pct, apply); } + void SetModDamageDonePercent(uint8 school, float pct) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDonePercent, school), pct); } void ApplyRatingMod(CombatRating cr, int32 value, bool apply); void UpdateRating(CombatRating cr); void UpdateAllRatings(); @@ -1779,7 +1780,7 @@ class TC_GAME_API Player : public Unit, public GridObject void UpdateHealingDonePercentMod(); bool CanUseMastery() const; - void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) override; + void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const override; void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);} void GetDodgeFromAgility(float &diminishing, float &nondiminishing) const; @@ -2003,11 +2004,19 @@ class TC_GAME_API Player : public Unit, public GridObject bool CanTameExoticPets() const { return IsGameMaster() || HasAuraType(SPELL_AURA_ALLOW_TAME_PET_TYPE); } void SetRegularAttackTime(); - void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; } - void HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply); + + void HandleBaseModFlatValue(BaseModGroup modGroup, float amount, bool apply); + void ApplyBaseModPctValue(BaseModGroup modGroup, float pct); + + void SetBaseModFlatValue(BaseModGroup modGroup, float val); + void SetBaseModPctValue(BaseModGroup modGroup, float val); + + void UpdateDamageDoneMods(WeaponAttackType attackType) override; + void UpdateBaseModGroup(BaseModGroup modGroup); + float GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const; float GetTotalBaseModValue(BaseModGroup modGroup) const; - float GetTotalPercentageModValue(BaseModGroup modGroup) const { return m_auraBaseMod[modGroup][FLAT_MOD] + m_auraBaseMod[modGroup][PCT_MOD]; } + void _ApplyAllStatBonuses(); void _RemoveAllStatBonuses(); @@ -2015,6 +2024,11 @@ class TC_GAME_API Player : public Unit, public GridObject void CastAllObtainSpells(); void ApplyItemObtainSpells(Item* item, bool apply); + + void UpdateWeaponDependentCritAuras(WeaponAttackType attackType); + void UpdateAllWeaponDependentCritAuras(); + + void UpdateWeaponDependentAuras(WeaponAttackType attackType); void ApplyItemDependentAuras(Item* item, bool apply); void _ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemAuras = true); @@ -2651,7 +2665,8 @@ class TC_GAME_API Player : public Unit, public GridObject ActionButtonList m_actionButtons; - float m_auraBaseMod[BASEMOD_END][MOD_END]; + float m_auraBaseFlatMod[BASEMOD_END]; + float m_auraBasePctMod[BASEMOD_END]; int16 m_baseRatingValue[MAX_COMBAT_RATING]; uint32 m_baseSpellPower; uint32 m_baseManaRegen; diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index e9f1fc359d9..2170ba4d7c7 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -200,7 +200,7 @@ void Player::UpdateSpellDamageAndHealingBonus() bool Player::UpdateAllStats() { - for (int8 i = STAT_STRENGTH; i < MAX_STATS; ++i) + for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i) { float value = GetTotalStatValue(Stats(i)); SetStat(Stats(i), int32(value)); @@ -254,10 +254,10 @@ void Player::UpdateArmor() { UnitMods unitMod = UNIT_MOD_ARMOR; - float value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items) + float value = GetFlatModifierValue(unitMod, BASE_VALUE); // base armor (from items) float baseValue = value; - value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items - value += GetModifierValue(unitMod, TOTAL_VALUE); + value *= GetPctModifierValue(unitMod, BASE_PCT); // armor percent from items + value += GetFlatModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods AuraEffectList const& mResbyIntellect = GetAuraEffectsByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT); @@ -267,7 +267,7 @@ void Player::UpdateArmor() value += CalculatePct(GetStat(Stats((*i)->GetMiscValueB())), (*i)->GetAmount()); } - value *= GetModifierValue(unitMod, TOTAL_PCT); + value *= GetPctModifierValue(unitMod, TOTAL_PCT); SetArmor(int32(baseValue), int32(value - baseValue)); @@ -294,10 +294,10 @@ void Player::UpdateMaxHealth() { UnitMods unitMod = UNIT_MOD_HEALTH; - float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth(); - value *= GetModifierValue(unitMod, BASE_PCT); - value += GetModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina(); - value *= GetModifierValue(unitMod, TOTAL_PCT); + float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateHealth(); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina(); + value *= GetPctModifierValue(unitMod, TOTAL_PCT); SetMaxHealth((uint32)value); } @@ -315,10 +315,10 @@ void Player::UpdateMaxPower(Powers power) UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); - float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); - value *= GetModifierValue(unitMod, BASE_PCT); - value += GetModifierValue(unitMod, TOTAL_VALUE); - value *= GetModifierValue(unitMod, TOTAL_PCT); + float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE); + value *= GetPctModifierValue(unitMod, TOTAL_PCT); SetMaxPower(power, (int32)std::lroundf(value)); } @@ -357,11 +357,11 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) val2 = CalculatePct(float(minSpellPower), *m_activePlayerData->OverrideAPBySpellPowerPercent); } - SetModifierValue(unitMod, BASE_VALUE, val2); + SetStatFlatModifier(unitMod, BASE_VALUE, val2); - float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); - float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); - float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; + float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT); + float attPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE); + float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f; if (ranged) { @@ -405,7 +405,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) } } -void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) +void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const { UnitMods unitMod; @@ -425,10 +425,10 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo float attackPowerMod = std::max(GetAPMultiplier(attType, normalized), 0.25f); - float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 3.5f * attackPowerMod; - float basePct = GetModifierValue(unitMod, BASE_PCT); - float totalValue = GetModifierValue(unitMod, TOTAL_VALUE); - float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f; + float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 3.5f * attackPowerMod; + float basePct = GetPctModifierValue(unitMod, BASE_PCT); + float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE); + float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f; float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE); float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE); @@ -492,16 +492,16 @@ void Player::UpdateCritPercentage(WeaponAttackType attType) { case OFF_ATTACK: SetUpdateFieldStatValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::OffhandCritPercentage), - applyCritLimit(GetTotalPercentageModValue(OFFHAND_CRIT_PERCENTAGE) + GetRatingBonusValue(CR_CRIT_MELEE))); + applyCritLimit(GetBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD) + GetBaseModValue(OFFHAND_CRIT_PERCENTAGE, PCT_MOD) + GetRatingBonusValue(CR_CRIT_MELEE))); break; case RANGED_ATTACK: SetUpdateFieldStatValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::RangedCritPercentage), - applyCritLimit(GetTotalPercentageModValue(RANGED_CRIT_PERCENTAGE) + GetRatingBonusValue(CR_CRIT_RANGED))); + applyCritLimit(GetBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD) + GetBaseModValue(RANGED_CRIT_PERCENTAGE, PCT_MOD) + GetRatingBonusValue(CR_CRIT_RANGED))); break; case BASE_ATTACK: default: SetUpdateFieldStatValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::CritPercentage), - applyCritLimit(GetTotalPercentageModValue(CRIT_PERCENTAGE) + GetRatingBonusValue(CR_CRIT_MELEE))); + applyCritLimit(GetBaseModValue(CRIT_PERCENTAGE, FLAT_MOD) + GetBaseModValue(CRIT_PERCENTAGE, PCT_MOD) + GetRatingBonusValue(CR_CRIT_MELEE))); break; } } @@ -510,9 +510,9 @@ void Player::UpdateAllCritPercentages() { float value = 5.0f; - SetBaseModValue(CRIT_PERCENTAGE, PCT_MOD, value); - SetBaseModValue(OFFHAND_CRIT_PERCENTAGE, PCT_MOD, value); - SetBaseModValue(RANGED_CRIT_PERCENTAGE, PCT_MOD, value); + SetBaseModPctValue(CRIT_PERCENTAGE, value); + SetBaseModPctValue(OFFHAND_CRIT_PERCENTAGE, value); + SetBaseModPctValue(RANGED_CRIT_PERCENTAGE, value); UpdateCritPercentage(BASE_ATTACK); UpdateCritPercentage(OFF_ATTACK); @@ -835,7 +835,7 @@ bool Creature::UpdateAllStats() void Creature::UpdateArmor() { - float baseValue = GetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE); + float baseValue = GetFlatModifierValue(UNIT_MOD_ARMOR, BASE_VALUE); float value = GetTotalAuraModValue(UNIT_MOD_ARMOR); SetArmor(int32(baseValue), int32(value - baseValue)); } @@ -864,10 +864,10 @@ void Creature::UpdateMaxPower(Powers power) UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); - float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); - value *= GetModifierValue(unitMod, BASE_PCT); - value += GetModifierValue(unitMod, TOTAL_VALUE); - value *= GetModifierValue(unitMod, TOTAL_PCT); + float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE); + value *= GetPctModifierValue(unitMod, TOTAL_PCT); SetMaxPower(power, (int32)std::lroundf(value)); } @@ -876,8 +876,8 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged) { UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; - float baseAttackPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); - float attackPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; + float baseAttackPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT); + float attackPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f; if (ranged) { @@ -900,7 +900,7 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged) } } -void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) +void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const { float variance = 1.0f; UnitMods unitMod; @@ -939,10 +939,10 @@ void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float attackPower = GetTotalAttackPowerValue(attType); float attackSpeedMulti = GetAPMultiplier(attType, normalized); - float baseValue = GetModifierValue(unitMod, BASE_VALUE) + (attackPower / 3.5f) * variance; - float basePct = GetModifierValue(unitMod, BASE_PCT) * attackSpeedMulti; - float totalValue = GetModifierValue(unitMod, TOTAL_VALUE); - float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f; + float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + (attackPower / 3.5f) * variance; + float basePct = GetPctModifierValue(unitMod, BASE_PCT) * attackSpeedMulti; + float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE); + float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f; float dmgMultiplier = GetCreatureTemplate()->ModDamage; // = ModDamage * _GetDamageMod(rank); minDamage = ((weaponMinDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct; @@ -970,7 +970,7 @@ bool Guardian::UpdateStats(Stats stat) { // value = ((base_value * base_pct) + total_value) * total_pct float value = GetTotalStatValue(stat); - ApplyStatBuffMod(stat, m_statFromOwner[stat], false); + UpdateStatBuffMod(stat); float ownersBonus = 0.0f; Unit* owner = GetOwner(); @@ -1010,7 +1010,7 @@ bool Guardian::UpdateStats(Stats stat) SetStat(stat, int32(value)); m_statFromOwner[stat] = ownersBonus; - ApplyStatBuffMod(stat, m_statFromOwner[stat], true); + UpdateStatBuffMod(stat); switch (stat) { @@ -1044,7 +1044,7 @@ void Guardian::UpdateResistances(uint32 school) { if (school > SPELL_SCHOOL_NORMAL) { - float baseValue = GetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + school), BASE_VALUE); + float baseValue = GetFlatModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + school), BASE_VALUE); float bonusValue = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school)) - baseValue; // hunter and warlock pets gain 40% of owner's resistance @@ -1074,11 +1074,11 @@ void Guardian::UpdateArmor() else if (IsPet()) bonus_armor = m_owner->GetArmor(); - value = GetModifierValue(unitMod, BASE_VALUE); + value = GetFlatModifierValue(unitMod, BASE_VALUE); baseValue = value; - value *= GetModifierValue(unitMod, BASE_PCT); - value += GetModifierValue(unitMod, TOTAL_VALUE) + bonus_armor; - value *= GetModifierValue(unitMod, TOTAL_PCT); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + bonus_armor; + value *= GetPctModifierValue(unitMod, TOTAL_PCT); SetArmor(int32(baseValue), int32(value - baseValue)); } @@ -1100,10 +1100,10 @@ void Guardian::UpdateMaxHealth() default: multiplicator = 10.0f; break; } - float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth(); - value *= GetModifierValue(unitMod, BASE_PCT); - value += GetModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator; - value *= GetModifierValue(unitMod, TOTAL_PCT); + float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateHealth(); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator; + value *= GetPctModifierValue(unitMod, TOTAL_PCT); SetMaxHealth((uint32)value); } @@ -1115,10 +1115,10 @@ void Guardian::UpdateMaxPower(Powers power) UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); - float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); - value *= GetModifierValue(unitMod, BASE_PCT); - value += GetModifierValue(unitMod, TOTAL_VALUE); - value *= GetModifierValue(unitMod, TOTAL_PCT); + float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE); + value *= GetPctModifierValue(unitMod, TOTAL_PCT); SetMaxPower(power, int32(value)); } @@ -1178,11 +1178,11 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged) } } - SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP); + SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP); //in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB - float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); - float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; + float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT); + float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f; SetAttackPower(int32(base_attPower)); SetAttackPowerMultiplier(attPowerMultiplier); @@ -1219,10 +1219,10 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType) float att_speed = float(GetBaseAttackTime(BASE_ATTACK))/1000.0f; - float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 3.5f * att_speed + bonusDamage; - float base_pct = GetModifierValue(unitMod, BASE_PCT); - float total_value = GetModifierValue(unitMod, TOTAL_VALUE); - float total_pct = GetModifierValue(unitMod, TOTAL_PCT); + float base_value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 3.5f * att_speed + bonusDamage; + float base_pct = GetPctModifierValue(unitMod, BASE_PCT); + float total_value = GetFlatModifierValue(unitMod, TOTAL_VALUE); + float total_pct = GetPctModifierValue(unitMod, TOTAL_PCT); float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 62790919a9c..be6324229d8 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -331,14 +331,14 @@ Unit::Unit(bool isWorldObject) : for (uint8 i = 0; i < UNIT_MOD_END; ++i) { - m_auraModifiersGroup[i][BASE_VALUE] = 0.0f; - m_auraModifiersGroup[i][BASE_PCT_EXCLUDE_CREATE] = 100.0f; - m_auraModifiersGroup[i][BASE_PCT] = 1.0f; - m_auraModifiersGroup[i][TOTAL_VALUE] = 0.0f; - m_auraModifiersGroup[i][TOTAL_PCT] = 1.0f; + m_auraFlatModifiersGroup[i][BASE_VALUE] = 0.0f; + m_auraFlatModifiersGroup[i][BASE_PCT_EXCLUDE_CREATE] = 100.0f; + m_auraFlatModifiersGroup[i][TOTAL_VALUE] = 0.0f; + m_auraPctModifiersGroup[i][BASE_PCT] = 1.0f; + m_auraPctModifiersGroup[i][TOTAL_PCT] = 1.0f; } // implement 50% base damage from offhand - m_auraModifiersGroup[UNIT_MOD_DAMAGE_OFFHAND][TOTAL_PCT] = 0.5f; + m_auraPctModifiersGroup[UNIT_MOD_DAMAGE_OFFHAND][TOTAL_PCT] = 0.5f; for (uint8 i = 0; i < MAX_ATTACK; ++i) { @@ -2258,7 +2258,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(Unit const* victim, WeaponAttackTy return MELEE_HIT_NORMAL; } -uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct) +uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct) const { float minDamage = 0.0f; float maxDamage = 0.0f; @@ -4892,16 +4892,69 @@ void Unit::InitStatBuffMods() } } -void Unit::ApplyStatBuffMod(Stats stat, float val, bool apply) +void Unit::UpdateStatBuffMod(Stats stat) { - ApplyPercentModFloatVar((val > 0 ? m_floatStatPosBuff[stat] : m_floatStatNegBuff[stat]), val, apply); - UpdateStatBuffModForClient(stat); -} + float modPos = 0.0f; + float modNeg = 0.0f; + float factor = 0.0f; -void Unit::ApplyStatPercentBuffMod(Stats stat, float val, bool apply) -{ - ApplyPercentModFloatVar(m_floatStatPosBuff[stat], val, apply); - ApplyPercentModFloatVar(m_floatStatNegBuff[stat], val, apply); + UnitMods const unitMod = static_cast(UNIT_MOD_STAT_START + stat); + + // includes value from items and enchantments + float modValue = GetFlatModifierValue(unitMod, BASE_VALUE); + if (modValue > 0.f) + modPos += modValue; + else + modNeg += modValue; + + if (IsGuardian()) + { + modValue = static_cast(this)->GetBonusStatFromOwner(stat); + if (modValue > 0.f) + modPos += modValue; + else + modNeg += modValue; + } + + // SPELL_AURA_MOD_STAT_BONUS_PCT only affects BASE_VALUE + modPos = CalculatePct(modPos, std::max(GetFlatModifierValue(unitMod, BASE_PCT_EXCLUDE_CREATE), -100.0f)); + modNeg = CalculatePct(modPos, std::max(GetFlatModifierValue(unitMod, BASE_PCT_EXCLUDE_CREATE), -100.0f)); + + modPos += GetTotalAuraModifier(SPELL_AURA_MOD_STAT, [stat](AuraEffect const* aurEff) -> bool + { + if ((aurEff->GetMiscValue() < 0 || aurEff->GetMiscValue() == stat) && aurEff->GetAmount() > 0) + return true; + return false; + }); + + modNeg += GetTotalAuraModifier(SPELL_AURA_MOD_STAT, [stat](AuraEffect const* aurEff) -> bool + { + if ((aurEff->GetMiscValue() < 0 || aurEff->GetMiscValue() == stat) && aurEff->GetAmount() < 0) + return true; + return false; + }); + + factor = GetTotalAuraMultiplier(SPELL_AURA_MOD_PERCENT_STAT, [stat](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetMiscValue() == -1 || aurEff->GetMiscValue() == stat) + return true; + return false; + }); + + factor *= GetTotalAuraMultiplier(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, [stat](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetMiscValue() == -1 || aurEff->GetMiscValue() == stat) + return true; + return false; + }); + + modPos *= factor; + modNeg *= factor; + + m_floatStatPosBuff[stat] = modPos; + m_floatStatNegBuff[stat] = modNeg; + + UpdateStatBuffModForClient(stat); } void Unit::UpdateStatBuffModForClient(Stats stat) @@ -9371,31 +9424,99 @@ bool Unit::IsDisallowedMountForm(uint32 spellId, ShapeshiftForm form, uint32 dis ######## ######## #######################################*/ -bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply) +void Unit::HandleStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float amount, bool apply) { - if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END) + if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_FLAT_END) { - TC_LOG_ERROR("entities.unit", "ERROR in HandleStatModifier(): non-existing UnitMods or wrong UnitModifierType!"); - return false; + TC_LOG_ERROR("entities.unit", "ERROR in HandleStatFlatModifier(): non-existing UnitMods or wrong UnitModifierType!"); + return; } + if (!amount) + return; + switch (modifierType) { case BASE_VALUE: case BASE_PCT_EXCLUDE_CREATE: case TOTAL_VALUE: - m_auraModifiersGroup[unitMod][modifierType] += apply ? amount : -amount; + m_auraFlatModifiersGroup[unitMod][modifierType] += apply ? amount : -amount; + break; + default: break; + } + + UpdateUnitMod(unitMod); +} + +void Unit::ApplyStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float pct) +{ + if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_PCT_END) + { + TC_LOG_ERROR("entities.unit", "ERROR in ApplyStatPctModifier(): non-existing UnitMods or wrong UnitModifierType!"); + return; + } + + if (!pct) + return; + + switch (modifierType) + { case BASE_PCT: case TOTAL_PCT: - ApplyPercentModFloatVar(m_auraModifiersGroup[unitMod][modifierType], amount, apply); + AddPct(m_auraPctModifiersGroup[unitMod][modifierType], pct); break; default: break; } + UpdateUnitMod(unitMod); +} + +void Unit::SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val) +{ + if (m_auraFlatModifiersGroup[unitMod][modifierType] == val) + return; + + m_auraFlatModifiersGroup[unitMod][modifierType] = val; + UpdateUnitMod(unitMod); +} + +void Unit::SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val) +{ + if (m_auraPctModifiersGroup[unitMod][modifierType] == val) + return; + + m_auraPctModifiersGroup[unitMod][modifierType] = val; + UpdateUnitMod(unitMod); +} + +float Unit::GetFlatModifierValue(UnitMods unitMod, UnitModifierFlatType modifierType) const +{ + if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_FLAT_END) + { + TC_LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!"); + return 0.0f; + } + + return m_auraFlatModifiersGroup[unitMod][modifierType]; +} + +float Unit::GetPctModifierValue(UnitMods unitMod, UnitModifierPctType modifierType) const +{ + if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_PCT_END) + { + TC_LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!"); + return 0.0f; + } + + return m_auraPctModifiersGroup[unitMod][modifierType]; +} + +void Unit::UpdateUnitMod(UnitMods unitMod) +{ if (!CanModifyStats()) - return false; + return; switch (unitMod) { @@ -9445,37 +9566,109 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f ASSERT(false, "Not implemented UnitMod %u", unitMod); break; } +} + +bool Unit::CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect const* aurEff) const +{ + // only players have item requirements + if (GetTypeId() != TYPEID_PLAYER) + return true; + + SpellInfo const* spellInfo = aurEff->GetSpellInfo(); + if (spellInfo->EquippedItemClass == -1) + return true; + + Item* item = ToPlayer()->GetWeaponForAttack(attackType, true); + if (!item || !item->IsFitToSpellRequirements(spellInfo)) + return false; return true; } -float Unit::GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const +void Unit::UpdateDamageDoneMods(WeaponAttackType attackType) { - if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END) + UnitMods unitMod; + switch (attackType) { - TC_LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!"); - return 0.0f; + case BASE_ATTACK: + unitMod = UNIT_MOD_DAMAGE_MAINHAND; + break; + case OFF_ATTACK: + unitMod = UNIT_MOD_DAMAGE_OFFHAND; + break; + case RANGED_ATTACK: + unitMod = UNIT_MOD_DAMAGE_RANGED; + break; + default: + ABORT(); + break; } - if (modifierType == TOTAL_PCT && m_auraModifiersGroup[unitMod][modifierType] <= 0.0f) - return 0.0f; + float amount = GetTotalAuraModifier(SPELL_AURA_MOD_DAMAGE_DONE, std::bind(&Unit::CheckAttackFitToAuraRequirement, this, attackType, std::placeholders::_1)); + + SetStatFlatModifier(unitMod, TOTAL_VALUE, amount); +} + +void Unit::UpdateAllDamageDoneMods() +{ + for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i) + UpdateDamageDoneMods(WeaponAttackType(i)); +} + +void Unit::UpdateDamagePctDoneMods(WeaponAttackType attackType) +{ + float factor; + UnitMods unitMod; + switch (attackType) + { + case BASE_ATTACK: + factor = 1.0f; + unitMod = UNIT_MOD_DAMAGE_MAINHAND; + break; + case OFF_ATTACK: + // off hand has 50% penalty + factor = 0.5f; + unitMod = UNIT_MOD_DAMAGE_OFFHAND; + break; + case RANGED_ATTACK: + factor = 1.0f; + unitMod = UNIT_MOD_DAMAGE_RANGED; + break; + default: + ABORT(); + break; + } - return m_auraModifiersGroup[unitMod][modifierType]; + factor *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, [attackType, this](AuraEffect const* aurEff) -> bool + { + if (!(aurEff->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) + return false; + + return CheckAttackFitToAuraRequirement(attackType, aurEff); + }); + + if (attackType == OFF_ATTACK) + factor *= GetTotalAuraMultiplier(SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT, std::bind(&Unit::CheckAttackFitToAuraRequirement, this, attackType, std::placeholders::_1)); + + SetStatPctModifier(unitMod, TOTAL_PCT, factor); +} + +void Unit::UpdateAllDamagePctDoneMods() +{ + for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i) + UpdateDamagePctDoneMods(WeaponAttackType(i)); } float Unit::GetTotalStatValue(Stats stat) const { UnitMods unitMod = UnitMods(UNIT_MOD_STAT_START + stat); - if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f) - return 0.0f; - // value = ((base_value * base_pct) + total_value) * total_pct - float value = CalculatePct(m_auraModifiersGroup[unitMod][BASE_VALUE], std::max(m_auraModifiersGroup[unitMod][BASE_PCT_EXCLUDE_CREATE], -100.0f)); + float value = CalculatePct(GetFlatModifierValue(unitMod, BASE_VALUE), std::max(GetFlatModifierValue(unitMod, BASE_PCT_EXCLUDE_CREATE), -100.0f)); value += GetCreateStat(stat); - value *= m_auraModifiersGroup[unitMod][BASE_PCT]; - value += m_auraModifiersGroup[unitMod][TOTAL_VALUE]; - value *= m_auraModifiersGroup[unitMod][TOTAL_PCT]; + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE); + value *= GetPctModifierValue(unitMod, TOTAL_PCT); return value; } @@ -9488,13 +9681,10 @@ float Unit::GetTotalAuraModValue(UnitMods unitMod) const return 0.0f; } - if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f) - return 0.0f; - - float value = CalculatePct(m_auraModifiersGroup[unitMod][BASE_VALUE], std::max(m_auraModifiersGroup[unitMod][BASE_PCT_EXCLUDE_CREATE], -100.0f)); - value *= m_auraModifiersGroup[unitMod][BASE_PCT]; - value += m_auraModifiersGroup[unitMod][TOTAL_VALUE]; - value *= m_auraModifiersGroup[unitMod][TOTAL_PCT]; + float value = CalculatePct(GetFlatModifierValue(unitMod, BASE_VALUE), std::max(GetFlatModifierValue(unitMod, BASE_PCT_EXCLUDE_CREATE), -100.0f)); + value *= GetPctModifierValue(unitMod, BASE_PCT); + value += GetFlatModifierValue(unitMod, TOTAL_VALUE); + value *= GetPctModifierValue(unitMod, TOTAL_PCT); return value; } @@ -9542,7 +9732,7 @@ void Unit::UpdateResistances(uint32 school) { UnitMods unitMod = UnitMods(UNIT_MOD_RESISTANCE_START + school); - SetResistance(SpellSchools(school), int32(m_auraModifiersGroup[unitMod][BASE_VALUE])); + SetResistance(SpellSchools(school), int32(GetFlatModifierValue(unitMod, BASE_VALUE))); SetBonusResistanceMod(SpellSchools(school), int32(GetTotalAuraModValue(unitMod) - GetResistance(SpellSchools(school)))); } else @@ -10734,10 +10924,15 @@ void Unit::UpdateAttackTimeField(WeaponAttackType att) } } +void ApplyPercentModFloatVar(float& var, float val, bool apply) +{ + var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val)); +} + void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply) { float remainingTimePct = float(m_attackTimer[att]) / (m_baseAttackSpeed[att] * m_modAttackSpeedPct[att]); - if (val > 0) + if (val > 0.f) { ApplyPercentModFloatVar(m_modAttackSpeedPct[att], val, !apply); @@ -10762,7 +10957,7 @@ void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply void Unit::ApplyCastTimePercentMod(float val, bool apply) { - if (val > 0) + if (val > 0.f) { ApplyPercentModUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ModCastingSpeed), val, !apply); ApplyPercentModUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ModSpellHaste), val, !apply); @@ -10920,7 +11115,7 @@ float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffect return (CastingTime / 3500.0f) * DotFactor; } -float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized) +float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized) const { if (GetTypeId() != TYPEID_PLAYER || (IsInFeralForm() && !normalized)) return GetBaseAttackTime(attType) / 1000.0f; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 51815fe7eff..0838d2b226b 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -257,14 +257,19 @@ typedef std::vector DispelChargesList; typedef std::unordered_multimap SpellImmuneContainer; -enum UnitModifierType +enum UnitModifierFlatType { BASE_VALUE = 0, BASE_PCT_EXCLUDE_CREATE = 1, // percent modifier affecting all stat values from auras and gear but not player base for level - BASE_PCT = 2, - TOTAL_VALUE = 3, - TOTAL_PCT = 4, - MODIFIER_TYPE_END = 5 + TOTAL_VALUE = 2, + MODIFIER_TYPE_FLAT_END = 3 +}; + +enum UnitModifierPctType +{ + BASE_PCT = 0, + TOTAL_PCT = 1, + MODIFIER_TYPE_PCT_END = 2 }; enum WeaponDamageRange @@ -1600,8 +1605,7 @@ class TC_GAME_API Unit : public WorldObject int32 GetMaxNegativeAuraModifierByAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const; void InitStatBuffMods(); - void ApplyStatBuffMod(Stats stat, float val, bool apply); - void ApplyStatPercentBuffMod(Stats stat, float val, bool apply); + void UpdateStatBuffMod(Stats stat); void UpdateStatBuffModForClient(Stats stat); void SetCreateStat(Stats stat, float val) { m_createStats[stat] = val; } void SetCreateHealth(uint32 val) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::BaseHealth), val); } @@ -1685,9 +1689,25 @@ class TC_GAME_API Unit : public WorldObject EventProcessor m_Events; // stat system - bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply); - void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value) { m_auraModifiersGroup[unitMod][modifierType] = value; } - float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const; + void HandleStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float amount, bool apply); + void ApplyStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float amount); + + void SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val); + void SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val); + + float GetFlatModifierValue(UnitMods unitMod, UnitModifierFlatType modifierType) const; + float GetPctModifierValue(UnitMods unitMod, UnitModifierPctType modifierType) const; + + void UpdateUnitMod(UnitMods unitMod); + + bool CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect const* aurEff) const; + + virtual void UpdateDamageDoneMods(WeaponAttackType attackType); + void UpdateAllDamageDoneMods(); + + void UpdateDamagePctDoneMods(WeaponAttackType attackType); + void UpdateAllDamagePctDoneMods(); + float GetTotalStatValue(Stats stat) const; float GetTotalAuraModValue(UnitMods unitMod) const; SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod) const; @@ -1715,9 +1735,9 @@ class TC_GAME_API Unit : public WorldObject float GetTotalAttackPowerValue(WeaponAttackType attType) const; float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type) const; void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; } - virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) = 0; - uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct); - float GetAPMultiplier(WeaponAttackType attType, bool normalized); + virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const = 0; + uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct) const; + float GetAPMultiplier(WeaponAttackType attType, bool normalized) const; bool isInFrontInMap(Unit const* target, float distance, float arc = float(M_PI)) const; bool isInBackInMap(Unit const* target, float distance, float arc = float(M_PI)) const; @@ -2058,7 +2078,8 @@ class TC_GAME_API Unit : public WorldObject AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove std::array m_interruptMask; - float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; + float m_auraFlatModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_FLAT_END]; + float m_auraPctModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_PCT_END]; float m_weaponDamage[MAX_ATTACK][2]; bool m_canModifyStats; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 14db03c5b92..cac6834abc5 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -215,7 +215,7 @@ NonDefaultConstructible AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleModMechanicImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK &AuraEffect::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS &AuraEffect::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK - &AuraEffect::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT + &AuraEffect::HandleShieldBlockValuePercent, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT &AuraEffect::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED &AuraEffect::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance &AuraEffect::HandleUnused, //153 Unused (4.3.4) old SPELL_AURA_SPLIT_DAMAGE_FLAT @@ -347,7 +347,7 @@ NonDefaultConstructible AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNoImmediateEffect, //279 SPELL_AURA_INITIALIZE_IMAGES &AuraEffect::HandleUnused, //280 unused (4.3.4) old SPELL_AURA_MOD_ARMOR_PENETRATION_PCT &AuraEffect::HandleNULL, //281 SPELL_AURA_MOD_GUILD_REPUTATION_GAIN_PCT - &AuraEffect::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT + &AuraEffect::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_MOD_BASE_HEALTH_PCT &AuraEffect::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus &AuraEffect::HandleAuraLinked, //284 SPELL_AURA_LINKED &AuraEffect::HandleAuraLinked, //285 SPELL_AURA_LINKED_2 @@ -2038,7 +2038,7 @@ void AuraEffect::HandleAuraModScale(AuraApplication const* aurApp, uint8 mode, b Unit* target = aurApp->GetTarget(); float scale = target->GetObjectScale(); - ApplyPercentModFloatVar(scale, float(GetAmount()), apply); + scale += CalculatePct(1.0f, apply ? GetAmount() : -GetAmount()); target->SetObjectScale(scale); } @@ -2223,11 +2223,15 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode, Player* player = target->ToPlayer(); if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) { - uint8 attacktype = Player::GetAttackBySlot(slot, item->GetTemplate()->GetInventoryType()); + WeaponAttackType const attackType = Player::GetAttackBySlot(slot, item->GetTemplate()->GetInventoryType()); player->ApplyItemDependentAuras(item, !apply); - if (attacktype < MAX_ATTACK) + if (attackType != MAX_ATTACK) + { player->_ApplyWeaponDamage(slot, item, !apply); + if (!apply) // apply case already handled on item dependent aura removal (if any) + player->UpdateWeaponDependentAuras(attackType); + } } } @@ -2719,9 +2723,19 @@ void AuraEffect::HandleModThreat(AuraApplication const* aurApp, uint8 mode, bool return; Unit* target = aurApp->GetTarget(); - for (int8 i = 0; i < MAX_SPELL_SCHOOL; ++i) + for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i) + { if (GetMiscValue() & (1 << i)) - ApplyPercentModFloatVar(target->m_threatModifier[i], float(GetAmount()), apply); + { + if (apply) + AddPct(target->m_threatModifier[i], GetAmount()); + else + { + float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_THREAT, 1 << i); + target->m_threatModifier[i] = amount; + } + } + } } void AuraEffect::HandleAuraModTotalThreat(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -3210,9 +3224,9 @@ void AuraEffect::HandleAuraModResistance(AuraApplication const* aurApp, uint8 mo Unit* target = aurApp->GetTarget(); - for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) - if (GetMiscValue() & int32(1<HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply); + for (uint8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; ++x) + if (GetMiscValue() & (1 << x)) + target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply); } void AuraEffect::HandleAuraModBaseResistancePCT(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -3227,14 +3241,30 @@ void AuraEffect::HandleAuraModBaseResistancePCT(AuraApplication const* aurApp, u { //pets only have base armor if (target->IsPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) - target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetAmount()), apply); + { + if (apply) + target->ApplyStatPctModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_BASE_RESISTANCE_PCT, SPELL_SCHOOL_MASK_NORMAL); + target->SetStatPctModifier(UNIT_MOD_ARMOR, BASE_PCT, amount); + } + } } else { - for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) + for (uint8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; ++x) { - if (GetMiscValue() & int32(1<HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount()), apply); + if (GetMiscValue() & (1 << x)) + { + if (apply) + target->ApplyStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_BASE_RESISTANCE_PCT, 1 << x); + target->SetStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, amount); + } + } } } } @@ -3245,18 +3275,16 @@ void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8 return; Unit* target = aurApp->GetTarget(); - int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_RESISTANCE_PCT); - if (abs(spellGroupVal) >= abs(GetAmount())) - return; - for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) + for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) { - if (GetMiscValue() & int32(1<HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, (float)spellGroupVal, !apply); + float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_RESISTANCE_PCT, 1 << i); + if (target->GetPctModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT) == amount) + continue; - target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply); + target->SetStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, amount); } } } @@ -3271,15 +3299,15 @@ void AuraEffect::HandleModBaseResistance(AuraApplication const* aurApp, uint8 mo // only players have base stats if (target->GetTypeId() != TYPEID_PLAYER) { - //only pets have base stats + //pets only have base armor if (target->IsPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) - target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetAmount()), apply); } else { - for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) - if (GetMiscValue() & (1<HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply); + for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i) + if (GetMiscValue() & (1 << i)) + target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply); } } @@ -3323,22 +3351,21 @@ void AuraEffect::HandleAuraModStat(AuraApplication const* aurApp, uint8 mode, bo if (abs(spellGroupVal) >= abs(GetAmount())) return; - for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) + for (uint32 i = STAT_STRENGTH; i < MAX_STATS; ++i) { // -1 or -2 is all stats (misc < -2 checked in function beginning) if (GetMiscValue() < 0 || GetMiscValue() == i) { if (spellGroupVal) { - target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(spellGroupVal), !apply); + target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(spellGroupVal), !apply); if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet()) - target->ApplyStatBuffMod(Stats(i), float(spellGroupVal), !apply); + target->UpdateStatBuffMod(Stats(i)); } - //target->ApplyStatMod(Stats(i), m_amount, apply); - target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply); if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet()) - target->ApplyStatBuffMod(Stats(i), (float)GetAmount(), apply); + target->UpdateStatBuffMod(Stats(i)); } } } @@ -3360,10 +3387,23 @@ void AuraEffect::HandleModPercentStat(AuraApplication const* aurApp, uint8 mode, if (target->GetTypeId() != TYPEID_PLAYER) return; - for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i) + for (uint32 i = STAT_STRENGTH; i < MAX_STATS; ++i) { if (GetMiscValue() == i || GetMiscValue() == -1) - target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount), apply); + { + if (apply) + target->ApplyStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount)); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_PERCENT_STAT, [i](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetMiscValue() == i || aurEff->GetMiscValue() == -1) + return true; + return false; + }); + target->SetStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, amount); + } + } } } @@ -3456,22 +3496,6 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8 return; Unit* target = aurApp->GetTarget(); - int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, true, -1); - if (abs(spellGroupVal) >= abs(GetAmount())) - return; - - if (spellGroupVal) - { - for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) - { - if (GetMiscValue() == i || GetMiscValue() == -1) // affect the same stats - { - target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(spellGroupVal), !apply); - if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet()) - target->ApplyStatPercentBuffMod(Stats(i), float(spellGroupVal), !apply); - } - } - } // save current health state float healthPct = target->GetHealthPct(); @@ -3483,30 +3507,29 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8 if (target->getDeathState() == CORPSE) zeroHealth = (target->GetHealth() == 0); - for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) + for (uint32 i = STAT_STRENGTH; i < MAX_STATS; ++i) { if (GetMiscValueB() & 1 << i || !GetMiscValueB()) // 0 is also used for all stats { - int32 spellGroupVal2 = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, true, i); - if (abs(spellGroupVal2) >= abs(GetAmount())) - continue; - - if (spellGroupVal2) + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, [i](AuraEffect const* aurEff) -> bool { - target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(spellGroupVal2), !apply); - if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet()) - target->ApplyStatPercentBuffMod(Stats(i), float(spellGroupVal2), !apply); - } + if (aurEff->GetMiscValueB() & 1 << i || !aurEff->GetMiscValueB()) + return true; + return false; + }); + + if (target->GetPctModifierValue(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT) == amount) + continue; - target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetAmount()), apply); + target->SetStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, amount); if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet()) - target->ApplyStatPercentBuffMod(Stats(i), float(GetAmount()), apply); + target->UpdateStatBuffMod(Stats(i)); } } - // recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_UNK4 0x00000010 flag) + // recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_ABILITY 0x00000010 flag) // this check is total bullshit i think - if (GetMiscValueB() & 1 << STAT_STAMINA && (m_spellInfo->HasAttribute(SPELL_ATTR0_ABILITY))) + if ((GetMiscValueB() & 1 << STAT_STAMINA || !GetMiscValueB()) && (m_spellInfo->HasAttribute(SPELL_ATTR0_ABILITY))) target->SetHealth(std::max(CalculatePct(target->GetMaxHealth(), healthPct), (zeroHealth ? 0 : 1))); } @@ -3567,8 +3590,8 @@ void AuraEffect::HandleModStatBonusPercent(AuraApplication const* aurApp, uint8 { if (GetMiscValue() == i || GetMiscValue() == -1) { - target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT_EXCLUDE_CREATE, float(m_amount), apply); - target->ApplyStatPercentBuffMod(Stats(i), float(m_amount), apply); + target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT_EXCLUDE_CREATE, float(m_amount), apply); + target->UpdateStatBuffMod(Stats(i)); } } } @@ -3623,7 +3646,7 @@ void AuraEffect::HandleAuraModMaxPower(AuraApplication const* aurApp, uint8 mode Powers power = Powers(GetMiscValue()); UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); - target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply); } /********************************/ @@ -3688,7 +3711,7 @@ void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint if (apply) { - target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); target->ModifyHealth(GetAmount()); } else @@ -3698,7 +3721,7 @@ void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint int32 value = std::min(target->GetHealth() - 1, GetAmount()); target->ModifyHealth(-value); } - target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); } } @@ -3711,7 +3734,7 @@ void AuraEffect::HandleAuraModIncreaseMaxHealth(AuraApplication const* aurApp, u float percent = target->GetHealthPct(); - target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); // refresh percentage if (target->GetHealth() > 0) @@ -3730,7 +3753,7 @@ void AuraEffect::HandleAuraModIncreaseEnergy(AuraApplication const* aurApp, uint Powers powerType = Powers(GetMiscValue()); UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType); - target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply); } void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -3748,7 +3771,26 @@ void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const* aurAp int32 oldMaxPower = target->GetMaxPower(powerType); // Handle aura effect for max power - target->HandleStatModifier(unitMod, TOTAL_PCT, float(GetAmount()), apply); + if (apply) + target->ApplyStatPctModifier(unitMod, TOTAL_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT, [powerType](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetMiscValue() == powerType) + return true; + return false; + }); + + amount *= target->GetTotalAuraMultiplier(SPELL_AURA_MOD_MAX_POWER_PCT, [powerType](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetMiscValue() == powerType) + return true; + return false; + }); + + target->SetStatPctModifier(unitMod, TOTAL_PCT, amount); + } // Calculate the current power change int32 change = target->GetMaxPower(powerType) - oldMaxPower; @@ -3765,11 +3807,17 @@ void AuraEffect::HandleAuraModIncreaseHealthPercent(AuraApplication const* aurAp // Unit will keep hp% after MaxHealth being modified if unit is alive. float percent = target->GetHealthPct(); - target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()), apply); + if (apply) + target->ApplyStatPctModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT); + target->SetStatPctModifier(UNIT_MOD_HEALTH, TOTAL_PCT, amount); + } if (target->GetHealth() > 0) { - uint32 newHealth = std::max(target->CountPctFromMaxHealth(int32(percent)), 1); + uint32 newHealth = std::max(CalculatePct(target->GetMaxHealth(), percent), 1); target->SetHealth(newHealth); } } @@ -3781,7 +3829,13 @@ void AuraEffect::HandleAuraIncreaseBaseHealthPercent(AuraApplication const* aurA Unit* target = aurApp->GetTarget(); - target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount()), apply); + if (apply) + target->ApplyStatPctModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_BASE_HEALTH_PCT); + target->SetStatPctModifier(UNIT_MOD_HEALTH, BASE_PCT, amount); + } } void AuraEffect::HandleAuraModIncreaseBaseManaPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -3789,7 +3843,15 @@ void AuraEffect::HandleAuraModIncreaseBaseManaPercent(AuraApplication const* aur if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) return; - aurApp->GetTarget()->HandleStatModifier(UNIT_MOD_MANA, BASE_PCT, float(GetAmount()), apply); + Unit* target = aurApp->GetTarget(); + + if (apply) + target->ApplyStatPctModifier(UNIT_MOD_MANA, BASE_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_BASE_MANA_PCT); + target->SetStatPctModifier(UNIT_MOD_MANA, BASE_PCT, amount); + } } void AuraEffect::HandleAuraModPowerDisplay(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -3845,7 +3907,26 @@ void AuraEffect::HandleAuraModMaxPowerPct(AuraApplication const* aurApp, uint8 m int32 oldMaxPower = target->GetMaxPower(powerType); // Handle aura effect for max power - target->HandleStatModifier(unitMod, TOTAL_PCT, float(GetAmount()), apply); + if (apply) + target->ApplyStatPctModifier(unitMod, TOTAL_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_MAX_POWER_PCT, [powerType](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetMiscValue() == powerType) + return true; + return false; + }); + + amount *= target->GetTotalAuraMultiplier(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT, [powerType](AuraEffect const* aurEff) -> bool + { + if (aurEff->GetMiscValue() == powerType) + return true; + return false; + }); + + target->SetStatPctModifier(unitMod, TOTAL_PCT, amount); + } // Calculate the current power change int32 change = target->GetMaxPower(powerType) - oldMaxPower; @@ -3907,13 +3988,10 @@ void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const* aurApp, u return; Player* target = aurApp->GetTarget()->ToPlayer(); - if (!target) return; - target->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply); - target->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply); - target->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply); + target->UpdateAllWeaponDependentCritAuras(); } void AuraEffect::HandleModHitChance(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -3945,7 +4023,7 @@ void AuraEffect::HandleModSpellHitChance(AuraApplication const* aurApp, uint8 mo if (target->GetTypeId() == TYPEID_PLAYER) target->ToPlayer()->UpdateSpellHitChances(); else - target->m_modSpellHitChance += (apply) ? GetAmount(): (-GetAmount()); + target->m_modSpellHitChance += (apply) ? GetAmount() : (-GetAmount()); } void AuraEffect::HandleModSpellCritChance(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -3958,7 +4036,7 @@ void AuraEffect::HandleModSpellCritChance(AuraApplication const* aurApp, uint8 m if (target->GetTypeId() == TYPEID_PLAYER) target->ToPlayer()->UpdateSpellCritChance(); else - target->m_baseSpellCritChance += (apply) ? GetAmount():-GetAmount(); + target->m_baseSpellCritChance += (apply) ? GetAmount() : -GetAmount(); } void AuraEffect::HandleAuraModCritPct(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -3970,13 +4048,11 @@ void AuraEffect::HandleAuraModCritPct(AuraApplication const* aurApp, uint8 mode, if (target->GetTypeId() != TYPEID_PLAYER) { - target->m_baseSpellCritChance += (apply) ? GetAmount():-GetAmount(); + target->m_baseSpellCritChance += (apply) ? GetAmount() : -GetAmount(); return; } - target->ToPlayer()->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); - target->ToPlayer()->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); - target->ToPlayer()->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); + target->ToPlayer()->UpdateAllWeaponDependentCritAuras(); // included in Player::UpdateSpellCritChance calculation target->ToPlayer()->UpdateSpellCritChance(); @@ -4136,7 +4212,7 @@ void AuraEffect::HandleAuraModAttackPower(AuraApplication const* aurApp, uint8 m Unit* target = aurApp->GetTarget(); - target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetAmount()), apply); } void AuraEffect::HandleAuraModRangedAttackPower(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4149,7 +4225,7 @@ void AuraEffect::HandleAuraModRangedAttackPower(AuraApplication const* aurApp, u if ((target->getClassMask() & CLASSMASK_WAND_USERS) != 0) return; - target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetAmount()), apply); } void AuraEffect::HandleAuraModAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4160,7 +4236,13 @@ void AuraEffect::HandleAuraModAttackPowerPercent(AuraApplication const* aurApp, Unit* target = aurApp->GetTarget(); //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1 - target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetAmount()), apply); + if (apply) + target->ApplyStatPctModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_ATTACK_POWER_PCT); + target->SetStatPctModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, amount); + } } void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4174,7 +4256,13 @@ void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const* au return; //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1 - target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount()), apply); + if (apply) + target->ApplyStatPctModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT); + target->SetStatPctModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, amount); + } } /********************************/ @@ -4188,11 +4276,7 @@ void AuraEffect::HandleModDamageDone(AuraApplication const* aurApp, uint8 mode, Unit* target = aurApp->GetTarget(); if (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) - { - target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetAmount()), apply); - target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetAmount()), apply); - target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetAmount()), apply); - } + target->UpdateAllDamageDoneMods(); // Magic damage modifiers implemented in Unit::SpellBaseDamageBonusDone // This information for client side use only @@ -4218,34 +4302,20 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 return; Unit* target = aurApp->GetTarget(); - int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); - if (abs(spellGroupVal) >= abs(GetAmount())) - return; + // also handles spell group stacks if (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) - { - if (spellGroupVal) - { - target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(spellGroupVal), !apply); - target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(spellGroupVal), !apply); - target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(spellGroupVal), !apply); - } - - target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply); - target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply); - target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply); - } + target->UpdateAllDamagePctDoneMods(); if (Player* thisPlayer = target->ToPlayer()) { - for (uint16 i = 0; i < MAX_SPELL_SCHOOL; ++i) + for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i) { if (GetMiscValue() & (1 << i)) { - if (spellGroupVal) - thisPlayer->ApplyModDamageDonePercent(SpellSchools(i), float(spellGroupVal), !apply); - - thisPlayer->ApplyModDamageDonePercent(SpellSchools(i), float(GetAmount()), apply); + // only aura type modifying PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + float amount = thisPlayer->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, 1 << i); + thisPlayer->SetModDamageDonePercent(i, amount); } } } @@ -4258,7 +4328,8 @@ void AuraEffect::HandleModOffhandDamagePercent(AuraApplication const* aurApp, ui Unit* target = aurApp->GetTarget(); - target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply); + // also handles spell group stacks + target->UpdateDamagePctDoneMods(OFF_ATTACK); } void AuraEffect::HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4267,7 +4338,25 @@ void AuraEffect::HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mod return; if (Player* player = aurApp->GetTarget()->ToPlayer()) - player->HandleBaseModValue(SHIELD_BLOCK_VALUE, PCT_MOD, float(GetAmount()), apply); + player->HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(GetAmount()), apply); +} + +void AuraEffect::HandleShieldBlockValuePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const +{ + if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Player* target = aurApp->GetTarget()->ToPlayer(); + if (!target) + return; + + if (apply) + target->ApplyBaseModPctValue(SHIELD_BLOCK_VALUE, float(GetAmount())); + else + { + float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT); + target->SetBaseModPctValue(SHIELD_BLOCK_VALUE, amount); + } } /********************************/ diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 138ea474e31..7b74320bdef 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -290,6 +290,7 @@ class TC_GAME_API AuraEffect void HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleModOffhandDamagePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleShieldBlockValuePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const; // power cost void HandleModPowerCostPCT(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleModPowerCost(AuraApplication const* aurApp, uint8 mode, bool apply) const; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 6acb790d8e8..74148998c51 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2912,7 +2912,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break; } - float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT); + float weapon_total_pct = m_caster->GetPctModifierValue(unitMod, TOTAL_PCT); if (fixed_bonus) fixed_bonus = int32(fixed_bonus * weapon_total_pct); if (spell_bonus) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 1d0ef4ccea0..d70f0d07c54 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -881,26 +881,20 @@ public: { PrepareAuraScript(spell_kelthuzad_chains_AuraScript); - void HandleApply(AuraEffect const* /*eff*/, AuraEffectHandleModes /*mode*/) + void HandleApply(AuraEffect const* aurEff, AuraEffectHandleModes mode) { - Unit* target = GetTarget(); - float scale = target->GetObjectScale(); - ApplyPercentModFloatVar(scale, 200.0f, true); - target->SetObjectScale(scale); + aurEff->HandleAuraModScale(GetTargetApplication(), mode, true); } - void HandleRemove(AuraEffect const* /*eff*/, AuraEffectHandleModes /*mode*/) + void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes mode) { - Unit* target = GetTarget(); - float scale = target->GetObjectScale(); - ApplyPercentModFloatVar(scale, 200.0f, false); - target->SetObjectScale(scale); + aurEff->HandleAuraModScale(GetTargetApplication(), mode, false); } void Register() override { - AfterEffectApply += AuraEffectApplyFn(spell_kelthuzad_chains_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL); - AfterEffectRemove += AuraEffectApplyFn(spell_kelthuzad_chains_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL); + AfterEffectApply += AuraEffectApplyFn(spell_kelthuzad_chains_AuraScript::HandleApply, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectApplyFn(spell_kelthuzad_chains_AuraScript::HandleRemove, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL); } }; diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp index c0b570cbf46..7aaba87a2da 100644 --- a/src/server/scripts/Spells/spell_pet.cpp +++ b/src/server/scripts/Spells/spell_pet.cpp @@ -314,7 +314,7 @@ public: { if (AuraEffect* /* aurEff */ect = owner->GetAuraEffect(56246, EFFECT_0)) { - float base_attPower = pet->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE) * pet->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_PCT); + float base_attPower = pet->GetFlatModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE) * pet->GetPctModifierValue(UNIT_MOD_ATTACK_POWER, BASE_PCT); amount += CalculatePct(amount+base_attPower, /* aurEff */ect->GetAmount()); } } -- cgit v1.2.3 From b2346586179b3b9ceea731da3c3f7e475a3dbcfe Mon Sep 17 00:00:00 2001 From: Keader Date: Mon, 20 Mar 2017 16:49:42 -0300 Subject: Core/Scripts: Fixed wrong calculation of Aura of Desire Closes #19322 (cherry picked from commit 333a4034099e262db8db0a1736d01c30a8cf9d52) --- .../scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/server/scripts') diff --git a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp index e2e8a6bbef7..50fbd937d53 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp @@ -351,6 +351,8 @@ public: Talk(SUFF_SAY_RECAP); me->AttackStop(); me->SetReactState(REACT_PASSIVE); + events.Reset(); + me->InterruptNonMeleeSpells(false); me->GetMotionMaster()->MovePoint(RELIQUARY_DESPAWN_WAYPOINT, DespawnPoint); } } @@ -479,6 +481,8 @@ public: Talk(DESI_SAY_RECAP); me->AttackStop(); me->SetReactState(REACT_PASSIVE); + events.Reset(); + me->InterruptNonMeleeSpells(false); me->GetMotionMaster()->MovePoint(RELIQUARY_DESPAWN_WAYPOINT, DespawnPoint); } } @@ -743,7 +747,7 @@ class spell_reliquary_of_souls_aura_of_desire : public SpellScriptLoader caster->CastCustomSpell(SPELL_AURA_OF_DESIRE_DAMAGE, SPELLVALUE_BASE_POINT0, bp, caster, true, nullptr, aurEff); } - void UpdateAmount(AuraEffect const* /*effect*/) + void UpdateAmount(AuraEffect* /*aurEff*/) { if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_1)) effect->ChangeAmount(effect->GetAmount() - 5); @@ -752,7 +756,7 @@ class spell_reliquary_of_souls_aura_of_desire : public SpellScriptLoader void Register() override { OnEffectProc += AuraEffectProcFn(spell_reliquary_of_souls_aura_of_desire_AuraScript::OnProcSpell, EFFECT_0, SPELL_AURA_MOD_HEALING_PCT); - OnEffectPeriodic += AuraEffectPeriodicFn(spell_reliquary_of_souls_aura_of_desire_AuraScript::UpdateAmount, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_reliquary_of_souls_aura_of_desire_AuraScript::UpdateAmount, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); } }; -- cgit v1.2.3 From 5d076cfe291980bc5be9d44ffbae887e3dd5ad59 Mon Sep 17 00:00:00 2001 From: Chaouki Dhib Date: Thu, 23 Mar 2017 00:43:04 +0100 Subject: Core/Spells: fix wrong distance calculations in AoE spells [Needs testing] (#16290) Core/Spells: Fix wrong distance calculations in AoE spells. Pull request #16290 by chaodhib. God bless, finally. (cherry picked from commit a1f2f30c145f6ad9c4baeffeff32618e71ff537c) --- src/server/game/Entities/Creature/Creature.cpp | 6 +- src/server/game/Entities/GameObject/GameObject.h | 2 +- src/server/game/Entities/Object/Object.cpp | 84 +++++++++------------- src/server/game/Entities/Object/Object.h | 6 +- src/server/game/Entities/Object/ObjectDefines.h | 10 +-- src/server/game/Entities/Object/Position.cpp | 6 ++ src/server/game/Entities/Object/Position.h | 5 ++ src/server/game/Entities/Pet/Pet.cpp | 4 +- src/server/game/Entities/Player/Player.cpp | 4 +- src/server/game/Entities/Unit/Unit.cpp | 2 +- src/server/game/Entities/Unit/Unit.h | 2 +- src/server/game/Entities/Unit/UnitDefines.h | 1 - src/server/game/Globals/ObjectMgr.cpp | 2 +- src/server/game/Grids/Cells/CellImpl.h | 2 +- src/server/game/Grids/Notifiers/GridNotifiers.h | 59 ++++++++++++--- src/server/game/Movement/MotionMaster.cpp | 4 +- .../TargetedMovementGenerator.cpp | 6 +- src/server/game/Spells/Auras/SpellAuras.cpp | 10 +-- src/server/game/Spells/Spell.cpp | 37 +++++++--- src/server/game/Spells/SpellEffects.cpp | 20 +++--- src/server/game/Spells/SpellInfo.cpp | 29 ++++++++ src/server/game/Spells/SpellInfo.h | 1 + src/server/scripts/Commands/cs_debug.cpp | 2 +- src/server/scripts/Commands/cs_group.cpp | 2 +- src/server/scripts/Commands/cs_misc.cpp | 2 +- src/server/scripts/Commands/cs_npc.cpp | 2 +- .../MagistersTerrace/boss_selin_fireheart.cpp | 2 +- .../ScarletEnclave/zone_the_scarlet_enclave.cpp | 2 +- .../Kalimdor/HallsOfOrigination/boss_anraphet.cpp | 2 +- .../Northrend/DraktharonKeep/boss_king_dred.cpp | 2 +- .../FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp | 2 +- .../IcecrownCitadel/boss_deathbringer_saurfang.cpp | 2 +- .../IcecrownCitadel/boss_lord_marrowgar.cpp | 6 +- src/server/scripts/Northrend/zone_zuldrak.cpp | 4 +- .../scripts/Outland/zone_shadowmoon_valley.cpp | 2 +- src/server/scripts/World/go_scripts.cpp | 2 +- src/server/scripts/World/item_scripts.cpp | 2 +- 37 files changed, 210 insertions(+), 128 deletions(-) (limited to 'src/server/scripts') diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 4af0dda1212..3f28b03c031 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2437,7 +2437,7 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const else { // include sizes for huge npcs - dist += GetObjectSize() + victim->GetObjectSize(); + dist += GetCombatReach() + victim->GetCombatReach(); // to prevent creatures in air ignore attacks because distance is already too high... if (GetCreatureTemplate()->InhabitType & INHABIT_AIR) @@ -2995,7 +2995,7 @@ void Creature::SetObjectScale(float scale) if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(GetDisplayId())) { SetBoundingRadius((IsPet() ? 1.0f : minfo->bounding_radius) * scale); - SetCombatReach((IsPet() ? DEFAULT_COMBAT_REACH : minfo->combat_reach) * scale); + SetCombatReach((IsPet() ? DEFAULT_PLAYER_COMBAT_REACH : minfo->combat_reach) * scale); } } @@ -3006,7 +3006,7 @@ void Creature::SetDisplayId(uint32 modelId, float displayScale /*= 1.f*/) if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId)) { SetBoundingRadius((IsPet() ? 1.0f : minfo->bounding_radius) * GetObjectScale()); - SetCombatReach((IsPet() ? DEFAULT_COMBAT_REACH : minfo->combat_reach) * GetObjectScale()); + SetCombatReach((IsPet() ? DEFAULT_PLAYER_COMBAT_REACH : minfo->combat_reach) * GetObjectScale()); } } diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index b34f5e7951d..1e166f033ed 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -363,7 +363,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject void UpdatePackedRotation(); //! Object distance/size - overridden from Object::_IsWithinDist. Needs to take in account proper GO size. - bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool /*is3D*/) const override + bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool /*is3D*/, bool /*incOwnRadius*/, bool /*incTargetRadius*/) const override { //! Following check does check 3d distance return IsInRange(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), dist2compare); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index c0fbdaaf530..94fd3e932c8 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -969,39 +969,31 @@ InstanceScript* WorldObject::GetInstanceScript() float WorldObject::GetDistanceZ(const WorldObject* obj) const { float dz = std::fabs(GetPositionZ() - obj->GetPositionZ()); - float sizefactor = GetObjectSize() + obj->GetObjectSize(); + float sizefactor = GetCombatReach() + obj->GetCombatReach(); float dist = dz - sizefactor; return (dist > 0 ? dist : 0); } -bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const +bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius, bool incTargetRadius) const { - float sizefactor = GetObjectSize() + obj->GetObjectSize(); + float sizefactor = 0; + sizefactor += incOwnRadius ? GetCombatReach() : 0.0f; + sizefactor += incTargetRadius ? obj->GetCombatReach() : 0.0f; float maxdist = dist2compare + sizefactor; + Position const* thisOrTransport = this; + Position const* objOrObjTransport = obj; + if (GetTransport() && obj->GetTransport() && obj->GetTransport()->GetGUID() == GetTransport()->GetGUID()) { - float dtx = m_movementInfo.transport.pos.m_positionX - obj->m_movementInfo.transport.pos.m_positionX; - float dty = m_movementInfo.transport.pos.m_positionY - obj->m_movementInfo.transport.pos.m_positionY; - float disttsq = dtx * dtx + dty * dty; - if (is3D) - { - float dtz = m_movementInfo.transport.pos.m_positionZ - obj->m_movementInfo.transport.pos.m_positionZ; - disttsq += dtz * dtz; - } - return disttsq < (maxdist * maxdist); + thisOrTransport = &m_movementInfo.transport.pos; + objOrObjTransport = &obj->m_movementInfo.transport.pos; } - float dx = GetPositionX() - obj->GetPositionX(); - float dy = GetPositionY() - obj->GetPositionY(); - float distsq = dx*dx + dy*dy; if (is3D) - { - float dz = GetPositionZ() - obj->GetPositionZ(); - distsq += dz*dz; - } - - return distsq < maxdist * maxdist; + return thisOrTransport->IsInDist(objOrObjTransport, maxdist); + else + return thisOrTransport->IsInDist2d(objOrObjTransport, maxdist); } bool WorldObject::IsWithinLOSInMap(const WorldObject* obj, VMAP::ModelIgnoreFlags ignoreFlags) const @@ -1020,31 +1012,31 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj, VMAP::ModelIgnoreFlag float WorldObject::GetDistance(const WorldObject* obj) const { - float d = GetExactDist(obj) - GetObjectSize() - obj->GetObjectSize(); + float d = GetExactDist(obj) - GetCombatReach() - obj->GetCombatReach(); return d > 0.0f ? d : 0.0f; } float WorldObject::GetDistance(const Position &pos) const { - float d = GetExactDist(&pos) - GetObjectSize(); + float d = GetExactDist(&pos) - GetCombatReach(); return d > 0.0f ? d : 0.0f; } float WorldObject::GetDistance(float x, float y, float z) const { - float d = GetExactDist(x, y, z) - GetObjectSize(); + float d = GetExactDist(x, y, z) - GetCombatReach(); return d > 0.0f ? d : 0.0f; } float WorldObject::GetDistance2d(const WorldObject* obj) const { - float d = GetExactDist2d(obj) - GetObjectSize() - obj->GetObjectSize(); + float d = GetExactDist2d(obj) - GetCombatReach() - obj->GetCombatReach(); return d > 0.0f ? d : 0.0f; } float WorldObject::GetDistance2d(float x, float y) const { - float d = GetExactDist2d(x, y) - GetObjectSize(); + float d = GetExactDist2d(x, y) - GetCombatReach(); return d > 0.0f ? d : 0.0f; } @@ -1064,22 +1056,22 @@ bool WorldObject::IsInMap(const WorldObject* obj) const bool WorldObject::IsWithinDist3d(float x, float y, float z, float dist) const { - return IsInDist(x, y, z, dist + GetObjectSize()); + return IsInDist(x, y, z, dist + GetCombatReach()); } bool WorldObject::IsWithinDist3d(const Position* pos, float dist) const { - return IsInDist(pos, dist + GetObjectSize()); + return IsInDist(pos, dist + GetCombatReach()); } bool WorldObject::IsWithinDist2d(float x, float y, float dist) const { - return IsInDist2d(x, y, dist + GetObjectSize()); + return IsInDist2d(x, y, dist + GetCombatReach()); } bool WorldObject::IsWithinDist2d(const Position* pos, float dist) const { - return IsInDist2d(pos, dist + GetObjectSize()); + return IsInDist2d(pos, dist + GetCombatReach()); } bool WorldObject::IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D /*= true*/) const @@ -1087,9 +1079,9 @@ bool WorldObject::IsWithinDist(WorldObject const* obj, float dist2compare, bool return obj && _IsWithinDist(obj, dist2compare, is3D); } -bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D /*= true*/) const +bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D /*= true*/, bool incOwnRadius /*= true*/, bool incTargetRadius /*= true*/) const { - return obj && IsInMap(obj) && IsInPhase(obj) && _IsWithinDist(obj, dist2compare, is3D); + return obj && IsInMap(obj) && IsInPhase(obj) && _IsWithinDist(obj, dist2compare, is3D, incOwnRadius, incTargetRadius); } bool WorldObject::IsWithinLOS(float ox, float oy, float oz, VMAP::ModelIgnoreFlags ignoreFlags) const @@ -1116,7 +1108,7 @@ Position WorldObject::GetHitSpherePointFor(Position const& dest) const { G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ()); G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ()); - G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * std::min(dest.GetExactDist(GetPosition()), GetObjectSize()); + G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * std::min(dest.GetExactDist(GetPosition()), GetCombatReach()); return Position(contactPoint.x, contactPoint.y, contactPoint.z, GetAngle(contactPoint.x, contactPoint.y)); } @@ -1163,7 +1155,7 @@ bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRan distsq += dz*dz; } - float sizefactor = GetObjectSize() + obj->GetObjectSize(); + float sizefactor = GetCombatReach() + obj->GetCombatReach(); // check only for real range if (minRange > 0.0f) @@ -1183,7 +1175,7 @@ bool WorldObject::IsInRange2d(float x, float y, float minRange, float maxRange) float dy = GetPositionY() - y; float distsq = dx*dx + dy*dy; - float sizefactor = GetObjectSize(); + float sizefactor = GetCombatReach(); // check only for real range if (minRange > 0.0f) @@ -1204,7 +1196,7 @@ bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float m float dz = GetPositionZ() - z; float distsq = dx*dx + dy*dy + dz*dz; - float sizefactor = GetObjectSize(); + float sizefactor = GetCombatReach(); // check only for real range if (minRange > 0.0f) @@ -1227,7 +1219,7 @@ bool WorldObject::IsInBetween(Position const& pos1, Position const& pos2, float return false; if (!size) - size = GetObjectSize() / 2; + size = GetCombatReach() / 2; float angle = pos1.GetAngle(pos2); @@ -1837,7 +1829,7 @@ TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, fl { if (!x && !y && !z) { - GetClosePoint(x, y, z, GetObjectSize()); + GetClosePoint(x, y, z, GetCombatReach()); ang = GetOrientation(); } @@ -1879,7 +1871,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float { if (!x && !y && !z) { - GetClosePoint(x, y, z, GetObjectSize()); + GetClosePoint(x, y, z, GetCombatReach()); ang = GetOrientation(); } @@ -1993,8 +1985,8 @@ void WorldObject::GetPlayerListInGrid(Container& playerContainer, float maxSearc void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float absAngle) const { - x = GetPositionX() + (GetObjectSize() + distance2d) * std::cos(absAngle); - y = GetPositionY() + (GetObjectSize() + distance2d) * std::sin(absAngle); + x = GetPositionX() + (GetCombatReach() + distance2d) * std::cos(absAngle); + y = GetPositionY() + (GetCombatReach() + distance2d) * std::sin(absAngle); Trinity::NormalizeMapCoord(x); Trinity::NormalizeMapCoord(y); @@ -2066,15 +2058,7 @@ Position WorldObject::GetRandomNearPosition(float radius) void WorldObject::GetContactPoint(const WorldObject* obj, float &x, float &y, float &z, float distance2d /*= CONTACT_DISTANCE*/) const { // angle to face `obj` to `this` using distance includes size of `obj` - GetNearPoint(obj, x, y, z, obj->GetObjectSize(), distance2d, GetAngle(obj)); -} - -float WorldObject::GetObjectSize() const -{ - if (Unit const* thisUnit = ToUnit()) - return thisUnit->m_unitData->CombatReach; - - return DEFAULT_WORLD_OBJECT_SIZE; + GetNearPoint(obj, x, y, z, obj->GetCombatReach(), distance2d, GetAngle(obj)); } void WorldObject::MovePosition(Position &pos, float dist, float angle) diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index c5e22c86c3a..1d48e1f2384 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -395,7 +395,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation Position GetRandomNearPosition(float radius); void GetContactPoint(WorldObject const* obj, float &x, float &y, float &z, float distance2d = CONTACT_DISTANCE) const; - float GetObjectSize() const; + virtual float GetCombatReach() const { return 0.0f; } // overridden (only) in Unit void UpdateGroundPositionZ(float x, float y, float &z) const; void UpdateAllowedPositionZ(float x, float y, float &z) const; @@ -445,7 +445,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation bool IsWithinDist2d(Position const* pos, float dist) const; // use only if you will sure about placing both object at same map bool IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D = true) const; - bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true) const; + bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true, bool incOwnRadius = true, bool incTargetRadius = true) const; bool IsWithinLOS(float x, float y, float z, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const; bool IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing) const; Position GetHitSpherePointFor(Position const& dest) const; @@ -605,7 +605,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation uint16 m_notifyflags; uint16 m_executed_notifies; - virtual bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const; + virtual bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius = true, bool incTargetRadius = true) const; bool CanNeverSee(WorldObject const* obj) const; virtual bool CanAlwaysSee(WorldObject const* /*obj*/) const { return false; } diff --git a/src/server/game/Entities/Object/ObjectDefines.h b/src/server/game/Entities/Object/ObjectDefines.h index b0db49bcf9f..43f2ea15a4d 100644 --- a/src/server/game/Entities/Object/ObjectDefines.h +++ b/src/server/game/Entities/Object/ObjectDefines.h @@ -36,11 +36,11 @@ #define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards #define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards -#define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects -#define DEFAULT_COMBAT_REACH 1.5f -#define MIN_MELEE_REACH 2.0f -#define NOMINAL_MELEE_RANGE 5.0f -#define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players +#define DEFAULT_PLAYER_BOUNDING_RADIUS 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects +#define DEFAULT_PLAYER_COMBAT_REACH 1.5f +#define MIN_MELEE_REACH 2.0f +#define NOMINAL_MELEE_RANGE 5.0f +#define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players enum class VisibilityDistanceType : uint8 { diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp index ae0fc14e173..a63a3da76d6 100644 --- a/src/server/game/Entities/Object/Position.cpp +++ b/src/server/game/Entities/Object/Position.cpp @@ -148,6 +148,12 @@ bool Position::IsWithinBox(const Position& center, float xradius, float yradius, return true; } +bool Position::IsWithinDoubleVerticalCylinder(Position const* center, float radius, float height) const +{ + float verticalDelta = GetPositionZ() - center->GetPositionZ(); + return IsInDist2d(center, radius) && std::abs(verticalDelta) <= height; +} + bool Position::HasInArc(float arc, const Position* obj, float border) const { // always have self in arc diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h index 37f1231e709..f247c7fb860 100644 --- a/src/server/game/Entities/Object/Position.h +++ b/src/server/game/Entities/Object/Position.h @@ -218,6 +218,11 @@ public: } bool IsWithinBox(const Position& center, float xradius, float yradius, float zradius) const; + + /* + search using this relation: dist2d < radius && abs(dz) < height + */ + bool IsWithinDoubleVerticalCylinder(Position const* center, float radius, float height) const; bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const; bool HasInLine(Position const* pos, float objSize, float width) const; std::string ToString() const; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 2da7bf4c81d..9c16502dd25 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -192,7 +192,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c if (IsCritter()) { float px, py, pz; - owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, GetFollowAngle()); + owner->GetClosePoint(px, py, pz, GetCombatReach(), PET_FOLLOW_DIST, GetFollowAngle()); Relocate(px, py, pz, owner->GetOrientation()); if (!IsPositionValid()) @@ -245,7 +245,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c // Set pet's position after setting level, its size depends on it float px, py, pz; - owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, GetFollowAngle()); + owner->GetClosePoint(px, py, pz, GetCombatReach(), PET_FOLLOW_DIST, GetFollowAngle()); Relocate(px, py, pz, owner->GetOrientation()); if (!IsPositionValid()) { diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 981004300ba..5f2199d9f52 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1767,8 +1767,8 @@ void Player::RemoveFromWorld() void Player::SetObjectScale(float scale) { Unit::SetObjectScale(scale); - SetBoundingRadius(scale * DEFAULT_WORLD_OBJECT_SIZE); - SetCombatReach(scale * DEFAULT_COMBAT_REACH); + SetBoundingRadius(scale * DEFAULT_PLAYER_BOUNDING_RADIUS); + SetCombatReach(scale * DEFAULT_PLAYER_COMBAT_REACH); if (IsInWorld()) SendMovementSetCollisionHeight(scale * GetCollisionHeight(IsMounted())); } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 27ed7760160..e43423468d4 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -627,7 +627,7 @@ void Unit::GetRandomContactPoint(const Unit* obj, float &x, float &y, float &z, { float combat_reach = GetCombatReach(); if (combat_reach < 0.1f) // sometimes bugged for players - combat_reach = DEFAULT_COMBAT_REACH; + combat_reach = DEFAULT_PLAYER_COMBAT_REACH; uint32 attacker_number = uint32(getAttackers().size()); if (attacker_number > 0) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 32e109a5392..f286c91a713 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -963,7 +963,7 @@ class TC_GAME_API Unit : public WorldObject bool haveOffhandWeapon() const; bool CanDualWield() const { return m_canDualWield; } virtual void SetCanDualWield(bool value) { m_canDualWield = value; } - float GetCombatReach() const { return m_unitData->CombatReach; } + float GetCombatReach() const override { return m_unitData->CombatReach; } void SetCombatReach(float combatReach) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::CombatReach), combatReach); } float GetBoundingRadius() const { return m_unitData->BoundingRadius; } void SetBoundingRadius(float boundingRadius) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::BoundingRadius), boundingRadius); } diff --git a/src/server/game/Entities/Unit/UnitDefines.h b/src/server/game/Entities/Unit/UnitDefines.h index 158943800c8..9bf875ee810 100644 --- a/src/server/game/Entities/Unit/UnitDefines.h +++ b/src/server/game/Entities/Unit/UnitDefines.h @@ -21,7 +21,6 @@ #include "Define.h" #include -#define DEFAULT_COMBAT_REACH 1.5f #define MIN_MELEE_REACH 2.0f #define NOMINAL_MELEE_RANGE 5.0f #define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 84196190cce..b4127934e95 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1538,7 +1538,7 @@ void ObjectMgr::LoadCreatureModelInfo() } if (modelInfo.combat_reach < 0.1f) - modelInfo.combat_reach = DEFAULT_COMBAT_REACH; + modelInfo.combat_reach = DEFAULT_PLAYER_COMBAT_REACH; if (CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(creatureDisplay->ModelID)) { diff --git a/src/server/game/Grids/Cells/CellImpl.h b/src/server/game/Grids/Cells/CellImpl.h index a06a84eaebc..3b343851bb2 100644 --- a/src/server/game/Grids/Cells/CellImpl.h +++ b/src/server/game/Grids/Cells/CellImpl.h @@ -64,7 +64,7 @@ inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index e786935b538..23f3cf2ddc0 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -944,14 +944,27 @@ namespace Trinity class AnyFriendlyUnitInObjectRangeCheck { public: - AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool playerOnly = false) : i_obj(obj), i_funit(funit), i_range(range), i_playerOnly(playerOnly) { } + AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool playerOnly = false, bool incOwnRadius = true, bool incTargetRadius = true) + : i_obj(obj), i_funit(funit), i_range(range), i_playerOnly(playerOnly), i_incOwnRadius(incOwnRadius), i_incTargetRadius(incTargetRadius) { } bool operator()(Unit* u) const { - if (u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u) && (!i_playerOnly || u->GetTypeId() == TYPEID_PLAYER)) - return true; - else + if (!u->IsAlive()) + return false; + + float searchRadius = i_range; + if (i_incOwnRadius) + searchRadius += i_obj->GetCombatReach(); + if (i_incTargetRadius) + searchRadius += u->GetCombatReach(); + + if (!u->IsInMap(i_obj) || !u->IsInPhase(i_obj) || !u->IsWithinDoubleVerticalCylinder(i_obj, searchRadius, searchRadius)) return false; + + if (!i_funit->IsFriendlyTo(u)) + return false; + + return !i_playerOnly || u->GetTypeId() == TYPEID_PLAYER; } private: @@ -959,12 +972,15 @@ namespace Trinity Unit const* i_funit; float i_range; bool i_playerOnly; + bool i_incOwnRadius; + bool i_incTargetRadius; }; class AnyGroupedUnitInObjectRangeCheck { public: - AnyGroupedUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool raid, bool playerOnly = false) : _source(obj), _refUnit(funit), _range(range), _raid(raid), _playerOnly(playerOnly) { } + AnyGroupedUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool raid, bool playerOnly = false, bool incOwnRadius = true, bool incTargetRadius = true) + : _source(obj), _refUnit(funit), _range(range), _raid(raid), _playerOnly(playerOnly), i_incOwnRadius(incOwnRadius), i_incTargetRadius(incTargetRadius) { } bool operator()(Unit* u) const { @@ -979,7 +995,19 @@ namespace Trinity else if (!_refUnit->IsInPartyWith(u)) return false; - return !_refUnit->IsHostileTo(u) && u->IsAlive() && _source->IsWithinDistInMap(u, _range); + if (_refUnit->IsHostileTo(u)) + return false; + + if (!u->IsAlive()) + return false; + + float searchRadius = _range; + if (i_incOwnRadius) + searchRadius += _source->GetCombatReach(); + if (i_incTargetRadius) + searchRadius += u->GetCombatReach(); + + return u->IsInMap(_source) && u->IsInPhase(_source) && u->IsWithinDoubleVerticalCylinder(_source, searchRadius, searchRadius); } private: @@ -988,6 +1016,8 @@ namespace Trinity float _range; bool _raid; bool _playerOnly; + bool i_incOwnRadius; + bool i_incTargetRadius; }; class AnyUnitInObjectRangeCheck @@ -1039,8 +1069,8 @@ namespace Trinity class AnyAoETargetUnitInObjectRangeCheck { public: - AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, SpellInfo const* spellInfo = nullptr) - : i_obj(obj), i_funit(funit), _spellInfo(spellInfo), i_range(range) + AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, SpellInfo const* spellInfo = nullptr, bool incOwnRadius = true, bool incTargetRadius = true) + : i_obj(obj), i_funit(funit), _spellInfo(spellInfo), i_range(range), i_incOwnRadius(incOwnRadius), i_incTargetRadius(incTargetRadius) { if (!_spellInfo) if (DynamicObject const* dynObj = i_obj->ToDynObject()) @@ -1056,7 +1086,16 @@ namespace Trinity if (_spellInfo && _spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS) && u->GetTypeId() != TYPEID_PLAYER) return false; - return i_funit->_IsValidAttackTarget(u, _spellInfo, i_obj->GetTypeId() == TYPEID_DYNAMICOBJECT ? i_obj : nullptr) && i_obj->IsWithinDistInMap(u, i_range); + if (!i_funit->_IsValidAttackTarget(u, _spellInfo, i_obj->GetTypeId() == TYPEID_DYNAMICOBJECT ? i_obj : nullptr)) + return false; + + float searchRadius = i_range; + if (i_incOwnRadius) + searchRadius += i_obj->GetCombatReach(); + if (i_incTargetRadius) + searchRadius += u->GetCombatReach(); + + return u->IsInMap(i_obj) && u->IsInPhase(i_obj) && u->IsWithinDoubleVerticalCylinder(i_obj, searchRadius, searchRadius); } private: @@ -1064,6 +1103,8 @@ namespace Trinity Unit const* i_funit; SpellInfo const* _spellInfo; float i_range; + bool i_incOwnRadius; + bool i_incTargetRadius; }; // do attack at call of help to friendly crearture diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index f4190f2520c..02e6aad28af 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -429,7 +429,7 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa float dist = 2 * moveTimeHalf * speedXY; float max_height = -Movement::computeFallElevation(moveTimeHalf, false, -speedZ); - _owner->GetNearPoint(_owner, x, y, z, _owner->GetObjectSize(), dist, _owner->GetAngle(srcX, srcY) + float(M_PI)); + _owner->GetNearPoint(_owner, x, y, z, _owner->GetCombatReach(), dist, _owner->GetAngle(srcX, srcY) + float(M_PI)); Movement::MoveSplineInit init(_owner); init.MoveTo(x, y, z); @@ -453,7 +453,7 @@ void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ) float moveTimeHalf = speedZ / Movement::gravity; float dist = 2 * moveTimeHalf * speedXY; - _owner->GetClosePoint(x, y, z, _owner->GetObjectSize(), dist, angle); + _owner->GetClosePoint(x, y, z, _owner->GetCombatReach(), dist, angle); MoveJump(x, y, z, 0.0f, speedXY, speedZ); } diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 0a1206a8d48..54cc97ab418 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -65,7 +65,7 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner, bool up float size; // Pets need special handling. - // We need to subtract GetObjectSize() because it gets added back further down the chain + // We need to subtract GetCombatReach() because it gets added back further down the chain // and that makes pets too far away. Subtracting it allows pets to properly // be (GetCombatReach() + i_offset) away. // Only applies when i_target is pet's owner otherwise pets and mobs end up @@ -73,12 +73,12 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner, bool up if (owner->IsPet() && i_target->GetTypeId() == TYPEID_PLAYER) { dist = 1.0f; //i_target->GetCombatReach(); - size = 1.0f; //i_target->GetCombatReach() - i_target->GetObjectSize(); + size = 1.0f; //i_target->GetCombatReach() - i_target->GetCombatReach(); } else { dist = i_offset + 1.0f; - size = owner->GetObjectSize(); + size = owner->GetCombatReach(); } if (i_target->IsWithinDistInMap(owner, dist)) diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 074da315ad3..175959a15d4 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -2312,7 +2312,7 @@ void UnitAura::FillTargetMap(std::unordered_map& targets, Unit* c case SPELL_EFFECT_APPLY_AREA_AURA_RAID: { units.push_back(GetUnitOwner()); - Trinity::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS)); + Trinity::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS), false, true); Trinity::UnitListSearcher searcher(GetUnitOwner(), units, u_check); Cell::VisitAllObjects(GetUnitOwner(), searcher, radius); break; @@ -2320,14 +2320,14 @@ void UnitAura::FillTargetMap(std::unordered_map& targets, Unit* c case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: { units.push_back(GetUnitOwner()); - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS)); + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS), false, true); Trinity::UnitListSearcher searcher(GetUnitOwner(), units, u_check); Cell::VisitAllObjects(GetUnitOwner(), searcher, radius); break; } case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: { - Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo); // No GetCharmer in searcher + Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo, false, true); // No GetCharmer in searcher Trinity::UnitListSearcher searcher(GetUnitOwner(), units, u_check); Cell::VisitAllObjects(GetUnitOwner(), searcher, radius); break; @@ -2396,13 +2396,13 @@ void DynObjAura::FillTargetMap(std::unordered_map& targets, Unit* if (effect->TargetB.GetTarget() == TARGET_DEST_DYNOBJ_ALLY || effect->TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ALLY) { - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS)); + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS), false, true); Trinity::UnitListSearcher searcher(GetDynobjOwner(), units, u_check); Cell::VisitAllObjects(GetDynobjOwner(), searcher, radius); } else { - Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius); + Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius, nullptr, false, true); Trinity::UnitListSearcher searcher(GetDynobjOwner(), units, u_check); Cell::VisitAllObjects(GetDynobjOwner(), searcher, radius); } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 8ef877e6881..779b0d0495c 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1245,6 +1245,11 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge if (!effect) return; float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod; + + // if this is a proximity based aoe (Frost Nova, Psychic Scream, ...), include the caster's own combat reach + if (targetType.IsProximityBasedAoe()) + radius += GetCaster()->GetCombatReach(); + SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), effect->ImplicitTargetConditions); CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); @@ -1300,7 +1305,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici float dist = frand(minDist, maxDist); float x, y, z; float angle = float(rand_norm()) * static_cast(M_PI * 35.0f / 180.0f) - static_cast(M_PI * 17.5f / 180.0f); - m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dist, angle); + m_caster->GetClosePoint(x, y, z, DEFAULT_PLAYER_BOUNDING_RADIUS, dist, angle); float ground = m_caster->GetMap()->GetHeight(m_caster->GetPhaseShift(), x, y, z, true, 50.0f); float liquidLevel = VMAP_INVALID_HEIGHT_VALUE; @@ -1333,7 +1338,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici { float dist = effect->CalcRadius(m_caster); float angle = targetType.CalcDirectionAngle(); - float objSize = m_caster->GetObjectSize(); + float objSize = m_caster->GetCombatReach(); switch (targetType.GetTarget()) { @@ -1391,7 +1396,7 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplici if (SpellEffectInfo const* effect = GetEffect(effIndex)) { float angle = targetType.CalcDirectionAngle(); - float objSize = target->GetObjectSize(); + float objSize = target->GetCombatReach(); float dist = effect->CalcRadius(m_caster); if (dist < objSize) dist = objSize; @@ -1615,7 +1620,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge } } - const float size = std::max((*itr)->GetObjectSize(), 1.0f); + const float size = std::max((*itr)->GetCombatReach(), 1.0f); const float objDist2d = srcPos.GetExactDist2d(*itr); const float dz = (*itr)->GetPositionZ() - srcPos.m_positionZ; @@ -5300,13 +5305,13 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!target->IsWithinLOSInMap(m_caster)) //Do full LoS/Path check. Don't exclude m2 return SPELL_FAILED_LINE_OF_SIGHT; - float objSize = target->GetObjectSize(); + float objSize = target->GetCombatReach(); float range = m_spellInfo->GetMaxRange(true, m_caster, this) * 1.5f + objSize; // can't be overly strict m_preGeneratedPath = Trinity::make_unique(m_caster); m_preGeneratedPath->SetPathLengthLimit(range); // first try with raycast, if it fails fall back to normal path - float targetObjectSize = std::min(target->GetObjectSize(), 4.0f); + float targetObjectSize = std::min(target->GetCombatReach(), 4.0f); bool result = m_preGeneratedPath->CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + targetObjectSize, false, true); if (m_preGeneratedPath->GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; @@ -7895,8 +7900,20 @@ WorldObjectSpellAreaTargetCheck::WorldObjectSpellAreaTargetCheck(float range, Po bool WorldObjectSpellAreaTargetCheck::operator()(WorldObject* target) { - if (!target->IsWithinDist3d(_position, _range) && !(target->ToGameObject() && target->ToGameObject()->IsInRange(_position->GetPositionX(), _position->GetPositionY(), _position->GetPositionZ(), _range))) - return false; + if (target->ToGameObject()) + { + // isInRange including the dimension of the GO + bool isInRange = target->ToGameObject()->IsInRange(_position->GetPositionX(), _position->GetPositionY(), _position->GetPositionZ(), _range); + if (!isInRange) + return false; + } + else + { + bool isInsideCylinder = target->IsWithinDist2d(_position, _range) && std::abs(target->GetPositionZ() - _position->GetPositionZ()) <= _range; + if (!isInsideCylinder) + return false; + } + return WorldObjectSpellTargetCheck::operator ()(target); } @@ -7913,7 +7930,7 @@ bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target) } else if (_spellInfo->HasAttribute(SPELL_ATTR0_CU_CONE_LINE)) { - if (!_caster->HasInLine(target, target->GetObjectSize(), _caster->GetObjectSize())) + if (!_caster->HasInLine(target, target->GetCombatReach(), _caster->GetCombatReach())) return false; } else @@ -7933,7 +7950,7 @@ WorldObjectSpellTrajTargetCheck::WorldObjectSpellTrajTargetCheck(float range, Po bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target) { // return all targets on missile trajectory (0 - size of a missile) - if (!_caster->HasInLine(target, target->GetObjectSize(), TRAJECTORY_MISSILE_SIZE)) + if (!_caster->HasInLine(target, target->GetCombatReach(), TRAJECTORY_MISSILE_SIZE)) return false; if (target->GetExactDist2d(_position) > _range) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 74148998c51..e370f558d4b 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2306,7 +2306,7 @@ void Spell::EffectTeleUnitsFaceCaster(SpellEffIndex /*effIndex*/) float dis = effectInfo->CalcRadius(m_caster); float fx, fy, fz; - m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis); + m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetCombatReach(), dis); unitTarget->NearTeleportTo(fx, fy, fz, -m_caster->GetOrientation(), unitTarget == m_caster); } @@ -2659,7 +2659,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex) //OldSummon->GetMap()->Remove(OldSummon->ToCreature(), false); float px, py, pz; - owner->GetClosePoint(px, py, pz, OldSummon->GetObjectSize()); + owner->GetClosePoint(px, py, pz, OldSummon->GetCombatReach()); OldSummon->NearTeleportTo(px, py, pz, OldSummon->GetOrientation()); //OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation()); @@ -2679,7 +2679,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex) } float x, y, z; - owner->GetClosePoint(x, y, z, owner->GetObjectSize()); + owner->GetClosePoint(x, y, z, owner->GetCombatReach()); Pet* pet = owner->SummonPet(petentry, x, y, z, owner->GetOrientation(), SUMMON_PET, 0); if (!pet) return; @@ -3041,7 +3041,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) if (m_targets.HasDst()) destTarget->GetPosition(x, y, z); else - m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); + m_caster->GetClosePoint(x, y, z, DEFAULT_PLAYER_BOUNDING_RADIUS); Map* map = target->GetMap(); Position pos = Position(x, y, z, target->GetOrientation()); @@ -3922,7 +3922,7 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex) destTarget->GetPosition(x, y, z); // Summon in random point all other units if location present else - m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); + m_caster->GetClosePoint(x, y, z, DEFAULT_PLAYER_BOUNDING_RADIUS); Map* map = m_caster->GetMap(); Position pos = Position(x, y, z, m_caster->GetOrientation()); @@ -4219,7 +4219,7 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/) if (m_preGeneratedPath->GetPathType() == PATHFIND_BLANK) { //unitTarget->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); - Position pos = unitTarget->GetFirstCollisionPosition(unitTarget->GetObjectSize(), unitTarget->GetRelativeAngle(m_caster)); + Position pos = unitTarget->GetFirstCollisionPosition(unitTarget->GetCombatReach(), unitTarget->GetRelativeAngle(m_caster)); if (G3D::fuzzyGt(m_spellInfo->Speed, 0.0f) && m_spellInfo->HasAttribute(SPELL_ATTR9_SPECIAL_DELAY_CALCULATION)) speed = pos.GetExactDist(m_caster) / speed; @@ -4493,7 +4493,7 @@ void Spell::EffectResurrectPet(SpellEffIndex /*effIndex*/) // Reposition the pet's corpse before reviving so as not to grab aggro // We can use a different, more accurate version of GetClosePoint() since we have a pet float x, y, z; // Will be used later to reposition the pet if we have one - player->GetClosePoint(x, y, z, pet->GetObjectSize(), PET_FOLLOW_DIST, pet->GetFollowAngle()); + player->GetClosePoint(x, y, z, pet->GetCombatReach(), PET_FOLLOW_DIST, pet->GetFollowAngle()); pet->NearTeleportTo(x, y, z, player->GetOrientation()); pet->Relocate(x, y, z, player->GetOrientation()); // This is needed so SaveStayPosition() will get the proper coords. } @@ -4656,7 +4656,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) else if (effectInfo->HasRadius() && m_spellInfo->Speed == 0) { float dis = effectInfo->CalcRadius(m_originalCaster); - m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis); + m_caster->GetClosePoint(fx, fy, fz, DEFAULT_PLAYER_BOUNDING_RADIUS, dis); } else { @@ -4665,7 +4665,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) float max_dis = m_spellInfo->GetMaxRange(true); float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis; - m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis); + m_caster->GetClosePoint(fx, fy, fz, DEFAULT_PLAYER_BOUNDING_RADIUS, dis); } Map* cMap = m_caster->GetMap(); @@ -5076,7 +5076,7 @@ void Spell::EffectCreateTamedPet(SpellEffIndex /*effIndex*/) // relocate float px, py, pz; - unitTarget->GetClosePoint(px, py, pz, pet->GetObjectSize(), PET_FOLLOW_DIST, pet->GetFollowAngle()); + unitTarget->GetClosePoint(px, py, pz, pet->GetCombatReach(), PET_FOLLOW_DIST, pet->GetFollowAngle()); pet->Relocate(px, py, pz, unitTarget->GetOrientation()); // add to world diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 3266343d8b3..12eb37b6861 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -75,6 +75,35 @@ bool SpellImplicitTargetInfo::IsArea() const return GetSelectionCategory() == TARGET_SELECT_CATEGORY_AREA || GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE; } +bool SpellImplicitTargetInfo::IsProximityBasedAoe() const +{ + switch (_target) + { + case TARGET_UNIT_SRC_AREA_ENTRY: + case TARGET_UNIT_SRC_AREA_ENEMY: + case TARGET_UNIT_CASTER_AREA_PARTY: + case TARGET_UNIT_SRC_AREA_ALLY: + case TARGET_UNIT_SRC_AREA_PARTY: + case TARGET_UNIT_LASTTARGET_AREA_PARTY: + case TARGET_GAMEOBJECT_SRC_AREA: + case TARGET_UNIT_CASTER_AREA_RAID: + case TARGET_CORPSE_SRC_AREA_ENEMY: + return true; + + case TARGET_UNIT_DEST_AREA_ENTRY: + case TARGET_UNIT_DEST_AREA_ENEMY: + case TARGET_UNIT_DEST_AREA_ALLY: + case TARGET_UNIT_DEST_AREA_PARTY: + case TARGET_GAMEOBJECT_DEST_AREA: + case TARGET_UNIT_TARGET_AREA_RAID_CLASS: + return false; + + default: + TC_LOG_WARN("spells", "SpellImplicitTargetInfo::IsProximityBasedAoe called a non-aoe spell"); + return false; + } +} + SpellTargetSelectionCategories SpellImplicitTargetInfo::GetSelectionCategory() const { return _data[_target].SelectionCategory; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index d663c2359f0..e4b8709308b 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -286,6 +286,7 @@ public: SpellImplicitTargetInfo(uint32 target); bool IsArea() const; + bool IsProximityBasedAoe() const; SpellTargetSelectionCategories GetSelectionCategory() const; SpellTargetReferenceTypes GetReferenceType() const; SpellTargetObjectTypes GetObjectType() const; diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 3cd797d5e00..11417b305a5 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -918,7 +918,7 @@ public: uint32 entry = atoul(e); float x, y, z, o = handler->GetSession()->GetPlayer()->GetOrientation(); - handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, handler->GetSession()->GetPlayer()->GetObjectSize()); + handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, handler->GetSession()->GetPlayer()->GetCombatReach()); if (!i) return handler->GetSession()->GetPlayer()->SummonCreature(entry, x, y, z, o) != nullptr; diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp index afe3b3c2645..f6866734a7c 100644 --- a/src/server/scripts/Commands/cs_group.cpp +++ b/src/server/scripts/Commands/cs_group.cpp @@ -143,7 +143,7 @@ public: // before GM float x, y, z; - gmPlayer->GetClosePoint(x, y, z, player->GetObjectSize()); + gmPlayer->GetClosePoint(x, y, z, player->GetCombatReach()); player->TeleportTo(gmPlayer->GetMapId(), x, y, z, player->GetOrientation()); } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 1067283431d..d5bb43c9607 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -591,7 +591,7 @@ public: // before GM float x, y, z; - handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, target->GetObjectSize()); + handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, target->GetCombatReach()); target->TeleportTo(handler->GetSession()->GetPlayer()->GetMapId(), x, y, z, target->GetOrientation()); PhasingHandler::InheritPhaseShift(target, handler->GetSession()->GetPlayer()); target->UpdateObjectVisibility(); diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index ac4d8abb366..7a2e6cff30e 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -1457,7 +1457,7 @@ public: // place pet before player float x, y, z; - player->GetClosePoint (x, y, z, creatureTarget->GetObjectSize(), CONTACT_DISTANCE); + player->GetClosePoint (x, y, z, creatureTarget->GetCombatReach(), CONTACT_DISTANCE); pet->Relocate(x, y, z, float(M_PI) - player->GetOrientation()); // set pet to defensive mode by default (some classes can't control controlled pets in fact). diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp index 22efdea4071..c0ae774c5f1 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp @@ -126,7 +126,7 @@ class boss_selin_fireheart : public CreatureScript Crystals.remove(CrystalChosen); float x, y, z; - CrystalChosen->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE); + CrystalChosen->GetClosePoint(x, y, z, me->GetCombatReach(), CONTACT_DISTANCE); events.SetPhase(PHASE_DRAIN); me->SetWalk(false); diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp index d47bf3c7862..fea8c330b9c 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp @@ -101,7 +101,7 @@ public: FlyBackTimer = 500; break; case 1: - player->GetClosePoint(x, y, z, me->GetObjectSize()); + player->GetClosePoint(x, y, z, me->GetCombatReach()); z += 2.5f; x -= 2.0f; y -= 1.5f; diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp index 58690c3a171..71784911f34 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp @@ -539,7 +539,7 @@ public: /// TODO: Remove this once we find a general rule for WorldObject::MovePosition (this spell shouldn't take the Z change into consideration) Unit* caster = GetCaster(); float angle = float(rand_norm()) * static_cast(2 * M_PI); - uint32 dist = caster->GetObjectSize() + GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(caster) * (float)rand_norm(); + uint32 dist = caster->GetCombatReach() + GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(caster) * (float)rand_norm(); float x = caster->GetPositionX() + dist * std::cos(angle); float y = caster->GetPositionY() + dist * std::sin(angle); diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp index 1df68607625..ff4343f31fd 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_king_dred.cpp @@ -146,7 +146,7 @@ class boss_king_dred : public CreatureScript float x, y, z; - me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 10.0f); + me->GetClosePoint(x, y, z, me->GetCombatReach() / 3, 10.0f); me->SummonCreature(RAND(NPC_DRAKKARI_GUTRIPPER, NPC_DRAKKARI_SCYTHECLAW), x, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 1000); events.ScheduleEvent(EVENT_RAPTOR_CALL, urand(20000, 25000)); break; diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp index c67179d67eb..c78424c0078 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp @@ -131,7 +131,7 @@ class boss_bronjahm : public CreatureScript { summons.Summon(summon); summon->SetReactState(REACT_PASSIVE); - summon->GetMotionMaster()->MoveFollow(me, me->GetObjectSize(), 0.0f); + summon->GetMotionMaster()->MoveFollow(me, me->GetCombatReach(), 0.0f); summon->CastSpell(summon, SPELL_PURPLE_BANISH_VISUAL, true); } } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 98ee4e6194e..80ab44fe32a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -790,7 +790,7 @@ class npc_high_overlord_saurfang_icc : public CreatureScript if (Creature* deathbringer = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_DEATHBRINGER_SAURFANG))) { float x, y, z; - deathbringer->GetClosePoint(x, y, z, deathbringer->GetObjectSize()); + deathbringer->GetClosePoint(x, y, z, deathbringer->GetCombatReach()); me->SetWalk(true); me->GetMotionMaster()->MovePoint(POINT_CORPSE, x, y, z); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 99060220471..1ab35165e5a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -387,7 +387,7 @@ class npc_coldflame : public CreatureScript { float ang = Position::NormalizeOrientation(pos.GetAngle(me)); me->SetOrientation(ang); - owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 5.0f - owner->GetObjectSize(), ang); + owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 5.0f - owner->GetCombatReach(), ang); } else { @@ -400,7 +400,7 @@ class npc_coldflame : public CreatureScript float ang = Position::NormalizeOrientation(pos.GetAngle(target)); me->SetOrientation(ang); - owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 15.0f - owner->GetObjectSize(), ang); + owner->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 15.0f - owner->GetCombatReach(), ang); } me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), me->GetPositionZ(), me->GetOrientation()); @@ -518,7 +518,7 @@ class spell_marrowgar_coldflame : public SpellScriptLoader { targets.clear(); // select any unit but not the tank (by owners threatlist) - Unit* target = GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 1, -GetCaster()->GetObjectSize(), true, -SPELL_IMPALED); + Unit* target = GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 1, -GetCaster()->GetCombatReach(), true, -SPELL_IMPALED); if (!target) target = GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true); // or the tank if its solo if (!target) diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp index e7f17a1033b..0e42a431d93 100644 --- a/src/server/scripts/Northrend/zone_zuldrak.cpp +++ b/src/server/scripts/Northrend/zone_zuldrak.cpp @@ -58,7 +58,7 @@ public: me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE); float x, y, z; - me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 0.1f); + me->GetClosePoint(x, y, z, me->GetCombatReach() / 3, 0.1f); if (Creature* summon = me->SummonCreature(NPC_RAGECLAW, x, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 1000)) { @@ -183,7 +183,7 @@ public: void Reset() override { float x, y, z; - me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 25.0f); + me->GetClosePoint(x, y, z, me->GetCombatReach() / 3, 25.0f); me->GetMotionMaster()->MovePoint(0, x, y, z); } diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index a482096ce7c..a8bd85023a2 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -525,7 +525,7 @@ public: Tapped = true; float x, y, z; - caster->GetClosePoint(x, y, z, me->GetObjectSize()); + caster->GetClosePoint(x, y, z, me->GetCombatReach()); me->SetWalk(false); me->GetMotionMaster()->MovePoint(1, x, y, z); diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp index 98814128a34..c0e1fdaae33 100644 --- a/src/server/scripts/World/go_scripts.cpp +++ b/src/server/scripts/World/go_scripts.cpp @@ -361,7 +361,7 @@ public: uint32 BirdEntry = 0; float fX, fY, fZ; - go->GetClosePoint(fX, fY, fZ, go->GetObjectSize(), INTERACTION_DISTANCE); + go->GetClosePoint(fX, fY, fZ, go->GetCombatReach(), INTERACTION_DISTANCE); switch (go->GetEntry()) { diff --git a/src/server/scripts/World/item_scripts.cpp b/src/server/scripts/World/item_scripts.cpp index 55b7d571d56..628ca0edcae 100644 --- a/src/server/scripts/World/item_scripts.cpp +++ b/src/server/scripts/World/item_scripts.cpp @@ -243,7 +243,7 @@ public: return true; float x, y, z; - go->GetClosePoint(x, y, z, go->GetObjectSize() / 3, 7.0f); + go->GetClosePoint(x, y, z, go->GetCombatReach() / 3, 7.0f); go->SummonGameObject(GO_HIGH_QUALITY_FUR, *go, QuaternionData::fromEulerAnglesZYX(go->GetOrientation(), 0.0f, 0.0f), 1); if (TempSummon* summon = player->SummonCreature(NPC_NESINGWARY_TRAPPER, x, y, z, go->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 1000)) { -- cgit v1.2.3 From 7a561ad045f7003aad6ff678c34ad4aafffea79d Mon Sep 17 00:00:00 2001 From: ariel- Date: Thu, 23 Mar 2017 03:23:48 -0300 Subject: Core/Scripts: Updated Ulduar instance model - Codestyle/indent fixes - Added ObjectData for some GOs - Added GetUlduarAI to creatures - Fixed possible out-of-bounds access in boss_razorscale_controllerAI (boss AI number beyond allocated boss size) (cherry picked from commit b74cc8085946fed1eb41a6332e3a5cca6f9edd7f) --- .../Ulduar/Ulduar/boss_algalon_the_observer.cpp | 2 +- .../Northrend/Ulduar/Ulduar/boss_auriaya.cpp | 8 +- .../Ulduar/Ulduar/boss_flame_leviathan.cpp | 11 +- .../scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp | 30 +- .../Northrend/Ulduar/Ulduar/boss_general_vezax.cpp | 8 +- .../scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp | 38 +-- .../scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp | 2 +- .../Northrend/Ulduar/Ulduar/boss_mimiron.cpp | 40 +-- .../Northrend/Ulduar/Ulduar/boss_razorscale.cpp | 77 ++--- .../scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp | 58 ++-- .../Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp | 44 +-- .../Northrend/Ulduar/Ulduar/instance_ulduar.cpp | 323 +++++---------------- 12 files changed, 235 insertions(+), 406 deletions(-) (limited to 'src/server/scripts') diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index 818485e4440..4e5019618ec 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -410,7 +410,7 @@ class boss_algalon_the_observer : public CreatureScript { _firstPull = false; Talk(SAY_ALGALON_START_TIMER); - if (Creature* brann = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BRANN_BRONZEBEARD_ALG))) + if (Creature* brann = instance->GetCreature(DATA_BRANN_BRONZEBEARD_ALG)) brann->AI()->DoAction(ACTION_FINISH_INTRO); me->setActive(true); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp index b8f23964df6..fe01a917cd6 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp @@ -393,8 +393,8 @@ class npc_sanctum_sentry : public CreatureScript void JustDied(Unit* /*killer*/) override { - if (Creature* Auriaya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_AURIAYA))) - Auriaya->AI()->DoAction(ACTION_CRAZY_CAT_LADY); + if (Creature* auriaya = instance->GetCreature(BOSS_AURIAYA)) + auriaya->AI()->DoAction(ACTION_CRAZY_CAT_LADY); } private: @@ -472,8 +472,8 @@ class npc_feral_defender : public CreatureScript void JustDied(Unit* /*killer*/) override { DoCast(me, SPELL_SUMMON_ESSENCE); - if (Creature* Auriaya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_AURIAYA))) - Auriaya->AI()->DoAction(ACTION_RESPAWN_DEFENDER); + if (Creature* auriaya = instance->GetCreature(BOSS_AURIAYA)) + auriaya->AI()->DoAction(ACTION_RESPAWN_DEFENDER); } private: diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index b2958daf07c..8e734e6d3e7 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -974,11 +974,6 @@ class npc_mimirons_inferno : public CreatureScript public: npc_mimirons_inferno() : CreatureScript("npc_mimirons_inferno") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } - struct npc_mimirons_infernoAI : public npc_escortAI { npc_mimirons_infernoAI(Creature* creature) : npc_escortAI(creature) @@ -1031,6 +1026,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } }; class npc_hodirs_fury : public CreatureScript @@ -1247,7 +1246,7 @@ class npc_lorekeeper : public CreatureScript CloseGossipMenuFor(player); me->GetMap()->LoadGrid(364, -16); // make sure leviathan is loaded - if (Creature* leviathan = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_LEVIATHAN))) + if (Creature* leviathan = _instance->GetCreature(BOSS_LEVIATHAN)) { leviathan->AI()->DoAction(ACTION_START_HARD_MODE); me->SetVisible(false); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index ad4b7c6413f..5cfc0d75481 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -1061,8 +1061,8 @@ class npc_ancient_water_spirit : public CreatureScript { Initialize(); instance = me->GetInstanceScript(); - if (Creature* Freya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_FREYA))) - waveCount = ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->trioWaveCount; + if (Creature* freya = instance->GetCreature(BOSS_FREYA)) + waveCount = ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->trioWaveCount; else waveCount = 0; } @@ -1099,10 +1099,10 @@ class npc_ancient_water_spirit : public CreatureScript void JustDied(Unit* /*killer*/) override { - if (Creature* Freya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_FREYA))) + if (Creature* freya = instance->GetCreature(BOSS_FREYA)) { - ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->checkElementalAlive[waveCount] = false; - ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->LasherDead(1); + ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->checkElementalAlive[waveCount] = false; + ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->LasherDead(1); } } @@ -1129,8 +1129,8 @@ class npc_storm_lasher : public CreatureScript { Initialize(); instance = me->GetInstanceScript(); - if (Creature* Freya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_FREYA))) - waveCount = ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->trioWaveCount; + if (Creature* freya = instance->GetCreature(BOSS_FREYA)) + waveCount = ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->trioWaveCount; else waveCount = 0; } @@ -1173,10 +1173,10 @@ class npc_storm_lasher : public CreatureScript void JustDied(Unit* /*killer*/) override { - if (Creature* Freya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_FREYA))) + if (Creature* freya = instance->GetCreature(BOSS_FREYA)) { - ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->checkElementalAlive[waveCount] = false; - ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->LasherDead(2); + ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->checkElementalAlive[waveCount] = false; + ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->LasherDead(2); } } @@ -1203,8 +1203,8 @@ class npc_snaplasher : public CreatureScript npc_snaplasherAI(Creature* creature) : ScriptedAI(creature) { instance = me->GetInstanceScript(); - if (Creature* Freya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_FREYA))) - waveCount = ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->trioWaveCount; + if (Creature* freya = instance->GetCreature(BOSS_FREYA)) + waveCount = ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->trioWaveCount; else waveCount = 0; } @@ -1222,10 +1222,10 @@ class npc_snaplasher : public CreatureScript void JustDied(Unit* /*killer*/) override { - if (Creature* Freya = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_FREYA))) + if (Creature* freya = instance->GetCreature(BOSS_FREYA)) { - ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->checkElementalAlive[waveCount] = false; - ENSURE_AI(boss_freya::boss_freyaAI, Freya->AI())->LasherDead(4); + ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->checkElementalAlive[waveCount] = false; + ENSURE_AI(boss_freya::boss_freyaAI, freya->AI())->LasherDead(4); } } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp index 9630f1ddbfe..6c03b9f5ecb 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp @@ -336,8 +336,8 @@ class boss_saronite_animus : public CreatureScript void JustDied(Unit* /*killer*/) override { - if (Creature* Vezax = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_VEZAX))) - Vezax->AI()->DoAction(ACTION_ANIMUS_DIE); + if (Creature* vezax = instance->GetCreature(BOSS_VEZAX)) + vezax->AI()->DoAction(ACTION_ANIMUS_DIE); } void UpdateAI(uint32 diff) override @@ -434,8 +434,8 @@ class npc_saronite_vapors : public CreatureScript DoCast(me, SPELL_SARONITE_VAPORS); me->DespawnOrUnsummon(30000); - if (Creature* Vezax = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_VEZAX))) - Vezax->AI()->DoAction(ACTION_VAPORS_DIE); + if (Creature* vezax = instance->GetCreature(BOSS_VEZAX)) + vezax->AI()->DoAction(ACTION_VAPORS_DIE); } } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp index 57b96e26943..4d8a49160bc 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp @@ -242,8 +242,8 @@ class npc_flash_freeze : public CreatureScript // Prevents to have Ice Block on other place than target is me->NearTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation()); if (target->GetTypeId() == TYPEID_PLAYER) - if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR))) - Hodir->AI()->DoAction(ACTION_CHEESE_THE_FREEZE); + if (Creature* hodir = instance->GetCreature(BOSS_HODIR)) + hodir->AI()->DoAction(ACTION_CHEESE_THE_FREEZE); } } }; @@ -291,21 +291,21 @@ class npc_ice_block : public CreatureScript void DamageTaken(Unit* who, uint32& /*damage*/) override { - if (Creature* Helper = ObjectAccessor::GetCreature(*me, targetGUID)) + if (Creature* helper = ObjectAccessor::GetCreature(*me, targetGUID)) { - Helper->RemoveUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED)); - Helper->SetControlled(false, UNIT_STATE_ROOT); + helper->RemoveUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED)); + helper->SetControlled(false, UNIT_STATE_ROOT); - if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR))) + if (Creature* hodir = instance->GetCreature(BOSS_HODIR)) { - if (!Hodir->IsInCombat()) + if (!hodir->IsInCombat()) { - Hodir->SetReactState(REACT_AGGRESSIVE); - Hodir->AI()->DoZoneInCombat(); - Hodir->AI()->AttackStart(who); + hodir->SetReactState(REACT_AGGRESSIVE); + hodir->AI()->DoZoneInCombat(); + hodir->AI()->AttackStart(who); } - Helper->AI()->AttackStart(Hodir); + helper->AI()->AttackStart(hodir); } } } @@ -717,8 +717,8 @@ class npc_hodir_priest : public CreatureScript void JustDied(Unit* /*killer*/) override { - if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR))) - Hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS); + if (Creature* hodir = instance->GetCreature(BOSS_HODIR)) + hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS); } private: @@ -782,8 +782,8 @@ class npc_hodir_shaman : public CreatureScript void JustDied(Unit* /*killer*/) override { - if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR))) - Hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS); + if (Creature* hodir = instance->GetCreature(BOSS_HODIR)) + hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS); } private: @@ -846,8 +846,8 @@ class npc_hodir_druid : public CreatureScript void JustDied(Unit* /*killer*/) override { - if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR))) - Hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS); + if (Creature* hodir = instance->GetCreature(BOSS_HODIR)) + hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS); } private: @@ -929,8 +929,8 @@ class npc_hodir_mage : public CreatureScript void JustDied(Unit* /*killer*/) override { - if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR))) - Hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS); + if (Creature* hodir = instance->GetCreature(BOSS_HODIR)) + hodir->AI()->DoAction(ACTION_I_HAVE_THE_COOLEST_FRIENDS); } private: diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp index e4040a44a36..37141085731 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp @@ -328,7 +328,7 @@ class npc_iron_construct : public CreatureScript if (me->HasAura(RAID_MODE(SPELL_BRITTLE, SPELL_BRITTLE_25)) && damage >= 5000) { DoCast(SPELL_SHATTER); - if (Creature* ignis = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_IGNIS))) + if (Creature* ignis = _instance->GetCreature(BOSS_IGNIS)) if (ignis->AI()) ignis->AI()->DoAction(ACTION_REMOVE_BUFF); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index 5cf1cf67de8..fd4d7b02229 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -371,7 +371,7 @@ static bool IsEncounterFinished(Unit* who) mkii->DespawnOrUnsummon(120000); vx001->DespawnOrUnsummon(120000); aerial->DespawnOrUnsummon(120000); - if (Creature* mimiron = ObjectAccessor::GetCreature(*who, instance->GetGuidData(BOSS_MIMIRON))) + if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON)) mimiron->AI()->JustDied(who); return true; } @@ -428,7 +428,7 @@ class boss_mimiron : public CreatureScript me->RemoveAurasDueToSpell(SPELL_WELD); DoCast(me->GetVehicleBase(), SPELL_SEAT_6); - if (GameObject* button = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MIMIRON_BUTTON))) + if (GameObject* button = instance->GetGameObject(DATA_MIMIRON_BUTTON)) button->AddFlag(GO_FLAG_NOT_SELECTABLE); if (_fireFighter) @@ -458,14 +458,14 @@ class boss_mimiron : public CreatureScript _Reset(); me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - if (GameObject* elevator = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MIMIRON_ELEVATOR))) + if (GameObject* elevator = instance->GetGameObject(DATA_MIMIRON_ELEVATOR)) elevator->SetGoState(GO_STATE_ACTIVE); if (_fireFighter) - if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_COMPUTER))) + if (Creature* computer = instance->GetCreature(DATA_COMPUTER)) computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER); - if (GameObject* button = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MIMIRON_BUTTON))) + if (GameObject* button = instance->GetGameObject(DATA_MIMIRON_BUTTON)) { button->SetGoState(GO_STATE_READY); button->RemoveFlag(GO_FLAG_NOT_SELECTABLE); @@ -493,7 +493,7 @@ class boss_mimiron : public CreatureScript switch (eventId) { case EVENT_SUMMON_FLAMES: - if (Unit* worldtrigger = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MIMIRON_WORLD_TRIGGER))) + if (Creature* worldtrigger = instance->GetCreature(DATA_MIMIRON_WORLD_TRIGGER)) worldtrigger->CastCustomSpell(SPELL_SCRIPT_EFFECT_SUMMON_FLAMES_INITIAL, SPELLVALUE_MAX_TARGETS, 3, NULL, true, NULL, NULL, me->GetGUID()); events.RescheduleEvent(EVENT_SUMMON_FLAMES, 28000); break; @@ -529,14 +529,14 @@ class boss_mimiron : public CreatureScript events.ScheduleEvent(EVENT_VX001_ACTIVATION_4, 5000); break; case EVENT_VX001_ACTIVATION_4: - if (GameObject* elevator = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MIMIRON_ELEVATOR))) + if (GameObject* elevator = instance->GetGameObject(DATA_MIMIRON_ELEVATOR)) elevator->SetGoState(GO_STATE_READY); - if (Unit* worldtrigger = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MIMIRON_WORLD_TRIGGER))) + if (Creature* worldtrigger = instance->GetCreature(DATA_MIMIRON_WORLD_TRIGGER)) worldtrigger->CastSpell(worldtrigger, SPELL_ELEVATOR_KNOCKBACK); events.ScheduleEvent(EVENT_VX001_ACTIVATION_5, 6000); break; case EVENT_VX001_ACTIVATION_5: - if (GameObject* elevator = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MIMIRON_ELEVATOR))) + if (GameObject* elevator = instance->GetGameObject(DATA_MIMIRON_ELEVATOR)) elevator->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); if (Creature* vx001 = me->SummonCreature(NPC_VX_001, VX001SummonPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000)) vx001->CastSpell(vx001, SPELL_FREEZE_ANIM); @@ -644,7 +644,7 @@ class boss_mimiron : public CreatureScript Talk(SAY_V07TRON_DEATH); if (_fireFighter) { - if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_COMPUTER))) + if (Creature* computer = instance->GetCreature(DATA_COMPUTER)) computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER); me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION_FIREFIGHTER, GO_CACHE_OF_INNOVATION_FIREFIGHTER_HERO), 2744.040f, 2569.352f, 364.3135f, 3.124123f, QuaternionData(0.f, 0.f, 0.9999619f, 0.008734641f), 604800); } @@ -783,7 +783,7 @@ class boss_leviathan_mk_ii : public CreatureScript void KilledUnit(Unit* victim) override { if (victim->GetTypeId() == TYPEID_PLAYER) - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON))) + if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON)) mimiron->AI()->Talk(events.IsInPhase(PHASE_LEVIATHAN_MK_II) ? SAY_MKII_SLAY : SAY_V07TRON_SLAY); } @@ -798,7 +798,7 @@ class boss_leviathan_mk_ii : public CreatureScript me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE); DoCast(me, SPELL_HALF_HEAL); - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON))) + if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON)) mimiron->AI()->DoAction(DO_ACTIVATE_VX001); break; case WP_MKII_P4_POS_1: @@ -808,7 +808,7 @@ class boss_leviathan_mk_ii : public CreatureScript events.ScheduleEvent(EVENT_MOVE_POINT_3, 1); break; case WP_MKII_P4_POS_3: - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON))) + if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON)) mimiron->AI()->DoAction(DO_ACTIVATE_V0L7R0N_2); break; case WP_MKII_P4_POS_4: @@ -951,7 +951,7 @@ class boss_vx_001 : public CreatureScript me->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE); // | UNIT_FLAG_NOT_SELECTABLE); DoCast(me, SPELL_HALF_HEAL); // has no effect, wat DoCast(me, SPELL_TORSO_DISABLED); - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON))) + if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON)) mimiron->AI()->DoAction(DO_ACTIVATE_AERIAL); } else if (events.IsInPhase(PHASE_VOL7RON)) @@ -1022,7 +1022,7 @@ class boss_vx_001 : public CreatureScript void KilledUnit(Unit* victim) override { if (victim->GetTypeId() == TYPEID_PLAYER) - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON))) + if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON)) mimiron->AI()->Talk(events.IsInPhase(PHASE_VX_001) ? SAY_VX001_SLAY : SAY_V07TRON_SLAY); } @@ -1201,7 +1201,7 @@ class boss_aerial_command_unit : public CreatureScript void KilledUnit(Unit* victim) override { if (victim->GetTypeId() == TYPEID_PLAYER) - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON))) + if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON)) mimiron->AI()->Talk(events.IsInPhase(PHASE_AERIAL_COMMAND_UNIT) ? SAY_AERIAL_SLAY : SAY_V07TRON_SLAY); } @@ -1211,7 +1211,7 @@ class boss_aerial_command_unit : public CreatureScript { me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON))) + if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON)) mimiron->AI()->DoAction(DO_ACTIVATE_V0L7R0N_1); } } @@ -1435,7 +1435,7 @@ class npc_mimiron_computer : public CreatureScript { case EVENT_SELF_DESTRUCT_10: Talk(SAY_SELF_DESTRUCT_10); - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON))) + if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON)) mimiron->AI()->DoAction(DO_ACTIVATE_HARD_MODE); events.ScheduleEvent(EVENT_SELF_DESTRUCT_9, 60000); break; @@ -1477,7 +1477,7 @@ class npc_mimiron_computer : public CreatureScript break; case EVENT_SELF_DESTRUCT_FINALIZED: Talk(SAY_SELF_DESTRUCT_FINALIZED); - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MIMIRON))) + if (Creature* mimiron = instance->GetCreature(BOSS_MIMIRON)) mimiron->AI()->DoAction(DO_ACTIVATE_SELF_DESTRUCT); DoCast(me, SPELL_SELF_DESTRUCTION_AURA); DoCast(me, SPELL_SELF_DESTRUCTION_VISUAL); @@ -1658,7 +1658,7 @@ class go_mimiron_hardmode_button : public GameObjectScript if (!instance) return false; - if (Creature* computer = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_COMPUTER))) + if (Creature* computer = instance->GetCreature(DATA_COMPUTER)) computer->AI()->DoAction(DO_ACTIVATE_COMPUTER); go->SetGoState(GO_STATE_ACTIVE); go->AddFlag(GO_FLAG_NOT_SELECTABLE); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp index 8a1bbfe712c..3f56f4523cc 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp @@ -189,16 +189,22 @@ class boss_razorscale_controller : public CreatureScript public: boss_razorscale_controller() : CreatureScript("boss_razorscale_controller") { } - struct boss_razorscale_controllerAI : public BossAI + struct boss_razorscale_controllerAI : public ScriptedAI { - boss_razorscale_controllerAI(Creature* creature) : BossAI(creature, DATA_RAZORSCALE_CONTROL) + boss_razorscale_controllerAI(Creature* creature) : ScriptedAI(creature), summons(me) { + instance = creature->GetInstanceScript(); me->SetDisplayFromModel(1); } + InstanceScript* instance; + EventMap events; + SummonList summons; + void Reset() override { - _Reset(); + events.Reset(); + summons.DespawnAll(); me->SetReactState(REACT_PASSIVE); } @@ -207,14 +213,14 @@ class boss_razorscale_controller : public CreatureScript switch (spell->Id) { case SPELL_FLAMED: - if (GameObject* Harpoon1 = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_RAZOR_HARPOON_1))) - Harpoon1->RemoveFromWorld(); - if (GameObject* Harpoon2 = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_RAZOR_HARPOON_2))) - Harpoon2->RemoveFromWorld(); - if (GameObject* Harpoon3 = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_RAZOR_HARPOON_3))) - Harpoon3->RemoveFromWorld(); - if (GameObject* Harpoon4 = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_RAZOR_HARPOON_4))) - Harpoon4->RemoveFromWorld(); + if (GameObject* harpoon = instance->GetGameObject(GO_RAZOR_HARPOON_1)) + harpoon->RemoveFromWorld(); + if (GameObject* harpoon = instance->GetGameObject(GO_RAZOR_HARPOON_2)) + harpoon->RemoveFromWorld(); + if (GameObject* harpoon = instance->GetGameObject(GO_RAZOR_HARPOON_3)) + harpoon->RemoveFromWorld(); + if (GameObject* harpoon = instance->GetGameObject(GO_RAZOR_HARPOON_4)) + harpoon->RemoveFromWorld(); DoAction(ACTION_HARPOON_BUILD); DoAction(ACTION_PLACE_BROKEN_HARPOON); break; @@ -229,7 +235,8 @@ class boss_razorscale_controller : public CreatureScript void JustDied(Unit* /*killer*/) override { - _JustDied(); + events.Reset(); + summons.DespawnAll(); } void DoAction(int32 action) override @@ -261,39 +268,39 @@ class boss_razorscale_controller : public CreatureScript { case EVENT_BUILD_HARPOON_1: Talk(EMOTE_HARPOON); - if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_1, PosHarpoon[0].GetPositionX(), PosHarpoon[0].GetPositionY(), PosHarpoon[0].GetPositionZ(), 4.790f, QuaternionData::fromEulerAnglesZYX(4.790f, 0.0f, 0.0f), uint32(me->GetRespawnTime()))) + if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_1, PosHarpoon[0].GetPositionX(), PosHarpoon[0].GetPositionY(), PosHarpoon[0].GetPositionZ(), 4.790f, QuaternionData::fromEulerAnglesZYX(4.790f, 0.0f, 0.0f), uint32(me->GetRespawnTime()))) { - if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) //only nearest broken harpoon - BrokenHarpoon->RemoveFromWorld(); + if (GameObject* brokenHarpoon = harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) //only nearest broken harpoon + brokenHarpoon->RemoveFromWorld(); events.ScheduleEvent(EVENT_BUILD_HARPOON_2, 20000); events.CancelEvent(EVENT_BUILD_HARPOON_1); } return; case EVENT_BUILD_HARPOON_2: Talk(EMOTE_HARPOON); - if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_2, PosHarpoon[1].GetPositionX(), PosHarpoon[1].GetPositionY(), PosHarpoon[1].GetPositionZ(), 4.659f, QuaternionData::fromEulerAnglesZYX(4.659f, 0.0f, 0.0f), uint32(me->GetRespawnTime()))) + if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_2, PosHarpoon[1].GetPositionX(), PosHarpoon[1].GetPositionY(), PosHarpoon[1].GetPositionZ(), 4.659f, QuaternionData::fromEulerAnglesZYX(4.659f, 0.0f, 0.0f), uint32(me->GetRespawnTime()))) { - if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) - BrokenHarpoon->RemoveFromWorld(); + if (GameObject* brokenHarpoon = harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) + brokenHarpoon->RemoveFromWorld(); events.CancelEvent(EVENT_BUILD_HARPOON_2); } return; case EVENT_BUILD_HARPOON_3: Talk(EMOTE_HARPOON); - if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_3, PosHarpoon[2].GetPositionX(), PosHarpoon[2].GetPositionY(), PosHarpoon[2].GetPositionZ(), 5.382f, QuaternionData::fromEulerAnglesZYX(5.382f, 0.0f, 0.0f), uint32(me->GetRespawnTime()))) + if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_3, PosHarpoon[2].GetPositionX(), PosHarpoon[2].GetPositionY(), PosHarpoon[2].GetPositionZ(), 5.382f, QuaternionData::fromEulerAnglesZYX(5.382f, 0.0f, 0.0f), uint32(me->GetRespawnTime()))) { - if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) - BrokenHarpoon->RemoveFromWorld(); + if (GameObject* brokenHarpoon = harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) + brokenHarpoon->RemoveFromWorld(); events.ScheduleEvent(EVENT_BUILD_HARPOON_4, 20000); events.CancelEvent(EVENT_BUILD_HARPOON_3); } return; case EVENT_BUILD_HARPOON_4: Talk(EMOTE_HARPOON); - if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_4, PosHarpoon[3].GetPositionX(), PosHarpoon[3].GetPositionY(), PosHarpoon[3].GetPositionZ(), 4.266f, QuaternionData::fromEulerAnglesZYX(4.266f, 0.0f, 0.0f), uint32(me->GetRespawnTime()))) + if (GameObject* harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_4, PosHarpoon[3].GetPositionX(), PosHarpoon[3].GetPositionY(), PosHarpoon[3].GetPositionZ(), 4.266f, QuaternionData::fromEulerAnglesZYX(4.266f, 0.0f, 0.0f), uint32(me->GetRespawnTime()))) { - if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) - BrokenHarpoon->RemoveFromWorld(); + if (GameObject* brokenHarpoon = harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) + brokenHarpoon->RemoveFromWorld(); events.CancelEvent(EVENT_BUILD_HARPOON_4); } return; @@ -315,9 +322,9 @@ class go_razorscale_harpoon : public GameObjectScript bool OnGossipHello(Player* /*player*/, GameObject* go) override { - InstanceScript* instance = go->GetInstanceScript(); - if (ObjectAccessor::GetCreature(*go, instance->GetGuidData(BOSS_RAZORSCALE))) - go->AddFlag(GO_FLAG_NOT_SELECTABLE); + if (InstanceScript* instance = go->GetInstanceScript()) + if (instance->GetCreature(BOSS_RAZORSCALE)) + go->AddFlag(GO_FLAG_NOT_SELECTABLE); return false; } }; @@ -361,14 +368,14 @@ class boss_razorscale : public CreatureScript me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE); me->SetReactState(REACT_PASSIVE); Initialize(); - if (Creature* commander = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXPEDITION_COMMANDER))) + if (Creature* commander = instance->GetCreature(DATA_EXPEDITION_COMMANDER)) commander->AI()->DoAction(ACTION_COMMANDER_RESET); } void EnterCombat(Unit* /*who*/) override { _EnterCombat(); - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAZORSCALE_CONTROL))) + if (Creature* controller = instance->GetCreature(DATA_RAZORSCALE_CONTROL)) controller->AI()->DoAction(ACTION_HARPOON_BUILD); me->SetSpeedRate(MOVE_FLIGHT, 3.0f); me->SetReactState(REACT_PASSIVE); @@ -383,7 +390,7 @@ class boss_razorscale : public CreatureScript void JustDied(Unit* /*killer*/) override { _JustDied(); - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAZORSCALE_CONTROL))) + if (Creature* controller = instance->GetCreature(DATA_RAZORSCALE_CONTROL)) controller->AI()->Reset(); } @@ -459,7 +466,7 @@ class boss_razorscale : public CreatureScript me->SetCanFly(false); me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); me->AddUnitFlag(UnitFlags(UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED)); - if (Creature* commander = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXPEDITION_COMMANDER))) + if (Creature* commander = instance->GetCreature(DATA_EXPEDITION_COMMANDER)) commander->AI()->DoAction(ACTION_GROUND_PHASE); events.ScheduleEvent(EVENT_BREATH, 30000, 0, PHASE_GROUND); events.ScheduleEvent(EVENT_BUFFET, 33000, 0, PHASE_GROUND); @@ -475,7 +482,7 @@ class boss_razorscale : public CreatureScript return; case EVENT_BUFFET: DoCastAOE(SPELL_WINGBUFFET); - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAZORSCALE_CONTROL))) + if (Creature* controller = instance->GetCreature(DATA_RAZORSCALE_CONTROL)) controller->CastSpell(controller, SPELL_FLAMED, true); events.CancelEvent(EVENT_BUFFET); return; @@ -717,10 +724,10 @@ class npc_expedition_commander : public CreatureScript Phase = 5; break; case 5: - if (Creature* Razorscale = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_RAZORSCALE))) + if (Creature* razorscale = instance->GetCreature(BOSS_RAZORSCALE)) { - Razorscale->AI()->DoAction(ACTION_EVENT_START); - me->SetInCombatWith(Razorscale); + razorscale->AI()->DoAction(ACTION_EVENT_START); + me->SetInCombatWith(razorscale); } if (Creature* firstEngineer = ObjectAccessor::GetCreature(*me, Engineer[0])) firstEngineer->AI()->Talk(SAY_AGGRO_1); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp index 0366f1534ba..c6fc0925bf6 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp @@ -176,11 +176,6 @@ class boss_xt002 : public CreatureScript public: boss_xt002() : CreatureScript("boss_xt002") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } - struct boss_xt002_AI : public BossAI { boss_xt002_AI(Creature* creature) : BossAI(creature, BOSS_XT002) @@ -441,6 +436,12 @@ class boss_xt002 : public CreatureScript uint8 _heartExposed; uint32 _transferHealth; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } + }; /*------------------------------------------------------- @@ -460,7 +461,7 @@ class npc_xt002_heart : public CreatureScript void JustDied(Unit* /*killer*/) override { - if (Creature* xt002 = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_XT002))) + if (Creature* xt002 = _instance->GetCreature(BOSS_XT002)) { xt002->AI()->SetData(DATA_TRANSFERED_HEALTH, me->GetHealth()); xt002->AI()->DoAction(ACTION_ENTER_HARD_MODE); @@ -487,11 +488,6 @@ class npc_scrapbot : public CreatureScript public: npc_scrapbot() : CreatureScript("npc_scrapbot") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } - struct npc_scrapbotAI : public ScriptedAI { npc_scrapbotAI(Creature* creature) : ScriptedAI(creature) @@ -511,15 +507,15 @@ class npc_scrapbot : public CreatureScript Initialize(); - if (Creature* pXT002 = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_XT002))) - me->GetMotionMaster()->MoveFollow(pXT002, 0.0f, 0.0f); + if (Creature* xt002 = _instance->GetCreature(BOSS_XT002)) + me->GetMotionMaster()->MoveFollow(xt002, 0.0f, 0.0f); } void UpdateAI(uint32 diff) override { if (_rangeCheckTimer <= diff) { - if (Creature* xt002 = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_XT002))) + if (Creature* xt002 = _instance->GetCreature(BOSS_XT002)) { if (me->IsWithinMeleeRange(xt002)) { @@ -538,6 +534,12 @@ class npc_scrapbot : public CreatureScript InstanceScript* _instance; uint32 _rangeCheckTimer; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } + }; /*------------------------------------------------------- @@ -550,11 +552,6 @@ class npc_pummeller : public CreatureScript public: npc_pummeller() : CreatureScript("npc_pummeller") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } - struct npc_pummellerAI : public ScriptedAI { npc_pummellerAI(Creature* creature) : ScriptedAI(creature) @@ -574,7 +571,7 @@ class npc_pummeller : public CreatureScript { Initialize(); - if (Creature* xt002 = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_XT002))) + if (Creature* xt002 = _instance->GetCreature(BOSS_XT002)) { Position pos = xt002->GetPosition(); me->GetMotionMaster()->MovePoint(0, pos); @@ -622,6 +619,12 @@ class npc_pummeller : public CreatureScript uint32 _trampleTimer; uint32 _uppercutTimer; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } + }; /*------------------------------------------------------- @@ -657,11 +660,6 @@ class npc_boombot : public CreatureScript public: npc_boombot() : CreatureScript("npc_boombot") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } - struct npc_boombotAI : public ScriptedAI { npc_boombotAI(Creature* creature) : ScriptedAI(creature) @@ -682,8 +680,8 @@ class npc_boombot : public CreatureScript DoCast(SPELL_AURA_BOOMBOT); // For achievement /// @todo proper waypoints? - if (Creature* pXT002 = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_XT002))) - me->GetMotionMaster()->MoveFollow(pXT002, 0.0f, 0.0f); + if (Creature* xt002 = _instance->GetCreature(BOSS_XT002)) + me->GetMotionMaster()->MoveFollow(xt002, 0.0f, 0.0f); } void DamageTaken(Unit* /*who*/, uint32& damage) override @@ -723,6 +721,12 @@ class npc_boombot : public CreatureScript InstanceScript* _instance; bool _boomed; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } + }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp index 6c1101d433d..79214b5b0e1 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp @@ -511,7 +511,7 @@ class boss_voice_of_yogg_saron : public CreatureScript void EnterCombat(Unit* /*who*/) override { - if (Creature* sara = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SARA))) + if (Creature* sara = instance->GetCreature(DATA_SARA)) sara->SetInCombatWith(me); for (uint8 i = DATA_FREYA_YS; i <= DATA_MIMIRON_YS; ++i) @@ -531,7 +531,7 @@ class boss_voice_of_yogg_saron : public CreatureScript void JustDied(Unit* killer) override { // don't despawn Yogg-Saron's corpse, remove him from SummonList! - if (Creature* yogg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_YOGG_SARON))) + if (Creature* yogg = instance->GetCreature(BOSS_YOGG_SARON)) summons.Despawn(yogg); BossAI::JustDied(killer); @@ -556,7 +556,7 @@ class boss_voice_of_yogg_saron : public CreatureScript instance->SetBossState(BOSS_YOGG_SARON, IN_PROGRESS); break; case EVENT_EXTINGUISH_ALL_LIFE: - if (Creature* yogg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_YOGG_SARON))) + if (Creature* yogg = instance->GetCreature(BOSS_YOGG_SARON)) { yogg->AI()->Talk(EMOTE_YOGG_SARON_EXTINGUISH_ALL_LIFE, me); yogg->CastSpell((Unit*)NULL, SPELL_EXTINGUISH_ALL_LIFE, true); @@ -584,7 +584,7 @@ class boss_voice_of_yogg_saron : public CreatureScript break; case EVENT_ILLUSION: { - if (Creature* yogg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_YOGG_SARON))) + if (Creature* yogg = instance->GetCreature(BOSS_YOGG_SARON)) { yogg->AI()->Talk(EMOTE_YOGG_SARON_MADNESS); yogg->AI()->Talk(SAY_YOGG_SARON_MADNESS); @@ -597,7 +597,7 @@ class boss_voice_of_yogg_saron : public CreatureScript uint8 illusion = urand(CHAMBER_ILLUSION, STORMWIND_ILLUSION); instance->SetData(DATA_ILLUSION, illusion); - if (Creature* brain = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BRAIN_OF_YOGG_SARON))) + if (Creature* brain = instance->GetCreature(DATA_BRAIN_OF_YOGG_SARON)) brain->AI()->DoAction(ACTION_INDUCE_MADNESS); events.ScheduleEvent(EVENT_ILLUSION, 80000, 0, PHASE_TWO); // wowwiki says 80 secs, wowhead says something about 90 secs break; @@ -623,7 +623,7 @@ class boss_voice_of_yogg_saron : public CreatureScript case ACTION_PHASE_TWO: events.SetPhase(PHASE_TWO); me->SummonCreature(NPC_YOGG_SARON, YoggSaronSpawnPos); - if (Creature* brain = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BRAIN_OF_YOGG_SARON))) + if (Creature* brain = instance->GetCreature(DATA_BRAIN_OF_YOGG_SARON)) brain->SetInCombatWithZone(); events.ScheduleEvent(EVENT_SUMMON_CORRUPTOR_TENTACLE, 1, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO); events.ScheduleEvent(EVENT_SUMMON_CONSTRICTOR_TENTACLE, 1, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO); @@ -722,7 +722,7 @@ class boss_sara : public CreatureScript if (_events.IsInPhase(PHASE_ONE)) { - if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) + if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON)) voice->AI()->DoAction(ACTION_PHASE_TRANSFORM); Talk(SAY_SARA_TRANSFORM_1); @@ -818,14 +818,14 @@ class boss_sara : public CreatureScript Talk(SAY_SARA_TRANSFORM_4); DoCast(me, SPELL_FULL_HEAL); me->setFaction(16); - if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) + if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON)) voice->AI()->DoAction(ACTION_PHASE_TWO); if (Creature* mimiron = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_MIMIRON_YS))) mimiron->AI()->DoAction(ACTION_PHASE_TWO); break; case EVENT_TRANSFORM_4: DoCast(me, SPELL_PHASE_2_TRANSFORM); - if (Creature* yogg = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_YOGG_SARON))) + if (Creature* yogg = _instance->GetCreature(BOSS_YOGG_SARON)) DoCast(yogg, SPELL_RIDE_YOGG_SARON_VEHICLE); DoCast(me, SPELL_SHADOWY_BARRIER_SARA); _events.SetPhase(PHASE_TWO); @@ -881,7 +881,7 @@ class boss_sara : public CreatureScript break; } - if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) + if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON)) voice->AI()->JustSummoned(summon); } @@ -948,7 +948,7 @@ class boss_yogg_saron : public CreatureScript { Talk(SAY_YOGG_SARON_DEATH); - if (Creature* creature = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) + if (Creature* creature = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON)) me->Kill(creature); for (uint8 i = DATA_SARA; i <= DATA_BRAIN_OF_YOGG_SARON; ++i) @@ -1065,11 +1065,11 @@ class boss_brain_of_yogg_saron : public CreatureScript DoCast(me, SPELL_BRAIN_HURT_VISUAL, true); me->AddUnitFlag(UnitFlags(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE)); - if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) + if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON)) voice->AI()->DoAction(ACTION_PHASE_THREE); - if (Creature* sara = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SARA))) + if (Creature* sara = _instance->GetCreature(DATA_SARA)) sara->AI()->DoAction(ACTION_PHASE_THREE); - if (Creature* yogg = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(BOSS_YOGG_SARON))) + if (Creature* yogg = _instance->GetCreature(BOSS_YOGG_SARON)) yogg->AI()->DoAction(ACTION_PHASE_THREE); for (uint8 i = DATA_THORIM_YS; i <= DATA_MIMIRON_YS; ++i) @@ -1107,7 +1107,7 @@ class boss_brain_of_yogg_saron : public CreatureScript DoCastAOE(SPELL_SHATTERED_ILLUSION, true); _instance->HandleGameObject(_instance->GetGuidData(GO_BRAIN_ROOM_DOOR_1 + illusion), true); - if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) + if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON)) voice->AI()->DoAction(ACTION_TOGGLE_SHATTERED_ILLUSION); } break; @@ -1214,7 +1214,7 @@ class npc_guardian_of_yogg_saron : public CreatureScript return; // Guardian can be summoned both by Voice of Yogg-Saron and by Ominous Cloud - if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) + if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON)) voice->AI()->JustSummoned(me); } @@ -1317,7 +1317,7 @@ class npc_constrictor_tentacle : public CreatureScript void IsSummonedBy(Unit* /*summoner*/) override { - if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) + if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON)) voice->AI()->JustSummoned(me); } @@ -1408,7 +1408,7 @@ class npc_influence_tentacle : public CreatureScript void JustDied(Unit* /*killer*/) override { - if (Creature* brain = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BRAIN_OF_YOGG_SARON))) + if (Creature* brain = _instance->GetCreature(DATA_BRAIN_OF_YOGG_SARON)) brain->AI()->DoAction(ACTION_TENTACLE_KILLED); } @@ -2779,7 +2779,7 @@ class spell_yogg_saron_induce_madness : public SpellScriptLoader // 64059 GetCaster()->CastSpell((Unit*)NULL, SPELL_SHATTERED_ILLUSION_REMOVE); if (InstanceScript* instance = GetCaster()->GetInstanceScript()) - if (Creature* voice = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) + if (Creature* voice = instance->GetCreature(DATA_VOICE_OF_YOGG_SARON)) voice->AI()->DoAction(ACTION_TOGGLE_SHATTERED_ILLUSION); } @@ -3053,7 +3053,9 @@ class spell_yogg_saron_in_the_maws_of_the_old_god : public SpellScriptLoader SpellCastResult CheckRequirement() { if (InstanceScript* instance = GetCaster()->GetInstanceScript()) - if (Creature* yogg = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(BOSS_YOGG_SARON))) + { + if (Creature* yogg = instance->GetCreature(BOSS_YOGG_SARON)) + { if (yogg->FindCurrentSpellBySpellId(SPELL_DEAFENING_ROAR)) { if (GetCaster()->GetDistance(yogg) > 20.0f) @@ -3061,6 +3063,8 @@ class spell_yogg_saron_in_the_maws_of_the_old_god : public SpellScriptLoader else return SPELL_CAST_OK; } + } + } return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index 3683e9f5ea3..d34a7ac516c 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -79,6 +79,28 @@ MinionData const minionData[] = ObjectData const creatureData[] = { + { NPC_FLAME_LEVIATHAN, BOSS_LEVIATHAN }, + { NPC_IGNIS, BOSS_IGNIS }, + { NPC_RAZORSCALE, BOSS_RAZORSCALE }, + { NPC_XT002, BOSS_XT002 }, + { NPC_KOLOGARN, BOSS_KOLOGARN }, + { NPC_AURIAYA, BOSS_AURIAYA }, + { NPC_HODIR, BOSS_HODIR }, + { NPC_THORIM, BOSS_THORIM }, + { NPC_FREYA, BOSS_FREYA }, + { NPC_MIMIRON, BOSS_MIMIRON }, + { NPC_VEZAX, BOSS_VEZAX }, + { NPC_YOGG_SARON, BOSS_YOGG_SARON }, + { NPC_ALGALON, BOSS_ALGALON }, + + { NPC_EXPEDITION_COMMANDER, DATA_EXPEDITION_COMMANDER }, + { NPC_RAZORSCALE_CONTROLLER, DATA_RAZORSCALE_CONTROL }, + { NPC_COMPUTER, DATA_COMPUTER }, + { NPC_WORLD_TRIGGER_MIMIRON, DATA_MIMIRON_WORLD_TRIGGER }, + { NPC_VOICE_OF_YOGG_SARON, DATA_VOICE_OF_YOGG_SARON }, + { NPC_SARA, DATA_SARA }, + { NPC_BRAIN_OF_YOGG_SARON, DATA_BRAIN_OF_YOGG_SARON }, + { NPC_BRANN_BRONZBEARD_ALG, DATA_BRANN_BRONZEBEARD_ALG }, { NPC_BRANN_BRONZEBEARD_INTRO, DATA_BRANN_BRONZEBEARD_INTRO }, { NPC_LORE_KEEPER_OF_NORGANNON, DATA_LORE_KEEPER_OF_NORGANNON }, { NPC_HIGH_EXPLORER_DELLORAH, DATA_DELLORAH }, @@ -86,6 +108,19 @@ ObjectData const creatureData[] = { 0, 0, } }; +ObjectData const objectData[] = +{ + { GO_MIMIRON_ELEVATOR, DATA_MIMIRON_ELEVATOR }, + { GO_MIMIRON_BUTTON, DATA_MIMIRON_BUTTON }, + { GO_DOODAD_UL_UNIVERSEGLOBE01, DATA_UNIVERSE_GLOBE }, + { GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, DATA_ALGALON_TRAPDOOR }, + { GO_RAZOR_HARPOON_1, GO_RAZOR_HARPOON_1 }, + { GO_RAZOR_HARPOON_2, GO_RAZOR_HARPOON_2 }, + { GO_RAZOR_HARPOON_3, GO_RAZOR_HARPOON_3 }, + { GO_RAZOR_HARPOON_4, GO_RAZOR_HARPOON_4 }, + { 0, 0 } +}; + class instance_ulduar : public InstanceMapScript { public: @@ -100,7 +135,7 @@ class instance_ulduar : public InstanceMapScript LoadBossBoundaries(boundaries); LoadDoorData(doorData); LoadMinionData(minionData); - LoadObjectData(creatureData, nullptr); + LoadObjectData(creatureData, objectData); _algalonTimer = 61; _maxArmorItemLevel = 0; @@ -124,51 +159,29 @@ class instance_ulduar : public InstanceMapScript } // Creatures - ObjectGuid LeviathanGUID; GuidVector LeviathanVehicleGUIDs; - ObjectGuid IgnisGUID; - ObjectGuid RazorscaleGUID; - ObjectGuid RazorscaleController; - ObjectGuid ExpeditionCommanderGUID; - ObjectGuid XT002GUID; + ObjectGuid XTToyPileGUIDs[4]; ObjectGuid AssemblyGUIDs[3]; - ObjectGuid KologarnGUID; - ObjectGuid AuriayaGUID; - ObjectGuid HodirGUID; - ObjectGuid ThorimGUID; - ObjectGuid FreyaGUID; + ObjectGuid ElderGUIDs[3]; ObjectGuid FreyaAchieveTriggerGUID; - ObjectGuid MimironGUID; ObjectGuid MimironVehicleGUIDs[3]; - ObjectGuid MimironComputerGUID; - ObjectGuid MimironWorldTriggerGUID; - ObjectGuid VezaxGUID; - ObjectGuid YoggSaronGUID; - ObjectGuid VoiceOfYoggSaronGUID; - ObjectGuid SaraGUID; - ObjectGuid BrainOfYoggSaronGUID; ObjectGuid KeeperGUIDs[4]; - ObjectGuid AlgalonGUID; - ObjectGuid BrannBronzebeardAlgGUID; // GameObjects ObjectGuid LeviathanGateGUID; - ObjectGuid RazorHarpoonGUIDs[4]; ObjectGuid KologarnChestGUID; ObjectGuid KologarnBridgeGUID; ObjectGuid ThorimChestGUID; ObjectGuid HodirRareCacheGUID; ObjectGuid HodirChestGUID; ObjectGuid MimironTramGUID; - ObjectGuid MimironElevatorGUID; - ObjectGuid MimironButtonGUID; + ObjectGuid BrainRoomDoorGUIDs[3]; ObjectGuid AlgalonSigilDoorGUID[3]; ObjectGuid AlgalonFloorGUID[2]; - ObjectGuid AlgalonUniverseGUID; - ObjectGuid AlgalonTrapdoorGUID; + ObjectGuid GiftOfTheObserverGUID; // Miscellaneous @@ -239,6 +252,8 @@ class instance_ulduar : public InstanceMapScript void OnCreatureCreate(Creature* creature) override { + InstanceScript::OnCreatureCreate(creature); + if (!TeamInInstance) { Map::PlayerList const& Players = instance->GetPlayers(); @@ -249,40 +264,22 @@ class instance_ulduar : public InstanceMapScript switch (creature->GetEntry()) { - case NPC_LEVIATHAN: - LeviathanGUID = creature->GetGUID(); - break; case NPC_SALVAGED_DEMOLISHER: case NPC_SALVAGED_SIEGE_ENGINE: case NPC_SALVAGED_CHOPPER: LeviathanVehicleGUIDs.push_back(creature->GetGUID()); break; - case NPC_IGNIS: - IgnisGUID = creature->GetGUID(); - break; - - // Razorscale - case NPC_RAZORSCALE: - RazorscaleGUID = creature->GetGUID(); - break; - case NPC_RAZORSCALE_CONTROLLER: - RazorscaleController = creature->GetGUID(); - break; - case NPC_EXPEDITION_COMMANDER: - ExpeditionCommanderGUID = creature->GetGUID(); - break; // XT-002 Deconstructor - case NPC_XT002: - XT002GUID = creature->GetGUID(); - break; case NPC_XT_TOY_PILE: for (uint8 i = 0; i < 4; ++i) + { if (!XTToyPileGUIDs[i]) { XTToyPileGUIDs[i] = creature->GetGUID(); break; } + } break; // Assembly of Iron @@ -299,17 +296,7 @@ class instance_ulduar : public InstanceMapScript AddMinion(creature, true); break; - case NPC_KOLOGARN: - KologarnGUID = creature->GetGUID(); - break; - case NPC_AURIAYA: - AuriayaGUID = creature->GetGUID(); - break; - // Hodir - case NPC_HODIR: - HodirGUID = creature->GetGUID(); - break; case NPC_EIVI_NIGHTFEATHER: if (TeamInInstance == HORDE) creature->UpdateEntry(NPC_TOR_GREYCLOUD); @@ -343,14 +330,7 @@ class instance_ulduar : public InstanceMapScript creature->UpdateEntry(NPC_BATTLE_PRIEST_GINA); break; - case NPC_THORIM: - ThorimGUID = creature->GetGUID(); - break; - // Freya - case NPC_FREYA: - FreyaGUID = creature->GetGUID(); - break; case NPC_IRONBRANCH: ElderGUIDs[0] = creature->GetGUID(); if (GetBossState(BOSS_FREYA) == DONE) @@ -371,9 +351,6 @@ class instance_ulduar : public InstanceMapScript break; // Mimiron - case NPC_MIMIRON: - MimironGUID = creature->GetGUID(); - break; case NPC_LEVIATHAN_MKII: MimironVehicleGUIDs[0] = creature->GetGUID(); break; @@ -383,30 +360,8 @@ class instance_ulduar : public InstanceMapScript case NPC_AERIAL_COMMAND_UNIT: MimironVehicleGUIDs[2] = creature->GetGUID(); break; - case NPC_COMPUTER: - MimironComputerGUID = creature->GetGUID(); - break; - case NPC_WORLD_TRIGGER_MIMIRON: - MimironWorldTriggerGUID = creature->GetGUID(); - break; - - case NPC_VEZAX: - VezaxGUID = creature->GetGUID(); - break; // Yogg-Saron - case NPC_YOGG_SARON: - YoggSaronGUID = creature->GetGUID(); - break; - case NPC_VOICE_OF_YOGG_SARON: - VoiceOfYoggSaronGUID = creature->GetGUID(); - break; - case NPC_BRAIN_OF_YOGG_SARON: - BrainOfYoggSaronGUID = creature->GetGUID(); - break; - case NPC_SARA: - SaraGUID = creature->GetGUID(); - break; case NPC_FREYA_YS: KeeperGUIDs[0] = creature->GetGUID(); _summonYSKeeper[0] = false; @@ -436,12 +391,6 @@ class instance_ulduar : public InstanceMapScript break; // Algalon - case NPC_ALGALON: - AlgalonGUID = creature->GetGUID(); - break; - case NPC_BRANN_BRONZBEARD_ALG: - BrannBronzebeardAlgGUID = creature->GetGUID(); - break; //! These creatures are summoned by something else than Algalon //! but need to be controlled/despawned by him - so they need to be //! registered in his summon list @@ -449,7 +398,7 @@ class instance_ulduar : public InstanceMapScript case NPC_ALGALON_STALKER_ASTEROID_TARGET_01: case NPC_ALGALON_STALKER_ASTEROID_TARGET_02: case NPC_UNLEASHED_DARK_MATTER: - if (Creature* algalon = instance->GetCreature(AlgalonGUID)) + if (Creature* algalon = GetCreature(BOSS_ALGALON)) algalon->AI()->JustSummoned(creature); break; } @@ -459,34 +408,34 @@ class instance_ulduar : public InstanceMapScript void OnCreatureRemove(Creature* creature) override { + InstanceScript::OnCreatureRemove(creature); + switch (creature->GetEntry()) { case NPC_XT_TOY_PILE: for (uint8 i = 0; i < 4; ++i) + { if (XTToyPileGUIDs[i] == creature->GetGUID()) { XTToyPileGUIDs[i].Clear(); break; } + } break; case NPC_STEELBREAKER: case NPC_MOLGEIM: case NPC_BRUNDIR: AddMinion(creature, false); break; - case NPC_BRANN_BRONZBEARD_ALG: - if (BrannBronzebeardAlgGUID == creature->GetGUID()) - BrannBronzebeardAlgGUID.Clear(); - break; default: break; } - - InstanceScript::OnCreatureRemove(creature); } void OnGameObjectCreate(GameObject* gameObject) override { + InstanceScript::OnGameObjectCreate(gameObject); + switch (gameObject->GetEntry()) { case GO_KOLOGARN_CHEST_HERO: @@ -513,43 +462,11 @@ class instance_ulduar : public InstanceMapScript case GO_MIMIRON_TRAM: MimironTramGUID = gameObject->GetGUID(); break; - case GO_MIMIRON_ELEVATOR: - MimironElevatorGUID = gameObject->GetGUID(); - break; - case GO_MIMIRON_BUTTON: - MimironButtonGUID = gameObject->GetGUID(); - break; case GO_LEVIATHAN_GATE: LeviathanGateGUID = gameObject->GetGUID(); if (GetBossState(BOSS_LEVIATHAN) == DONE) gameObject->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); break; - case GO_LEVIATHAN_DOOR: - case GO_XT_002_DOOR: - case GO_IRON_COUNCIL_DOOR: - case GO_ARCHIVUM_DOOR: - case GO_HODIR_ENTRANCE: - case GO_HODIR_DOOR: - case GO_HODIR_ICE_DOOR: - case GO_MIMIRON_DOOR_1: - case GO_MIMIRON_DOOR_2: - case GO_MIMIRON_DOOR_3: - case GO_VEZAX_DOOR: - case GO_YOGG_SARON_DOOR: - AddDoor(gameObject, true); - break; - case GO_RAZOR_HARPOON_1: - RazorHarpoonGUIDs[0] = gameObject->GetGUID(); - break; - case GO_RAZOR_HARPOON_2: - RazorHarpoonGUIDs[1] = gameObject->GetGUID(); - break; - case GO_RAZOR_HARPOON_3: - RazorHarpoonGUIDs[2] = gameObject->GetGUID(); - break; - case GO_RAZOR_HARPOON_4: - RazorHarpoonGUIDs[3] = gameObject->GetGUID(); - break; case GO_MOLE_MACHINE: if (GetBossState(BOSS_RAZORSCALE) == IN_PROGRESS) gameObject->SetGoState(GO_STATE_ACTIVE); @@ -580,23 +497,12 @@ class instance_ulduar : public InstanceMapScript break; case GO_DOODAD_UL_SIGILDOOR_03: AlgalonSigilDoorGUID[2] = gameObject->GetGUID(); - AddDoor(gameObject, true); break; case GO_DOODAD_UL_UNIVERSEFLOOR_01: AlgalonFloorGUID[0] = gameObject->GetGUID(); - AddDoor(gameObject, true); break; case GO_DOODAD_UL_UNIVERSEFLOOR_02: AlgalonFloorGUID[1] = gameObject->GetGUID(); - AddDoor(gameObject, true); - break; - case GO_DOODAD_UL_UNIVERSEGLOBE01: - AlgalonUniverseGUID = gameObject->GetGUID(); - AddDoor(gameObject, true); - break; - case GO_DOODAD_UL_ULDUAR_TRAPDOOR_03: - AlgalonTrapdoorGUID = gameObject->GetGUID(); - AddDoor(gameObject, true); break; case GO_GIFT_OF_THE_OBSERVER_10: case GO_GIFT_OF_THE_OBSERVER_25: @@ -607,40 +513,12 @@ class instance_ulduar : public InstanceMapScript } } - void OnGameObjectRemove(GameObject* gameObject) override - { - switch (gameObject->GetEntry()) - { - case GO_LEVIATHAN_DOOR: - case GO_XT_002_DOOR: - case GO_IRON_COUNCIL_DOOR: - case GO_ARCHIVUM_DOOR: - case GO_HODIR_ENTRANCE: - case GO_HODIR_DOOR: - case GO_HODIR_ICE_DOOR: - case GO_MIMIRON_DOOR_1: - case GO_MIMIRON_DOOR_2: - case GO_MIMIRON_DOOR_3: - case GO_VEZAX_DOOR: - case GO_YOGG_SARON_DOOR: - case GO_DOODAD_UL_SIGILDOOR_03: - case GO_DOODAD_UL_UNIVERSEFLOOR_01: - case GO_DOODAD_UL_UNIVERSEFLOOR_02: - case GO_DOODAD_UL_UNIVERSEGLOBE01: - case GO_DOODAD_UL_ULDUAR_TRAPDOOR_03: - AddDoor(gameObject, false); - break; - default: - break; - } - } - void OnUnitDeath(Unit* unit) override { // Champion/Conqueror of Ulduar if (unit->GetTypeId() == TYPEID_PLAYER) { - for (uint8 i = 0; i < BOSS_ALGALON; i++) + for (uint8 i = 0; i < BOSS_ALGALON; ++i) { if (GetBossState(i) == IN_PROGRESS) { @@ -686,27 +564,27 @@ class instance_ulduar : public InstanceMapScript void ProcessEvent(WorldObject* /*gameObject*/, uint32 eventId) override { - // Flame Leviathan's Tower Event triggers - Creature* FlameLeviathan = instance->GetCreature(LeviathanGUID); - switch (eventId) { + // Flame Leviathan's Tower Event triggers case EVENT_TOWER_OF_STORM_DESTROYED: - if (FlameLeviathan && FlameLeviathan->IsAlive()) - FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_STORM_DESTROYED); + if (Creature* flameLeviathan = GetCreature(BOSS_LEVIATHAN)) + flameLeviathan->AI()->DoAction(ACTION_TOWER_OF_STORM_DESTROYED); break; case EVENT_TOWER_OF_FROST_DESTROYED: - if (FlameLeviathan && FlameLeviathan->IsAlive()) - FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_FROST_DESTROYED); + if (Creature* flameLeviathan = GetCreature(BOSS_LEVIATHAN)) + flameLeviathan->AI()->DoAction(ACTION_TOWER_OF_FROST_DESTROYED); break; case EVENT_TOWER_OF_FLAMES_DESTROYED: - if (FlameLeviathan && FlameLeviathan->IsAlive()) - FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_FLAMES_DESTROYED); + if (Creature* flameLeviathan = GetCreature(BOSS_LEVIATHAN)) + flameLeviathan->AI()->DoAction(ACTION_TOWER_OF_FLAMES_DESTROYED); break; case EVENT_TOWER_OF_LIFE_DESTROYED: - if (FlameLeviathan && FlameLeviathan->IsAlive()) - FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_LIFE_DESTROYED); + if (Creature* flameLeviathan = GetCreature(BOSS_LEVIATHAN)) + flameLeviathan->AI()->DoAction(ACTION_TOWER_OF_LIFE_DESTROYED); break; + + // Yogg-Saron Event triggers case EVENT_ACTIVATE_SANITY_WELL: if (Creature* freya = instance->GetCreature(KeeperGUIDs[0])) freya->AI()->DoAction(4/*ACTION_SANITY_WELLS*/); @@ -851,9 +729,9 @@ class instance_ulduar : public InstanceMapScript HodirRareCacheData = data; if (!HodirRareCacheData) { - if (Creature* Hodir = instance->GetCreature(HodirGUID)) + if (Creature* hodir = GetCreature(BOSS_HODIR)) if (GameObject* gameObject = instance->GetGameObject(HodirRareCacheGUID)) - Hodir->RemoveGameObject(gameObject, false); + hodir->RemoveGameObject(gameObject, false); } break; case DATA_UNBROKEN: @@ -888,30 +766,7 @@ class instance_ulduar : public InstanceMapScript { switch (data) { - case BOSS_LEVIATHAN: - return LeviathanGUID; - case BOSS_IGNIS: - return IgnisGUID; - - // Razorscale - case BOSS_RAZORSCALE: - return RazorscaleGUID; - case DATA_RAZORSCALE_CONTROL: - return RazorscaleController; - case DATA_EXPEDITION_COMMANDER: - return ExpeditionCommanderGUID; - case GO_RAZOR_HARPOON_1: - return RazorHarpoonGUIDs[0]; - case GO_RAZOR_HARPOON_2: - return RazorHarpoonGUIDs[1]; - case GO_RAZOR_HARPOON_3: - return RazorHarpoonGUIDs[2]; - case GO_RAZOR_HARPOON_4: - return RazorHarpoonGUIDs[3]; - // XT-002 Deconstructor - case BOSS_XT002: - return XT002GUID; case DATA_TOY_PILE_0: case DATA_TOY_PILE_1: case DATA_TOY_PILE_2: @@ -926,18 +781,7 @@ class instance_ulduar : public InstanceMapScript case DATA_BRUNDIR: return AssemblyGUIDs[2]; - case BOSS_KOLOGARN: - return KologarnGUID; - case BOSS_AURIAYA: - return AuriayaGUID; - case BOSS_HODIR: - return HodirGUID; - case BOSS_THORIM: - return ThorimGUID; - // Freya - case BOSS_FREYA: - return FreyaGUID; case BOSS_BRIGHTLEAF: return ElderGUIDs[0]; case BOSS_IRONBRANCH: @@ -946,35 +790,14 @@ class instance_ulduar : public InstanceMapScript return ElderGUIDs[2]; // Mimiron - case BOSS_MIMIRON: - return MimironGUID; case DATA_LEVIATHAN_MK_II: return MimironVehicleGUIDs[0]; case DATA_VX_001: return MimironVehicleGUIDs[1]; case DATA_AERIAL_COMMAND_UNIT: return MimironVehicleGUIDs[2]; - case DATA_COMPUTER: - return MimironComputerGUID; - case DATA_MIMIRON_WORLD_TRIGGER: - return MimironWorldTriggerGUID; - case DATA_MIMIRON_ELEVATOR: - return MimironElevatorGUID; - case DATA_MIMIRON_BUTTON: - return MimironButtonGUID; - - case BOSS_VEZAX: - return VezaxGUID; // Yogg-Saron - case BOSS_YOGG_SARON: - return YoggSaronGUID; - case DATA_VOICE_OF_YOGG_SARON: - return VoiceOfYoggSaronGUID; - case DATA_BRAIN_OF_YOGG_SARON: - return BrainOfYoggSaronGUID; - case DATA_SARA: - return SaraGUID; case GO_BRAIN_ROOM_DOOR_1: return BrainRoomDoorGUIDs[0]; case GO_BRAIN_ROOM_DOOR_2: @@ -991,8 +814,6 @@ class instance_ulduar : public InstanceMapScript return KeeperGUIDs[3]; // Algalon - case BOSS_ALGALON: - return AlgalonGUID; case DATA_SIGILDOOR_01: return AlgalonSigilDoorGUID[0]; case DATA_SIGILDOOR_02: @@ -1003,15 +824,9 @@ class instance_ulduar : public InstanceMapScript return AlgalonFloorGUID[0]; case DATA_UNIVERSE_FLOOR_02: return AlgalonFloorGUID[1]; - case DATA_UNIVERSE_GLOBE: - return AlgalonUniverseGUID; - case DATA_ALGALON_TRAPDOOR: - return AlgalonTrapdoorGUID; - case DATA_BRANN_BRONZEBEARD_ALG: - return BrannBronzebeardAlgGUID; } - return ObjectGuid::Empty; + return InstanceScript::GetGuidData(data); } uint32 GetData(uint32 type) const override @@ -1179,7 +994,7 @@ class instance_ulduar : public InstanceMapScript { DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 0); _events.CancelEvent(EVENT_UPDATE_ALGALON_TIMER); - if (Creature* algalon = instance->GetCreature(AlgalonGUID)) + if (Creature* algalon = GetCreature(BOSS_ALGALON)) algalon->AI()->DoAction(EVENT_DESPAWN_ALGALON); } break; @@ -1200,8 +1015,8 @@ class instance_ulduar : public InstanceMapScript } break; case EVENT_LEVIATHAN_BREAK_DOOR: - if (Creature* Leviathan = instance->GetCreature(LeviathanGUID)) - Leviathan->AI()->DoAction(ACTION_MOVE_TO_CENTER_POSITION); + if (Creature* leviathan = GetCreature(BOSS_LEVIATHAN)) + leviathan->AI()->DoAction(ACTION_MOVE_TO_CENTER_POSITION); if (GameObject* gameObject = instance->GetGameObject(LeviathanGateGUID)) gameObject->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); break; -- cgit v1.2.3 From 6f523b4fb65331acca28b5ac00f14551427d038d Mon Sep 17 00:00:00 2001 From: Gustavo Date: Fri, 24 Mar 2017 08:59:04 -0300 Subject: Core/Scripts: minor fixes in boss_the_lich_king (#19311) Closes #4427 Closes #7091 (cherry picked from commit 2792046dc7a229180d27dfdc4ce37ccfb84c8a27) --- .../2020_04_16_00_world_2017_03_24_00_world.sql | 14 + src/server/game/Spells/SpellMgr.cpp | 8 +- .../IcecrownCitadel/boss_the_lich_king.cpp | 316 +++++++++++++-------- .../Northrend/IcecrownCitadel/icecrown_citadel.h | 4 +- 4 files changed, 215 insertions(+), 127 deletions(-) create mode 100644 sql/updates/world/master/2020_04_16_00_world_2017_03_24_00_world.sql (limited to 'src/server/scripts') diff --git a/sql/updates/world/master/2020_04_16_00_world_2017_03_24_00_world.sql b/sql/updates/world/master/2020_04_16_00_world_2017_03_24_00_world.sql new file mode 100644 index 00000000000..84277ee86c2 --- /dev/null +++ b/sql/updates/world/master/2020_04_16_00_world_2017_03_24_00_world.sql @@ -0,0 +1,14 @@ +-- Correct speed for Wicked Spirits and Spirit Bombs +UPDATE `creature_template` SET `speed_walk`=1.2, `speed_run`=0.428571 WHERE `entry` IN(39189,39190,39287,39288,39289); +UPDATE `creature_template` SET `InhabitType`=4, `HoverHeight`=4 WHERE `entry` IN(36609,39120,39121,39122); + +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_the_lich_king_harvest_souls_teleport'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(73655,'spell_the_lich_king_harvest_souls_teleport'); + +DELETE FROM `spell_custom_attr` WHERE `entry` IN(69409,73797,73798,73799); +INSERT INTO `spell_custom_attr` (`entry`,`attributes`) VALUES +(69409,32768), +(73797,32768), +(73798,32768), +(73799,32768); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index fbd5235cdfa..3c15a374d1b 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3418,14 +3418,16 @@ void SpellMgr::LoadSpellInfoCorrections() // Jump ApplySpellFix({ 71809 }, [](SpellInfo* spellInfo) { - spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(3); // 20yd - const_cast(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_25_YARDS); // 25yd + spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(5); // 40yd + const_cast(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_10_YARDS); // 10yd + const_cast(spellInfo->GetEffect(EFFECT_0))->MiscValue = 190; }); // Broken Frostmourne ApplySpellFix({ 72405 }, [](SpellInfo* spellInfo) { - const_cast(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd + const_cast(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_20_YARDS); // 20yd + spellInfo->AttributesEx |= SPELL_ATTR1_NO_THREAT; }); // ENDOF ICECROWN CITADEL SPELLS diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index e525c2efa45..94bf769b771 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -197,77 +197,80 @@ enum Events { // The Lich King // intro events - EVENT_INTRO_MOVE_1 = 1, - EVENT_INTRO_MOVE_2 = 2, - EVENT_INTRO_MOVE_3 = 3, - EVENT_INTRO_TALK_1 = 4, - EVENT_EMOTE_CAST_SHOUT = 5, - EVENT_INTRO_EMOTE_1 = 6, - EVENT_INTRO_CHARGE = 7, - EVENT_INTRO_CAST_FREEZE = 8, - EVENT_FINISH_INTRO = 9, + EVENT_INTRO_MOVE_1 = 1, + EVENT_INTRO_MOVE_2, + EVENT_INTRO_MOVE_3, + EVENT_INTRO_TALK_1, + EVENT_EMOTE_CAST_SHOUT, + EVENT_INTRO_EMOTE_1, + EVENT_INTRO_CHARGE, + EVENT_INTRO_CAST_FREEZE, + EVENT_FINISH_INTRO, // combat events - EVENT_SUMMON_SHAMBLING_HORROR = 10, - EVENT_SUMMON_DRUDGE_GHOUL = 11, - EVENT_INFEST = 12, - EVENT_NECROTIC_PLAGUE = 13, - EVENT_SHADOW_TRAP = 14, // heroic only - EVENT_SOUL_REAPER = 15, - EVENT_DEFILE = 16, - EVENT_HARVEST_SOUL = 17, // normal mode only - EVENT_PAIN_AND_SUFFERING = 18, - EVENT_SUMMON_ICE_SPHERE = 19, - EVENT_SUMMON_RAGING_SPIRIT = 20, - EVENT_QUAKE = 21, - EVENT_SUMMON_VALKYR = 22, - EVENT_GRAB_PLAYER = 23, - EVENT_MOVE_TO_DROP_POS = 24, - EVENT_LIFE_SIPHON = 25, // heroic only - EVENT_START_ATTACK = 26, - EVENT_QUAKE_2 = 27, - EVENT_VILE_SPIRITS = 28, - EVENT_HARVEST_SOULS = 29, // heroic only - EVENT_BERSERK = 30, - EVENT_SOUL_RIP = 31, - EVENT_DESTROY_SOUL = 32, - EVENT_FROSTMOURNE_TALK_1 = 33, - EVENT_FROSTMOURNE_TALK_2 = 34, - EVENT_FROSTMOURNE_TALK_3 = 35, - EVENT_TELEPORT_BACK = 36, - EVENT_FROSTMOURNE_HEROIC = 37, - EVENT_OUTRO_TALK_1 = 38, - EVENT_OUTRO_TALK_2 = 39, - EVENT_OUTRO_EMOTE_TALK = 40, - EVENT_OUTRO_TALK_3 = 41, - EVENT_OUTRO_MOVE_CENTER = 42, - EVENT_OUTRO_TALK_4 = 43, - EVENT_OUTRO_RAISE_DEAD = 44, - EVENT_OUTRO_TALK_5 = 45, - EVENT_OUTRO_BLESS = 46, - EVENT_OUTRO_REMOVE_ICE = 47, - EVENT_OUTRO_MOVE_1 = 48, - EVENT_OUTRO_JUMP = 49, - EVENT_OUTRO_TALK_6 = 50, - EVENT_OUTRO_KNOCK_BACK = 51, - EVENT_OUTRO_SOUL_BARRAGE = 52, - EVENT_OUTRO_SUMMON_TERENAS = 53, - EVENT_OUTRO_TERENAS_TALK_1 = 54, - EVENT_OUTRO_TERENAS_TALK_2 = 55, - EVENT_OUTRO_TALK_7 = 56, - EVENT_OUTRO_TALK_8 = 57, + EVENT_SUMMON_SHAMBLING_HORROR, + EVENT_SUMMON_DRUDGE_GHOUL, + EVENT_INFEST, + EVENT_NECROTIC_PLAGUE, + EVENT_SHADOW_TRAP, // heroic only + EVENT_SOUL_REAPER, + EVENT_DEFILE, + EVENT_HARVEST_SOUL, // normal mode only + EVENT_PAIN_AND_SUFFERING, + EVENT_SUMMON_ICE_SPHERE, + EVENT_SUMMON_RAGING_SPIRIT, + EVENT_QUAKE, + EVENT_SUMMON_VALKYR, + EVENT_GRAB_PLAYER, + EVENT_MOVE_TO_DROP_POS, + EVENT_LIFE_SIPHON, // heroic only + EVENT_MOVE_TO_CENTER, // heroic only + EVENT_START_ATTACK, + EVENT_SUMMON_RAGING_SPIRIT_2, + EVENT_QUAKE_2, + EVENT_VILE_SPIRITS, + EVENT_HARVEST_SOULS, // heroic only + EVENT_BERSERK, + EVENT_SOUL_RIP, + EVENT_DESTROY_SOUL, + EVENT_FROSTMOURNE_TALK_1, + EVENT_FROSTMOURNE_TALK_2, + EVENT_FROSTMOURNE_TALK_3, + EVENT_TELEPORT_BACK, + EVENT_FROSTMOURNE_HEROIC, + EVENT_OUTRO_TALK_1, + EVENT_OUTRO_TALK_2, + EVENT_OUTRO_EMOTE_TALK, + EVENT_OUTRO_TALK_3, + EVENT_OUTRO_MOVE_CENTER, + EVENT_OUTRO_TALK_4, + EVENT_OUTRO_RAISE_DEAD, + EVENT_OUTRO_TALK_5, + EVENT_OUTRO_BLESS, + EVENT_OUTRO_REMOVE_ICE, + EVENT_OUTRO_MOVE_1, + EVENT_OUTRO_JUMP, + EVENT_OUTRO_TALK_6, + EVENT_OUTRO_KNOCK_BACK, + EVENT_OUTRO_SOUL_BARRAGE, + EVENT_OUTRO_SUMMON_TERENAS, + EVENT_OUTRO_TERENAS_TALK_1, + EVENT_OUTRO_TERENAS_TALK_2, + EVENT_OUTRO_TALK_7, + EVENT_OUTRO_TALK_8, // Shambling Horror - EVENT_SHOCKWAVE = 58, - EVENT_ENRAGE = 59, + EVENT_SHOCKWAVE, + EVENT_ENRAGE, // Raging Spirit - EVENT_SOUL_SHRIEK = 60, + EVENT_SOUL_SHRIEK, + EVENT_SET_AGRESSIVE, // Strangulate Vehicle (Harvest Soul) - EVENT_TELEPORT = 61, - EVENT_MOVE_TO_LICH_KING = 62, - EVENT_DESPAWN_SELF = 63, + EVENT_TELEPORT, + EVENT_MOVE_TO_LICH_KING, + EVENT_DESPAWN_SELF, }; enum EventGroups @@ -320,6 +323,7 @@ enum MovePoints POINT_OUTRO_JUMP = 11, POINT_LK_OUTRO_2 = 12, POINT_GROUND = 13, + POINT_SIPHON = 14, POINT_CHARGE = 1003, // globally used number for charge spell effects }; @@ -334,12 +338,14 @@ enum EncounterActions ACTION_SUMMON_TERENAS = 6, ACTION_FINISH_OUTRO = 7, ACTION_TELEPORT_BACK = 8, + ACTION_DISABLE_RAGING = 9 }; enum MiscData { LIGHT_SNOWSTORM = 2490, LIGHT_SOULSTORM = 2508, + LIGHT_FOG = 2509, MUSIC_FROZEN_THRONE = 17457, MUSIC_SPECIAL = 17458, // Summon Shambling Horror, Remorseless Winter, Quake, Summon Val'kyr Periodic, Harvest Soul, Vile Spirits @@ -499,17 +505,7 @@ class boss_the_lich_king : public CreatureScript _vileSpiritExplosions = 0; } - void InitializeAI() override - { - SetupEncounter(); - } - - void JustRespawned() override - { - SetupEncounter(); - } - - void SetupEncounter() + void Reset() override { _Reset(); me->AddUnitFlag(UNIT_FLAG_IMMUNE_TO_PC); @@ -524,9 +520,10 @@ class boss_the_lich_king : public CreatureScript Cell::VisitGridObjects(me, worker, 333.0f); // Reset any light override - me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, 0, 5000); + me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, 0, 5000); - me->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING_LK, TirionSpawn, TEMPSUMMON_MANUAL_DESPAWN); + if (!ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) + me->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING_LK, TirionSpawn, TEMPSUMMON_MANUAL_DESPAWN); } void JustDied(Unit* /*killer*/) override @@ -538,6 +535,8 @@ class boss_the_lich_king : public CreatureScript me->GetMotionMaster()->MoveFall(); if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f)) frostmourne->DespawnOrUnsummon(); + me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_FOG, 5000); + me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_FOG, 0.0f); } void EnterCombat(Unit* target) override @@ -550,6 +549,7 @@ class boss_the_lich_king : public CreatureScript } me->setActive(true); + me->SetCombatPulseDelay(5); DoZoneInCombat(); events.SetPhase(PHASE_ONE); @@ -592,7 +592,7 @@ class boss_the_lich_king : public CreatureScript case ACTION_START_ENCOUNTER: instance->SetBossState(DATA_THE_LICH_KING, IN_PROGRESS); Talk(SAY_LK_INTRO_1); - me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FROZEN_THRONE); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FROZEN_THRONE); // schedule talks me->SetStandState(UNIT_STAND_STATE_STAND); events.ScheduleEvent(EVENT_INTRO_MOVE_1, 4000); @@ -601,10 +601,10 @@ class boss_the_lich_king : public CreatureScript events.ScheduleEvent(EVENT_START_ATTACK, 5000); break; case ACTION_PLAY_MUSIC: - me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FINAL); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FINAL); break; case ACTION_RESTORE_LIGHT: - me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, 0, 5000); + me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, 0, 5000); break; case ACTION_BREAK_FROSTMOURNE: me->CastSpell((Unit*)NULL, SPELL_SUMMON_BROKEN_FROSTMOURNE, TRIGGERED_IGNORE_CAST_IN_PROGRESS); @@ -666,6 +666,7 @@ class boss_the_lich_king : public CreatureScript events.SetPhase(PHASE_TRANSITION); me->SetReactState(REACT_PASSIVE); me->AttackStop(); + me->InterruptNonMeleeSpells(true); me->GetMotionMaster()->MovePoint(POINT_CENTER_1, CenterPosition); return; } @@ -675,6 +676,7 @@ class boss_the_lich_king : public CreatureScript events.SetPhase(PHASE_TRANSITION); me->SetReactState(REACT_PASSIVE); me->AttackStop(); + me->InterruptNonMeleeSpells(true); me->GetMotionMaster()->MovePoint(POINT_CENTER_2, CenterPosition); return; } @@ -686,7 +688,7 @@ class boss_the_lich_king : public CreatureScript events.Reset(); events.SetPhase(PHASE_OUTRO); summons.DespawnAll(); - me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FURY_OF_FROSTMOURNE); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FURY_OF_FROSTMOURNE); me->InterruptNonMeleeSpells(true); me->CastSpell((Unit*)NULL, SPELL_FURY_OF_FROSTMOURNE, TRIGGERED_NONE); me->SetWalk(true); @@ -738,8 +740,8 @@ class boss_the_lich_king : public CreatureScript { summon->CastSpell((Unit*)NULL, SPELL_BROKEN_FROSTMOURNE, true); - me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, LIGHT_SOULSTORM, 10000); - me->GetMap()->SetZoneWeather(AREA_THE_FROZEN_THRONE, WEATHER_STATE_BLACKSNOW, 0.5f); + me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_SOULSTORM, 10000); + me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_BLACKSNOW, 0.5f); events.ScheduleEvent(EVENT_OUTRO_SOUL_BARRAGE, 5000, 0, PHASE_OUTRO); return; @@ -793,8 +795,8 @@ class boss_the_lich_king : public CreatureScript { if (spell->Id == REMORSELESS_WINTER_1 || spell->Id == REMORSELESS_WINTER_2) { - me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, LIGHT_SNOWSTORM, 5000); - me->GetMap()->SetZoneWeather(AREA_THE_FROZEN_THRONE, WEATHER_STATE_LIGHT_SNOW, 0.5f); + me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_SNOWSTORM, 5000); + me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_LIGHT_SNOW, 0.5f); } } @@ -820,13 +822,14 @@ class boss_the_lich_king : public CreatureScript case POINT_CENTER_1: me->SetFacingTo(0.0f, true); Talk(SAY_LK_REMORSELESS_WINTER); - me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); DoCast(me, SPELL_REMORSELESS_WINTER_1); + summons.DespawnEntry(NPC_SHADOW_TRAP); events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions events.ScheduleEvent(EVENT_QUAKE, 62500, 0, PHASE_TRANSITION); events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 4000, 0, PHASE_TRANSITION); events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 8000, 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 3000, 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 6000, 0, PHASE_TRANSITION); events.ScheduleEvent(EVENT_SUMMON_VALKYR, 78000, 0, PHASE_TWO); events.ScheduleEvent(EVENT_INFEST, 70000, 0, PHASE_TWO); events.ScheduleEvent(EVENT_DEFILE, 97000, 0, PHASE_TWO); @@ -835,14 +838,14 @@ class boss_the_lich_king : public CreatureScript case POINT_CENTER_2: me->SetFacingTo(0.0f, true); Talk(SAY_LK_REMORSELESS_WINTER); - me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); DoCast(me, SPELL_REMORSELESS_WINTER_2); summons.DespawnEntry(NPC_VALKYR_SHADOWGUARD); events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions events.ScheduleEvent(EVENT_QUAKE_2, 62500, 0, PHASE_TRANSITION); events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 6000, 0, PHASE_TRANSITION); events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 8000, 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 5000, 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT_2, 5000, 0, PHASE_TRANSITION); events.ScheduleEvent(EVENT_DEFILE, 95500, 0, PHASE_THREE); events.ScheduleEvent(EVENT_SOUL_REAPER, 99500, 0, PHASE_THREE); events.ScheduleEvent(EVENT_VILE_SPIRITS, 79500, EVENT_GROUP_VILE_SPIRITS, PHASE_THREE); @@ -921,7 +924,7 @@ class boss_the_lich_king : public CreatureScript break; case EVENT_SUMMON_SHAMBLING_HORROR: DoCast(me, SPELL_SUMMON_SHAMBLING_HORROR); - me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); events.ScheduleEvent(EVENT_SUMMON_SHAMBLING_HORROR, 60000, 0, PHASE_ONE); break; case EVENT_SUMMON_DRUDGE_GHOUL: @@ -977,24 +980,29 @@ class boss_the_lich_king : public CreatureScript me->CastSpell(target, SPELL_RAGING_SPIRIT, TRIGGERED_NONE); events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, urand(22000, 23000), 0, PHASE_TRANSITION); break; + case EVENT_SUMMON_RAGING_SPIRIT_2: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + me->CastSpell(target, SPELL_RAGING_SPIRIT, TRIGGERED_NONE); + events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 18000, 0, PHASE_TRANSITION); + break; case EVENT_QUAKE: events.SetPhase(PHASE_TWO); me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes DoCastAOE(SPELL_QUAKE); - me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); Talk(SAY_LK_QUAKE); break; case EVENT_QUAKE_2: events.SetPhase(PHASE_THREE); me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes DoCastAOE(SPELL_QUAKE); - me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); Talk(SAY_LK_QUAKE); break; case EVENT_SUMMON_VALKYR: - me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); Talk(SAY_LK_SUMMON_VALKYR); - DoCastAOE(SUMMON_VALKYR); + DoCastAOE(SUMMON_VALKYR, true); events.ScheduleEvent(EVENT_SUMMON_VALKYR, urand(45000, 50000), 0, PHASE_TWO); break; case EVENT_START_ATTACK: @@ -1003,7 +1011,7 @@ class boss_the_lich_king : public CreatureScript events.SetPhase(PHASE_THREE); break; case EVENT_VILE_SPIRITS: - me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); DoCastAOE(SPELL_VILE_SPIRITS); events.ScheduleEvent(EVENT_VILE_SPIRITS, urand(35000, 40000), EVENT_GROUP_VILE_SPIRITS, PHASE_THREE); break; @@ -1019,6 +1027,25 @@ class boss_the_lich_king : public CreatureScript events.RescheduleEvent(EVENT_SOUL_REAPER, urand(57000, 62000), 0, PHASE_THREE); events.ScheduleEvent(EVENT_START_ATTACK, 49000); events.ScheduleEvent(EVENT_FROSTMOURNE_HEROIC, 6500); + for (ObjectGuid guid : summons) + { + if (Creature* summon = ObjectAccessor::GetCreature(*me, guid)) + { + if (summon->GetEntry() == NPC_VILE_SPIRIT) + { + summon->m_Events.KillAllEvents(true); + summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(56500)); + summon->SetReactState(REACT_PASSIVE); + summon->CombatStop(true); + summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_MOVE_SEARCH); + summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_DAMAGE_SEARCH); + summon->GetMotionMaster()->MoveTargetedHome(); + summon->GetMotionMaster()->MoveRandom(10.0f); + } + else if (summon->GetEntry() == NPC_RAGING_SPIRIT) + summon->AI()->DoAction(ACTION_DISABLE_RAGING); + } + } break; case EVENT_FROSTMOURNE_HEROIC: if (TempSummon* terenas = me->GetMap()->SummonCreature(NPC_TERENAS_MENETHIL_FROSTMOURNE_H, TerenasSpawnHeroic, NULL, 50000)) @@ -1034,18 +1061,6 @@ class boss_the_lich_king : public CreatureScript spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_2, true); // summons bombs on players spawner->m_Events.AddEvent(new TriggerWickedSpirit(spawner), spawner->m_Events.CalculateTime(3000)); } - - for (SummonList::iterator i = summons.begin(); i != summons.end(); ++i) - { - Creature* summon = ObjectAccessor::GetCreature(*me, *i); - if (summon && summon->GetEntry() == NPC_VILE_SPIRIT) - { - summon->m_Events.KillAllEvents(true); - summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(50000)); - summon->GetMotionMaster()->MoveRandom(10.0f); - summon->SetReactState(REACT_PASSIVE); - } - } } break; case EVENT_OUTRO_TALK_1: @@ -1074,7 +1089,7 @@ class boss_the_lich_king : public CreatureScript case EVENT_OUTRO_RAISE_DEAD: DoCastAOE(SPELL_RAISE_DEAD); me->ClearUnitState(UNIT_STATE_CASTING); - me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FINAL); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FINAL); break; case EVENT_OUTRO_TALK_5: Talk(SAY_LK_OUTRO_5); @@ -1189,7 +1204,7 @@ class npc_tirion_fordring_tft : public CreatureScript if (spell->Id == SPELL_ICE_LOCK) me->SetFacingTo(3.085098f); else if (spell->Id == SPELL_BROKEN_FROSTMOURNE_KNOCK) - SetEquipmentSlots(true); // remove glow on ashbringer + me->LoadEquipment(1); // remove glow on ashbringer } void sGossipSelect(Player* /*player*/, uint32 menuId, uint32 gossipListId) override @@ -1357,7 +1372,9 @@ class npc_raging_spirit : public CreatureScript void Reset() override { + me->SetReactState(REACT_PASSIVE); _events.Reset(); + _events.ScheduleEvent(EVENT_SET_AGRESSIVE, 2000); _events.ScheduleEvent(EVENT_SOUL_SHRIEK, urand(12000, 15000)); DoCast(me, SPELL_PLAGUE_AVOIDANCE, true); DoCast(me, SPELL_RAGING_SPIRIT_VISUAL, true); @@ -1367,6 +1384,19 @@ class npc_raging_spirit : public CreatureScript DoCast(me, SPELL_BOSS_HITTIN_YA, true); } + void DoAction(int32 action) override + { + if (action == ACTION_DISABLE_RAGING) + { + _events.Reset(); + _events.SetPhase(PHASE_FROSTMOURNE); + _events.ScheduleEvent(EVENT_SET_AGRESSIVE, 52000); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + me->InterruptNonMeleeSpells(true); + } + } + void IsSummonedBy(Unit* /*summoner*/) override { // player is the spellcaster so register summon manually @@ -1384,7 +1414,7 @@ class npc_raging_spirit : public CreatureScript void UpdateAI(uint32 diff) override { - if (!UpdateVictim()) + if (!_events.IsInPhase(PHASE_FROSTMOURNE) && !UpdateVictim()) return; _events.Update(diff); @@ -1400,6 +1430,14 @@ class npc_raging_spirit : public CreatureScript DoCastAOE(SPELL_SOUL_SHRIEK); _events.ScheduleEvent(EVENT_SOUL_SHRIEK, urand(12000, 15000)); break; + case EVENT_SET_AGRESSIVE: + me->SetReactState(REACT_AGGRESSIVE); + if (_events.IsInPhase(PHASE_FROSTMOURNE)) + { + _events.SetPhase(PHASE_THREE); + _events.ScheduleEvent(EVENT_SOUL_SHRIEK, urand(12000, 15000)); + } + break; default: break; } @@ -1454,19 +1492,18 @@ class npc_valkyr_shadowguard : public CreatureScript if (me->HealthBelowPctDamaged(50, damage)) { - _events.Reset(); DoCastAOE(SPELL_EJECT_ALL_PASSENGERS); - me->GetMotionMaster()->MoveTargetedHome(); - me->ClearUnitState(UNIT_STATE_EVADE); + ScheduleHeroicEvents(); } } - void JustReachedHome() override + void ScheduleHeroicEvents() { - // schedule siphon life event (heroic only) DoZoneInCombat(); _events.Reset(); + _events.ScheduleEvent(EVENT_MOVE_TO_CENTER, 1); _events.ScheduleEvent(EVENT_LIFE_SIPHON, 2000); + me->ClearUnitState(UNIT_STATE_EVADE); } void AttackStart(Unit* /*target*/) override @@ -1482,7 +1519,10 @@ class npc_valkyr_shadowguard : public CreatureScript { case POINT_DROP_PLAYER: DoCastAOE(SPELL_EJECT_ALL_PASSENGERS); - me->DespawnOrUnsummon(1000); + if (IsHeroic()) + ScheduleHeroicEvents(); + else + me->DespawnOrUnsummon(1000); break; case POINT_CHARGE: if (Player* target = ObjectAccessor::GetPlayer(*me, _grabbedPlayer)) @@ -1545,6 +1585,13 @@ class npc_valkyr_shadowguard : public CreatureScript DoCast(target, SPELL_LIFE_SIPHON); _events.ScheduleEvent(EVENT_LIFE_SIPHON, 2500); break; + case EVENT_MOVE_TO_CENTER: + { + Position pos = me->GetRandomPoint(CenterPosition, 4.0f); + pos.m_positionZ = me->GetHomePosition().m_positionZ; + me->GetMotionMaster()->MovePoint(POINT_SIPHON, pos); + break; + } default: break; } @@ -1607,6 +1654,7 @@ class npc_strangulate_vehicle : public CreatureScript if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) lichKing->AI()->SummonedCreatureDespawn(me); + me->DespawnOrUnsummon(); } void UpdateAI(uint32 diff) override @@ -2099,7 +2147,7 @@ class spell_the_lich_king_necrotic_plague_jump : public SpellScriptLoader } private: - void SelectTarget(std::list& targets) + void SelectTarget(std::list& targets) { targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster())); if (targets.size() < 2) @@ -2125,6 +2173,7 @@ class spell_the_lich_king_necrotic_plague_jump : public SpellScriptLoader void Register() override { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_necrotic_plague_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); BeforeHit += BeforeSpellHitFn(spell_the_lich_king_necrotic_plague_SpellScript::CheckAura); OnHit += SpellHitFn(spell_the_lich_king_necrotic_plague_SpellScript::AddMissingStack); } @@ -2357,12 +2406,6 @@ class spell_the_lich_king_raging_spirit : public SpellScriptLoader { PrepareSpellScript(spell_the_lich_king_raging_spirit_SpellScript); - bool Validate(SpellInfo const* spell) override - { - SpellEffectInfo const* effect0 = spell->GetEffect(EFFECT_0); - return effect0 && ValidateSpellInfo({ uint32(effect0->CalcValue()) }); - } - void HandleScript(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); @@ -3134,6 +3177,34 @@ class spell_the_lich_king_jump_remove_aura : public SpellScriptLoader } }; +class spell_the_lich_king_harvest_souls_teleport : public SpellScriptLoader +{ +public: + spell_the_lich_king_harvest_souls_teleport() : SpellScriptLoader("spell_the_lich_king_harvest_souls_teleport") { } + + class spell_the_lich_king_harvest_souls_teleport_SpellScript : public SpellScript + { + PrepareSpellScript(spell_the_lich_king_harvest_souls_teleport_SpellScript); + + void RelocateTransportOffset(SpellEffIndex /*effIndex*/) + { + float randCoordX = frand(-18.0f, 18.0f); + float randCoordY = frand(-18.0f, 18.0f); + GetHitDest()->RelocateOffset({ randCoordX, randCoordY, 0.0f, 0.0f }); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_harvest_souls_teleport_SpellScript::RelocateTransportOffset, EFFECT_1, SPELL_EFFECT_TELEPORT_UNITS); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_the_lich_king_harvest_souls_teleport_SpellScript(); + } +}; + class achievement_been_waiting_long_time : public AchievementCriteriaScript { public: @@ -3203,6 +3274,7 @@ void AddSC_boss_the_lich_king() new spell_the_lich_king_jump(); new spell_the_lich_king_jump_remove_aura(); new spell_trigger_spell_from_caster("spell_the_lich_king_mass_resurrection", SPELL_MASS_RESURRECTION_REAL); + new spell_the_lich_king_harvest_souls_teleport(); new achievement_been_waiting_long_time(); new achievement_neck_deep_in_vile(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h index 1f9d88ea885..8fff8922983 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h @@ -321,6 +321,7 @@ enum ICCreaturesIds NPC_WORLD_TRIGGER_INFINITE_AOI = 36171, NPC_SPIRIT_BOMB = 39189, NPC_FROSTMOURNE_TRIGGER = 38584, + NPC_SHADOW_TRAP = 39137, // Generic NPC_INVISIBLE_STALKER = 30298 @@ -524,8 +525,7 @@ enum ICWorldStatesICC enum ICAreaIds { - AREA_ICECROWN_CITADEL = 4812, - AREA_THE_FROZEN_THRONE = 4859 + AREA_ICECROWN_CITADEL = 4812 }; class spell_trigger_spell_from_caster : public SpellScriptLoader -- cgit v1.2.3 From f135b7aea15e06f4d85ed453da8989f738c5537d Mon Sep 17 00:00:00 2001 From: ccrs Date: Sat, 25 Mar 2017 13:17:29 +0100 Subject: Core/Movement: 96f4c7c followup (cherry picked from commit 9be7f5f57b897888983a9ca6f441479f3571513c) --- .../master/2020_04_16_01_world_2017_03_25_00_world.sql | 1 + src/server/game/Miscellaneous/Language.h | 2 +- src/server/game/Movement/MotionMaster.cpp | 16 +++++++++++----- src/server/game/Movement/MotionMaster.h | 2 +- src/server/scripts/Commands/cs_misc.cpp | 3 --- 5 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 sql/updates/world/master/2020_04_16_01_world_2017_03_25_00_world.sql (limited to 'src/server/scripts') diff --git a/sql/updates/world/master/2020_04_16_01_world_2017_03_25_00_world.sql b/sql/updates/world/master/2020_04_16_01_world_2017_03_25_00_world.sql new file mode 100644 index 00000000000..1e678704466 --- /dev/null +++ b/sql/updates/world/master/2020_04_16_01_world_2017_03_25_00_world.sql @@ -0,0 +1 @@ +DELETE FROM `trinity_string` WHERE `entry`=530; diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 283b0b42fc7..4355789458a 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -547,7 +547,7 @@ enum TrinityStrings LANG_MOVEGENS_IDLE = 527, LANG_MOVEGENS_RANDOM = 528, LANG_MOVEGENS_WAYPOINT = 529, - LANG_MOVEGENS_ANIMAL_RANDOM = 530, + // = 530, not used LANG_MOVEGENS_CONFUSED = 531, LANG_MOVEGENS_CHASE_PLAYER = 532, LANG_MOVEGENS_CHASE_CREATURE = 533, diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index b9efa1cf273..3e775d238a4 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -43,10 +43,16 @@ MotionMaster::~MotionMaster() // clear ALL movement generators (including default) while (!empty()) { - MovementGenerator *curr = top(); + MovementGenerator* movement = top(); pop(); - if (curr && !IsStatic(curr)) - delete curr; // Skip finalizing on delete, it might launch new movement + if (movement && !IsStatic(movement)) + delete movement; + } + + while (!_expireList.empty()) + { + delete _expireList.back(); + _expireList.pop_back(); } } @@ -117,8 +123,8 @@ void MotionMaster::Clear(bool reset /*= true*/) void MotionMaster::ClearExpireList() { - for (auto itr = _expireList.begin(); itr != _expireList.end(); itr++) - DirectDelete(*itr); + for (auto itr : _expireList) + DirectDelete(itr); _expireList.clear(); diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index ca81c65c8a1..09efe7d3188 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -99,7 +99,7 @@ struct JumpArrivalCastArgs class TC_GAME_API MotionMaster { public: - explicit MotionMaster(Unit* unit) : _expireList(nullptr), _top(-1), _owner(unit), _cleanFlag(MMCF_NONE) + explicit MotionMaster(Unit* unit) : _top(-1), _owner(unit), _cleanFlag(MMCF_NONE) { for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i) { diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index d5bb43c9607..23dbd8e3d1a 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -2201,9 +2201,6 @@ public: case WAYPOINT_MOTION_TYPE: handler->SendSysMessage(LANG_MOVEGENS_WAYPOINT); break; - case ANIMAL_RANDOM_MOTION_TYPE: - handler->SendSysMessage(LANG_MOVEGENS_ANIMAL_RANDOM); - break; case CONFUSED_MOTION_TYPE: handler->SendSysMessage(LANG_MOVEGENS_CONFUSED); break; -- cgit v1.2.3 From 70d5775d3f679e77c2b00418375f180f6209484d Mon Sep 17 00:00:00 2001 From: xinef1 Date: Mon, 27 Mar 2017 06:41:53 +0200 Subject: Added new creature extra flag which makes npc visible only to dead units closes #19333 * Rename 9999_99_99_99_world.sql to 2017_99_99_99_world_335.sql - file affects creature removed in patch 4.0.3a * Update Creature.cpp (cherry picked from commit e72b380b9374c92e5688002bf3a15065419a2ea0) --- ...2020_04_16_06_world_2017_99_99_99_world_335.sql | 11 +++++++ src/server/game/Entities/Creature/Creature.cpp | 3 +- src/server/game/Entities/Creature/CreatureData.h | 1 + src/server/scripts/Spells/spell_generic.cpp | 37 ---------------------- 4 files changed, 13 insertions(+), 39 deletions(-) create mode 100644 sql/updates/world/master/2020_04_16_06_world_2017_99_99_99_world_335.sql (limited to 'src/server/scripts') diff --git a/sql/updates/world/master/2020_04_16_06_world_2017_99_99_99_world_335.sql b/sql/updates/world/master/2020_04_16_06_world_2017_99_99_99_world_335.sql new file mode 100644 index 00000000000..ebcafe18e14 --- /dev/null +++ b/sql/updates/world/master/2020_04_16_06_world_2017_99_99_99_world_335.sql @@ -0,0 +1,11 @@ + +-- Franclorn Forgewright +-- SET @ENTRY := 8888; +-- UPDATE `creature_template` SET `flags_extra`=`flags_extra`|0x400 WHERE `entry`=@ENTRY; + +-- Gaeriyan +-- SET @ENTRY := 9299; +-- UPDATE `creature_template` SET `flags_extra`=`flags_extra`|0x400 WHERE `entry`=@ENTRY; + +-- Shroud of Death Spell +DELETE FROM `spell_script_names` WHERE spell_id=10848; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 49bf0c34aea..42311dcbc41 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1043,8 +1043,7 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, float LastUsedScriptID = GetScriptId(); - /// @todo Replace with spell, handle from DB - if (IsSpiritHealer() || IsSpiritGuide()) + if (IsSpiritHealer() || IsSpiritGuide() || (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_GHOST_VISIBILITY)) { m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST); m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST); diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index f94e8dbe22a..84bf27beb37 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -267,6 +267,7 @@ enum CreatureFlagsExtra CREATURE_FLAG_EXTRA_TRIGGER = 0x00000080, // trigger creature CREATURE_FLAG_EXTRA_NO_TAUNT = 0x00000100, // creature is immune to taunt auras and effect attack me CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE = 0x00000200, // creature won't update movement flags + CREATURE_FLAG_EXTRA_GHOST_VISIBILITY = 0x00000400, // creature will be only visible for dead players CREATURE_FLAG_EXTRA_WORLDEVENT = 0x00004000, // custom flag for world event creatures (left room for merging) CREATURE_FLAG_EXTRA_GUARD = 0x00008000, // Creature is guard CREATURE_FLAG_EXTRA_NO_CRIT = 0x00020000, // creature can't do critical strikes diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 7adb0d0d4cf..eb800765b7c 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -4207,42 +4207,6 @@ class spell_gen_pony_mount_check : public SpellScriptLoader } }; -class spell_gen_shroud_of_death : public SpellScriptLoader -{ -public: - spell_gen_shroud_of_death() : SpellScriptLoader("spell_gen_shroud_of_death") { } - - class spell_gen_shroud_of_death_AuraScript : public AuraScript - { - PrepareAuraScript(spell_gen_shroud_of_death_AuraScript); - - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - PreventDefaultAction(); - GetUnitOwner()->m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST); - GetUnitOwner()->m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST); - } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - PreventDefaultAction(); - GetUnitOwner()->m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE); - GetUnitOwner()->m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE); - } - - void Register() override - { - OnEffectApply += AuraEffectApplyFn(spell_gen_shroud_of_death_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - OnEffectRemove += AuraEffectRemoveFn(spell_gen_shroud_of_death_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_gen_shroud_of_death_AuraScript(); - } -}; - // 169869 - Transformation Sickness class spell_gen_decimatus_transformation_sickness : public SpellScriptLoader { @@ -4568,7 +4532,6 @@ void AddSC_generic_spell_scripts() new spell_gen_landmine_knockback_achievement(); new spell_gen_clear_debuffs(); new spell_gen_pony_mount_check(); - new spell_gen_shroud_of_death(); new spell_gen_decimatus_transformation_sickness(); new spell_gen_anetheron_summon_towering_infernal(); new spell_gen_mark_of_kazrogal_hellfire(); -- cgit v1.2.3 From 3f79c9f69674618a7d7e2bf8484f9ec6ce15b2df Mon Sep 17 00:00:00 2001 From: ariel- Date: Tue, 28 Mar 2017 01:52:49 -0300 Subject: Core/AI: AreaBoundary refactor - Added an auxiliary function IsInBounds to base CreatureAI - Changed container to vector. Set had no sense because we're storing new pointers, they have different addresses even if the boundary is the same (cherry picked from commit 2f99fa09c9bacbad376d7a296c3311f94ec8a552) --- src/server/game/AI/CreatureAI.cpp | 16 ++++- src/server/game/AI/CreatureAI.h | 4 +- src/server/game/Instances/InstanceScript.cpp | 2 +- src/server/game/Instances/InstanceScript.h | 2 +- src/server/game/Maps/AreaBoundary.cpp | 14 ++-- src/server/game/Maps/AreaBoundary.h | 78 ++++++++++++---------- .../AzjolNerub/AzjolNerub/boss_anubarak.cpp | 11 +-- 7 files changed, 68 insertions(+), 59 deletions(-) (limited to 'src/server/scripts') diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 7fbc8ed2ed5..b9d052cb528 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -368,13 +368,25 @@ bool CreatureAI::CheckBoundary(Position const* who) const who = me; if (_boundary) - for (AreaBoundary const* boundary : *_boundary) - if (!boundary->IsWithinBoundary(who)) + for (AreaBoundary const* areaBoundary : *_boundary) + if (!areaBoundary->IsWithinBoundary(who)) return false; return true; } +bool CreatureAI::IsInBounds(CreatureBoundary const* boundary, Position const* pos) +{ + if (!boundary) + return true; + + for (AreaBoundary const* areaBoundary : *boundary) + if (!areaBoundary->IsWithinBoundary(pos)) + return false; + + return true; +} + void CreatureAI::SetBoundary(CreatureBoundary const* boundary) { _boundary = boundary; diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index e36a41795a0..1e6f2a817ec 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -31,7 +31,7 @@ class PlayerAI; class WorldObject; struct Position; -typedef std::set CreatureBoundary; +typedef std::vector CreatureBoundary; #define TIME_INTERVAL_LOOK 5000 #define VISIBILITY_RANGE 10000 @@ -82,6 +82,8 @@ class TC_GAME_API CreatureAI : public UnitAI Creature* DoSummonFlyer(uint32 entry, WorldObject* obj, float flightZ, float radius = 5.0f, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN); bool CheckBoundary(Position const* who = nullptr) const; + static bool IsInBounds(CreatureBoundary const* boundary, Position const* who); + void SetBoundary(CreatureBoundary const* boundary); public: enum EvadeReason diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 90582235948..4f124dd9567 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -145,7 +145,7 @@ void InstanceScript::LoadBossBoundaries(const BossBoundaryData& data) { for (BossBoundaryEntry const& entry : data) if (entry.BossId < bosses.size()) - bosses[entry.BossId].boundary.insert(entry.Boundary); + bosses[entry.BossId].boundary.push_back(entry.Boundary); } void InstanceScript::LoadMinionData(const MinionData* data) diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 0fc37d470ec..a87779f7f22 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -119,7 +119,7 @@ struct ObjectData uint32 type; }; -typedef std::set CreatureBoundary; +typedef std::vector CreatureBoundary; struct BossInfo { diff --git a/src/server/game/Maps/AreaBoundary.cpp b/src/server/game/Maps/AreaBoundary.cpp index f7ae5b4c9b6..af5e6ffe734 100644 --- a/src/server/game/Maps/AreaBoundary.cpp +++ b/src/server/game/Maps/AreaBoundary.cpp @@ -21,7 +21,7 @@ // ---== RECTANGLE ==--- RectangleBoundary::RectangleBoundary(float southX, float northX, float eastY, float westY, bool isInverted) : - AreaBoundary(BoundaryType::BOUNDARY_RECTANGLE, isInverted), _minX(southX), _maxX(northX), _minY(eastY), _maxY(westY) { } + AreaBoundary(isInverted), _minX(southX), _maxX(northX), _minY(eastY), _maxY(westY) { } bool RectangleBoundary::IsWithinBoundaryArea(Position const* pos) const { if (!pos) @@ -40,11 +40,11 @@ bool RectangleBoundary::IsWithinBoundaryArea(Position const* pos) const CircleBoundary::CircleBoundary(Position const& center, double radius, bool isInverted) : CircleBoundary(DoublePosition(center), radius, isInverted) { } CircleBoundary::CircleBoundary(DoublePosition const& center, double radius, bool isInverted) : - AreaBoundary(BoundaryType::BOUNDARY_CIRCLE, isInverted), _center(center), _radiusSq(radius*radius) { } + AreaBoundary(isInverted), _center(center), _radiusSq(radius*radius) { } CircleBoundary::CircleBoundary(Position const& center, Position const& pointOnCircle, bool isInverted) : CircleBoundary(DoublePosition(center), DoublePosition(pointOnCircle), isInverted) { } CircleBoundary::CircleBoundary(DoublePosition const& center, DoublePosition const& pointOnCircle, bool isInverted) : - AreaBoundary(BoundaryType::BOUNDARY_CIRCLE, isInverted), _center(center), _radiusSq(center.GetDoubleExactDist2dSq(pointOnCircle)) { } + AreaBoundary(isInverted), _center(center), _radiusSq(center.GetDoubleExactDist2dSq(pointOnCircle)) { } bool CircleBoundary::IsWithinBoundaryArea(Position const* pos) const { if (!pos) @@ -60,7 +60,7 @@ bool CircleBoundary::IsWithinBoundaryArea(Position const* pos) const EllipseBoundary::EllipseBoundary(Position const& center, double radiusX, double radiusY, bool isInverted) : EllipseBoundary(DoublePosition(center), radiusX, radiusY, isInverted) { } EllipseBoundary::EllipseBoundary(DoublePosition const& center, double radiusX, double radiusY, bool isInverted) : - AreaBoundary(BoundaryType::BOUNDARY_ELLIPSE, isInverted), _center(center), _radiusYSq(radiusY*radiusY), _scaleXSq(_radiusYSq / (radiusX*radiusX)) { } + AreaBoundary(isInverted), _center(center), _radiusYSq(radiusY*radiusY), _scaleXSq(_radiusYSq / (radiusX*radiusX)) { } bool EllipseBoundary::IsWithinBoundaryArea(Position const* pos) const { if (!pos) @@ -75,7 +75,7 @@ bool EllipseBoundary::IsWithinBoundaryArea(Position const* pos) const TriangleBoundary::TriangleBoundary(Position const& pointA, Position const& pointB, Position const& pointC, bool isInverted) : TriangleBoundary(DoublePosition(pointA), DoublePosition(pointB), DoublePosition(pointC), isInverted) { } TriangleBoundary::TriangleBoundary(DoublePosition const& pointA, DoublePosition const& pointB, DoublePosition const& pointC, bool isInverted) : - AreaBoundary(BoundaryType::BOUNDARY_TRIANGLE, isInverted), _a(pointA), _b(pointB), _c(pointC), _abx(_b.GetDoublePositionX()-_a.GetDoublePositionX()), _bcx(_c.GetDoublePositionX()-_b.GetDoublePositionX()), _cax(_a.GetDoublePositionX() - _c.GetDoublePositionX()), _aby(_b.GetDoublePositionY()-_a.GetDoublePositionY()), _bcy(_c.GetDoublePositionY()-_b.GetDoublePositionY()), _cay(_a.GetDoublePositionY() - _c.GetDoublePositionY()) { } + AreaBoundary(isInverted), _a(pointA), _b(pointB), _c(pointC), _abx(_b.GetDoublePositionX()-_a.GetDoublePositionX()), _bcx(_c.GetDoublePositionX()-_b.GetDoublePositionX()), _cax(_a.GetDoublePositionX() - _c.GetDoublePositionX()), _aby(_b.GetDoublePositionY()-_a.GetDoublePositionY()), _bcy(_c.GetDoublePositionY()-_b.GetDoublePositionY()), _cay(_a.GetDoublePositionY() - _c.GetDoublePositionY()) { } bool TriangleBoundary::IsWithinBoundaryArea(Position const* pos) const { if (!pos) @@ -95,7 +95,7 @@ bool TriangleBoundary::IsWithinBoundaryArea(Position const* pos) const ParallelogramBoundary::ParallelogramBoundary(Position const& cornerA, Position const& cornerB, Position const& cornerD, bool isInverted) : ParallelogramBoundary(DoublePosition(cornerA), DoublePosition(cornerB), DoublePosition(cornerD), isInverted) { } ParallelogramBoundary::ParallelogramBoundary(DoublePosition const& cornerA, DoublePosition const& cornerB, DoublePosition const& cornerD, bool isInverted) : - AreaBoundary(BoundaryType::BOUNDARY_PARALLELOGRAM, isInverted), _a(cornerA), _b(cornerB), _d(cornerD), _c(DoublePosition(_d.GetDoublePositionX() + (_b.GetDoublePositionX() - _a.GetDoublePositionX()), _d.GetDoublePositionY() + (_b.GetDoublePositionY() - _a.GetDoublePositionY()))), _abx(_b.GetDoublePositionX() - _a.GetDoublePositionX()), _dax(_a.GetDoublePositionX() - _d.GetDoublePositionX()), _aby(_b.GetDoublePositionY() - _a.GetDoublePositionY()), _day(_a.GetDoublePositionY() - _d.GetDoublePositionY()) { } + AreaBoundary(isInverted), _a(cornerA), _b(cornerB), _d(cornerD), _c(DoublePosition(_d.GetDoublePositionX() + (_b.GetDoublePositionX() - _a.GetDoublePositionX()), _d.GetDoublePositionY() + (_b.GetDoublePositionY() - _a.GetDoublePositionY()))), _abx(_b.GetDoublePositionX() - _a.GetDoublePositionX()), _dax(_a.GetDoublePositionX() - _d.GetDoublePositionX()), _aby(_b.GetDoublePositionY() - _a.GetDoublePositionY()), _day(_a.GetDoublePositionY() - _d.GetDoublePositionY()) { } bool ParallelogramBoundary::IsWithinBoundaryArea(Position const* pos) const { if (!pos) @@ -114,7 +114,7 @@ bool ParallelogramBoundary::IsWithinBoundaryArea(Position const* pos) const // ---== Z RANGE ==--- ZRangeBoundary::ZRangeBoundary(float minZ, float maxZ, bool isInverted) : - AreaBoundary(BoundaryType::BOUNDARY_Z_RANGE, isInverted), _minZ(minZ), _maxZ(maxZ) { } + AreaBoundary(isInverted), _minZ(minZ), _maxZ(maxZ) { } bool ZRangeBoundary::IsWithinBoundaryArea(Position const* pos) const { if (!pos) diff --git a/src/server/game/Maps/AreaBoundary.h b/src/server/game/Maps/AreaBoundary.h index 069701775eb..b2fdc49a7a6 100644 --- a/src/server/game/Maps/AreaBoundary.h +++ b/src/server/game/Maps/AreaBoundary.h @@ -23,48 +23,52 @@ class TC_GAME_API AreaBoundary { public: - enum BoundaryType - { - BOUNDARY_RECTANGLE, // Rectangle aligned with the coordinate axis - BOUNDARY_CIRCLE, - BOUNDARY_ELLIPSE, - BOUNDARY_TRIANGLE, - BOUNDARY_PARALLELOGRAM, - BOUNDARY_Z_RANGE, - }; - virtual ~AreaBoundary() { } - BoundaryType GetBoundaryType() const { return m_boundaryType; } - bool IsWithinBoundary(Position const* pos) const { return (IsWithinBoundaryArea(pos) != m_isInvertedBoundary); } + bool IsWithinBoundary(Position const* pos) const { return (IsWithinBoundaryArea(pos) != _isInvertedBoundary); } bool IsWithinBoundary(Position const& pos) const { return IsWithinBoundary(&pos); } + virtual ~AreaBoundary() { } + + protected: + explicit AreaBoundary(bool isInverted) : _isInvertedBoundary(isInverted) { } + struct DoublePosition : Position { - double d_positionX, d_positionY, d_positionZ; DoublePosition(double x = 0.0, double y = 0.0, double z = 0.0, float o = 0.0f) - : Position(float(x), float(y), float(z), o), d_positionX(x), d_positionY(y), d_positionZ(z) { } + : Position(float(x), float(y), float(z), o), DoublePosX(x), DoublePosY(y), DoublePosZ(z) { } + DoublePosition(float x, float y = 0.0f, float z = 0.0f, float o = 0.0f) - : Position(x, y, z, o), d_positionX(x), d_positionY(y), d_positionZ(z) { } + : Position(x, y, z, o), DoublePosX(x), DoublePosY(y), DoublePosZ(z) { } + DoublePosition(Position const & pos) - : DoublePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()) { } + : Position(pos), DoublePosX(pos.m_positionX), DoublePosY(pos.m_positionY), DoublePosZ(pos.m_positionZ) { } - double GetDoublePositionX() const { return d_positionX; } - double GetDoublePositionY() const { return d_positionY; } - double GetDoublePositionZ() const { return d_positionZ; } + double GetDoublePositionX() const { return DoublePosX; } + double GetDoublePositionY() const { return DoublePosY; } + double GetDoublePositionZ() const { return DoublePosZ; } double GetDoubleExactDist2dSq(DoublePosition const& pos) const { - double offX = GetDoublePositionX() - pos.GetDoublePositionX(); - double offY = GetDoublePositionY() - pos.GetDoublePositionY(); - return (offX*offX) + (offY*offY); + double const offX = GetDoublePositionX() - pos.GetDoublePositionX(); + double const offY = GetDoublePositionY() - pos.GetDoublePositionY(); + return (offX * offX) + (offY * offY); + } + + Position* sync() + { + m_positionX = float(DoublePosX); + m_positionY = float(DoublePosY); + m_positionZ = float(DoublePosZ); + return this; } - Position* sync() { m_positionX = (float)d_positionX; m_positionY = (float)d_positionY; m_positionZ = (float)d_positionZ; return this; } + double DoublePosX; + double DoublePosY; + double DoublePosZ; }; - protected: - AreaBoundary(BoundaryType bType, bool isInverted) : m_boundaryType(bType), m_isInvertedBoundary(isInverted) { } virtual bool IsWithinBoundaryArea(Position const* pos) const = 0; - const BoundaryType m_boundaryType; - bool m_isInvertedBoundary; + + private: + bool _isInvertedBoundary; }; class TC_GAME_API RectangleBoundary : public AreaBoundary @@ -77,7 +81,7 @@ class TC_GAME_API RectangleBoundary : public AreaBoundary bool IsWithinBoundaryArea(Position const* pos) const override; private: - const float _minX, _maxX, _minY, _maxY; + float const _minX, _maxX, _minY, _maxY; }; class TC_GAME_API CircleBoundary : public AreaBoundary @@ -92,8 +96,8 @@ class TC_GAME_API CircleBoundary : public AreaBoundary bool IsWithinBoundaryArea(Position const* pos) const override; private: - const DoublePosition _center; - const double _radiusSq; + DoublePosition const _center; + double const _radiusSq; }; class TC_GAME_API EllipseBoundary : public AreaBoundary @@ -106,8 +110,8 @@ class TC_GAME_API EllipseBoundary : public AreaBoundary bool IsWithinBoundaryArea(Position const* pos) const override; private: - const DoublePosition _center; - const double _radiusYSq, _scaleXSq; + DoublePosition const _center; + double const _radiusYSq, _scaleXSq; }; class TC_GAME_API TriangleBoundary : public AreaBoundary @@ -120,8 +124,8 @@ class TC_GAME_API TriangleBoundary : public AreaBoundary bool IsWithinBoundaryArea(Position const* pos) const override; private: - const DoublePosition _a, _b, _c; - const double _abx, _bcx, _cax, _aby, _bcy, _cay; + DoublePosition const _a, _b, _c; + double const _abx, _bcx, _cax, _aby, _bcy, _cay; }; class TC_GAME_API ParallelogramBoundary : public AreaBoundary @@ -135,8 +139,8 @@ class TC_GAME_API ParallelogramBoundary : public AreaBoundary bool IsWithinBoundaryArea(Position const* pos) const override; private: - const DoublePosition _a, _b, _d, _c; - const double _abx, _dax, _aby, _day; + DoublePosition const _a, _b, _d, _c; + double const _abx, _dax, _aby, _day; }; class TC_GAME_API ZRangeBoundary : public AreaBoundary @@ -148,7 +152,7 @@ class TC_GAME_API ZRangeBoundary : public AreaBoundary bool IsWithinBoundaryArea(Position const* pos) const override; private: - const float _minZ, _maxZ; + float const _minZ, _maxZ; }; #endif //TRINITY_AREA_BOUNDARY_H diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp index f00f96660a8..9112fd9ccd2 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp @@ -483,15 +483,6 @@ class npc_anubarak_anub_ar_assassin : public CreatureScript { npc_anubarak_anub_ar_assassinAI(Creature* creature) : npc_anubarak_pet_template(creature, false), _backstabTimer(6 * IN_MILLISECONDS) { } - bool IsInBounds(Position const& jumpTo, CreatureBoundary const* boundary) - { - if (!boundary) - return true; - for (AreaBoundary const* it : *boundary) - if (!it->IsWithinBoundary(&jumpTo)) - return false; - return true; - } Position GetRandomPositionAround(Creature* anubarak) { static float DISTANCE_MIN = 10.0f; @@ -508,7 +499,7 @@ class npc_anubarak_anub_ar_assassin : public CreatureScript Position jumpTo; do jumpTo = GetRandomPositionAround(anubarak); - while (!IsInBounds(jumpTo, boundary)); + while (!CreatureAI::IsInBounds(boundary, &jumpTo)); me->GetMotionMaster()->MoveJump(jumpTo, 40.0f, 40.0f); DoCastSelf(SPELL_ASSASSIN_VISUAL, true); } -- cgit v1.2.3 From cbcc4601ad192f0e470ed594d57c0a11622c8b0f Mon Sep 17 00:00:00 2001 From: ariel- Date: Tue, 28 Mar 2017 02:41:50 -0300 Subject: Core/AI: Build fix - Stop exposing DoublePosition constructor versions, they're only used for internal representation - Moved IsInBounds function to public scope (cherry picked from commit 83162fafa453c1d34fe23ddd86a43c3dff058300) --- src/server/game/AI/CreatureAI.h | 3 ++- src/server/game/Maps/AreaBoundary.cpp | 12 +----------- src/server/game/Maps/AreaBoundary.h | 5 ----- .../scripts/Northrend/Naxxramas/instance_naxxramas.cpp | 6 +++--- 4 files changed, 6 insertions(+), 20 deletions(-) (limited to 'src/server/scripts') diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index 1e6f2a817ec..5fe93e7675a 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -82,7 +82,6 @@ class TC_GAME_API CreatureAI : public UnitAI Creature* DoSummonFlyer(uint32 entry, WorldObject* obj, float flightZ, float radius = 5.0f, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN); bool CheckBoundary(Position const* who = nullptr) const; - static bool IsInBounds(CreatureBoundary const* boundary, Position const* who); void SetBoundary(CreatureBoundary const* boundary); public: @@ -216,6 +215,8 @@ class TC_GAME_API CreatureAI : public UnitAI virtual bool CheckInRoom(); CreatureBoundary const* GetBoundary() const { return _boundary; } + static bool IsInBounds(CreatureBoundary const* boundary, Position const* who); + protected: virtual void MoveInLineOfSight(Unit* /*who*/); diff --git a/src/server/game/Maps/AreaBoundary.cpp b/src/server/game/Maps/AreaBoundary.cpp index af5e6ffe734..407b5c27e53 100644 --- a/src/server/game/Maps/AreaBoundary.cpp +++ b/src/server/game/Maps/AreaBoundary.cpp @@ -38,13 +38,9 @@ bool RectangleBoundary::IsWithinBoundaryArea(Position const* pos) const // ---== CIRCLE ==--- CircleBoundary::CircleBoundary(Position const& center, double radius, bool isInverted) : - CircleBoundary(DoublePosition(center), radius, isInverted) { } -CircleBoundary::CircleBoundary(DoublePosition const& center, double radius, bool isInverted) : AreaBoundary(isInverted), _center(center), _radiusSq(radius*radius) { } CircleBoundary::CircleBoundary(Position const& center, Position const& pointOnCircle, bool isInverted) : - CircleBoundary(DoublePosition(center), DoublePosition(pointOnCircle), isInverted) { } -CircleBoundary::CircleBoundary(DoublePosition const& center, DoublePosition const& pointOnCircle, bool isInverted) : - AreaBoundary(isInverted), _center(center), _radiusSq(center.GetDoubleExactDist2dSq(pointOnCircle)) { } + AreaBoundary(isInverted), _center(center), _radiusSq(_center.GetDoubleExactDist2dSq(pointOnCircle)) { } bool CircleBoundary::IsWithinBoundaryArea(Position const* pos) const { if (!pos) @@ -58,8 +54,6 @@ bool CircleBoundary::IsWithinBoundaryArea(Position const* pos) const // ---== ELLIPSE ==--- EllipseBoundary::EllipseBoundary(Position const& center, double radiusX, double radiusY, bool isInverted) : - EllipseBoundary(DoublePosition(center), radiusX, radiusY, isInverted) { } -EllipseBoundary::EllipseBoundary(DoublePosition const& center, double radiusX, double radiusY, bool isInverted) : AreaBoundary(isInverted), _center(center), _radiusYSq(radiusY*radiusY), _scaleXSq(_radiusYSq / (radiusX*radiusX)) { } bool EllipseBoundary::IsWithinBoundaryArea(Position const* pos) const { @@ -73,8 +67,6 @@ bool EllipseBoundary::IsWithinBoundaryArea(Position const* pos) const // ---== TRIANGLE ==--- TriangleBoundary::TriangleBoundary(Position const& pointA, Position const& pointB, Position const& pointC, bool isInverted) : - TriangleBoundary(DoublePosition(pointA), DoublePosition(pointB), DoublePosition(pointC), isInverted) { } -TriangleBoundary::TriangleBoundary(DoublePosition const& pointA, DoublePosition const& pointB, DoublePosition const& pointC, bool isInverted) : AreaBoundary(isInverted), _a(pointA), _b(pointB), _c(pointC), _abx(_b.GetDoublePositionX()-_a.GetDoublePositionX()), _bcx(_c.GetDoublePositionX()-_b.GetDoublePositionX()), _cax(_a.GetDoublePositionX() - _c.GetDoublePositionX()), _aby(_b.GetDoublePositionY()-_a.GetDoublePositionY()), _bcy(_c.GetDoublePositionY()-_b.GetDoublePositionY()), _cay(_a.GetDoublePositionY() - _c.GetDoublePositionY()) { } bool TriangleBoundary::IsWithinBoundaryArea(Position const* pos) const { @@ -93,8 +85,6 @@ bool TriangleBoundary::IsWithinBoundaryArea(Position const* pos) const // ---== PARALLELOGRAM ==--- ParallelogramBoundary::ParallelogramBoundary(Position const& cornerA, Position const& cornerB, Position const& cornerD, bool isInverted) : - ParallelogramBoundary(DoublePosition(cornerA), DoublePosition(cornerB), DoublePosition(cornerD), isInverted) { } -ParallelogramBoundary::ParallelogramBoundary(DoublePosition const& cornerA, DoublePosition const& cornerB, DoublePosition const& cornerD, bool isInverted) : AreaBoundary(isInverted), _a(cornerA), _b(cornerB), _d(cornerD), _c(DoublePosition(_d.GetDoublePositionX() + (_b.GetDoublePositionX() - _a.GetDoublePositionX()), _d.GetDoublePositionY() + (_b.GetDoublePositionY() - _a.GetDoublePositionY()))), _abx(_b.GetDoublePositionX() - _a.GetDoublePositionX()), _dax(_a.GetDoublePositionX() - _d.GetDoublePositionX()), _aby(_b.GetDoublePositionY() - _a.GetDoublePositionY()), _day(_a.GetDoublePositionY() - _d.GetDoublePositionY()) { } bool ParallelogramBoundary::IsWithinBoundaryArea(Position const* pos) const { diff --git a/src/server/game/Maps/AreaBoundary.h b/src/server/game/Maps/AreaBoundary.h index b2fdc49a7a6..6aa7e4185cc 100644 --- a/src/server/game/Maps/AreaBoundary.h +++ b/src/server/game/Maps/AreaBoundary.h @@ -88,9 +88,7 @@ class TC_GAME_API CircleBoundary : public AreaBoundary { public: CircleBoundary(Position const& center, double radius, bool isInverted = false); - CircleBoundary(DoublePosition const& center, double radius, bool isInverted = false); CircleBoundary(Position const& center, Position const& pointOnCircle, bool isInverted = false); - CircleBoundary(DoublePosition const& center, DoublePosition const& pointOnCircle, bool isInverted = false); protected: bool IsWithinBoundaryArea(Position const* pos) const override; @@ -104,7 +102,6 @@ class TC_GAME_API EllipseBoundary : public AreaBoundary { public: EllipseBoundary(Position const& center, double radiusX, double radiusY, bool isInverted = false); - EllipseBoundary(DoublePosition const& center, double radiusX, double radiusY, bool isInverted = false); protected: bool IsWithinBoundaryArea(Position const* pos) const override; @@ -118,7 +115,6 @@ class TC_GAME_API TriangleBoundary : public AreaBoundary { public: TriangleBoundary(Position const& pointA, Position const& pointB, Position const& pointC, bool isInverted = false); - TriangleBoundary(DoublePosition const& pointA, DoublePosition const& pointB, DoublePosition const& pointC, bool isInverted = false); protected: bool IsWithinBoundaryArea(Position const* pos) const override; @@ -133,7 +129,6 @@ class TC_GAME_API ParallelogramBoundary : public AreaBoundary public: // Note: AB must be orthogonal to AD ParallelogramBoundary(Position const& cornerA, Position const& cornerB, Position const& cornerD, bool isInverted = false); - ParallelogramBoundary(DoublePosition const& cornerA, DoublePosition const& cornerB, DoublePosition const& cornerD, bool isInverted = false); protected: bool IsWithinBoundaryArea(Position const* pos) const override; diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index b61e42974ac..1569697c81c 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -43,7 +43,7 @@ BossBoundaryData const boundaries = /* Military Quarter */ { BOSS_RAZUVIOUS, new ZRangeBoundary(260.0f, 287.0f) }, // will not chase onto the upper floor { BOSS_GOTHIK, new RectangleBoundary(2627.0f, 2764.0f, -3440.0f, -3275.0f) }, - { BOSS_HORSEMEN, new ParallelogramBoundary(AreaBoundary::DoublePosition(2646.0, -2959.0), AreaBoundary::DoublePosition(2529.0, -3075.0), AreaBoundary::DoublePosition(2506.0, -2854.0)) }, + { BOSS_HORSEMEN, new ParallelogramBoundary(Position(2646.0f, -2959.0f), Position(2529.0f, -3075.0f), Position(2506.0f, -2854.0f)) }, /* Construct Quarter */ { BOSS_PATCHWERK, new CircleBoundary(Position(3204.0f, -3241.4f), 240.0f) }, @@ -51,9 +51,9 @@ BossBoundaryData const boundaries = { BOSS_GROBBULUS, new CircleBoundary(Position(3204.0f, -3241.4f), 240.0f) }, { BOSS_GROBBULUS, new RectangleBoundary(3295.0f, 3340.0f, -3254.2f, -3230.18f, true) }, // entrance door blocker { BOSS_GLUTH, new CircleBoundary(Position(3293.0f, -3142.0f), 80.0) }, - { BOSS_GLUTH, new ParallelogramBoundary(AreaBoundary::DoublePosition(3401.0, -3149.0), AreaBoundary::DoublePosition(3261.0, -3028.0), AreaBoundary::DoublePosition(3320.0, -3267.0)) }, + { BOSS_GLUTH, new ParallelogramBoundary(Position(3401.0f, -3149.0f), Position(3261.0f, -3028.0f), Position(3320.0f, -3267.0f)) }, { BOSS_GLUTH, new ZRangeBoundary(285.0f, 310.0f) }, - { BOSS_THADDIUS, new ParallelogramBoundary(AreaBoundary::DoublePosition(3478.3, -3070.0), AreaBoundary::DoublePosition(3370.0, -2961.5), AreaBoundary::DoublePosition(3580.0, -2961.5)) }, + { BOSS_THADDIUS, new ParallelogramBoundary(Position(3478.3f, -3070.0f), Position(3370.0f, -2961.5f), Position(3580.0f, -2961.5f)) }, /* Frostwyrm Lair */ { BOSS_SAPPHIRON, new CircleBoundary(Position(3517.627f, -5255.5f), 110.0) }, -- cgit v1.2.3 From b259614778c2939707baf865863bbbedd9fa0125 Mon Sep 17 00:00:00 2001 From: tkrokli Date: Wed, 29 Mar 2017 10:06:06 +0200 Subject: Scripts: minimize duplicated enum names in header files (#19377) * Scripts: Minimize duplicated enum names in header files This reduces the number of cache resets with the Zapcc compiler - Standard followed is instance/raid TLA + DataTypes/CreaturesIds/etc - Partial cherry-pick of master commit 7eb4512eee5fc04994e2aa55126ccc97a8393506 - Removed unused defines in sunken_temple.h (the core scripts using these have been moved to SAI) (cherry picked from commit f6f36be004c3b8c7d09e0f320d5aabb8a9129109) --- .../scripts/EasternKingdoms/SunkenTemple/sunken_temple.h | 16 ++++------------ .../Northrend/Nexus/EyeOfEternity/eye_of_eternity.h | 12 ++++++------ src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h | 2 +- .../MagtheridonsLair/instance_magtheridons_lair.cpp | 4 ++-- .../HellfireCitadel/MagtheridonsLair/magtheridons_lair.h | 8 ++++---- 5 files changed, 17 insertions(+), 25 deletions(-) (limited to 'src/server/scripts') diff --git a/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h b/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h index 9f72ffe8183..c905702d3bc 100644 --- a/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h +++ b/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h @@ -20,17 +20,9 @@ #define DataHeader "ST" -#define TROLLBOSS1_DEATH 1 -#define TROLLBOSS2_DEATH 2 -#define TROLLBOSS3_DEATH 3 -#define TROLLBOSS4_DEATH 4 -#define TROLLBOSS5_DEATH 5 -#define TROLLBOSS6_DEATH 6 -#define JAMMALAN_DEATH 7 -#define MORPHAZ_DEATH 8 -#define HAZZAS_DEATH 9 -#define ERANIKUS_DEATH 10 -#define ATALALARION_DEATH 11 //optional +enum STEvents +{ + EVENT_STATE = 1 +}; -#define EVENT_STATE 1 #endif diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h index b066eb59bea..4c3faf67b5a 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h @@ -23,7 +23,7 @@ #define EoEScriptName "instance_eye_of_eternity" #define DataHeader "EOE" -enum InstanceData +enum EOEInstanceData { DATA_MALYGOS_EVENT, MAX_ENCOUNTER, @@ -33,7 +33,7 @@ enum InstanceData DATA_RESPAWN_IRIS }; -enum InstanceData64 +enum EOEInstanceData64 { DATA_TRIGGER, DATA_MALYGOS, @@ -44,7 +44,7 @@ enum InstanceData64 DATA_GIFT_BOX_BUNNY_GUID }; -enum InstanceNpcs +enum EOEInstanceNpcs { NPC_MALYGOS = 28859, NPC_VORTEX_TRIGGER = 30090, @@ -60,7 +60,7 @@ enum InstanceNpcs NPC_SURGE_OF_POWER = 30334 }; -enum InstanceGameObjects +enum EOEInstanceGameObjects { GO_NEXUS_RAID_PLATFORM = 193070, GO_EXIT_PORTAL = 193908, @@ -72,12 +72,12 @@ enum InstanceGameObjects GO_HEART_OF_MAGIC_25 = 194159 }; -enum InstanceEvents +enum EOEInstanceEvents { EVENT_FOCUSING_IRIS = 20711 }; -enum InstanceSpells +enum EOEInstanceSpells { SPELL_VORTEX_4 = 55853, // damage | used to enter to the vehicle SPELL_VORTEX_5 = 56263, // damage | used to enter to the vehicle diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h index 74adb6d1d13..a26b699b396 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h @@ -279,7 +279,7 @@ enum UlduarGameObjects GO_GIFT_OF_THE_OBSERVER_25 = 194822, }; -enum EventIds +enum UUEventIds { EVENT_TOWER_OF_STORM_DESTROYED = 21031, EVENT_TOWER_OF_FROST_DESTROYED = 21032, diff --git a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp index 515039e987b..8cd4bbc9cf0 100644 --- a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp @@ -55,7 +55,7 @@ ObjectData const gameObjectData[] = { 0, 0 } //END }; -static DataTypes const collapseObjectDatas[] = +static MLDataTypes const collapseObjectDatas[] = { DATA_MAGTHERIDON_COLUMN_0, DATA_MAGTHERIDON_COLUMN_1, @@ -116,7 +116,7 @@ class instance_magtheridons_lair : public InstanceMapScript HandleGameObject(ObjectGuid::Empty, value == ACTION_ENABLE ? true : false, hall); break; case DATA_COLLAPSE_2: - for (DataTypes data : collapseObjectDatas) + for (MLDataTypes data : collapseObjectDatas) if (GameObject* go = GetGameObject(data)) HandleGameObject(ObjectGuid::Empty, value == ACTION_ENABLE ? true : false, go); break; diff --git a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h index 4e46ecd98e7..87190d446b0 100644 --- a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h +++ b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h @@ -25,7 +25,7 @@ uint32 const EncounterCount = 1; -enum DataTypes +enum MLDataTypes { DATA_MAGTHERIDON = 0, DATA_WORLD_TRIGGER = 1, @@ -42,13 +42,13 @@ enum DataTypes DATA_CALL_WARDERS = 12 }; -enum Actions +enum MLActions { ACTION_ENABLE = 1, ACTION_DISABLE = 2 }; -enum CreatureIds +enum MLCreatureIds { NPC_MAGTHERIDON = 17257, NPC_ABYSSAL = 17454, @@ -61,7 +61,7 @@ enum CreatureIds NPC_HELLFIRE_WARDER = 18829 }; -enum GameObjectIds +enum MLGameObjectIds { GO_MAGTHERIDON_DOOR = 183847, GO_MANTICRON_CUBE = 181713, -- cgit v1.2.3