aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/SpellInfo.cpp
diff options
context:
space:
mode:
authorQAston <qaston@gmail.com>2011-08-19 14:53:40 +0200
committerQAston <qaston@gmail.com>2011-08-19 14:54:15 +0200
commitfc5e92413851835879f07460c82a988f742e5462 (patch)
treec0c32de7326b197750b47162d9a3ea84355dbb82 /src/server/game/Spells/SpellInfo.cpp
parent1bbab51284d7517a2505eb15004779749726746f (diff)
Core/Spells: Implement recently discovered target check attributes and move most of target checks to SpellInfo::CheckTarget function.
Diffstat (limited to 'src/server/game/Spells/SpellInfo.cpp')
-rw-r--r--src/server/game/Spells/SpellInfo.cpp121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 069864dfd74..11b7eea052a 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -1486,6 +1486,127 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
return SPELL_CAST_OK;
}
+SpellCastResult SpellInfo::CheckTarget(Unit const* caster, Unit const* target, bool implicit) const
+{
+ if (AttributesEx & SPELL_ATTR1_CANT_TARGET_SELF && caster == target)
+ return SPELL_FAILED_BAD_TARGETS;
+
+ if (AttributesEx & SPELL_ATTR1_CANT_TARGET_IN_COMBAT && target->isInCombat())
+ return SPELL_FAILED_TARGET_AFFECTING_COMBAT;
+
+ if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS && !target->ToPlayer())
+ return SPELL_FAILED_TARGET_NOT_PLAYER;
+
+ if (!(AttributesEx2 & SPELL_ATTR2_CAN_TARGET_DEAD) && !target->isAlive())
+ return SPELL_FAILED_TARGETS_DEAD;
+
+ if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS && !(target->ToPlayer() && !target->isAlive()))
+ return SPELL_FAILED_TARGET_NOT_GHOST;
+
+ if (AttributesEx6 & SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED && !target->CanFreeMove())
+ return SPELL_FAILED_BAD_TARGETS;
+
+ // check visibility - ignore stealth for implicit (area) targets
+ if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE) && !caster->canSeeOrDetect(target, implicit))
+ return SPELL_FAILED_BAD_TARGETS;
+
+ if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_UNTARGETABLE) && !target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
+ return SPELL_FAILED_BAD_TARGETS;
+
+ //if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_POSSESSED_FRIENDS)
+
+ if (!CheckTargetCreatureType(target))
+ {
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ return SPELL_FAILED_TARGET_IS_PLAYER;
+ else
+ return SPELL_FAILED_BAD_TARGETS;
+ }
+
+ // check UNIT_FLAG_NON_ATTACKABLE flag - a player can cast spells on his pet (or other controlled unit) though in any state
+ if (target != caster && target->GetCharmerOrOwnerGUID() != caster->GetGUID())
+ {
+ // any unattackable target skipped
+ if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE))
+ return SPELL_FAILED_BAD_TARGETS;
+ }
+
+ // check GM mode and GM invisibility - only for player casts (npc casts are controlled by AI)
+ if (target != caster && caster->IsControlledByPlayer() && target->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (!target->ToPlayer()->IsVisible())
+ return SPELL_FAILED_BAD_TARGETS;
+
+ if (target->ToPlayer()->isGameMaster())
+ return SPELL_FAILED_BAD_TARGETS;
+ }
+
+ // not allow casting on flying player
+ if (target->HasUnitState(UNIT_STAT_IN_FLIGHT))
+ return SPELL_FAILED_BAD_TARGETS;
+
+ if (TargetAuraState && !target->HasAuraState(AuraStateType(TargetAuraState), this, caster))
+ return SPELL_FAILED_TARGET_AURASTATE;
+
+ if (TargetAuraStateNot && target->HasAuraState(AuraStateType(TargetAuraStateNot), this, caster))
+ return SPELL_FAILED_TARGET_AURASTATE;
+
+ if (TargetAuraSpell && !target->HasAura(sSpellMgr->GetSpellIdForDifficulty(TargetAuraSpell, caster)))
+ return SPELL_FAILED_TARGET_AURASTATE;
+
+ if (ExcludeTargetAuraSpell && target->HasAura(sSpellMgr->GetSpellIdForDifficulty(ExcludeTargetAuraSpell, caster)))
+ return SPELL_FAILED_TARGET_AURASTATE;
+
+ if (caster != target)
+ {
+ if (caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ // Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells)
+ if (AttributesEx2 & SPELL_ATTR2_CANT_TARGET_TAPPED)
+ if (Creature const* targetCreature = target->ToCreature())
+ if (targetCreature->hasLootRecipient() && !targetCreature->isTappedBy(caster->ToPlayer()))
+ return SPELL_FAILED_CANT_CAST_ON_TAPPED;
+
+ if (AttributesCu & SPELL_ATTR0_CU_PICKPOCKET)
+ {
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ return SPELL_FAILED_BAD_TARGETS;
+ else if ((target->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0)
+ return SPELL_FAILED_TARGET_NO_POCKETS;
+ }
+
+ // Not allow disarm unarmed player
+ if (Mechanic == MECHANIC_DISARM)
+ {
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ {
+ Player const* player = target->ToPlayer();
+ if (!player->GetWeaponForAttack(BASE_ATTACK) || !player->IsUseEquipedWeapon(true))
+ return SPELL_FAILED_TARGET_NO_WEAPONS;
+ }
+ else if (!target->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID))
+ return SPELL_FAILED_TARGET_NO_WEAPONS;
+ }
+ }
+ }
+ return SPELL_CAST_OK;
+}
+
+bool SpellInfo::CheckTargetCreatureType(Unit const* target) const
+{
+ // Curse of Doom & Exorcism: not find another way to fix spell target check :/
+ if (SpellFamilyName == SPELLFAMILY_WARLOCK && Category == 1179)
+ {
+ // not allow cast at player
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ return false;
+ else
+ return true;
+ }
+ uint32 creatureType = target->GetCreatureTypeMask();
+ return !TargetCreatureType || !creatureType || (creatureType & TargetCreatureType);
+}
+
SpellSchoolMask SpellInfo::GetSchoolMask() const
{
return SpellSchoolMask(SchoolMask);