From 7fb5d850bf1854ccc2b7f98f9e6c3a2c6b76b205 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 4 Mar 2010 04:04:47 +0300 Subject: [PATCH] [9510] Gameobject casting improvements. * Add IsHostileTo/IsFriendlyTo and implement expected way checks for diff. world object types. For controlled object check redirected to specific owner, for wild gameobject base at gameobject faction. If faction not set expected to be hostile to anyone. * Update grid searchers to be usable with world object instead only unit case. Some grid searches lost redundent second object arg, AnyAoETargetUnitInObjectRangeCheck lost hitHidden arg (for hitHidden==true case added new AnyAoEVisibleTargetUnitInObjectRangeCheck) * Updated grid searchers used with gameobject area casts now. Note: Gameobject area spell cast animation will still wrong show around cast triggering target instead center around gameobject. * In case gameobject aura apply to target for restored use target itself as caster because we not have currently another way apply aura form wild gameobject. --- src/game/Corpse.cpp | 17 ++++++++ src/game/Corpse.h | 3 ++ src/game/DynamicObject.cpp | 16 +++++++ src/game/DynamicObject.h | 4 ++ src/game/GameObject.cpp | 87 ++++++++++++++++++++++++++++++++++++++ src/game/GameObject.h | 2 + src/game/GridNotifiers.cpp | 4 +- src/game/GridNotifiers.h | 81 +++++++++++++++++++++++------------ src/game/Object.cpp | 18 ++++++++ src/game/Object.h | 5 +++ src/game/Player.cpp | 2 +- src/game/Player.h | 2 +- src/game/Spell.cpp | 20 ++++----- src/game/Spell.h | 18 ++++---- src/game/SpellAuras.cpp | 4 +- src/game/SpellEffects.cpp | 9 +++- src/game/Unit.cpp | 2 +- src/shared/revision_nr.h | 2 +- 18 files changed, 242 insertions(+), 54 deletions(-) diff --git a/src/game/Corpse.cpp b/src/game/Corpse.cpp index be3d9ae9f..f9ec223c9 100644 --- a/src/game/Corpse.cpp +++ b/src/game/Corpse.cpp @@ -26,6 +26,7 @@ #include "Opcodes.h" #include "GossipDef.h" #include "World.h" +#include "ObjectMgr.h" Corpse::Corpse(CorpseType type) : WorldObject() { @@ -232,3 +233,19 @@ bool Corpse::isVisibleForInState(Player const* u, WorldObject const* viewPoint, { return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(viewPoint, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false); } + +bool Corpse::IsHostileTo( Unit const* unit ) const +{ + if (Player* owner = sObjectMgr.GetPlayer(GetOwnerGUID())) + return owner->IsHostileTo(unit); + else + return false; +} + +bool Corpse::IsFriendlyTo( Unit const* unit ) const +{ + if (Player* owner = sObjectMgr.GetPlayer(GetOwnerGUID())) + return owner->IsFriendlyTo(unit); + else + return true; +} \ No newline at end of file diff --git a/src/game/Corpse.h b/src/game/Corpse.h index c0fee3033..59812f4e1 100644 --- a/src/game/Corpse.h +++ b/src/game/Corpse.h @@ -71,6 +71,9 @@ class Corpse : public WorldObject void ResetGhostTime() { m_time = time(NULL); } CorpseType GetType() const { return m_type; } + bool IsHostileTo(Unit const* unit) const; + bool IsFriendlyTo(Unit const* unit) const; + GridPair const& GetGrid() const { return m_grid; } void SetGrid(GridPair const& grid) { m_grid = grid; } diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp index 7778b164e..696531633 100644 --- a/src/game/DynamicObject.cpp +++ b/src/game/DynamicObject.cpp @@ -161,3 +161,19 @@ bool DynamicObject::isVisibleForInState(Player const* u, WorldObject const* view // normal case return IsWithinDistInMap(viewPoint, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false); } + +bool DynamicObject::IsHostileTo( Unit const* unit ) const +{ + if (Unit* owner = GetCaster()) + return owner->IsHostileTo(unit); + else + return false; +} + +bool DynamicObject::IsFriendlyTo( Unit const* unit ) const +{ + if (Unit* owner = GetCaster()) + return owner->IsFriendlyTo(unit); + else + return true; +} \ No newline at end of file diff --git a/src/game/DynamicObject.h b/src/game/DynamicObject.h index 5bebb8870..fffdbec20 100644 --- a/src/game/DynamicObject.h +++ b/src/game/DynamicObject.h @@ -47,6 +47,10 @@ class DynamicObject : public WorldObject void AddAffected(Unit *unit) { m_affected.insert(unit); } void RemoveAffected(Unit *unit) { m_affected.erase(unit); } void Delay(int32 delaytime); + + bool IsHostileTo(Unit const* unit) const; + bool IsFriendlyTo(Unit const* unit) const; + bool isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const; void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index e49267dee..e4b24d9cb 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -1448,3 +1448,90 @@ void GameObject::UpdateRotationFields(float rotation2 /*=0.0f*/, float rotation3 SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2); SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3); } + +bool GameObject::IsHostileTo(Unit const* unit) const +{ + // always non-hostile to GM in GM mode + if(unit->GetTypeId()==TYPEID_PLAYER && ((Player const*)unit)->isGameMaster()) + return false; + + // test owner instead if have + if (Unit const* owner = GetOwner()) + return owner->IsHostileTo(unit); + + if (Unit const* targetOwner = unit->GetCharmerOrOwner()) + return IsHostileTo(targetOwner); + + // for not set faction case (wild object) use hostile case + if(!GetGOInfo()->faction) + return true; + + // faction base cases + FactionTemplateEntry const*tester_faction = sFactionTemplateStore.LookupEntry(GetGOInfo()->faction); + FactionTemplateEntry const*target_faction = unit->getFactionTemplateEntry(); + if(!tester_faction || !target_faction) + return false; + + // GvP forced reaction and reputation case + if(unit->GetTypeId()==TYPEID_PLAYER) + { + // forced reaction + if(tester_faction->faction) + { + if(ReputationRank const* force = ((Player*)unit)->GetReputationMgr().GetForcedRankIfAny(tester_faction)) + return *force <= REP_HOSTILE; + + // apply reputation state + FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction); + if(raw_tester_faction && raw_tester_faction->reputationListID >=0 ) + return ((Player const*)unit)->GetReputationMgr().GetRank(raw_tester_faction) <= REP_HOSTILE; + } + } + + // common faction based case (GvC,GvP) + return tester_faction->IsHostileTo(*target_faction); +} + +bool GameObject::IsFriendlyTo(Unit const* unit) const +{ + // always friendly to GM in GM mode + if(unit->GetTypeId()==TYPEID_PLAYER && ((Player const*)unit)->isGameMaster()) + return true; + + // test owner instead if have + if (Unit const* owner = GetOwner()) + return owner->IsFriendlyTo(unit); + + if (Unit const* targetOwner = unit->GetCharmerOrOwner()) + return IsFriendlyTo(targetOwner); + + // for not set faction case (wild object) use hostile case + if(!GetGOInfo()->faction) + return false; + + // faction base cases + FactionTemplateEntry const*tester_faction = sFactionTemplateStore.LookupEntry(GetGOInfo()->faction); + FactionTemplateEntry const*target_faction = unit->getFactionTemplateEntry(); + if(!tester_faction || !target_faction) + return false; + + // GvP forced reaction and reputation case + if(unit->GetTypeId()==TYPEID_PLAYER) + { + // forced reaction + if(tester_faction->faction) + { + if(ReputationRank const* force =((Player*)unit)->GetReputationMgr().GetForcedRankIfAny(tester_faction)) + return *force >= REP_FRIENDLY; + + // apply reputation state + if(FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction)) + if(raw_tester_faction->reputationListID >=0 ) + return ((Player const*)unit)->GetReputationMgr().GetRank(raw_tester_faction) >= REP_FRIENDLY; + } + } + + // common faction based case (GvC,GvP) + return tester_faction->IsFriendlyTo(*target_faction); +} + diff --git a/src/game/GameObject.h b/src/game/GameObject.h index 502f3f3ab..9cf06b3c9 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -677,6 +677,8 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject // 0 = use `gameobject`.`spawntimesecs` void ResetDoorOrButton(); + bool IsHostileTo(Unit const* unit) const; + bool IsFriendlyTo(Unit const* unit) const; void SummonLinkedTrapIfAny(); void TriggeringLinkedGameObject( uint32 trapEntry, Unit* target); diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp index d6f1e210d..e654cc7f3 100644 --- a/src/game/GridNotifiers.cpp +++ b/src/game/GridNotifiers.cpp @@ -229,10 +229,10 @@ bool CannibalizeObjectCheck::operator()(Corpse* u) Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID()); - if( !owner || i_funit->IsFriendlyTo(owner)) + if( !owner || i_fobj->IsFriendlyTo(owner)) return false; - if(i_funit->IsWithinDistInMap(u, i_range) ) + if(i_fobj->IsWithinDistInMap(u, i_range) ) return true; return false; diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h index 9d3255df2..9c4c66ce4 100644 --- a/src/game/GridNotifiers.h +++ b/src/game/GridNotifiers.h @@ -499,34 +499,34 @@ namespace MaNGOS class RaiseDeadObjectCheck { public: - RaiseDeadObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + RaiseDeadObjectCheck(Player const* fobj, float range) : i_fobj(fobj), i_range(range) {} bool operator()(Creature* u) { - if (i_funit->GetTypeId()!=TYPEID_PLAYER || !((Player*)i_funit)->isHonorOrXPTarget(u) || + if (i_fobj->isHonorOrXPTarget(u) || u->getDeathState() != CORPSE || u->isDeadByDefault() || u->isInFlight() || ( u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1)) )==0 || (u->GetDisplayId() != u->GetNativeDisplayId())) return false; - return i_funit->IsWithinDistInMap(u, i_range); + return i_fobj->IsWithinDistInMap(u, i_range); } template bool operator()(NOT_INTERESTED*) { return false; } private: - Unit* const i_funit; + Player const* i_fobj; float i_range; }; class ExplodeCorpseObjectCheck { public: - ExplodeCorpseObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + ExplodeCorpseObjectCheck(WorldObject const* fobj, float range) : i_fobj(fobj), i_range(range) {} bool operator()(Player* u) { if (u->getDeathState()!=CORPSE || u->isInFlight() || u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId())) return false; - return i_funit->IsWithinDistInMap(u, i_range); + return i_fobj->IsWithinDistInMap(u, i_range); } bool operator()(Creature* u) { @@ -535,37 +535,37 @@ namespace MaNGOS (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL)!=0) return false; - return i_funit->IsWithinDistInMap(u, i_range); + return i_fobj->IsWithinDistInMap(u, i_range); } template bool operator()(NOT_INTERESTED*) { return false; } private: - Unit* const i_funit; + WorldObject const* i_fobj; float i_range; }; class CannibalizeObjectCheck { public: - CannibalizeObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + CannibalizeObjectCheck(WorldObject const* fobj, float range) : i_fobj(fobj), i_range(range) {} bool operator()(Player* u) { - if( i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() ) + if( i_fobj->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() ) return false; - return i_funit->IsWithinDistInMap(u, i_range); + return i_fobj->IsWithinDistInMap(u, i_range); } bool operator()(Corpse* u); bool operator()(Creature* u) { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || + if (i_fobj->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD)==0) return false; - return i_funit->IsWithinDistInMap(u, i_range); + return i_fobj->IsWithinDistInMap(u, i_range); } template bool operator()(NOT_INTERESTED*) { return false; } private: - Unit* const i_funit; + WorldObject const* i_fobj; float i_range; }; @@ -688,7 +688,7 @@ namespace MaNGOS class FriendlyCCedInRange { public: - FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {} + FriendlyCCedInRange(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} bool operator()(Unit* u) { if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && @@ -699,14 +699,14 @@ namespace MaNGOS return false; } private: - Unit const* i_obj; + WorldObject const* i_obj; float i_range; }; class FriendlyMissingBuffInRange { public: - FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {} + FriendlyMissingBuffInRange(WorldObject const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {} bool operator()(Unit* u) { if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && @@ -717,7 +717,7 @@ namespace MaNGOS return false; } private: - Unit const* i_obj; + WorldObject const* i_obj; float i_range; uint32 i_spell; }; @@ -761,17 +761,16 @@ namespace MaNGOS class AnyFriendlyUnitInObjectRangeCheck { public: - AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} bool operator()(Unit* u) { - if(u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u)) + if(u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_obj->IsFriendlyTo(u)) return true; else return false; } private: WorldObject const* i_obj; - Unit const* i_funit; float i_range; }; @@ -816,11 +815,11 @@ namespace MaNGOS NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&); }; - class AnyAoETargetUnitInObjectRangeCheck + class AnyAoEVisibleTargetUnitInObjectRangeCheck { public: - AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool hitHidden = true) - : i_obj(obj), i_funit(funit), i_range(range), i_hitHidden(hitHidden) + AnyAoEVisibleTargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) + : i_obj(obj), i_funit(funit), i_range(range) { Unit const* check = i_funit; Unit const* owner = i_funit->GetOwner(); @@ -835,7 +834,7 @@ namespace MaNGOS return false; if(u->GetTypeId()==TYPEID_UNIT && ((Creature*)u)->isTotem()) return false; - if (!i_hitHidden && !u->isVisibleForOrDetect(i_funit, i_funit, false)) + if (!u->isVisibleForOrDetect(i_funit, i_funit, false)) return false; if(( i_targetForPlayer ? !i_funit->IsFriendlyTo(u) : i_funit->IsHostileTo(u) )&& i_obj->IsWithinDistInMap(u, i_range)) @@ -848,7 +847,36 @@ namespace MaNGOS WorldObject const* i_obj; Unit const* i_funit; float i_range; - bool i_hitHidden; + }; + + class AnyAoETargetUnitInObjectRangeCheck + { + public: + AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, float range) + : i_obj(obj), i_range(range) + { + i_targetForPlayer = i_obj->IsControlledByPlayer(); + } + + bool operator()(Unit* u) + { + // Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems + if (!u->isTargetableForAttack()) + return false; + + if(u->GetTypeId()==TYPEID_UNIT && ((Creature*)u)->isTotem()) + return false; + + if(( i_targetForPlayer ? !i_obj->IsFriendlyTo(u) : i_obj->IsHostileTo(u) )&& i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + + private: + bool i_targetForPlayer; + WorldObject const* i_obj; + float i_range; }; // do attack at call of help to friendly crearture @@ -877,6 +905,7 @@ namespace MaNGOS if (u->AI()) u->AI()->AttackStart(i_enemy); } + private: Unit* const i_funit; Unit* const i_enemy; diff --git a/src/game/Object.cpp b/src/game/Object.cpp index d53364deb..053b5bfcd 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1958,3 +1958,21 @@ void WorldObject::BuildUpdateData( UpdateDataMapType & update_players) ClearUpdateMask(false); } + +bool WorldObject::IsControlledByPlayer() const +{ + switch (GetTypeId()) + { + case TYPEID_GAMEOBJECT: + return IS_PLAYER_GUID(((GameObject*)this)->GetOwnerGUID()); + case TYPEID_UNIT: + case TYPEID_PLAYER: + return ((Unit*)this)->IsCharmerOrOwnerPlayerOrPlayerItself(); + case TYPEID_DYNAMICOBJECT: + return IS_PLAYER_GUID(((DynamicObject*)this)->GetCasterGUID()); + case TYPEID_CORPSE: + return true; + default: + return false; + } +} \ No newline at end of file diff --git a/src/game/Object.h b/src/game/Object.h index 0bad7b9bd..0467f51d2 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -91,6 +91,7 @@ class UpdateData; class WorldSession; class Creature; class Player; +class Unit; class Map; class UpdateMask; class InstanceData; @@ -472,6 +473,10 @@ class MANGOS_DLL_SPEC WorldObject : public Object void SendObjectDeSpawnAnim(uint64 guid); void SendGameObjectCustomAnim(uint64 guid); + virtual bool IsHostileTo(Unit const* unit) const =0; + virtual bool IsFriendlyTo(Unit const* unit) const =0; + bool IsControlledByPlayer() const; + virtual void SaveRespawnTime() {} void AddObjectToRemoveList(); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 096375817..00c2cef04 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -19771,7 +19771,7 @@ uint32 Player::GetResurrectionSpellId() } // Used in triggers for check "Only to targets that grant experience or honor" req -bool Player::isHonorOrXPTarget(Unit* pVictim) +bool Player::isHonorOrXPTarget(Unit* pVictim) const { uint32 v_level = pVictim->getLevel(); uint32 k_grey = MaNGOS::XP::GetGrayLevel(getLevel()); diff --git a/src/game/Player.h b/src/game/Player.h index f4b5cec74..0005e4dfb 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1895,7 +1895,7 @@ class MANGOS_DLL_SPEC Player : public Unit bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const; bool RewardPlayerAndGroupAtKill(Unit* pVictim); void RewardPlayerAndGroupAtEvent(uint32 creature_id,WorldObject* pRewardSource); - bool isHonorOrXPTarget(Unit* pVictim); + bool isHonorOrXPTarget(Unit* pVictim) const; ReputationMgr& GetReputationMgr() { return m_reputationMgr; } ReputationMgr const& GetReputationMgr() const { return m_reputationMgr; } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index afe8b113c..ad1ef2231 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1445,7 +1445,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& std::list tempTargetUnitMap; { - MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(m_caster, m_caster, max_range); + MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(m_caster, max_range); MaNGOS::UnitListSearcher searcher(m_caster, tempTargetUnitMap, u_check); TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); @@ -1514,7 +1514,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& cell.SetNoCreate(); std::list tempTargetUnitMap; { - MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, max_range); + MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, max_range); MaNGOS::UnitListSearcher searcher(m_caster, tempTargetUnitMap, u_check); TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); @@ -1610,10 +1610,10 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& std::list tempTargetUnitMap; { - MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(pUnitTarget, originalCaster, max_range, false); - MaNGOS::UnitListSearcher searcher(m_caster, tempTargetUnitMap, u_check); - TypeContainerVisitor, WorldTypeMapContainer> world_unit_searcher(searcher); - TypeContainerVisitor, GridTypeMapContainer> grid_unit_searcher(searcher); + MaNGOS::AnyAoEVisibleTargetUnitInObjectRangeCheck u_check(pUnitTarget, originalCaster, max_range); + MaNGOS::UnitListSearcher searcher(m_caster, tempTargetUnitMap, u_check); + TypeContainerVisitor, WorldTypeMapContainer> world_unit_searcher(searcher); + TypeContainerVisitor, GridTypeMapContainer> grid_unit_searcher(searcher); cell.Visit(p, world_unit_searcher, *m_caster->GetMap(), *pUnitTarget, max_range); cell.Visit(p, grid_unit_searcher, *m_caster->GetMap(), *pUnitTarget, max_range); @@ -3170,20 +3170,20 @@ void Spell::SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 ca void Spell::SendSpellStart() { - if(!IsNeedSendToClient()) + if (!IsNeedSendToClient()) return; sLog.outDebug("Sending SMSG_SPELL_START id=%u", m_spellInfo->Id); uint32 castFlags = CAST_FLAG_UNKNOWN1; - if(IsRangedSpell()) + if (IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; - if(m_spellInfo->runeCostID) + if (m_spellInfo->runeCostID) castFlags |= CAST_FLAG_UNKNOWN10; WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2)); - if(m_CastItem) + if (m_CastItem) data.append(m_CastItem->GetPackGUID()); else data.append(m_caster->GetPackGUID()); diff --git a/src/game/Spell.h b/src/game/Spell.h index 301ab53c5..206f55778 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -620,12 +620,12 @@ namespace MaNGOS Spell &i_spell; const uint32& i_index; float i_radius; - Unit* i_originalCaster; + WorldObject* i_originalCaster; SpellNotifierPlayer(Spell &spell, std::list &data, const uint32 &i, float radius) : i_data(data), i_spell(spell), i_index(i), i_radius(radius) { - i_originalCaster = i_spell.GetAffectiveCaster(); + i_originalCaster = i_spell.GetCastingObject(); } void Visit(PlayerMapType &m) @@ -656,13 +656,15 @@ namespace MaNGOS SpellNotifyPushType i_push_type; float i_radius; SpellTargets i_TargetType; - Unit* i_originalCaster; + WorldObject* i_originalCaster; + bool i_playerControled; SpellNotifierCreatureAndPlayer(Spell &spell, std::list &data, float radius, SpellNotifyPushType type, SpellTargets TargetType = SPELL_TARGETS_NOT_FRIENDLY) : i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_TargetType(TargetType) { - i_originalCaster = spell.GetAffectiveCaster(); + i_originalCaster = spell.GetCastingObject(); + i_playerControled = i_originalCaster->IsControlledByPlayer(); } template inline void Visit(GridRefManager &m) @@ -704,16 +706,14 @@ namespace MaNGOS if(itr->getSource()->GetTypeId()==TYPEID_UNIT && ((Creature*)itr->getSource())->isTotem()) continue; - Unit* check = i_originalCaster->GetCharmerOrOwnerOrSelf(); - - if( check->GetTypeId()==TYPEID_PLAYER ) + if (i_playerControled) { - if (check->IsFriendlyTo( itr->getSource() )) + if (i_originalCaster->IsFriendlyTo( itr->getSource() )) continue; } else { - if (!check->IsHostileTo( itr->getSource() )) + if (!i_originalCaster->IsHostileTo( itr->getSource() )) continue; } } diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index de92bd275..31ec03ee2 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -759,7 +759,7 @@ void AreaAura::Update(uint32 diff) cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(caster, owner, m_radius); + MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(caster, m_radius); MaNGOS::UnitListSearcher searcher(caster,targets, u_check); TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); @@ -774,7 +774,7 @@ void AreaAura::Update(uint32 diff) cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(caster, owner, m_radius); // No GetCharmer in searcher + MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(caster, m_radius); // No GetCharmer in searcher MaNGOS::UnitListSearcher searcher(caster, targets, u_check); TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 45592684a..9fc7024ab 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2826,7 +2826,14 @@ void Spell::EffectApplyAura(SpellEffectIndex eff_idx) Unit* caster = GetAffectiveCaster(); if(!caster) - return; + { + // FIXME: currently we can't have auras applied explIcitly by gameobjects + // so for auras from wild gameobjects (no owner) target used + if (IS_GAMEOBJECT_GUID(m_originalCasterGUID)) + caster = unitTarget; + else + return; + } sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[eff_idx]); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index da6419e08..d2c596595 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -12896,7 +12896,7 @@ Unit* Unit::SelectRandomFriendlyTarget(Unit* except /*= NULL*/, float radius /*= std::list targets; - MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(this, this, radius); + MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(this, radius); MaNGOS::UnitListSearcher searcher(this, targets, u_check); TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index a5639ee76..70a615730 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9509" + #define REVISION_NR "9510" #endif // __REVISION_NR_H__