Core/Spells: move Cannibalize and Carrion Feeder cast checks to SpellScripts.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
DELETE FROM `spell_script_names` WHERE `spell_id`=20577;
|
||||
INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`)
|
||||
VALUES
|
||||
(20577,'spell_gen_cannibalize');
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
if (i_funit->IsWithinDistInMap(u, i_range))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return !u->isAlive() && !u->HasAuraType(SPELL_AURA_GHOST) && i_searchObj->IsWithinDistInMap(u, i_range);
|
||||
}
|
||||
|
||||
bool CarrionFeederObjectCheck::operator()(Corpse* u)
|
||||
bool AnyDeadUnitObjectInRangeCheck::operator()(Corpse* u)
|
||||
{
|
||||
// ignore bones
|
||||
if (u->GetType() == CORPSE_BONES)
|
||||
return false;
|
||||
return u->GetType() != CORPSE_BONES && i_searchObj->IsWithinDistInMap(u, i_range);
|
||||
}
|
||||
|
||||
bool AnyDeadUnitObjectInRangeCheck::operator()(Creature* u)
|
||||
{
|
||||
return !u->isAlive() && i_searchObj->IsWithinDistInMap(u, i_range);
|
||||
}
|
||||
|
||||
bool AnyDeadUnitSpellTargetInRangeCheck::operator()(Player* u)
|
||||
{
|
||||
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 &);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user