diff options
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
| -rwxr-xr-x | src/server/game/Spells/Spell.cpp | 215 |
1 files changed, 89 insertions, 126 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index c5392a0e55b..68dde527ab7 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -656,7 +656,7 @@ void Spell::InitExplicitTargets(SpellCastTargets const& targets) else if ((m_caster->GetTypeId() == TYPEID_UNIT) && neededTargets & (TARGET_FLAG_UNIT_ENEMY | TARGET_FLAG_UNIT)) target = m_caster->getVictim(); // didn't find anything - let's use self as target - if (!target && neededTargets & (TARGET_FLAG_UNIT_RAID | TARGET_FLAG_UNIT_PARTY | TARGET_FLAG_UNIT_ALLY | TARGET_FLAG_UNIT)) + if (!target && neededTargets & (TARGET_FLAG_UNIT_RAID | TARGET_FLAG_UNIT_PARTY | TARGET_FLAG_UNIT_ALLY)) target = m_caster; m_targets.SetUnitTarget(target); @@ -709,121 +709,21 @@ void Spell::SelectSpellTargets() if (implicitTargetMask & (TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM)) m_targets.SetTargetFlag(TARGET_FLAG_GAMEOBJECT); - uint32 effectTargetType = m_spellInfo->Effects[i].GetRequiredTargetType(); - - // is it possible that areaaura is not applied to caster? - if (effectTargetType == SPELL_REQUIRE_NONE) - continue; - uint32 targetA = m_spellInfo->Effects[i].TargetA.GetTarget(); uint32 targetB = m_spellInfo->Effects[i].TargetB.GetTarget(); if (targetA) processedTargets |= SelectEffectTargets(i, m_spellInfo->Effects[i].TargetA); - if (targetB) // In very rare case !A && B + if (targetB) processedTargets |= SelectEffectTargets(i, m_spellInfo->Effects[i].TargetB); - if (effectTargetType != SPELL_REQUIRE_UNIT) - { - if (effectTargetType == SPELL_REQUIRE_CASTER) - AddUnitTarget(m_caster, 1 << i, false); - else if (effectTargetType == SPELL_REQUIRE_ITEM) - if (m_targets.GetItemTarget()) - AddItemTarget(m_targets.GetItemTarget(), 1 << i); - continue; - } - - if (!targetA && !targetB) - { - if (!m_spellInfo->GetMaxRange(true)) - { - AddUnitTarget(m_caster, 1 << i, false); - continue; - } + // Select targets of effect based on effect type + // those are used when no valid target could be added for spell effect based on spell target type + // some spell effects use explicit target as a default target added to target map (like SPELL_EFFECT_LEARN_SPELL) + // some spell effects add target to target map only when target type specified (like SPELL_EFFECT_WEAPON) + // some spell effects don't add anything to target map (confirmed with sniffs) (like SPELL_EFFECT_DESTROY_ALL_TOTEMS) + SelectEffectTypeImplicitTargets(i); - // add here custom effects that need default target. - // FOR EVERY TARGET TYPE THERE IS A DIFFERENT FILL!! - switch (m_spellInfo->Effects[i].Effect) - { - case SPELL_EFFECT_DUMMY: - { - if (m_targets.GetUnitTarget()) - AddUnitTarget(m_targets.GetUnitTarget(), 1 << i, false); - else - AddUnitTarget(m_caster, 1 << i, false); - break; - } - case SPELL_EFFECT_BIND: - case SPELL_EFFECT_RESURRECT: - case SPELL_EFFECT_CREATE_ITEM: - case SPELL_EFFECT_TRIGGER_SPELL: - case SPELL_EFFECT_SKILL_STEP: - case SPELL_EFFECT_PROFICIENCY: - case SPELL_EFFECT_SUMMON_OBJECT_WILD: - case SPELL_EFFECT_SELF_RESURRECT: - case SPELL_EFFECT_REPUTATION: - case SPELL_EFFECT_LEARN_SPELL: - case SPELL_EFFECT_SEND_TAXI: - if (m_targets.GetUnitTarget()) - AddUnitTarget(m_targets.GetUnitTarget(), 1 << i, false); - // Triggered spells have additional spell targets - cast them even if no explicit unit target is given (required for spell 50516 for example) - else if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_TRIGGER_SPELL) - AddUnitTarget(m_caster, 1 << i, false); - break; - case SPELL_EFFECT_SUMMON_RAF_FRIEND: - case SPELL_EFFECT_SUMMON_PLAYER: - if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->GetSelection()) - { - Player* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetSelection()); - if (target) - AddUnitTarget(target, 1 << i, false); - } - break; - case SPELL_EFFECT_SKIN_PLAYER_CORPSE: - case SPELL_EFFECT_RESURRECT_NEW: - if (WorldObject* target = m_targets.GetObjectTarget()) - { - if (Unit* unitTarget = target->ToUnit()) - AddUnitTarget(unitTarget, 1 << i, false); - else if (Corpse* corpseTarget = target->ToCorpse()) - { - Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()); - if (owner) - AddUnitTarget(owner, 1 << i, false); - } - } - break; - case SPELL_EFFECT_SUMMON_CHANGE_ITEM: - case SPELL_EFFECT_ADD_FARSIGHT: - case SPELL_EFFECT_APPLY_GLYPH: - case SPELL_EFFECT_STUCK: - case SPELL_EFFECT_FEED_PET: - case SPELL_EFFECT_DESTROY_ALL_TOTEMS: - case SPELL_EFFECT_KILL_CREDIT2: // only one spell: 42793 - AddUnitTarget(m_caster, 1 << i, false); - break; - case SPELL_EFFECT_LEARN_PET_SPELL: - if (Guardian* pet = m_caster->GetGuardianPet()) - AddUnitTarget(pet, 1 << i); - break; - case SPELL_EFFECT_APPLY_AURA: - switch (m_spellInfo->Effects[i].ApplyAuraName) - { - case SPELL_AURA_ADD_FLAT_MODIFIER: // some spell mods auras have 0 target modes instead expected TARGET_UNIT_CASTER(1) (and present for other ranks for same spell for example) - case SPELL_AURA_ADD_PCT_MODIFIER: - AddUnitTarget(m_caster, 1 << i, false); - break; - default: // apply to target in other case - if (m_targets.GetUnitTarget()) - AddUnitTarget(m_targets.GetUnitTarget(), 1 << i, false); - break; - } - break; - default: - AddUnitTarget(m_caster, 1 << i, false); - break; - } - } if (m_spellInfo->IsChanneled()) { uint8 mask = (1 << i); @@ -877,6 +777,82 @@ void Spell::SelectSpellTargets() } } +void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex) +{ + // special case for SPELL_EFFECT_SUMMON_RAF_FRIEND and SPELL_EFFECT_SUMMON_PLAYER + // TODO: this is a workaround - target shouldn't be stored in target map for those spells + switch (m_spellInfo->Effects[effIndex].Effect) + { + case SPELL_EFFECT_SUMMON_RAF_FRIEND: + case SPELL_EFFECT_SUMMON_PLAYER: + if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->GetSelection()) + { + Player* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetSelection()); + if (target) + AddUnitTarget(target, 1 << effIndex, false); + } + return; + default: + break; + } + + // select spell implicit targets based on effect type + if (!m_spellInfo->Effects[effIndex].GetImplicitTargetType()) + return; + + uint32 targetMask = m_spellInfo->Effects[effIndex].GetMissingTargetMask(); + + if (!targetMask) + return; + + switch (m_spellInfo->Effects[effIndex].GetImplicitTargetType()) + { + // add explicit object target or self to the target map + case EFFECT_IMPLICIT_TARGET_EXPLICIT: + // player which not released his spirit is Unit, but target flag for it is TARGET_FLAG_CORPSE_MASK + if (targetMask & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK)) + { + if (Unit* unitTarget = m_targets.GetUnitTarget()) + AddUnitTarget(unitTarget, 1 << effIndex, false); + else if (targetMask & TARGET_FLAG_CORPSE_MASK) + { + if (Corpse* corpseTarget = m_targets.GetCorpseTarget()) + { + // TODO: this is a workaround - corpses should be added to spell target map too, but we can't do that so we add owner instead + if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID())) + AddUnitTarget(owner, 1 << effIndex, false); + } + } + else //if (targetMask & TARGET_FLAG_UNIT_MASK) + { + AddUnitTarget(m_caster, 1 << effIndex, false); + } + } + if (targetMask & TARGET_FLAG_ITEM_MASK) + { + if (Item* itemTarget = m_targets.GetItemTarget()) + AddItemTarget(itemTarget, 1 << effIndex); + } + if (targetMask & TARGET_FLAG_GAMEOBJECT_MASK) + { + if (GameObject* gObjTarget = m_targets.GetGOTarget()) + AddGOTarget(gObjTarget, 1 << effIndex); + } + break; + // add self to the target map + case EFFECT_IMPLICIT_TARGET_CASTER: + if (targetMask & TARGET_FLAG_UNIT_MASK) + AddUnitTarget(m_caster, 1 << effIndex, false); + break; + // for EFFECT_LEARN_PET_SPELL - maybe should add unitTarget's pet instead of caster's? + case EFFECT_IMPLICIT_TARGET_PET: + if (targetMask & TARGET_FLAG_UNIT_MASK) + if (Guardian* pet = m_caster->GetGuardianPet()) + AddUnitTarget(pet, 1 << effIndex, false); + break; + } +} + void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/) { //========================================================================================== @@ -2505,10 +2481,6 @@ uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) } else if (pushType) { - // Dummy, just for client - if (m_spellInfo->Effects[i].GetRequiredTargetType() != SPELL_REQUIRE_UNIT) - return 0; - float radius; SpellTargets targetType; switch (cur.GetTarget()) @@ -3015,7 +2987,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered { m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CAST); for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_spellInfo->Effects[i].GetRequiredTargetType() == SPELL_REQUIRE_UNIT) + if (m_spellInfo->Effects[i].GetUsedTargetObjectType() == TARGET_OBJECT_TYPE_UNIT) { m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_SPELL_ATTACK); break; @@ -3438,17 +3410,17 @@ void Spell::_handle_immediate_phase() // process ground for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) { - if (m_spellInfo->Effects[j].Effect == 0) + if (!m_spellInfo->Effects[j].IsEffect()) continue; - if (m_spellInfo->Effects[j].GetRequiredTargetType() == SPELL_REQUIRE_DEST) + if (m_spellInfo->Effects[j].GetUsedTargetObjectType() == TARGET_OBJECT_TYPE_DEST) { if (!m_targets.HasDst()) // FIXME: this will ignore dest set in effect m_targets.SetDst(*m_caster); HandleEffects(m_originalCaster, NULL, NULL, j); m_effectMask |= (1<<j); } - else if (m_spellInfo->Effects[j].GetRequiredTargetType() == SPELL_REQUIRE_NONE) + else if (m_spellInfo->Effects[j].GetUsedTargetObjectType() && !m_spellInfo->Effects[j].GetImplicitTargetType()) { HandleEffects(m_originalCaster, NULL, NULL, j); m_effectMask |= (1<<j); @@ -5703,16 +5675,7 @@ SpellCastResult Spell::CheckRange(bool strict) if (!strict && m_casttime == 0) return SPELL_CAST_OK; - uint32 range_type = 0; - - if (m_spellInfo->RangeEntry) - { - // self cast doesn't need range checking -- also for Starshards fix - if (m_spellInfo->RangeEntry->ID == 1) - return SPELL_CAST_OK; - - range_type = m_spellInfo->RangeEntry->type; - } + uint32 range_type = m_spellInfo->RangeEntry ? m_spellInfo->RangeEntry->type : 0; Unit* target = m_targets.GetUnitTarget(); float max_range = m_caster->GetSpellMaxRangeForTarget(target, m_spellInfo); |
