From 73aababbd4e4ecab5783d1ab179b47bab133a490 Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 23 Jun 2016 22:19:52 +0200 Subject: Core/Spells: Fixed handling spell interrupts - PreventionType dbc field is a bitmask --- src/server/game/Spells/Spell.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/server/game/Spells/Spell.cpp') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 31bcfc39980..b77cac83e34 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5765,9 +5765,9 @@ SpellCastResult Spell::CheckCasterAuras() const prevented_reason = SPELL_FAILED_CONFUSED; else if (unitflag & UNIT_FLAG_FLEEING && !m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED)) prevented_reason = SPELL_FAILED_FLEEING; - else if (unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + else if (unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE) prevented_reason = SPELL_FAILED_SILENCED; - else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY) + else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_PACIFY) prevented_reason = SPELL_FAILED_PACIFIED; // Attr must make flag drop spell totally immune from all effects @@ -5814,9 +5814,9 @@ SpellCastResult Spell::CheckCasterAuras() const case SPELL_AURA_MOD_SILENCE: case SPELL_AURA_MOD_PACIFY: case SPELL_AURA_MOD_PACIFY_SILENCE: - if (m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY) + if (m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_PACIFY) return SPELL_FAILED_PACIFIED; - else if (m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + else if (m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE) return SPELL_FAILED_SILENCED; break; default: break; -- cgit v1.2.3 From 55d5cd37df8f3415b71dac1e50ecc970873d6deb Mon Sep 17 00:00:00 2001 From: Shauren Date: Sat, 25 Jun 2016 10:50:28 +0200 Subject: Core/Auras: Implemented aura 321 SPELL_AURA_MOD_NO_ACTIONS --- src/server/game/Entities/Unit/Unit.h | 3 ++- src/server/game/Spells/Auras/SpellAuraDefines.h | 2 +- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 31 ++++++++++++++++++++++- src/server/game/Spells/Auras/SpellAuraEffects.h | 1 + src/server/game/Spells/Spell.cpp | 4 ++- 5 files changed, 37 insertions(+), 4 deletions(-) (limited to 'src/server/game/Spells/Spell.cpp') diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 48e7cb86fcf..5cbe29996dc 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -729,7 +729,8 @@ enum UnitFlags2 UNIT_FLAG2_DISABLE_TURN = 0x00008000, UNIT_FLAG2_UNK2 = 0x00010000, UNIT_FLAG2_PLAY_DEATH_ANIM = 0x00020000, // Plays special death animation upon death - UNIT_FLAG2_ALLOW_CHEAT_SPELLS = 0x00040000 // Allows casting spells with AttributesEx7 & SPELL_ATTR7_IS_CHEAT_SPELL + UNIT_FLAG2_ALLOW_CHEAT_SPELLS = 0x00040000, // Allows casting spells with AttributesEx7 & SPELL_ATTR7_IS_CHEAT_SPELL + UNIT_FLAG2_NO_ACTIONS = 0x00800000 }; /// Non Player Character flags diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 70a08d05d5f..ae34e06fe37 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -378,7 +378,7 @@ enum AuraType SPELL_AURA_MASTERY = 318, SPELL_AURA_MOD_MELEE_HASTE_3 = 319, SPELL_AURA_MOD_RANGED_HASTE_2 = 320, - SPELL_AURA_321 = 321, + SPELL_AURA_MOD_NO_ACTIONS = 321, SPELL_AURA_INTERFERE_TARGETTING = 322, // NYI SPELL_AURA_323 = 323, // Not used in 4.3.4 SPELL_AURA_324 = 324, // spell critical chance (probably by school mask) diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 4ae91981448..9e46b2d1d35 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -380,7 +380,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleMastery, //318 SPELL_AURA_MASTERY &AuraEffect::HandleModMeleeSpeedPct, //319 SPELL_AURA_MOD_MELEE_HASTE_3 &AuraEffect::HandleAuraModRangedHaste, //320 SPELL_AURA_MOD_RANGED_HASTE_2 - &AuraEffect::HandleNULL, //321 SPELL_AURA_321 + &AuraEffect::HandleAuraModNoActions, //321 SPELL_AURA_MOD_NO_ACTIONS &AuraEffect::HandleNULL, //322 SPELL_AURA_INTERFERE_TARGETTING &AuraEffect::HandleUnused, //323 unused (4.3.4) &AuraEffect::HandleNULL, //324 SPELL_AURA_324 @@ -2509,6 +2509,35 @@ void AuraEffect::HandleAuraAllowOnlyAbility(AuraApplication const* aurApp, uint8 } } +void AuraEffect::HandleAuraModNoActions(AuraApplication const* aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit* target = aurApp->GetTarget(); + + if (apply) + { + target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_NO_ACTIONS); + + // call functions which may have additional effects after chainging state of unit + // Stop cast only spells vs PreventionType & SPELL_PREVENTION_TYPE_SILENCE + for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) + if (Spell* spell = target->GetCurrentSpell(CurrentSpellTypes(i))) + if (spell->m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_NO_ACTIONS) + // Stop spells on prepare or casting state + target->InterruptSpell(CurrentSpellTypes(i), false); + } + else + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if (target->HasAuraType(SPELL_AURA_MOD_NO_ACTIONS)) + return; + + target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_NO_ACTIONS); + } +} + /****************************/ /*** TRACKING ***/ /****************************/ diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 7d1df37eb42..a046a675eb4 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -167,6 +167,7 @@ class TC_GAME_API AuraEffect void HandleAuraModPacify(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraModPacifyAndSilence(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraAllowOnlyAbility(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleAuraModNoActions(AuraApplication const* aurApp, uint8 mode, bool apply) const; // tracking void HandleAuraTrackResources(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraTrackCreatures(AuraApplication const* aurApp, uint8 mode, bool apply) const; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index b77cac83e34..bc34002a33b 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5749,7 +5749,7 @@ SpellCastResult Spell::CheckCasterAuras() const Unit::AuraEffectList const& stunAuras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_STUN); for (Unit::AuraEffectList::const_iterator i = stunAuras.begin(); i != stunAuras.end(); ++i) { - if ((*i)->GetSpellInfo()->GetAllEffectsMechanicMask() && !((*i)->GetSpellInfo()->GetAllEffectsMechanicMask() & (1<GetSpellInfo()->GetAllEffectsMechanicMask() && !((*i)->GetSpellInfo()->GetAllEffectsMechanicMask() & (1 << MECHANIC_STUN))) { foundNotStun = true; break; @@ -5769,6 +5769,8 @@ SpellCastResult Spell::CheckCasterAuras() const prevented_reason = SPELL_FAILED_SILENCED; else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_PACIFY) prevented_reason = SPELL_FAILED_PACIFIED; + else if (m_caster->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_NO_ACTIONS) && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_NO_ACTIONS) + prevented_reason = SPELL_FAILED_NO_ACTIONS; // Attr must make flag drop spell totally immune from all effects if (prevented_reason != SPELL_CAST_OK) -- cgit v1.2.3 From b3d814ee50b265c140d65b6f92ce42482ce1f39b Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 28 Jun 2016 17:38:19 +0200 Subject: Core/Spells: Fixed spell effect on caster not being processed instantly for spells that have travel time and hit both caster and another unit --- src/server/game/Spells/Spell.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/server/game/Spells/Spell.cpp') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index bc34002a33b..34261f4f0e2 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -6824,8 +6824,8 @@ bool SpellEvent::Execute(uint64 e_time, uint32 p_time) return true; // spell is deletable, finish event } // event will be re-added automatically at the end of routine) - } break; - + break; + } case SPELL_STATE_DELAYED: { // first, check, if we have just started @@ -6875,17 +6875,21 @@ bool SpellEvent::Execute(uint64 e_time, uint32 p_time) { // delaying had just started, record the moment m_Spell->SetDelayStart(e_time); + // handle effects on caster if the spell has travel time but also affects the caster in some way + uint64 n_offset = m_Spell->handle_delayed(0); + ASSERT(n_offset == m_Spell->GetDelayMoment()); // re-plan the event for the delay moment m_Spell->GetCaster()->m_Events.AddEvent(this, e_time + m_Spell->GetDelayMoment(), false); return false; // event not complete } - } break; - + break; + } default: { // all other states // event will be re-added automatically at the end of routine) - } break; + break; + } } // spell processing not complete, plan event on the next update interval -- cgit v1.2.3 From 7ed1c47f6b336cc7953373de60e964ba0a076b36 Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 29 Jun 2016 19:49:23 +0200 Subject: Core/Auras: Implemented SPELL_AURA_OVERRIDE_SPELL_VISUAL --- .../game/Entities/AreaTrigger/AreaTrigger.cpp | 18 +++++--- src/server/game/Entities/AreaTrigger/AreaTrigger.h | 3 +- .../game/Entities/DynamicObject/DynamicObject.cpp | 11 +++-- .../game/Entities/DynamicObject/DynamicObject.h | 3 +- src/server/game/Entities/Unit/Unit.cpp | 18 ++++++++ src/server/game/Entities/Unit/Unit.h | 1 + src/server/game/Spells/Auras/SpellAuraEffects.cpp | 2 +- src/server/game/Spells/Auras/SpellAuras.cpp | 4 +- src/server/game/Spells/Auras/SpellAuras.h | 3 +- src/server/game/Spells/Spell.cpp | 6 +-- src/server/game/Spells/SpellEffects.cpp | 10 ++--- src/server/game/Spells/SpellInfo.cpp | 41 ++++++++++++------ src/server/game/Spells/SpellInfo.h | 4 +- src/server/game/Spells/SpellMgr.cpp | 48 +++++++++++----------- 14 files changed, 111 insertions(+), 61 deletions(-) (limited to 'src/server/game/Spells/Spell.cpp') diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp index 68ee386be3f..568c0e39469 100644 --- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp +++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp @@ -15,13 +15,14 @@ * with this program. If not, see . */ -#include "Unit.h" -#include "SpellInfo.h" +#include "AreaTrigger.h" +#include "DB2Stores.h" #include "Log.h" +#include "SpellInfo.h" +#include "Unit.h" #include "UpdateData.h" -#include "AreaTrigger.h" -AreaTrigger::AreaTrigger() : WorldObject(false), _duration(0) +AreaTrigger::AreaTrigger() : WorldObject(false), _duration(0), _spellXSpellVisualId(0) { m_objectType |= TYPEMASK_AREATRIGGER; m_objectTypeId = TYPEID_AREATRIGGER; @@ -56,8 +57,9 @@ void AreaTrigger::RemoveFromWorld() } } -bool AreaTrigger::CreateAreaTrigger(ObjectGuid::LowType guidlow, uint32 triggerEntry, Unit* caster, SpellInfo const* spell, Position const& pos) +bool AreaTrigger::CreateAreaTrigger(ObjectGuid::LowType guidlow, uint32 triggerEntry, Unit* caster, SpellInfo const* spell, Position const& pos, uint32 spellXSpellVisualId) { + _spellXSpellVisualId = spellXSpellVisualId; SetMap(caster->GetMap()); Relocate(pos); if (!IsPositionValid()) @@ -69,13 +71,17 @@ bool AreaTrigger::CreateAreaTrigger(ObjectGuid::LowType guidlow, uint32 triggerE Object::_Create(ObjectGuid::Create(GetMapId(), triggerEntry, guidlow)); SetPhaseMask(caster->GetPhaseMask(), false); + uint32 spellVisual = 0; + if (SpellXSpellVisualEntry const* visual = sSpellXSpellVisualStore.LookupEntry(spellXSpellVisualId)) + spellVisual = visual->SpellVisualID[0]; + SetEntry(triggerEntry); SetDuration(spell->GetDuration()); SetObjectScale(1); SetGuidValue(AREATRIGGER_CASTER, caster->GetGUID()); SetUInt32Value(AREATRIGGER_SPELLID, spell->Id); - SetUInt32Value(AREATRIGGER_SPELLVISUALID, spell->GetSpellVisual(GetMap()->GetDifficultyID())); + SetUInt32Value(AREATRIGGER_SPELLVISUALID, spellVisual); SetUInt32Value(AREATRIGGER_DURATION, spell->GetDuration()); CopyPhaseFrom(caster); diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.h b/src/server/game/Entities/AreaTrigger/AreaTrigger.h index e3caa6d2e95..1b3e6f02a3e 100644 --- a/src/server/game/Entities/AreaTrigger/AreaTrigger.h +++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.h @@ -32,7 +32,7 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObjectGetMap()); Relocate(pos); if (!IsPositionValid()) @@ -93,10 +94,14 @@ bool DynamicObject::CreateDynamicObject(ObjectGuid::LowType guidlow, Unit* caste WorldObject::_Create(ObjectGuid::Create(GetMapId(), spell->Id, guidlow)); SetPhaseMask(caster->GetPhaseMask(), false); + uint32 spellVisual = 0; + if (SpellXSpellVisualEntry const* visual = sSpellXSpellVisualStore.LookupEntry(spellXSpellVisualId)) + spellVisual = visual->SpellVisualID[0]; + SetEntry(spell->Id); SetObjectScale(1.0f); SetGuidValue(DYNAMICOBJECT_CASTER, caster->GetGUID()); - SetUInt32Value(DYNAMICOBJECT_BYTES, spell->GetSpellVisual(GetMap()->GetDifficultyID()) | (type << 28)); + SetUInt32Value(DYNAMICOBJECT_BYTES, spellVisual | (type << 28)); SetUInt32Value(DYNAMICOBJECT_SPELLID, spell->Id); SetFloatValue(DYNAMICOBJECT_RADIUS, radius); SetUInt32Value(DYNAMICOBJECT_CASTTIME, getMSTime()); diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.h b/src/server/game/Entities/DynamicObject/DynamicObject.h index 09426a3c044..4d1cdefdd48 100644 --- a/src/server/game/Entities/DynamicObject/DynamicObject.h +++ b/src/server/game/Entities/DynamicObject/DynamicObject.h @@ -41,7 +41,7 @@ class TC_GAME_API DynamicObject : public WorldObject, public GridObjectGetMiscValue() == spellInfo->Id) + { + if (SpellInfo const* visualSpell = sSpellMgr->GetSpellInfo(effect->GetMiscValueB())) + { + spellInfo = visualSpell; + break; + } + } + } + + return spellInfo->GetSpellXSpellVisualId(this); +} + struct CombatLogSender { WorldObject const* i_source; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 5cbe29996dc..2ee0ea8873a 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1931,6 +1931,7 @@ class TC_GAME_API Unit : public WorldObject Spell* FindCurrentSpellBySpellId(uint32 spell_id) const; int32 GetCurrentSpellCastTime(uint32 spell_id) const; virtual SpellInfo const* GetCastSpellInfo(SpellInfo const* spellInfo) const; + uint32 GetCastSpellXSpellVisualId(SpellInfo const* spellInfo) const; SpellHistory* GetSpellHistory() { return _spellHistory; } SpellHistory const* GetSpellHistory() const { return _spellHistory; } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 9e46b2d1d35..136aea7a811 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -462,7 +462,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleAuraModSkill, //400 SPELL_AURA_MOD_SKILL_2 &AuraEffect::HandleNULL, //401 &AuraEffect::HandleNULL, //402 - &AuraEffect::HandleNULL, //403 + &AuraEffect::HandleNoImmediateEffect, //403 SPELL_AURA_OVERRIDE_SPELL_VISUAL implemented in Unit::GetCastSpellXSpellVisualId &AuraEffect::HandleOverrideAttackPowerBySpellPower, //404 SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT &AuraEffect::HandleNULL, //405 SPELL_AURA_MOD_RATING_PCT &AuraEffect::HandleNULL, //406 diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index e7c932e8a3b..b337e4aca58 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -202,7 +202,7 @@ void AuraApplication::BuildUpdatePacket(WorldPackets::Spells::AuraInfo& auraInfo WorldPackets::Spells::AuraDataInfo auraData; auraData.SpellID = aura->GetId(); - auraData.SpellXSpellVisualID = aura->GetSpellInfo()->GetSpellXSpellVisualId(_target->GetMap()->GetDifficultyID()); + auraData.SpellXSpellVisualID = aura->GetSpellXSpellVisualId(); auraData.Flags = GetFlags(); if (aura->GetMaxDuration() > 0 && !(aura->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_HIDE_DURATION)) auraData.Flags |= AFLAG_DURATION; @@ -365,7 +365,7 @@ Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* own Aura::Aura(SpellInfo const* spellproto, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel) : m_spellInfo(spellproto), m_casterGuid(!casterGUID.IsEmpty() ? casterGUID : caster->GetGUID()), -m_castItemGuid(castItem ? castItem->GetGUID() : ObjectGuid::Empty), m_castItemLevel(castItemLevel), +m_castItemGuid(castItem ? castItem->GetGUID() : ObjectGuid::Empty), m_castItemLevel(castItemLevel), m_spellXSpellVisualId(caster ? caster->GetCastSpellXSpellVisualId(spellproto) : spellproto->GetSpellXSpellVisualId()), m_applyTime(time(NULL)), m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0), m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1), m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr), diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 27e2333bd97..33b4f41c34d 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -133,6 +133,7 @@ class TC_GAME_API Aura ObjectGuid GetCastItemGUID() const { return m_castItemGuid; } int32 GetCastItemLevel() const { return m_castItemLevel; } ObjectGuid GetCasterGUID() const { return m_casterGuid; } + uint32 GetSpellXSpellVisualId() const { return m_spellXSpellVisualId; } Unit* GetCaster() const; WorldObject* GetOwner() const { return m_owner; } Unit* GetUnitOwner() const { ASSERT(GetType() == UNIT_AURA_TYPE); return (Unit*)m_owner; } @@ -300,6 +301,7 @@ class TC_GAME_API Aura ObjectGuid const m_casterGuid; ObjectGuid const m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted int32 m_castItemLevel; + uint32 const m_spellXSpellVisualId; time_t const m_applyTime; WorldObject* const m_owner; @@ -313,7 +315,6 @@ class TC_GAME_API Aura uint8 m_procCharges; // Aura charges (0 for infinite) uint8 m_stackAmount; // Aura stack amount - //AuraEffect* m_effects[3]; ApplicationMap m_applications; bool m_isRemoved; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 34261f4f0e2..a09d97b8e68 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -591,7 +591,7 @@ m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)), focusObject = NULL; m_cast_count = 0; memset(m_misc.Raw.Data, 0, sizeof(m_misc.Raw.Data)); - m_SpellVisual = m_spellInfo->GetSpellXSpellVisualId(caster->GetMap()->GetDifficultyID()); + m_SpellVisual = caster->GetCastSpellXSpellVisualId(m_spellInfo); m_preCastSpell = 0; m_triggeredByAuraSpell = NULL; m_spellAura = NULL; @@ -4355,7 +4355,7 @@ void Spell::SendChannelStart(uint32 duration) m_caster->SetChannelObjectGuid(channelTarget); m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL, m_spellInfo->Id); - m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL_X_SPELL_VISUAL, m_spellInfo->GetSpellXSpellVisualId(m_caster->GetMap()->GetDifficultyID())); + m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL_X_SPELL_VISUAL, m_SpellVisual); } void Spell::SendResurrectRequest(Player* target) @@ -6763,7 +6763,7 @@ bool Spell::IsAutoActionResetSpell() const bool Spell::IsNeedSendToClient() const { - return m_spellInfo->GetSpellXSpellVisualId(m_caster->GetMap()->GetDifficultyID()) || m_spellInfo->IsChanneled() || + return m_SpellVisual || m_spellInfo->IsChanneled() || (m_spellInfo->HasAttribute(SPELL_ATTR8_AURA_SEND_AMOUNT)) || m_spellInfo->Speed > 0.0f || (!m_triggeredByAuraSpell && !IsTriggered()); } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 9f457e5672a..193cdeb2c8f 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1542,7 +1542,7 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex) if (!caster->IsInWorld()) return; DynamicObject* dynObj = new DynamicObject(false); - if (!dynObj->CreateDynamicObject(caster->GetMap()->GenerateLowGuid(), caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL)) + if (!dynObj->CreateDynamicObject(caster->GetMap()->GenerateLowGuid(), caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL, m_SpellVisual)) { delete dynObj; return; @@ -2383,7 +2383,7 @@ void Spell::EffectAddFarsight(SpellEffIndex /*effIndex*/) return; DynamicObject* dynObj = new DynamicObject(true); - if (!dynObj->CreateDynamicObject(m_caster->GetMap()->GenerateLowGuid(), m_caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS)) + if (!dynObj->CreateDynamicObject(m_caster->GetMap()->GenerateLowGuid(), m_caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS, m_SpellVisual)) { delete dynObj; return; @@ -2642,10 +2642,10 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex) else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN) duration = 3600; // 30 mins // other cases with this SpellVisual already selected - else if (m_spellInfo->GetSpellVisual(DIFFICULTY_NONE) == 215) + else if (m_spellInfo->GetSpellVisual() == 215) duration = 1800; // 30 mins // some fishing pole bonuses except Glow Worm which lasts full hour - else if (m_spellInfo->GetSpellVisual(DIFFICULTY_NONE) == 563 && m_spellInfo->Id != 64401) + else if (m_spellInfo->GetSpellVisual() == 563 && m_spellInfo->Id != 64401) duration = 600; // 10 mins else if (m_spellInfo->Id == 29702) duration = 300; // 5 mins @@ -5693,7 +5693,7 @@ void Spell::EffectCreateAreaTrigger(SpellEffIndex /*effIndex*/) uint32 triggerEntry = effectInfo->MiscValue; AreaTrigger * areaTrigger = new AreaTrigger; - if (!areaTrigger->CreateAreaTrigger(GetCaster()->GetMap()->GenerateLowGuid(), triggerEntry, GetCaster(), GetSpellInfo(), pos)) + if (!areaTrigger->CreateAreaTrigger(GetCaster()->GetMap()->GenerateLowGuid(), triggerEntry, GetCaster(), GetSpellInfo(), pos, m_SpellVisual)) delete areaTrigger; } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 25a5c874a58..f38cf40dd96 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1039,6 +1039,9 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectEntryMap const& ef ActiveIconID = _misc ? _misc->ActiveIconID : 0; _visuals = std::move(visuals); + // sort all visuals so that the ones without a condition requirement are last on the list + for (auto& visualPair : _visuals) + std::sort(visualPair.second.begin(), visualPair.second.end(), [](SpellXSpellVisualEntry const* first, SpellXSpellVisualEntry const* second) { return first->PlayerConditionID > second->PlayerConditionID; }); // SpellScalingEntry SpellScalingEntry const* _scaling = GetSpellScaling(); @@ -2935,32 +2938,46 @@ bool SpellInfo::IsHighRankOf(SpellInfo const* spellInfo) const return false; } -uint32 SpellInfo::GetSpellXSpellVisualId(Difficulty difficulty) const +uint32 SpellInfo::GetSpellXSpellVisualId(Unit const* caster /*= nullptr*/) const { - DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty); - while (difficultyEntry) + if (caster) { - auto itr = _visuals.find(difficulty); - if (itr != _visuals.end()) - for (SpellXSpellVisualEntry const* visual : itr->second) - if (!visual->PlayerConditionID) - return visual->ID; + Difficulty difficulty = caster->GetMap()->GetDifficultyID(); + DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty); + while (difficultyEntry) + { + auto itr = _visuals.find(difficulty); + if (itr != _visuals.end()) + { + for (SpellXSpellVisualEntry const* visual : itr->second) + { + PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(visual->PlayerConditionID); + if (!playerCondition || (caster->GetTypeId() == TYPEID_PLAYER && sConditionMgr->IsPlayerMeetingCondition(caster->ToPlayer(), playerCondition))) + return visual->ID; + } + } - difficultyEntry = sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID); + difficultyEntry = sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID); + } } auto itr = _visuals.find(DIFFICULTY_NONE); if (itr != _visuals.end()) + { for (SpellXSpellVisualEntry const* visual : itr->second) - if (!visual->PlayerConditionID) + { + PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(visual->PlayerConditionID); + if (!playerCondition || (caster && caster->GetTypeId() == TYPEID_PLAYER && sConditionMgr->IsPlayerMeetingCondition(caster->ToPlayer(), playerCondition))) return visual->ID; + } + } return 0; } -uint32 SpellInfo::GetSpellVisual(Difficulty difficulty, Player* /*forPlayer*/ /*= nullptr*/) const +uint32 SpellInfo::GetSpellVisual(Unit const* caster /*= nullptr*/) const { - if (SpellXSpellVisualEntry const* visual = sSpellXSpellVisualStore.LookupEntry(GetSpellXSpellVisualId(difficulty))) + if (SpellXSpellVisualEntry const* visual = sSpellXSpellVisualStore.LookupEntry(GetSpellXSpellVisualId(caster))) { //if (visual->SpellVisualID[1] && forPlayer->GetViolenceLevel() operator 2) // return visual->SpellVisualID[1]; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 3ca96b3c0e9..f749539f51f 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -573,8 +573,8 @@ public: bool IsDifferentRankOf(SpellInfo const* spellInfo) const; bool IsHighRankOf(SpellInfo const* spellInfo) const; - uint32 GetSpellXSpellVisualId(Difficulty difficulty) const; - uint32 GetSpellVisual(Difficulty difficulty, Player* forPlayer = nullptr) const; + uint32 GetSpellXSpellVisualId(Unit const* caster = nullptr) const; + uint32 GetSpellVisual(Unit const* caster = nullptr) const; // loading helpers void _InitializeExplicitTargetMask(); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index d001705bc79..6768eb10b46 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -69,24 +69,24 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) case SPELLFAMILY_GENERIC: { // Entrapment -- 135373 - if (spellproto->SpellIconID == 20 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39588) + if (spellproto->SpellIconID == 20 && spellproto->GetSpellVisual() == 39588) return DIMINISHING_ROOT; // Intimidation -- 24394 - if (spellproto->SpellIconID == 166 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 2816) + if (spellproto->SpellIconID == 166 && spellproto->GetSpellVisual() == 2816) return DIMINISHING_STUN; // Pulverize (Primal Earth Elemental) -- 118345 - if (spellproto->SpellIconID == 4507 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39877) + if (spellproto->SpellIconID == 4507 && spellproto->GetSpellVisual() == 39877) return DIMINISHING_STUN; // Static Charge (Capacitor Totem) -- 118905 - if (spellproto->SpellIconID == 54 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 24442) + if (spellproto->SpellIconID == 54 && spellproto->GetSpellVisual() == 24442) return DIMINISHING_STUN; // Remorseless Winter -- 115001 - if (spellproto->SpellIconID == 5744 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 23514) + if (spellproto->SpellIconID == 5744 && spellproto->GetSpellVisual() == 23514) return DIMINISHING_STUN; // Gorefiend's Grasp -- 108199 - if (spellproto->SpellIconID == 5743 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 28937) + if (spellproto->SpellIconID == 5743 && spellproto->GetSpellVisual() == 28937) return DIMINISHING_AOE_KNOCKBACK; break; } @@ -151,7 +151,7 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) if (spellproto->SpellFamilyFlags[1] & 0x8000000) return DIMINISHING_INCAPACITATE; // Blood Horror -- 137143, no flags (17986) - if (spellproto->SpellIconID == 6447 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 26758) + if (spellproto->SpellIconID == 6447 && spellproto->GetSpellVisual() == 26758) return DIMINISHING_INCAPACITATE; // Fear -- 118699 @@ -195,11 +195,11 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) if (spellproto->SpellFamilyFlags[0] & 0x2000) return DIMINISHING_STUN; // Rake -- 163505 -- no flags on the stun, 20490 - if (spellproto->SpellIconID == 494 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 38283) + if (spellproto->SpellIconID == 494 && spellproto->GetSpellVisual() == 38283) return DIMINISHING_STUN; // Incapacitating Roar -- 99, no flags on the stun, 14 - if (spellproto->SpellIconID == 960 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 38528) + if (spellproto->SpellIconID == 960 && spellproto->GetSpellVisual() == 38528) return DIMINISHING_INCAPACITATE; // Cyclone -- 33786 @@ -221,7 +221,7 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) if (spellproto->SpellFamilyFlags[0] & 0x200) return DIMINISHING_ROOT; // Mass Entanglement -- 102359, no flags on the root, 13535 - if (spellproto->SpellIconID == 5782 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 38269) + if (spellproto->SpellIconID == 5782 && spellproto->GetSpellVisual() == 38269) return DIMINISHING_ROOT; // Faerie Fire -- 770, 20 seconds in PvP (6.0) @@ -260,14 +260,14 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) // return DIMINISHING_AOE_KNOCKBACK; // Charge (Tenacity pet) -- 53148, no flags (5526) - if (spellproto->SpellIconID == 1559 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39480) + if (spellproto->SpellIconID == 1559 && spellproto->GetSpellVisual() == 39480) return DIMINISHING_ROOT; // Narrow Escape -- 136634, no flags (17964) if (spellproto->SpellIconID == 3342 && spellproto->SchoolMask == 8) return DIMINISHING_ROOT; // Binding Shot -- 117526, no flags (15581) - if (spellproto->SpellIconID == 4612 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 6859) + if (spellproto->SpellIconID == 4612 && spellproto->GetSpellVisual() == 6859) return DIMINISHING_STUN; // Freezing Trap -- 3355 @@ -314,7 +314,7 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) if (spellproto->SpellFamilyFlags[2] & 0x4000) return DIMINISHING_ROOT; // Frost Shock (with Frozen Power) -- 63685, no flags (6918) - if (spellproto->SpellIconID == 193 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39876) + if (spellproto->SpellIconID == 193 && spellproto->GetSpellVisual() == 39876) return DIMINISHING_ROOT; break; } @@ -325,31 +325,31 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) return DIMINISHING_SILENCE; // Chains of Ice (with Chilblains) -- 96294, no flags (13020) - if (spellproto->SpellIconID == 180 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 20135) + if (spellproto->SpellIconID == 180 && spellproto->GetSpellVisual() == 20135) return DIMINISHING_ROOT; // Asphyxiate -- 108194 if (spellproto->SpellFamilyFlags[2] & 0x100000) return DIMINISHING_STUN; // Gnaw (Ghoul) -- 91800, no flags (12511) - if (spellproto->SpellIconID == 3010 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 38760) + if (spellproto->SpellIconID == 3010 && spellproto->GetSpellVisual() == 38760) return DIMINISHING_STUN; // Monstrous Blow (Ghoul w/ Dark Transformation active) -- 91797, no flags (12510) - if (spellproto->SpellIconID == 15 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 38761) + if (spellproto->SpellIconID == 15 && spellproto->GetSpellVisual() == 38761) return DIMINISHING_STUN; break; } case SPELLFAMILY_PRIEST: { // Glyph of Mind Blast -- 87194, no flags (10092) - if (spellproto->SpellIconID == 2114 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 38927) + if (spellproto->SpellIconID == 2114 && spellproto->GetSpellVisual() == 38927) return DIMINISHING_ROOT; // Void Tendrils -- 114404, no flags (15067) - if (spellproto->SpellIconID == 5816 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 25199) + if (spellproto->SpellIconID == 5816 && spellproto->GetSpellVisual() == 25199) return DIMINISHING_ROOT; // Dominate Mind -- 605 - if (spellproto->SpellFamilyFlags[0] & 0x20000 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39068) + if (spellproto->SpellFamilyFlags[0] & 0x20000 && spellproto->GetSpellVisual() == 39068) return DIMINISHING_INCAPACITATE; // Holy Word: Chastise -- 88625 if (spellproto->SpellFamilyFlags[2] & 0x20) @@ -370,7 +370,7 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) case SPELLFAMILY_MONK: { // Disable -- 116706, no flags (15483) - if (spellproto->SpellIconID == 23 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39984) + if (spellproto->SpellIconID == 23 && spellproto->GetSpellVisual() == 39984) return DIMINISHING_ROOT; // Charging Ox Wave -- 119392 @@ -384,13 +384,13 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) return DIMINISHING_STUN; // Glyph of Breath of Fire -- 123393, no flags (16504) - if (spellproto->SpellIconID == 15 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 25408) + if (spellproto->SpellIconID == 15 && spellproto->GetSpellVisual() == 25408) return DIMINISHING_INCAPACITATE; // Paralysis -- 115078 if (spellproto->SpellFamilyFlags[2] & 0x800000) return DIMINISHING_INCAPACITATE; // Ring of Peace -- 137460, no flags (18006) - if (spellproto->SpellIconID == 7195 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39999) + if (spellproto->SpellIconID == 7195 && spellproto->GetSpellVisual() == 39999) return DIMINISHING_INCAPACITATE; break; } @@ -444,7 +444,7 @@ int32 GetDiminishingReturnsLimitDuration(SpellInfo const* spellproto) case SPELLFAMILY_HUNTER: { // Binding Shot - 3 seconds in PvP (6.0) - if (spellproto->SpellIconID == 4612 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 6859) + if (spellproto->SpellIconID == 4612 && spellproto->GetSpellVisual() == 6859) return 3 * IN_MILLISECONDS; // Wyvern Sting - 6 seconds in PvP (6.0) if (spellproto->SpellFamilyFlags[1] & 0x1000) @@ -2835,7 +2835,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes() if (!spellInfo->_IsPositiveEffect(EFFECT_2, false)) spellInfo->AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF2; - if (spellInfo->GetSpellVisual(DIFFICULTY_NONE) == 3879) + if (spellInfo->GetSpellVisual() == 3879) spellInfo->AttributesCu |= SPELL_ATTR0_CU_CONE_BACK; if (talentSpells.count(spellInfo->Id)) -- cgit v1.2.3 From ef396877ae68e6f71638b1da961a295131feb8da Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 1 Jul 2016 20:26:49 +0200 Subject: Core/Spells: Fixed spell range check Closes #17060 (cherry picked from commit e6a52d4aae9e8facc46c3b05e0560d540a928d73) --- src/server/game/Entities/Item/ItemTemplate.h | 1 + src/server/game/Entities/Unit/Unit.cpp | 8 +- src/server/game/Entities/Unit/Unit.h | 1 - src/server/game/Spells/Spell.cpp | 92 ++++++++++++++-------- .../EasternKingdoms/Karazhan/boss_moroes.cpp | 2 +- 5 files changed, 64 insertions(+), 40 deletions(-) (limited to 'src/server/game/Spells/Spell.cpp') diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h index d69f1c88845..76c129d325a 100644 --- a/src/server/game/Entities/Item/ItemTemplate.h +++ b/src/server/game/Entities/Item/ItemTemplate.h @@ -680,6 +680,7 @@ struct TC_GAME_API ItemTemplate uint32 GetScalingStatDistribution() const { return ExtendedData->ScalingStatDistribution; } uint32 GetDamageType() const { return ExtendedData->DamageType; } uint32 GetDelay() const { return ExtendedData->Delay; } + float GetRangedModRange() const { return ExtendedData->RangedModRange; } ItemBondingType GetBonding() const { return ItemBondingType(ExtendedData->Bonding); } char const* GetName(LocaleConstant locale) const; uint32 GetPageText() const { return ExtendedData->PageText; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f65449dbf74..c408d4390cd 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -484,12 +484,6 @@ void Unit::resetAttackTimer(WeaponAttackType type) m_attackTimer[type] = uint32(GetAttackTime(type) * m_modAttackSpeedPct[type]); } -float Unit::GetMeleeReach() const -{ - float reach = m_floatValues[UNIT_FIELD_COMBATREACH]; - return reach > MIN_MELEE_REACH ? reach : MIN_MELEE_REACH; -} - bool Unit::IsWithinCombatRange(const Unit* obj, float dist2compare) const { if (!obj || !IsInMap(obj) || !IsInPhase(obj)) @@ -516,7 +510,7 @@ bool Unit::IsWithinMeleeRange(const Unit* obj, float dist) const float dz = GetPositionZMinusOffset() - obj->GetPositionZMinusOffset(); float distsq = dx*dx + dy*dy + dz*dz; - float sizefactor = GetMeleeReach() + obj->GetMeleeReach(); + float sizefactor = GetCombatReach() + obj->GetCombatReach() + 4.0f / 3.0f; float maxdist = dist + sizefactor; return distsq < maxdist * maxdist; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 2ee0ea8873a..962d9549f2c 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1365,7 +1365,6 @@ class TC_GAME_API Unit : public WorldObject bool CanDualWield() const { return m_canDualWield; } virtual void SetCanDualWield(bool value) { m_canDualWield = value; } float GetCombatReach() const { return m_floatValues[UNIT_FIELD_COMBATREACH]; } - float GetMeleeReach() const; bool IsWithinCombatRange(const Unit* obj, float dist2compare) const; bool IsWithinMeleeRange(const Unit* obj, float dist = MELEE_RANGE) const; void GetRandomContactPoint(const Unit* target, float &x, float &y, float &z, float distance2dMin, float distance2dMax) const; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index a09d97b8e68..2b59926fa33 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5924,43 +5924,73 @@ SpellCastResult Spell::CheckRange(bool strict) if (!strict && m_casttime == 0) return SPELL_CAST_OK; - uint32 range_type = 0; + Unit* target = m_targets.GetUnitTarget(); + float minRange = 0.0f; + float maxRange = 0.0f; + float rangeMod = 0.0f; + if (strict && IsNextMeleeSwingSpell()) + maxRange = 100.0f; + else if (m_spellInfo->RangeEntry) + { + if (m_spellInfo->RangeEntry->Flags & SPELL_RANGE_MELEE) + { + rangeMod = m_caster->GetCombatReach() + 4.0f / 3.0f; + if (target) + rangeMod += target->GetCombatReach(); + else + rangeMod += m_caster->GetCombatReach(); - if (m_spellInfo->RangeEntry) - { - // check needed by 68766 51693 - both spells are cast on enemies and have 0 max range - // these are triggered by other spells - possibly we should omit range check in that case? - if (m_spellInfo->RangeEntry->ID == 1) - return SPELL_CAST_OK; + rangeMod = std::max(rangeMod, NOMINAL_MELEE_RANGE); + } + else + { + float meleeRange = 0.0f; + if (m_spellInfo->RangeEntry->Flags & SPELL_RANGE_RANGED) + { + meleeRange = m_caster->GetCombatReach() + 4.0f / 3.0f; + if (target) + meleeRange += target->GetCombatReach(); + else + meleeRange += m_caster->GetCombatReach(); + + meleeRange = std::max(meleeRange, NOMINAL_MELEE_RANGE); + } + + minRange = m_caster->GetSpellMinRangeForTarget(target, m_spellInfo) + meleeRange; + maxRange = m_caster->GetSpellMaxRangeForTarget(target, m_spellInfo); - range_type = m_spellInfo->RangeEntry->Flags; + if (target || m_targets.GetCorpseTarget()) + { + rangeMod = m_caster->GetCombatReach(); + if (target) + rangeMod += target->GetCombatReach(); + + if (minRange > 0.0f && !(m_spellInfo->RangeEntry->Flags & SPELL_RANGE_RANGED)) + minRange += rangeMod; + } + } + + if (target && m_caster->isMoving() && target->isMoving() && !m_caster->IsWalking() && !target->IsWalking() && + (m_spellInfo->RangeEntry->Flags & SPELL_RANGE_MELEE || target->GetTypeId() == TYPEID_PLAYER)) + rangeMod += 5.0f / 3.0f; } - Unit* target = m_targets.GetUnitTarget(); - float max_range = m_caster->GetSpellMaxRangeForTarget(target, m_spellInfo); - float min_range = m_caster->GetSpellMinRangeForTarget(target, m_spellInfo); + if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) && m_caster->GetTypeId() == TYPEID_PLAYER) + if (Item* ranged = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK, true)) + maxRange *= ranged->GetTemplate()->GetRangedModRange() * 0.01f; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, max_range, this); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, maxRange, this); + + maxRange += rangeMod; if (target && target != m_caster) { - if (range_type == SPELL_RANGE_MELEE) - { - // Because of lag, we can not check too strictly here. - if (!m_caster->IsWithinMeleeRange(target, max_range)) - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; - } - else if (!m_caster->IsWithinCombatRange(target, max_range)) - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; //0x5A; + if (!m_caster->IsInDist(target, maxRange)) + return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; - if (range_type == SPELL_RANGE_RANGED) - { - if (m_caster->IsWithinMeleeRange(target)) - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_TOO_CLOSE : SPELL_FAILED_DONT_REPORT; - } - else if (min_range && m_caster->IsWithinCombatRange(target, min_range)) // skip this check if min_range = 0 - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_TOO_CLOSE : SPELL_FAILED_DONT_REPORT; + if (minRange > 0.0f && m_caster->IsInDist(target, minRange)) + return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; if (m_caster->GetTypeId() == TYPEID_PLAYER && (m_spellInfo->FacingCasterFlags & SPELL_FACING_FLAG_INFRONT) && !m_caster->HasInArc(static_cast(M_PI), target)) @@ -5969,10 +5999,10 @@ SpellCastResult Spell::CheckRange(bool strict) if (m_targets.HasDst() && !m_targets.HasTraj()) { - if (!m_caster->IsWithinDist3d(m_targets.GetDstPos(), max_range)) - return SPELL_FAILED_OUT_OF_RANGE; - if (min_range && m_caster->IsWithinDist3d(m_targets.GetDstPos(), min_range)) - return SPELL_FAILED_TOO_CLOSE; + if (!m_caster->IsInDist(m_targets.GetDstPos(), maxRange)) + return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; + if (minRange > 0.0f && m_caster->IsInDist(m_targets.GetDstPos(), minRange)) + return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; } return SPELL_CAST_OK; diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp index b87c836c2a4..84ee5cd97db 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp @@ -298,7 +298,7 @@ public: if (Blind_Timer <= diff) { std::list targets; - SelectTargetList(targets, 5, SELECT_TARGET_RANDOM, me->GetMeleeReach()*5, true); + SelectTargetList(targets, 5, SELECT_TARGET_RANDOM, me->GetCombatReach()*5, true); for (std::list::const_iterator i = targets.begin(); i != targets.end(); ++i) if (!me->IsWithinMeleeRange(*i)) { -- cgit v1.2.3 From c0df97276815f6bdf10b3df938e242bec13d2a8b Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 5 Jul 2016 00:02:04 +0200 Subject: Core/Spells: Fixed crash with DEST targets added in b3d814ee50b265c140d65b6f92ce42482ce1f39b --- src/server/game/Spells/Spell.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/server/game/Spells/Spell.cpp') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 2b59926fa33..1068e406e78 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -6906,8 +6906,11 @@ bool SpellEvent::Execute(uint64 e_time, uint32 p_time) // delaying had just started, record the moment m_Spell->SetDelayStart(e_time); // handle effects on caster if the spell has travel time but also affects the caster in some way - uint64 n_offset = m_Spell->handle_delayed(0); - ASSERT(n_offset == m_Spell->GetDelayMoment()); + if (!m_Spell->m_targets.HasDst()) + { + uint64 n_offset = m_Spell->handle_delayed(0); + ASSERT(n_offset == m_Spell->GetDelayMoment()); + } // re-plan the event for the delay moment m_Spell->GetCaster()->m_Events.AddEvent(this, e_time + m_Spell->GetDelayMoment(), false); return false; // event not complete -- cgit v1.2.3 From b63346a25e2b7942bc618e91aa2b3d1690d6687a Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 5 Jul 2016 16:59:37 +0200 Subject: Core/Spells: Fixed spell dest range check failing on 0 distance max range requirement even if standing directly on top of destination (cherry picked from commit ba63361d7c20bf93a7089c517cd707c005949f62) --- src/server/game/Spells/Spell.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/server/game/Spells/Spell.cpp') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 1068e406e78..175b921b164 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5984,12 +5984,15 @@ SpellCastResult Spell::CheckRange(bool strict) maxRange += rangeMod; + minRange *= minRange; + maxRange *= maxRange; + if (target && target != m_caster) { - if (!m_caster->IsInDist(target, maxRange)) + if (m_caster->GetExactDistSq(target) > maxRange) return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; - if (minRange > 0.0f && m_caster->IsInDist(target, minRange)) + if (minRange > 0.0f && m_caster->GetExactDistSq(target) < minRange) return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; if (m_caster->GetTypeId() == TYPEID_PLAYER && @@ -5999,9 +6002,9 @@ SpellCastResult Spell::CheckRange(bool strict) if (m_targets.HasDst() && !m_targets.HasTraj()) { - if (!m_caster->IsInDist(m_targets.GetDstPos(), maxRange)) + if (m_caster->GetExactDistSq(m_targets.GetDstPos()) > maxRange) return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; - if (minRange > 0.0f && m_caster->IsInDist(m_targets.GetDstPos(), minRange)) + if (minRange > 0.0f && m_caster->GetExactDistSq(m_targets.GetDstPos()) < minRange) return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; } -- cgit v1.2.3