aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp20
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h2
-rwxr-xr-xsrc/server/game/Grids/Notifiers/GridNotifiers.cpp50
-rwxr-xr-xsrc/server/game/Grids/Notifiers/GridNotifiers.h53
-rwxr-xr-xsrc/server/game/Maps/Map.h20
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp49
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp4
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp56
-rw-r--r--src/server/scripts/Spells/spell_hunter.cpp18
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 &notifier);
+ template<class NOTIFIER> void VisitFirstFound(const float &x, const float &y, float radius, NOTIFIER &notifier);
template<class NOTIFIER> void VisitWorld(const float &x, const float &y, float radius, NOTIFIER &notifier);
template<class NOTIFIER> void VisitGrid(const float &x, const float &y, float radius, NOTIFIER &notifier);
CreatureGroupHolderType CreatureGroupHolder;
@@ -650,6 +651,25 @@ Map::VisitAll(const float &x, const float &y, float radius, NOTIFIER &notifier)
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 &notifier)
+{
+ 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 &notifier)
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()