diff options
-rw-r--r-- | src/bindings/scripts/include/sc_creature.cpp | 12 | ||||
-rw-r--r-- | src/bindings/scripts/include/sc_creature.h | 2 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp | 2 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp | 2 | ||||
-rw-r--r-- | src/game/Creature.cpp | 8 | ||||
-rw-r--r-- | src/game/GameObject.cpp | 15 | ||||
-rw-r--r-- | src/game/Spell.cpp | 73 | ||||
-rw-r--r-- | src/game/SpellAuras.cpp | 12 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 21 | ||||
-rw-r--r-- | src/game/SpellMgr.h | 9 | ||||
-rw-r--r-- | src/game/TotemAI.cpp | 4 | ||||
-rw-r--r-- | src/game/Unit.cpp | 149 | ||||
-rw-r--r-- | src/game/Unit.h | 5 | ||||
-rw-r--r-- | src/shared/Database/DBCStructure.h | 15 | ||||
-rw-r--r-- | src/shared/Database/DBCfmt.cpp | 2 |
15 files changed, 199 insertions, 132 deletions
diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp index 8764f612557..9ed263398dc 100644 --- a/src/bindings/scripts/include/sc_creature.cpp +++ b/src/bindings/scripts/include/sc_creature.cpp @@ -508,13 +508,13 @@ SpellEntry const* ScriptedAI::SelectSpell(Unit* Target, int32 School, int32 Mech continue; //Check if the spell meets our range requirements - if (RangeMin && TempRange->maxRange < RangeMin) + if (RangeMin && m_creature->GetSpellMinRangeForTarget(Target, TempRange) < RangeMin) continue; - if (RangeMax && TempRange->maxRange > RangeMax) + if (RangeMax && m_creature->GetSpellMaxRangeForTarget(Target, TempRange) > RangeMax) continue; //Check if our target is in range - if (m_creature->IsWithinDistInMap(Target, TempRange->minRange) || !m_creature->IsWithinDistInMap(Target, TempRange->maxRange)) + if (m_creature->IsWithinDistInMap(Target, m_creature->GetSpellMinRangeForTarget(Target, TempRange)) || !m_creature->IsWithinDistInMap(Target, m_creature->GetSpellMaxRangeForTarget(Target, TempRange))) continue; //All good so lets add it to the spell list @@ -552,20 +552,20 @@ bool ScriptedAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered) return false; //Unit is out of range of this spell - if (m_creature->GetDistance(Target) > TempRange->maxRange || m_creature->GetDistance(Target) < TempRange->minRange) + if (m_creature->GetDistance(Target) > m_creature->GetSpellMaxRangeForTarget(Target, TempRange) || m_creature->GetDistance(Target) < m_creature->GetSpellMinRangeForTarget(Target, TempRange)) return false; return true; } -float GetSpellMaxRange(uint32 id) +float GetSpellMaxRangeForHostile(uint32 id) { SpellEntry const *spellInfo = GetSpellStore()->LookupEntry(id); if(!spellInfo) return 0; SpellRangeEntry const *range = GetSpellRangeStore()->LookupEntry(spellInfo->rangeIndex); if(!range) return 0; - return range->maxRange; + return range->maxRangeHostile; } void FillSpellSummary() diff --git a/src/bindings/scripts/include/sc_creature.h b/src/bindings/scripts/include/sc_creature.h index 866007cc52a..f72278595c8 100644 --- a/src/bindings/scripts/include/sc_creature.h +++ b/src/bindings/scripts/include/sc_creature.h @@ -11,7 +11,7 @@ #include "CreatureAI.h" #include "Creature.h" -float GetSpellMaxRange(uint32 id); +float GetSpellMaxRangeForHostile(uint32 id); class SummonList : std::list<uint64> { diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp index fed536832bf..9bf7fe0a437 100644 --- a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp @@ -333,7 +333,7 @@ struct TRINITY_DLL_DECL boss_alarAI : public ScriptedAI if(Charge_Timer < diff) { - Unit *target= SelectUnit(SELECT_TARGET_RANDOM, 1, GetSpellMaxRange(SPELL_CHARGE), true); + Unit *target= SelectUnit(SELECT_TARGET_RANDOM, 1, GetSpellMaxRangeForHostile(SPELL_CHARGE), true); DoCast(target, SPELL_CHARGE); Charge_Timer = 30000; }else Charge_Timer -= diff; diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp index 0220523a1e2..b047ebd04d6 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp @@ -407,7 +407,7 @@ struct TRINITY_DLL_DECL boss_nalorakkAI : public ScriptedAI { DoYell(YELL_SURGE, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_YELL_SURGE); - Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 1, GetSpellMaxRange(SPELL_SURGE), true); + Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 1, GetSpellMaxRangeForHostile(SPELL_SURGE), true); DoCast(target, SPELL_SURGE); Surge_Timer = 15000 + rand()%5000; }else Surge_Timer -= diff; diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 9a4b35f21f7..b6444b7c493 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1776,8 +1776,8 @@ SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim) if(spellInfo->manaCost > GetPower(POWER_MANA)) continue; SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); - float range = GetSpellMaxRange(srange); - float minrange = GetSpellMinRange(srange); + float range = GetSpellMaxRangeForHostile(srange); + float minrange = GetSpellMinRangeForHostile(srange); float dist = GetDistance(pVictim); //if(!isInFront( pVictim, range ) && spellInfo->AttributesEx ) // continue; @@ -1822,8 +1822,8 @@ SpellEntry const *Creature::reachWithSpellCure(Unit *pVictim) if(spellInfo->manaCost > GetPower(POWER_MANA)) continue; SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); - float range = GetSpellMaxRange(srange); - float minrange = GetSpellMinRange(srange); + float range = GetSpellMaxRangeForFriend(srange); + float minrange = GetSpellMinRangeForFriend( srange); float dist = GetDistance(pVictim); //if(!isInFront( pVictim, range ) && spellInfo->AttributesEx ) // continue; diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 64d604a04fc..e22bd7264ab 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -826,7 +826,20 @@ void GameObject::TriggeringLinkedGameObject( uint32 trapEntry, Unit* target) if(!trapSpell) // checked at load already return; - float range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(trapSpell->rangeIndex)); + float range; + SpellRangeEntry const * srentry = sSpellRangeStore.LookupEntry(trapSpell->rangeIndex); + //get owner to check hostility of GameObject + if (GetSpellMaxRangeForHostile(srentry) == GetSpellMaxRangeForHostile(srentry)) + range = GetSpellMaxRangeForHostile(srentry); + else + { + Unit * owner=GetOwner(); + if (owner) + range = owner->GetSpellMaxRangeForTarget(target, srentry); + else + //if no owner assume that object is hostile to target + range = GetSpellMaxRangeForHostile(srentry); + } // search nearest linked GO GameObject* trapGO = NULL; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index d6d11ba80a7..15a31d670bb 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -474,7 +474,7 @@ void Spell::FillTargetMap() { // non-standard target selection SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); - float max_range = GetSpellMaxRange(srange); + float max_range = GetSpellMaxRangeForHostile(srange); WorldObject* result = NULL; Trinity::CannibalizeObjectCheck u_check(m_caster, max_range); @@ -1438,11 +1438,17 @@ Unit* Spell::SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 en void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) { - float radius; + float radius_h, radius_f; if (m_spellInfo->EffectRadiusIndex[i]) - radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + { + radius_h = GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + radius_f = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + } else - radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); + { + radius_h = GetSpellMaxRangeForHostile(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); + radius_f = GetSpellMaxRangeForFriend(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); + } //Chain: 2, 6, 22, 25, 45, 77 uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[i]; @@ -1459,7 +1465,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) { if(Player* modOwner = m_originalCaster->GetSpellModOwner()) { - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius,this); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius_f,this); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius_h,this); modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this); } } @@ -1490,13 +1497,13 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) TagUnitMap.push_back(pet); break; case TARGET_UNIT_PARTY_CASTER: - m_caster->GetPartyMember(TagUnitMap, radius); + m_caster->GetPartyMember(TagUnitMap, radius_f); break; case TARGET_UNIT_RAID: //if(Unit *target = m_targets.getUnitTarget()) // TagUnitMap.push_back(target); //else - m_caster->GetRaidMember(TagUnitMap, radius); + m_caster->GetRaidMember(TagUnitMap, radius_f); TagUnitMap.push_back(m_caster); break; } @@ -1524,19 +1531,19 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) TagUnitMap.push_back(target); break; case TARGET_UNIT_PARTY_TARGET: - target->GetPartyMember(TagUnitMap, radius); + target->GetPartyMember(TagUnitMap, radius_f); break; case TARGET_UNIT_TARGET_ENEMY: if(EffectChainTarget <= 1) TagUnitMap.push_back(SelectMagnetTarget()); else if(SelectMagnetTarget()) //TODO: chain target should also use magnet target - SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ENEMY); + SearchChainTarget(TagUnitMap, radius_h, EffectChainTarget, SPELL_TARGETS_ENEMY); break; case TARGET_UNIT_CHAINHEAL: if(EffectChainTarget <= 1) TagUnitMap.push_back(target); else - SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_CHAINHEAL); + SearchChainTarget(TagUnitMap, radius_f, EffectChainTarget, SPELL_TARGETS_CHAINHEAL); break; } }break; @@ -1583,17 +1590,17 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) case TARGET_UNIT_AREA_ENEMY_GROUND: m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; case TARGET_UNIT_AREA_ENEMY: - SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY); + SearchAreaTarget(TagUnitMap, radius_h, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY); break; case TARGET_UNIT_AREA_ALLY_GROUND: m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; case TARGET_UNIT_AREA_ALLY: - SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ALLY); + SearchAreaTarget(TagUnitMap, radius_f, PUSH_DEST_CENTER, SPELL_TARGETS_ALLY); break; case TARGET_UNIT_AREA_PARTY_GROUND: m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; case TARGET_UNIT_AREA_PARTY: - m_caster->GetPartyMember(TagUnitMap, radius); + m_caster->GetPartyMember(TagUnitMap, radius_f); break; case TARGET_UNIT_AREA_ENTRY_GROUND: m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; @@ -1603,7 +1610,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); if(lower==upper) { - SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY); + SearchAreaTarget(TagUnitMap, radius_h, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY); sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); break; } @@ -1615,7 +1622,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) sLog.outError( "SPELL: spell ID %u requires non-creature target\n", m_spellInfo->Id ); continue; } - SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ENTRY, i_spellST->second.targetEntry); + SearchAreaTarget(TagUnitMap, radius_f, PUSH_DEST_CENTER, SPELL_TARGETS_ENTRY, i_spellST->second.targetEntry); } } break; @@ -1662,38 +1669,38 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) case TARGET_IN_FRONT_OF_CASTER: case TARGET_UNIT_CONE_ENEMY_UNKNOWN: if(m_customAttr & SPELL_ATTR_CU_CONE_BACK) - SearchAreaTarget(TagUnitMap, radius, PUSH_IN_BACK, SPELL_TARGETS_ENEMY); + SearchAreaTarget(TagUnitMap, radius_h, PUSH_IN_BACK, SPELL_TARGETS_ENEMY); else if(m_customAttr & SPELL_ATTR_CU_CONE_LINE) - SearchAreaTarget(TagUnitMap, radius, PUSH_IN_LINE, SPELL_TARGETS_ENEMY); + SearchAreaTarget(TagUnitMap, radius_h, PUSH_IN_LINE, SPELL_TARGETS_ENEMY); else - SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_ENEMY); + SearchAreaTarget(TagUnitMap, radius_h, PUSH_IN_FRONT, SPELL_TARGETS_ENEMY); break; case TARGET_UNIT_CONE_ALLY: - SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_ALLY); + SearchAreaTarget(TagUnitMap, radius_f, PUSH_IN_FRONT, SPELL_TARGETS_ALLY); break; // nearby target case TARGET_UNIT_NEARBY_ALLY: case TARGET_UNIT_NEARBY_ALLY_UNK: if(!m_targets.getUnitTarget()) - m_targets.setUnitTarget(SearchNearbyTarget(radius, SPELL_TARGETS_ALLY)); + m_targets.setUnitTarget(SearchNearbyTarget(radius_f, SPELL_TARGETS_ALLY)); if(m_targets.getUnitTarget()) { if(EffectChainTarget <= 1) TagUnitMap.push_back(m_targets.getUnitTarget()); else - SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ALLY); + SearchChainTarget(TagUnitMap, radius_f, EffectChainTarget, SPELL_TARGETS_ALLY); } break; case TARGET_UNIT_NEARBY_ENEMY: if(!m_targets.getUnitTarget()) - m_targets.setUnitTarget(SearchNearbyTarget(radius, SPELL_TARGETS_ENEMY)); + m_targets.setUnitTarget(SearchNearbyTarget(radius_h, SPELL_TARGETS_ENEMY)); if(m_targets.getUnitTarget()) { if(EffectChainTarget <= 1) TagUnitMap.push_back(m_targets.getUnitTarget()); else - SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ENEMY); + SearchChainTarget(TagUnitMap, radius_h, EffectChainTarget, SPELL_TARGETS_ENEMY); } break; case TARGET_SCRIPT: @@ -1710,7 +1717,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) } SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); - float range = GetSpellMaxRange(srange); + float range = GetSpellMaxRangeForHostile(srange); Creature* creatureScriptTarget = NULL; GameObject* goScriptTarget = NULL; @@ -1805,7 +1812,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) Player* Target = itr->getSource(); // IsHostileTo check duel and controlled by enemy - if( Target && targetPlayer->IsWithinDistInMap(Target, radius) && + if( Target && targetPlayer->IsWithinDistInMap(Target, radius_f) && targetPlayer->getClass() == Target->getClass() && !m_caster->IsHostileTo(Target) ) { @@ -1836,7 +1843,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) float x, y, z, angle, dist; float objSize = m_caster->GetObjectSize(); - dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + dist = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); if(dist < objSize) dist = objSize; else if(cur == TARGET_DEST_CASTER_RANDOM) @@ -1884,7 +1891,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) float x, y, z, angle, dist; float objSize = target->GetObjectSize(); - dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + dist = target->GetSpellRadiusForTarget(target, sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); if(dist < objSize) dist = objSize; else if(cur == TARGET_DEST_CASTER_RANDOM) @@ -1920,7 +1927,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) float x, y, z, angle, dist; - dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + dist = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); if (cur == TARGET_DEST_DEST_RANDOM) dist *= rand_norm(); @@ -4325,7 +4332,7 @@ uint8 Spell::CanCast(bool strict) case SPELL_EFFECT_LEAP: case SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER: { - float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float dis = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); float fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation()); float fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation()); // teleport a bit above terrain level to avoid falling below it @@ -4674,15 +4681,15 @@ uint8 Spell::CheckRange(bool strict) range_mod = 6.25;*/ SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); - float max_range = GetSpellMaxRange(srange); // + range_mod; - float min_range = GetSpellMinRange(srange); + + Unit *target = m_targets.getUnitTarget(); + float max_range = m_caster->GetSpellMaxRangeForTarget(target, srange); // + range_mod; + float min_range = m_caster->GetSpellMinRangeForTarget(target, srange); uint32 range_type = GetSpellRangeType(srange); if(Player* modOwner = m_caster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, max_range, this); - Unit *target = m_targets.getUnitTarget(); - if(target && target != m_caster) { if(range_type == SPELL_RANGE_MELEE) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index d411d490f14..ac323efedd2 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -464,7 +464,11 @@ Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, // caster==NULL in constructor args if target==caster in fact Unit* caster_ptr = caster ? caster : target; - m_radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex])); + if (spellproto->Effect[eff]==SPELL_EFFECT_APPLY_AREA_AURA_ENEMY) + m_radius = GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex])); + else + m_radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex])); + if(Player* modOwner = caster_ptr->GetSpellModOwner()) modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, m_radius); @@ -588,12 +592,12 @@ void Aura::Update(uint32 diff) SpellModOp mod; if (m_spellProto->EffectRadiusIndex[GetEffIndex()]) { - radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[GetEffIndex()])); + radius = caster->GetSpellRadiusForTarget(m_target, sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[GetEffIndex()])); mod = SPELLMOD_RADIUS; } else { - radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex)); + radius = caster->GetSpellMaxRangeForTarget(m_target, sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex)) ; mod = SPELLMOD_RANGE; } @@ -1833,7 +1837,7 @@ void Aura::TriggerSpell() } } } - if(!GetSpellMaxRange(sSpellRangeStore.LookupEntry(triggeredSpellInfo->rangeIndex))) + if(!caster->GetSpellMaxRangeForTarget(m_target,sSpellRangeStore.LookupEntry(triggeredSpellInfo->rangeIndex))) target = m_target; //for druid dispel poison m_target->CastSpell(target, triggeredSpellInfo, true, 0, this, GetCasterGUID()); } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index d86cf091a5e..a3c291bc5bb 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -385,7 +385,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) if(unitTarget->GetGUID() == m_caster->GetGUID() || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[0])); + float radius = GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[0])); if(!radius) return; float distance = m_caster->GetDistance2d(unitTarget); damage = (distance > radius ) ? 0 : (int32)(m_spellInfo->EffectBasePoints[0]*((radius - distance)/radius)); @@ -2798,7 +2798,7 @@ void Spell::EffectCreateItem2(uint32 i) void Spell::EffectPersistentAA(uint32 i) { - float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); if(Player* modOwner = m_originalCaster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius); @@ -3665,7 +3665,7 @@ void Spell::EffectAddFarsight(uint32 i) if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); int32 duration = GetSpellDuration(m_spellInfo); DynamicObject* dynObj = new DynamicObject; if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius)) @@ -3715,7 +3715,7 @@ void Spell::EffectSummonWild(uint32 i) float center_y = m_targets.m_destY; float center_z = m_targets.m_destZ; - float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float radius = GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); int32 amount = damage > 0 ? damage : 1; @@ -3804,7 +3804,7 @@ void Spell::EffectSummonGuardian(uint32 i) float center_y = m_targets.m_destY; float center_z = m_targets.m_destZ; - float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); int32 amount = damage > 0 ? damage : 1; @@ -3908,7 +3908,7 @@ void Spell::EffectTeleUnitsFaceCaster(uint32 i) return; uint32 mapid = m_caster->GetMapId(); - float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float dis = m_caster->GetSpellRadiusForTarget(unitTarget, sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); float fx,fy,fz; m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis); @@ -6002,7 +6002,7 @@ void Spell::EffectMomentMove(uint32 i) return; uint32 mapid = m_caster->GetMapId(); - float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float dis = m_caster->GetSpellRadiusForTarget(unitTarget, sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); // src point float *fx = new float[11], *fy = new float[11], *fz = new float[11]; @@ -6520,13 +6520,14 @@ void Spell::EffectTransmitted(uint32 effIndex) //FIXME: this can be better check for most objects but still hack else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0) { - float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex])); + float dis = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex])); m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis); } else { - float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); - float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); + //GO is always friendly to it's creator, get range for friends + float min_dis = GetSpellMinRangeForFriend(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); + float max_dis = GetSpellMaxRangeForFriend(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); float dis = rand_norm() * (max_dis - min_dis) + min_dis; m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis); diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 9a44ee4ffac..83d17ec2b85 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -325,10 +325,13 @@ enum SpellLinkedType SpellSpecific GetSpellSpecific(uint32 spellId); // Different spell properties -inline float GetSpellRadius(SpellRadiusEntry const *radius) { return (radius ? radius->Radius : 0); } +inline float GetSpellRadiusForHostile(SpellRadiusEntry const *radius) { return (radius ? radius->radiusHostile : 0); } +inline float GetSpellRadiusForFriend(SpellRadiusEntry const *radius) { return (radius ? radius->radiusFriend : 0); } uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell = NULL); -inline float GetSpellMinRange(SpellRangeEntry const *range) { return (range ? range->minRange : 0); } -inline float GetSpellMaxRange(SpellRangeEntry const *range) { return (range ? range->maxRange : 0); } +inline float GetSpellMinRangeForHostile(SpellRangeEntry const *range) { return (range ? range->minRangeHostile : 0); } +inline float GetSpellMaxRangeForHostile(SpellRangeEntry const *range) { return (range ? range->maxRangeHostile : 0); } +inline float GetSpellMinRangeForFriend(SpellRangeEntry const *range) { return (range ? range->minRangeFriend : 0); } +inline float GetSpellMaxRangeForFriend(SpellRangeEntry const *range) { return (range ? range->maxRangeFriend : 0); } inline uint32 GetSpellRangeType(SpellRangeEntry const *range) { return (range ? range->type : 0); } inline uint32 GetSpellRecoveryTime(SpellEntry const *spellInfo) { return spellInfo->RecoveryTime > spellInfo->CategoryRecoveryTime ? spellInfo->RecoveryTime : spellInfo->CategoryRecoveryTime; } int32 GetSpellDuration(SpellEntry const *spellInfo); diff --git a/src/game/TotemAI.cpp b/src/game/TotemAI.cpp index 81113a3a9f8..184cb141913 100644 --- a/src/game/TotemAI.cpp +++ b/src/game/TotemAI.cpp @@ -68,9 +68,9 @@ TotemAI::UpdateAI(const uint32 /*diff*/) if (!spellInfo) return; - // Get spell rangy + // Get spell range SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); - float max_range = GetSpellMaxRange(srange); + float max_range = GetSpellMaxRangeForHostile(srange); // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 0801ba454bb..7fdbedb26c7 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -421,9 +421,9 @@ void Unit::GetRandomContactPoint( const Unit* obj, float &x, float &y, float &z, // sLog.outError("Creature entry %u has invalid combat_reach", ((Creature*)this)->GetEntry()); combat_reach = DEFAULT_COMBAT_REACH; } - uint32 attacker_number = getAttackers().size(); + uint32 attacker_number = getAttackers().size(); if(attacker_number > 0) --attacker_number; - GetNearPoint(obj,x,y,z,obj->GetCombatReach(), distance2dMin+(distance2dMax-distance2dMin)*rand_norm() + GetNearPoint(obj,x,y,z,obj->GetCombatReach(), distance2dMin+(distance2dMax-distance2dMin)*rand_norm() , GetAngle(obj) + (attacker_number ? (M_PI/2 - M_PI * rand_norm()) * (float)attacker_number / combat_reach / 3 : 0)); } @@ -543,34 +543,34 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa //Script Event damage taken if( pVictim->GetTypeId()== TYPEID_UNIT && ((Creature *)pVictim)->AI() ) - { - ((Creature *)pVictim)->AI()->DamageTaken(this, damage); - - // Set tagging - if(!pVictim->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_OTHER_TAGGER) && !((Creature*)pVictim)->isPet()) - { - //Set Loot - switch(GetTypeId()) - { - case TYPEID_PLAYER: - { - ((Creature *)pVictim)->SetLootRecipient(this); - //Set tagged - ((Creature *)pVictim)->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_OTHER_TAGGER); - break; - } - case TYPEID_UNIT: - { - if(((Creature*)this)->isPet()) - { - ((Creature *)pVictim)->SetLootRecipient(this->GetOwner()); - ((Creature *)pVictim)->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_OTHER_TAGGER); - } - break; - } - } - } - } + { + ((Creature *)pVictim)->AI()->DamageTaken(this, damage); + + // Set tagging + if(!pVictim->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_OTHER_TAGGER) && !((Creature*)pVictim)->isPet()) + { + //Set Loot + switch(GetTypeId()) + { + case TYPEID_PLAYER: + { + ((Creature *)pVictim)->SetLootRecipient(this); + //Set tagged + ((Creature *)pVictim)->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_OTHER_TAGGER); + break; + } + case TYPEID_UNIT: + { + if(((Creature*)this)->isPet()) + { + ((Creature *)pVictim)->SetLootRecipient(this->GetOwner()); + ((Creature *)pVictim)->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_OTHER_TAGGER); + } + break; + } + } + } + } if (damagetype != NODAMAGE) { @@ -3064,7 +3064,7 @@ uint32 Unit::GetWeaponSkillValue (WeaponAttackType attType, Unit const* target) if(attType != BASE_ATTACK && !item ) { if(attType == RANGED_ATTACK && getClass() == CLASS_PALADIN) //hammer - return GetMaxSkillValueForLevel(); + return GetMaxSkillValueForLevel(); return 0; } @@ -7132,6 +7132,8 @@ FactionTemplateEntry const* Unit::getFactionTemplateEntry() const bool Unit::IsHostileTo(Unit const* unit) const { + if(!unit) + return false; // always non-hostile to self if(unit==this) return false; @@ -7868,22 +7870,22 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 /*switch(spellProto->SpellFamilyName) { - case SPELLFAMILY_GENERIC: - // Siphon Essence - 0% - if(spellProto->AttributesEx == 268435456 && spellProto->SpellIconID == 2027) - { - CastingTime = 0; - } - // Goblin Rocket Launcher - 0% - else if (spellProto->SpellIconID == 184 && spellProto->Attributes == 4259840) - { - CastingTime = 0; - } - // Darkmoon Card: Vengeance - 0.1% - else if (spellProto->SpellVisual[0] == 9850 && spellProto->SpellIconID == 2230) - { - CastingTime = 3.5; - } + case SPELLFAMILY_GENERIC: + // Siphon Essence - 0% + if(spellProto->AttributesEx == 268435456 && spellProto->SpellIconID == 2027) + { + CastingTime = 0; + } + // Goblin Rocket Launcher - 0% + else if (spellProto->SpellIconID == 184 && spellProto->Attributes == 4259840) + { + CastingTime = 0; + } + // Darkmoon Card: Vengeance - 0.1% + else if (spellProto->SpellVisual[0] == 9850 && spellProto->SpellIconID == 2230) + { + CastingTime = 3.5; + } case SPELLFAMILY_MAGE: // Ignite - do not modify, it is (8*Rank)% damage of procing Spell if(spellProto->Id==12654) @@ -8465,7 +8467,7 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint if (spellProto->Id == 15290 || spellProto->Id == 39373 || spellProto->Id == 33778 || spellProto->Id == 379 || spellProto->Id == 38395 || spellProto->Id == 40972 || - spellProto->Id == 22845 || spellProto->Id == 33504 || + spellProto->Id == 22845 || spellProto->Id == 33504 || spellProto->Id == 34299) return healamount; @@ -8575,12 +8577,12 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint DotFactor = damagetype == DOT ? 0.705f : 1.0f; CastingTime = damagetype == DOT ? 3500 : 1010; } - // Improved Leader of the Pack - else if (spellProto->AttributesEx2 == 536870912 && spellProto->SpellIconID == 312 - && spellProto->AttributesEx3 == 33554432) - { - CastingTime = 0; - } + // Improved Leader of the Pack + else if (spellProto->AttributesEx2 == 536870912 && spellProto->SpellIconID == 312 + && spellProto->AttributesEx3 == 33554432) + { + CastingTime = 0; + } break; case SPELLFAMILY_PRIEST: // Holy Nova - 14% @@ -10158,13 +10160,13 @@ void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Un if(duration == -1 || group == DIMINISHING_NONE || caster->IsFriendlyTo(this) ) return; - // test pet/charm masters instead pets/charmeds - Unit const* targetOwner = GetCharmerOrOwner(); - Unit const* casterOwner = caster->GetCharmerOrOwner(); - // Duration of crowd control abilities on pvp target is limited by 10 sec. (2.2.0) if(duration > 10000 && IsDiminishingReturnsGroupDurationLimited(group)) { + // test pet/charm masters instead pets/charmeds + Unit const* targetOwner = GetCharmerOrOwner(); + Unit const* casterOwner = caster->GetCharmerOrOwner(); + Unit const* target = targetOwner ? targetOwner : this; Unit const* source = casterOwner ? casterOwner : caster; @@ -10175,7 +10177,7 @@ void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Un float mod = 1.0f; // Some diminishings applies to mobs too (for example, Stun) - if((GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER && (targetOwner ? targetOwner->GetTypeId():GetTypeId()) == TYPEID_PLAYER) || GetDiminishingReturnsGroupType(group) == DRTYPE_ALL) + if((GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER && GetTypeId() == TYPEID_PLAYER) || GetDiminishingReturnsGroupType(group) == DRTYPE_ALL) { DiminishingLevels diminish = Level; switch(diminish) @@ -10212,6 +10214,31 @@ void Unit::ApplyDiminishingAura( DiminishingGroup group, bool apply ) } } +uint32 Unit::GetSpellMaxRangeForTarget(Unit* target,const SpellRangeEntry * rangeEntry) +{ + if (rangeEntry->maxRangeHostile == rangeEntry->maxRangeFriend) + return rangeEntry->maxRangeFriend; + if (IsHostileTo(target)) + return rangeEntry->maxRangeHostile; + return rangeEntry->maxRangeFriend; +}; +uint32 Unit::GetSpellMinRangeForTarget(Unit* target,const SpellRangeEntry * rangeEntry) +{ + if (rangeEntry->minRangeHostile == rangeEntry->minRangeFriend) + return rangeEntry->minRangeFriend; + if (IsHostileTo(target)) + return rangeEntry->minRangeHostile; + return rangeEntry->minRangeFriend; +}; +uint32 Unit::GetSpellRadiusForTarget(Unit* target,const SpellRadiusEntry * radiusEntry) +{ + if (radiusEntry->radiusHostile == radiusEntry->radiusFriend) + return radiusEntry->radiusFriend; + if (IsHostileTo(target)) + return radiusEntry->radiusHostile; + return radiusEntry->radiusFriend; +}; + Unit* Unit::GetUnit(WorldObject& object, uint64 guid) { return ObjectAccessor::GetUnit(object,guid); @@ -11923,9 +11950,9 @@ bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura ) { float radius; if (spellProto->EffectRadiusIndex[effIdx]) - radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellProto->EffectRadiusIndex[effIdx])); + radius = GetSpellRadiusForTarget(triggeredByAura->GetCaster(), sSpellRadiusStore.LookupEntry(spellProto->EffectRadiusIndex[effIdx])); else - radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spellProto->rangeIndex)); + radius = GetSpellMaxRangeForTarget(triggeredByAura->GetCaster() ,sSpellRangeStore.LookupEntry(spellProto->rangeIndex)); if(Player* caster = ((Player*)triggeredByAura->GetCaster())) { diff --git a/src/game/Unit.h b/src/game/Unit.h index 9ed85ca9cc3..1f51558f3ec 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -844,6 +844,11 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void ApplyDiminishingAura(DiminishingGroup group, bool apply); void ClearDiminishings() { m_Diminishing.clear(); } + //target dependent range checks + uint32 GetSpellMaxRangeForTarget(Unit* target,const SpellRangeEntry * rangeEntry); + uint32 GetSpellMinRangeForTarget(Unit* target,const SpellRangeEntry * rangeEntry); + uint32 GetSpellRadiusForTarget(Unit* target,const SpellRadiusEntry * radiusEntry); + virtual void Update( uint32 time ); void setAttackTimer(WeaponAttackType type, uint32 time) { m_attackTimer[type] = time; } diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index ea14a587d8e..86079fb417a 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -1228,16 +1228,23 @@ struct SpellThreatEntry struct SpellRadiusEntry { uint32 ID; - float Radius; - float Radius2; + float radiusHostile; + //uint32 Unk //always 0 + float radiusFriend; }; struct SpellRangeEntry { uint32 ID; - float minRange; - float maxRange; + float minRangeHostile; + float minRangeFriend; + float maxRangeHostile; + float maxRangeFriend; //friend means unattackable unit here uint32 type; + //char* Name[16]; // 7-23 unused + // 24 string flags, unused + //char* Name2[16]; // 25-40 unused + // 41 string flags, unused }; struct SpellRuneCostEntry diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index 050e750cbca..481303406b1 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -79,7 +79,7 @@ const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx"; const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiixx"; const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"; const char SpellRadiusfmt[]="nfxf"; -const char SpellRangefmt[]="nfxfxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +const char SpellRangefmt[]="nffffixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char SpellRuneCostfmt[]="niiii"; const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxx"; const char StableSlotPricesfmt[] = "ni"; |