diff options
| author | QAston <qaston@gmail.com> | 2011-08-19 14:53:40 +0200 |
|---|---|---|
| committer | QAston <qaston@gmail.com> | 2011-08-19 14:54:15 +0200 |
| commit | fc5e92413851835879f07460c82a988f742e5462 (patch) | |
| tree | c0c32de7326b197750b47162d9a3ea84355dbb82 /src/server/game/Spells/SpellInfo.cpp | |
| parent | 1bbab51284d7517a2505eb15004779749726746f (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.cpp | 121 |
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); |
