diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 20 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.h | 2 | ||||
-rwxr-xr-x | src/server/game/Grids/Notifiers/GridNotifiers.cpp | 50 | ||||
-rwxr-xr-x | src/server/game/Grids/Notifiers/GridNotifiers.h | 53 | ||||
-rwxr-xr-x | src/server/game/Maps/Map.h | 20 | ||||
-rwxr-xr-x | src/server/game/Spells/Spell.cpp | 49 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellEffects.cpp | 4 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_generic.cpp | 56 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_hunter.cpp | 18 |
9 files changed, 159 insertions, 113 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 3f44d413250..55e11d26411 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -16180,6 +16180,26 @@ bool Unit::IsInRaidWith(Unit const* unit) const return false; } +bool Unit::IsTargetMatchingCheck(Unit const* target, SpellTargetSelectionCheckTypes check) const +{ + switch (check) + { + case TARGET_SELECT_CHECK_ENEMY: + if (IsControlledByPlayer()) + return !IsFriendlyTo(target); + else + return IsHostileTo(target); + case TARGET_SELECT_CHECK_ALLY: + return IsFriendlyTo(target); + case TARGET_SELECT_CHECK_PARTY: + return IsInPartyWith(target); + case TARGET_SELECT_CHECK_RAID: + return IsInRaidWith(target); + default: + return true; + } +} + void Unit::GetRaidMember(std::list<Unit*> &nearMembers, float radius) { Player* owner = GetCharmerOrOwnerPlayerOrPlayerItself(); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 0e6cccd0cd5..e7781be00c7 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -32,6 +32,7 @@ #include "EventProcessor.h" #include "MotionMaster.h" #include "DBCStructure.h" +#include "SpellInfo.h" #include "Path.h" #include "WorldPacket.h" #include "Timer.h" @@ -1391,6 +1392,7 @@ class Unit : public WorldObject bool IsNeutralToAll() const; bool IsInPartyWith(Unit const* unit) const; bool IsInRaidWith(Unit const* unit) const; + bool IsTargetMatchingCheck(Unit const* target, SpellTargetSelectionCheckTypes check) const; void GetPartyMemberInDist(std::list<Unit*> &units, float dist); void GetPartyMembers(std::list<Unit*> &units); void GetRaidMember(std::list<Unit*> &units, float dist); diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp index 13a88a26b89..9914426215c 100755 --- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp +++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp @@ -26,6 +26,7 @@ #include "Transport.h" #include "ObjectAccessor.h" #include "CellImpl.h" +#include "SpellInfo.h" using namespace Trinity; @@ -330,38 +331,41 @@ ObjectUpdater::Visit(GridRefManager<T> &m) } } -bool CannibalizeObjectCheck::operator()(Corpse* u) +bool AnyDeadUnitObjectInRangeCheck::operator()(Player* u) { - // ignore bones - if (u->GetType() == CORPSE_BONES) - return false; - - Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID()); - - if (!owner || i_funit->IsFriendlyTo(owner)) - return false; + return !u->isAlive() && !u->HasAuraType(SPELL_AURA_GHOST) && i_searchObj->IsWithinDistInMap(u, i_range); +} - if (i_funit->IsWithinDistInMap(u, i_range)) - return true; +bool AnyDeadUnitObjectInRangeCheck::operator()(Corpse* u) +{ + return u->GetType() != CORPSE_BONES && i_searchObj->IsWithinDistInMap(u, i_range); +} - return false; +bool AnyDeadUnitObjectInRangeCheck::operator()(Creature* u) +{ + return !u->isAlive() && i_searchObj->IsWithinDistInMap(u, i_range); } -bool CarrionFeederObjectCheck::operator()(Corpse* u) +bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Player* u) { - // ignore bones - if (u->GetType() == CORPSE_BONES) - return false; + return AnyDeadUnitObjectInRangeCheck::operator()(u) + && i_spellInfo->CheckTarget(i_searchObj, u, true) + && i_searchObj->IsTargetMatchingCheck(u, i_check); +} +bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Corpse* u) +{ Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID()); + return owner && AnyDeadUnitObjectInRangeCheck::operator()(u) + && i_spellInfo->CheckTarget(i_searchObj, owner, true) + && i_searchObj->IsTargetMatchingCheck(owner, i_check); +} - if (!owner || i_funit->IsFriendlyTo(owner)) - return false; - - if (i_funit->IsWithinDistInMap(u, i_range)) - return true; - - return false; +bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Creature* u) +{ + return AnyDeadUnitObjectInRangeCheck::operator()(u) + && i_spellInfo->CheckTarget(i_searchObj, u, true) + && i_searchObj->IsTargetMatchingCheck(u, i_check); } template void ObjectUpdater::Visit<GameObject>(GameObjectMapType &); diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index b4d20f25740..4d4f0bfe05e 100755 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -554,56 +554,31 @@ namespace Trinity float i_range; }; - class CannibalizeObjectCheck + class AnyDeadUnitObjectInRangeCheck { public: - CannibalizeObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Player* u) - { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight()) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } + AnyDeadUnitObjectInRangeCheck(Unit const* searchObj, float range) : i_searchObj(searchObj), i_range(range) {} + bool operator()(Player* u); bool operator()(Corpse* u); - bool operator()(Creature* u) - { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || - (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } + bool operator()(Creature* u); template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; + protected: + Unit const* const i_searchObj; float i_range; }; - class CarrionFeederObjectCheck + class AnyDeadUnitSpellTargetInRangeCheck : public AnyDeadUnitObjectInRangeCheck { public: - CarrionFeederObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Player* u) - { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight()) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } + AnyDeadUnitSpellTargetInRangeCheck(Unit const* searchObj, float range, SpellInfo const* spellInfo, SpellTargetSelectionCheckTypes check) + : AnyDeadUnitObjectInRangeCheck(searchObj, range), i_spellInfo(spellInfo), i_check(check) {} + bool operator()(Player* u); bool operator()(Corpse* u); - bool operator()(Creature* u) - { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || - (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) != 0) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } + bool operator()(Creature* u); template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; - float i_range; + protected: + SpellInfo const* i_spellInfo; + SpellTargetSelectionCheckTypes i_check; }; // WorldObject do classes diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 6ff4bf05d42..f430002fca6 100755 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -416,6 +416,7 @@ class Map : public GridRefManager<NGridType> template<class T> void SwitchGridContainers(T* obj, bool active); template<class NOTIFIER> void VisitAll(const float &x, const float &y, float radius, NOTIFIER ¬ifier); + template<class NOTIFIER> void VisitFirstFound(const float &x, const float &y, float radius, NOTIFIER ¬ifier); template<class NOTIFIER> void VisitWorld(const float &x, const float &y, float radius, NOTIFIER ¬ifier); template<class NOTIFIER> void VisitGrid(const float &x, const float &y, float radius, NOTIFIER ¬ifier); CreatureGroupHolderType CreatureGroupHolder; @@ -650,6 +651,25 @@ Map::VisitAll(const float &x, const float &y, float radius, NOTIFIER ¬ifier) cell.Visit(p, grid_object_notifier, *this, radius, x, y); } +// should be used with Searcher notifiers, tries to search world if nothing found in grid +template<class NOTIFIER> +inline void +Map::VisitFirstFound(const float &x, const float &y, float radius, NOTIFIER ¬ifier) +{ + CellPair p(Trinity::ComputeCellPair(x, y)); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + TypeContainerVisitor<NOTIFIER, WorldTypeMapContainer> world_object_notifier(notifier); + cell.Visit(p, world_object_notifier, *this, radius, x, y); + if (!notifier.i_object) + { + TypeContainerVisitor<NOTIFIER, GridTypeMapContainer > grid_object_notifier(notifier); + cell.Visit(p, grid_object_notifier, *this, radius, x, y); + } +} + template<class NOTIFIER> inline void Map::VisitWorld(const float &x, const float &y, float radius, NOTIFIER ¬ifier) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index c602a071c23..1dff9a2f3ce 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -652,51 +652,10 @@ void Spell::SelectSpellTargets() { case SPELL_EFFECT_DUMMY: { - switch(m_spellInfo->Id) - { - case 20577: // Cannibalize - case 54044: // Carrion Feeder - { - WorldObject* result = NULL; - if (m_spellInfo->Id == 20577) - result = FindCorpseUsing<Trinity::CannibalizeObjectCheck>(); - else - result = FindCorpseUsing<Trinity::CarrionFeederObjectCheck>(); - - if (result) - { - switch(result->GetTypeId()) - { - case TYPEID_UNIT: - case TYPEID_PLAYER: - AddUnitTarget((Unit*)result, i); - break; - case TYPEID_CORPSE: - m_targets.SetCorpseTarget((Corpse*)result); - if (Player* owner = ObjectAccessor::FindPlayer(((Corpse*)result)->GetOwnerGUID())) - AddUnitTarget(owner, i); - break; - default: - break; - } - } - else - { - // clear cooldown at fail - if (m_caster->GetTypeId() == TYPEID_PLAYER) - m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true); - SendCastResult(SPELL_FAILED_NO_EDIBLE_CORPSES); - finish(false); - } - break; - } - default: - if (m_targets.GetUnitTarget()) - AddUnitTarget(m_targets.GetUnitTarget(), i, false); - else - AddUnitTarget(m_caster, i, false); - break; - } + if (m_targets.GetUnitTarget()) + AddUnitTarget(m_targets.GetUnitTarget(), i, false); + else + AddUnitTarget(m_caster, i, false); break; } case SPELL_EFFECT_BIND: diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 9b3a020edc6..825c8c4fb14 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -816,10 +816,6 @@ void Spell::EffectDummy(SpellEffIndex effIndex) } return; } - case 20577: // Cannibalize - if (unitTarget) - m_caster->CastSpell(m_caster, 20578, false, NULL); - return; case 23019: // Crystal Prison Dummy DND { if (!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || unitTarget->ToCreature()->isPet()) diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 48deb028625..3d6b4fba8bc 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -25,6 +25,7 @@ #include "ScriptPCH.h" #include "SpellAuraEffects.h" #include "SkillDiscovery.h" +#include "GridNotifiers.h" class spell_gen_absorb0_hitlimit1 : public SpellScriptLoader { @@ -161,6 +162,60 @@ class spell_gen_burn_brutallus : public SpellScriptLoader } }; +enum eCannibalizeSpells +{ + SPELL_CANNIBALIZE_TRIGGERED = 20578, +}; + +class spell_gen_cannibalize : public SpellScriptLoader +{ + public: + spell_gen_cannibalize() : SpellScriptLoader("spell_gen_cannibalize") { } + + class spell_gen_cannibalize_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_cannibalize_SpellScript); + + bool Validate(SpellInfo const* /*spellEntry*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_CANNIBALIZE_TRIGGERED)) + return false; + return true; + } + + SpellCastResult CheckIfCorpseNear() + { + Unit* caster = GetCaster(); + float max_range = GetSpellInfo()->GetMaxRange(false); + WorldObject* result = NULL; + // search for nearby enemy corpse in range + Trinity::AnyDeadUnitSpellTargetInRangeCheck check(caster, max_range, GetSpellInfo(), TARGET_SELECT_CHECK_ENEMY); + Trinity::WorldObjectSearcher<Trinity::AnyDeadUnitSpellTargetInRangeCheck> searcher(caster, result, check); + caster->GetMap()->VisitFirstFound(caster->m_positionX, caster->m_positionY, max_range, searcher); + if (!result) + return SPELL_FAILED_NO_EDIBLE_CORPSES; + return SPELL_CAST_OK; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + caster->CastSpell(caster, SPELL_CANNIBALIZE_TRIGGERED, false); + } + + void Register() + { + OnEffect += SpellEffectFn(spell_gen_cannibalize_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + OnCheckCast += SpellCheckCastFn(spell_gen_cannibalize_SpellScript::CheckIfCorpseNear); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gen_cannibalize_SpellScript(); + } +}; + // 45472 Parachute enum eParachuteSpells { @@ -1264,6 +1319,7 @@ void AddSC_generic_spell_scripts() new spell_gen_aura_of_anger(); new spell_gen_av_drekthar_presence(); new spell_gen_burn_brutallus(); + new spell_gen_cannibalize(); new spell_gen_leeching_swarm(); new spell_gen_parachute(); new spell_gen_pet_summoned(); diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 79f92368ff9..0a81b13ed64 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -23,6 +23,7 @@ #include "ScriptPCH.h" #include "SpellAuraEffects.h" +#include "GridNotifiers.h" enum HunterSpells { @@ -468,10 +469,22 @@ public: return true; } + SpellCastResult CheckIfCorpseNear() + { + Unit* caster = GetCaster(); + float max_range = GetSpellInfo()->GetMaxRange(false); + WorldObject* result = NULL; + // search for nearby enemy corpse in range + Trinity::AnyDeadUnitSpellTargetInRangeCheck check(caster, max_range, GetSpellInfo(), TARGET_SELECT_CHECK_ENEMY); + Trinity::WorldObjectSearcher<Trinity::AnyDeadUnitSpellTargetInRangeCheck> searcher(caster, result, check); + caster->GetMap()->VisitFirstFound(caster->m_positionX, caster->m_positionY, max_range, searcher); + if (!result) + return SPELL_FAILED_NO_EDIBLE_CORPSES; + return SPELL_CAST_OK; + } + void HandleDummy(SpellEffIndex /*effIndex*/) { - if (!GetHitUnit()) - return; Unit* caster = GetCaster(); caster->CastSpell(caster, HUNTER_PET_SPELL_CARRION_FEEDER_TRIGGERED, false); } @@ -480,6 +493,7 @@ public: { // add dummy effect spell handler to pet's Last Stand OnEffect += SpellEffectFn(spell_hun_pet_carrion_feeder_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + OnCheckCast += SpellCheckCastFn(spell_hun_pet_carrion_feeder_SpellScript::CheckIfCorpseNear); } bool Load() |