diff options
author | Shauren <shauren.trinity@gmail.com> | 2011-09-16 11:40:53 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2011-09-16 11:40:53 +0200 |
commit | 732e27f1e86ce02642a66930fe00a4515debaf11 (patch) | |
tree | ddd00c230dab42a5a1bd68875dca5cbb0492313b /src | |
parent | c93c27d056234bfde756ae1c44c44cc5ac2913ad (diff) |
Core/Spells: Spells having the same effect types on multiple effects will now select them at the same time (except targets selected by entry) to ensure correct behavior with MaxAffectedTargets use
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/Spells/Spell.cpp | 265 | ||||
-rwxr-xr-x | src/server/game/Spells/Spell.h | 10 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellEffects.cpp | 2 |
3 files changed, 158 insertions, 119 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index e6c22b7442f..b0cd74391f3 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -691,11 +691,15 @@ void Spell::InitExplicitTargets(SpellCastTargets const& targets) void Spell::SelectSpellTargets() { + uint32 processedTargets = 0; for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { // not call for empty effect. // Also some spells use not used effect targets for store targets for dummy effect in triggered spells - if (!m_spellInfo->Effects[i].Effect) + if (!m_spellInfo->Effects[i].IsEffect()) + continue; + + if (processedTargets & (1 << i)) continue; // set expected type of implicit targets to be sent to client @@ -715,17 +719,17 @@ void Spell::SelectSpellTargets() uint32 targetB = m_spellInfo->Effects[i].TargetB.GetTarget(); if (targetA) - SelectEffectTargets(i, m_spellInfo->Effects[i].TargetA); + processedTargets |= SelectEffectTargets(i, m_spellInfo->Effects[i].TargetA); if (targetB) // In very rare case !A && B - SelectEffectTargets(i, m_spellInfo->Effects[i].TargetB); + processedTargets |= SelectEffectTargets(i, m_spellInfo->Effects[i].TargetB); if (effectTargetType != SPELL_REQUIRE_UNIT) { if (effectTargetType == SPELL_REQUIRE_CASTER) - AddUnitTarget(m_caster, i, false); + AddUnitTarget(m_caster, 1 << i, false); else if (effectTargetType == SPELL_REQUIRE_ITEM) if (m_targets.GetItemTarget()) - AddItemTarget(m_targets.GetItemTarget(), i); + AddItemTarget(m_targets.GetItemTarget(), 1 << i); continue; } @@ -733,7 +737,7 @@ void Spell::SelectSpellTargets() { if (!m_spellInfo->GetMaxRange(true)) { - AddUnitTarget(m_caster, i, false); + AddUnitTarget(m_caster, 1 << i, false); continue; } @@ -744,9 +748,9 @@ void Spell::SelectSpellTargets() case SPELL_EFFECT_DUMMY: { if (m_targets.GetUnitTarget()) - AddUnitTarget(m_targets.GetUnitTarget(), i, false); + AddUnitTarget(m_targets.GetUnitTarget(), 1 << i, false); else - AddUnitTarget(m_caster, i, false); + AddUnitTarget(m_caster, 1 << i, false); break; } case SPELL_EFFECT_BIND: @@ -761,10 +765,10 @@ void Spell::SelectSpellTargets() case SPELL_EFFECT_LEARN_SPELL: case SPELL_EFFECT_SEND_TAXI: if (m_targets.GetUnitTarget()) - AddUnitTarget(m_targets.GetUnitTarget(), i, false); + 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, i, false); + AddUnitTarget(m_caster, 1 << i, false); break; case SPELL_EFFECT_SUMMON_RAF_FRIEND: case SPELL_EFFECT_SUMMON_PLAYER: @@ -772,7 +776,7 @@ void Spell::SelectSpellTargets() { Player* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetSelection()); if (target) - AddUnitTarget(target, i, false); + AddUnitTarget(target, 1 << i, false); } break; case SPELL_EFFECT_SKIN_PLAYER_CORPSE: @@ -780,12 +784,12 @@ void Spell::SelectSpellTargets() if (WorldObject* target = m_targets.GetObjectTarget()) { if (Unit* unitTarget = target->ToUnit()) - AddUnitTarget(unitTarget, i, false); + AddUnitTarget(unitTarget, 1 << i, false); else if (Corpse* corpseTarget = target->ToCorpse()) { Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()); if (owner) - AddUnitTarget(owner, i, false); + AddUnitTarget(owner, 1 << i, false); } } break; @@ -796,33 +800,33 @@ void Spell::SelectSpellTargets() case SPELL_EFFECT_FEED_PET: case SPELL_EFFECT_DESTROY_ALL_TOTEMS: case SPELL_EFFECT_KILL_CREDIT2: // only one spell: 42793 - AddUnitTarget(m_caster, i, false); + AddUnitTarget(m_caster, 1 << i, false); break; case SPELL_EFFECT_LEARN_PET_SPELL: if (Guardian* pet = m_caster->GetGuardianPet()) - AddUnitTarget(pet, i); + 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, i, false); + AddUnitTarget(m_caster, 1 << i, false); break; default: // apply to target in other case if (m_targets.GetUnitTarget()) - AddUnitTarget(m_targets.GetUnitTarget(), i, false); + AddUnitTarget(m_targets.GetUnitTarget(), 1 << i, false); break; } break; default: - AddUnitTarget(m_caster, i, false); + AddUnitTarget(m_caster, 1 << i, false); break; } } if (m_spellInfo->IsChanneled()) { - uint8 mask = (1<<i); + uint8 mask = (1 << i); for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { if (ihit->effectMask & mask) @@ -960,34 +964,38 @@ void Spell::CleanupTargetList() m_delayMoment = 0; } -void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex, bool checkIfValid /*=true*/) +void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= true*/) { - if (!m_spellInfo->Effects[effIndex].IsEffect()) + for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + if (!m_spellInfo->Effects[effIndex].IsEffect() || !CheckEffectTarget(target, effIndex)) + effectMask &= ~(1 << effIndex); + + // no effects left + if (!effectMask) return; if (checkIfValid) - if (m_spellInfo->CheckTarget(m_caster, pVictim, true) != SPELL_CAST_OK) + if (m_spellInfo->CheckTarget(m_caster, target, true) != SPELL_CAST_OK) return; - if (!CheckEffectTarget(pVictim, effIndex)) - return; // Check for effect immune skip if immuned - bool immuned = pVictim->IsImmunedToSpellEffect(m_spellInfo, effIndex); + for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + if (target->IsImmunedToSpellEffect(m_spellInfo, effIndex)) + effectMask &= ~(1 << effIndex); - uint64 targetGUID = pVictim->GetGUID(); + uint64 targetGUID = target->GetGUID(); // Lookup target in already in list for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { - if (targetGUID == ihit->targetGUID) // Found in list + if (targetGUID == ihit->targetGUID) // Found in list { - if (!immuned) - ihit->effectMask |= 1 << effIndex; // Add only effect mask if not immuned + ihit->effectMask |= effectMask; // Immune effects removed from mask ihit->scaleAura = false; - if (m_auraScaleMask && ihit->effectMask == m_auraScaleMask && m_caster != pVictim) + if (m_auraScaleMask && ihit->effectMask == m_auraScaleMask && m_caster != target) { SpellInfo const* auraSpell = sSpellMgr->GetSpellInfo(sSpellMgr->GetFirstSpellInChain(m_spellInfo->Id)); - if (uint32(pVictim->getLevel() + 10) >= auraSpell->SpellLevel) + if (uint32(target->getLevel() + 10) >= auraSpell->SpellLevel) ihit->scaleAura = true; } return; @@ -997,85 +1005,94 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex, bool checkIfValid /*=t // This is new target calculate data for him // Get spell hit result on target - TargetInfo target; - target.targetGUID = targetGUID; // Store target GUID - target.effectMask = immuned ? 0 : 1 << effIndex; // Store index of effect if not immuned - target.processed = false; // Effects not apply on target - target.alive = pVictim->isAlive(); - target.damage = 0; - target.crit = false; - target.scaleAura = false; - if (m_auraScaleMask && target.effectMask == m_auraScaleMask && m_caster != pVictim) + TargetInfo targetInfo; + targetInfo.targetGUID = targetGUID; // Store target GUID + targetInfo.effectMask = effectMask; // Store all effects not immune + targetInfo.processed = false; // Effects not apply on target + targetInfo.alive = target->isAlive(); + targetInfo.damage = 0; + targetInfo.crit = false; + targetInfo.scaleAura = false; + if (m_auraScaleMask && targetInfo.effectMask == m_auraScaleMask && m_caster != target) { SpellInfo const* auraSpell = sSpellMgr->GetSpellInfo(sSpellMgr->GetFirstSpellInChain(m_spellInfo->Id)); - if (uint32(pVictim->getLevel() + 10) >= auraSpell->SpellLevel) - target.scaleAura = true; + if (uint32(target->getLevel() + 10) >= auraSpell->SpellLevel) + targetInfo.scaleAura = true; } // Calculate hit result if (m_originalCaster) { - target.missCondition = m_originalCaster->SpellHitResult(pVictim, m_spellInfo, m_canReflect); - if (m_skipCheck && target.missCondition != SPELL_MISS_IMMUNE) - target.missCondition = SPELL_MISS_NONE; + targetInfo.missCondition = m_originalCaster->SpellHitResult(target, m_spellInfo, m_canReflect); + if (m_skipCheck && targetInfo.missCondition != SPELL_MISS_IMMUNE) + targetInfo.missCondition = SPELL_MISS_NONE; } else - target.missCondition = SPELL_MISS_EVADE; //SPELL_MISS_NONE; + targetInfo.missCondition = SPELL_MISS_EVADE; //SPELL_MISS_NONE; // Spell have speed - need calculate incoming time // Incoming time is zero for self casts. At least I think so. - if (m_spellInfo->Speed > 0.0f && m_caster != pVictim) + if (m_spellInfo->Speed > 0.0f && m_caster != target) { // calculate spell incoming interval // TODO: this is a hack - float dist = m_caster->GetDistance(pVictim->GetPositionX(), pVictim->GetPositionY(), pVictim->GetPositionZ()); + float dist = m_caster->GetDistance(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()); - if (dist < 5.0f) dist = 5.0f; - target.timeDelay = (uint64) floor(dist / m_spellInfo->Speed * 1000.0f); + if (dist < 5.0f) + dist = 5.0f; + targetInfo.timeDelay = (uint64) floor(dist / m_spellInfo->Speed * 1000.0f); // Calculate minimum incoming time - if (m_delayMoment == 0 || m_delayMoment>target.timeDelay) - m_delayMoment = target.timeDelay; + if (m_delayMoment == 0 || m_delayMoment > targetInfo.timeDelay) + m_delayMoment = targetInfo.timeDelay; } else - target.timeDelay = 0LL; + targetInfo.timeDelay = 0LL; // If target reflect spell back to caster - if (target.missCondition == SPELL_MISS_REFLECT) + if (targetInfo.missCondition == SPELL_MISS_REFLECT) { // Calculate reflected spell result on caster - target.reflectResult = m_caster->SpellHitResult(m_caster, m_spellInfo, m_canReflect); + targetInfo.reflectResult = m_caster->SpellHitResult(m_caster, m_spellInfo, m_canReflect); - if (target.reflectResult == SPELL_MISS_REFLECT) // Impossible reflect again, so simply deflect spell - target.reflectResult = SPELL_MISS_PARRY; + if (targetInfo.reflectResult == SPELL_MISS_REFLECT) // Impossible reflect again, so simply deflect spell + targetInfo.reflectResult = SPELL_MISS_PARRY; // Increase time interval for reflected spells by 1.5 - target.timeDelay += target.timeDelay >> 1; + targetInfo.timeDelay += targetInfo.timeDelay >> 1; } else - target.reflectResult = SPELL_MISS_NONE; + targetInfo.reflectResult = SPELL_MISS_NONE; // Add target to list - m_UniqueTargetInfo.push_back(target); + m_UniqueTargetInfo.push_back(targetInfo); } -void Spell::AddGOTarget(GameObject* go, uint32 effIndex) +void Spell::AddGOTarget(GameObject* go, uint32 effectMask) { - if (!m_spellInfo->Effects[effIndex].IsEffect()) - return; - - switch (m_spellInfo->Effects[effIndex].Effect) + for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) { - case SPELL_EFFECT_GAMEOBJECT_DAMAGE: - case SPELL_EFFECT_GAMEOBJECT_REPAIR: - case SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE: - if (go->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) - return; - break; - default: - break; + if (!m_spellInfo->Effects[effIndex].IsEffect()) + effectMask &= ~(1 << effIndex); + else + { + switch (m_spellInfo->Effects[effIndex].Effect) + { + case SPELL_EFFECT_GAMEOBJECT_DAMAGE: + case SPELL_EFFECT_GAMEOBJECT_REPAIR: + case SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE: + if (go->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) + effectMask &= ~(1 << effIndex); + break; + default: + break; + } + } } + if (!effectMask) + return; + uint64 targetGUID = go->GetGUID(); // Lookup target in already in list @@ -1083,7 +1100,7 @@ void Spell::AddGOTarget(GameObject* go, uint32 effIndex) { if (targetGUID == ihit->targetGUID) // Found in list { - ihit->effectMask |= 1 << effIndex; // Add only effect mask + ihit->effectMask |= effectMask; // Add only effect mask return; } } @@ -1092,7 +1109,7 @@ void Spell::AddGOTarget(GameObject* go, uint32 effIndex) GOTargetInfo target; target.targetGUID = targetGUID; - target.effectMask = 1 << effIndex; + target.effectMask = effectMask; target.processed = false; // Effects not apply on target // Spell have speed - need calculate incoming time @@ -1113,30 +1130,38 @@ void Spell::AddGOTarget(GameObject* go, uint32 effIndex) m_UniqueGOTargetInfo.push_back(target); } -void Spell::AddGOTarget(uint64 goGUID, uint32 effIndex) +void Spell::AddGOTarget(uint64 goGUID, uint32 effectMask) { if (GameObject* go = m_caster->GetMap()->GetGameObject(goGUID)) - AddGOTarget(go, effIndex); + AddGOTarget(go, effectMask); } -void Spell::AddItemTarget(Item* pitem, uint32 effIndex) +void Spell::AddItemTarget(Item* item, uint32 effectMask) { - if (!m_spellInfo->Effects[effIndex].IsEffect()) + for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + if (!m_spellInfo->Effects[effIndex].IsEffect()) + effectMask &= ~(1 << effIndex); + + // no effects left + if (!effectMask) return; // Lookup target in already in list for (std::list<ItemTargetInfo>::iterator ihit = m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit) - if (pitem == ihit->item) // Found in list + { + if (item == ihit->item) // Found in list { - ihit->effectMask |= 1 << effIndex; // Add only effect mask + ihit->effectMask |= effectMask; // Add only effect mask return; } + } // This is new target add data ItemTargetInfo target; - target.item = pitem; - target.effectMask = 1 << effIndex; + target.item = item; + target.effectMask = effectMask; + m_UniqueItemInfo.push_back(target); } @@ -2007,13 +2032,23 @@ WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType, Spe } } -void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) +uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) { SpellNotifyPushType pushType = PUSH_NONE; Player* modOwner = NULL; if (m_originalCaster) modOwner = m_originalCaster->GetSpellModOwner(); + uint32 effectMask = 1 << i; + // ENTRY targets may have different selection lists, skip those for now until we can compare lists easily and quickly + if (GetSpellInfo()->Effects[i].TargetA.GetSelectionCheckType() != TARGET_SELECT_CHECK_ENTRY && + GetSpellInfo()->Effects[i].TargetB.GetSelectionCheckType() != TARGET_SELECT_CHECK_ENTRY) + for (uint32 j = i + 1; j < MAX_SPELL_EFFECTS; ++j) + if (GetSpellInfo()->Effects[i].TargetA.GetTarget() == GetSpellInfo()->Effects[j].TargetA.GetTarget() && + GetSpellInfo()->Effects[i].TargetB.GetTarget() == GetSpellInfo()->Effects[j].TargetB.GetTarget() && + GetSpellInfo()->Effects[i].CalcRadius(m_caster) == GetSpellInfo()->Effects[j].CalcRadius(m_caster)) + effectMask |= 1 << j; + switch (cur.GetType()) { case TARGET_TYPE_UNIT_CASTER: @@ -2021,7 +2056,7 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) switch (cur.GetTarget()) { case TARGET_UNIT_CASTER: - AddUnitTarget(m_caster, i, false); + AddUnitTarget(m_caster, effectMask, false); break; case TARGET_DEST_CASTER_FISHING: { @@ -2036,16 +2071,16 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) } case TARGET_UNIT_MASTER: if (Unit* owner = m_caster->GetCharmerOrOwner()) - AddUnitTarget(owner, i); + AddUnitTarget(owner, effectMask); break; case TARGET_UNIT_PET: if (Guardian* pet = m_caster->GetGuardianPet()) - AddUnitTarget(pet, i); + AddUnitTarget(pet, effectMask); break; case TARGET_UNIT_SUMMONER: if (m_caster->isSummon()) if (Unit* unit = m_caster->ToTempSummon()->GetSummoner()) - AddUnitTarget(unit, i); + AddUnitTarget(unit, effectMask); break; case TARGET_UNIT_CASTER_AREA_PARTY: case TARGET_UNIT_CASTER_AREA_RAID: @@ -2053,7 +2088,7 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) break; case TARGET_UNIT_VEHICLE: if (Unit* vehicle = m_caster->GetVehicleBase()) - AddUnitTarget(vehicle, i); + AddUnitTarget(vehicle, effectMask); break; case TARGET_UNIT_PASSENGER_0: case TARGET_UNIT_PASSENGER_1: @@ -2065,7 +2100,7 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) case TARGET_UNIT_PASSENGER_7: if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsVehicle()) if (Unit* unit = m_caster->GetVehicleKit()->GetPassenger(cur.GetTarget() - TARGET_UNIT_PASSENGER_0)) - AddUnitTarget(unit, i); + AddUnitTarget(unit, effectMask); break; default: break; @@ -2101,15 +2136,15 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) pushType = PUSH_CHAIN; break; case TARGET_UNIT_TARGET_ALLY: - AddUnitTarget(target, i, false); + AddUnitTarget(target, effectMask, false); break; case TARGET_UNIT_TARGET_RAID: case TARGET_UNIT_TARGET_PARTY: case TARGET_UNIT_TARGET_MINIPET: - AddUnitTarget(target, i, false); + AddUnitTarget(target, effectMask, false); break; case TARGET_UNIT_TARGET_PASSENGER: - AddUnitTarget(target, i, false); + AddUnitTarget(target, effectMask, false); break; case TARGET_UNIT_LASTTARGET_AREA_PARTY: case TARGET_UNIT_TARGET_AREA_RAID_CLASS: @@ -2151,9 +2186,9 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) } if (!target) - return; + return 0; else if (target->GetTypeId() == TYPEID_GAMEOBJECT) - AddGOTarget((GameObject*)target, i); + AddGOTarget((GameObject*)target, effectMask); else { pushType = PUSH_CHAIN; @@ -2292,10 +2327,10 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) case TARGET_DEST_DYNOBJ_ALLY: case TARGET_DEST_DYNOBJ_NONE: case TARGET_DEST_DEST: - return; + return effectMask; case TARGET_DEST_TRAJ: SelectTrajTargets(); - return; + return effectMask; case TARGET_DEST_DEST_FRONT: angle = 0.0f; break; case TARGET_DEST_DEST_BACK: angle = static_cast<float>(M_PI); break; case TARGET_DEST_DEST_RIGHT: angle = static_cast<float>(M_PI/2); break; @@ -2372,7 +2407,7 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) case TARGET_UNIT_CHANNEL_TARGET: // unit target may be no longer avalible - teleported out of map for example if (Unit* target = Unit::GetUnit(*m_caster, m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets.GetUnitTargetGUID())) - AddUnitTarget(target, i); + AddUnitTarget(target, effectMask); else sLog->outError("SPELL: cannot find channel spell target for spell ID %u", m_spellInfo->Id); break; @@ -2399,13 +2434,13 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) { case TARGET_GAMEOBJECT_TARGET: if (m_targets.GetGOTarget()) - AddGOTarget(m_targets.GetGOTarget(), i); + AddGOTarget(m_targets.GetGOTarget(), effectMask); break; case TARGET_GAMEOBJECT_ITEM_TARGET: if (m_targets.GetGOTargetGUID()) - AddGOTarget(m_targets.GetGOTarget(), i); + AddGOTarget(m_targets.GetGOTarget(), effectMask); else if (m_targets.GetItemTarget()) - AddItemTarget(m_targets.GetItemTarget(), i); + AddItemTarget(m_targets.GetItemTarget(), effectMask); break; default: sLog->outError("SPELL (caster[type: %u; guidlow: %u], spell: %u): unhandled spell target (%u)", @@ -2422,7 +2457,7 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) if (!target) { sLog->outError("SPELL: no chain unit target for spell ID %u", m_spellInfo->Id); - return; + return 0; } //Chain: 2, 6, 22, 25, 45, 77 @@ -2433,8 +2468,10 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) if (maxTargets > 1) { //otherwise, this multiplier is used for something else - m_damageMultipliers[i] = 1.0f; - m_applyMultiplierMask |= 1 << i; + for (uint32 k = i; k < MAX_SPELL_EFFECTS; ++k) + if (effectMask & (1 << k)) + m_damageMultipliers[k] = 1.0f; + m_applyMultiplierMask |= effectMask; float range; std::list<Unit*> unitList; @@ -2463,16 +2500,16 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) CallScriptAfterUnitTargetSelectHandlers(unitList, SpellEffIndex(i)); for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) - AddUnitTarget(*itr, i, false); + AddUnitTarget(*itr, effectMask, false); } else - AddUnitTarget(target, i, false); + AddUnitTarget(target, effectMask, false); } else if (pushType) { // Dummy, just for client if (m_spellInfo->Effects[i].GetRequiredTargetType() != SPELL_REQUIRE_UNIT) - return; + return 0; float radius; SpellTargets targetType; @@ -2527,7 +2564,7 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) { if ((*i_spellST)->mConditionType != CONDITION_SPELL_SCRIPT_TARGET) continue; - if ((*i_spellST)->mConditionValue3 && !((*i_spellST)->mConditionValue3 & (1<<i))) + if ((*i_spellST)->mConditionValue3 && !((*i_spellST)->mConditionValue3 & effectMask)) continue; if ((*i_spellST)->mConditionValue1 == SPELL_TARGET_TYPE_CREATURE) SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, (*i_spellST)->mConditionValue2); @@ -2622,7 +2659,7 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) { if ((*i_spellST)->mConditionType != CONDITION_SPELL_SCRIPT_TARGET) continue; - if ((*i_spellST)->mConditionValue3 && !((*i_spellST)->mConditionValue3 & (1<<i))) + if ((*i_spellST)->mConditionValue3 && !((*i_spellST)->mConditionValue3 & effectMask)) continue; if ((*i_spellST)->mConditionValue1 == SPELL_TARGET_TYPE_GAMEOBJECT) SearchGOAreaTarget(gobjectList, radius, pushType, SPELL_TARGETS_GO, (*i_spellST)->mConditionValue2); @@ -2672,11 +2709,11 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) // IsHostileTo check duel and controlled by enemy if (Target && targetPlayer->IsWithinDistInMap(Target, radius) && targetPlayer->getClass() == Target->getClass() && !m_caster->IsHostileTo(Target)) - AddUnitTarget(Target, i); + AddUnitTarget(Target, effectMask); } } else if (m_targets.GetUnitTarget()) - AddUnitTarget(m_targets.GetUnitTarget(), i); + AddUnitTarget(m_targets.GetUnitTarget(), effectMask); break; } default: @@ -2822,7 +2859,7 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) CallScriptAfterUnitTargetSelectHandlers(unitList, SpellEffIndex(i)); for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) - AddUnitTarget(*itr, i, false); + AddUnitTarget(*itr, effectMask, false); } if (!gobjectList.empty()) @@ -2837,9 +2874,11 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) Trinity::RandomResizeList(gobjectList, maxTargets); } for (std::list<GameObject*>::iterator itr = gobjectList.begin(); itr != gobjectList.end(); ++itr) - AddGOTarget(*itr, i); + AddGOTarget(*itr, effectMask); } } + + return effectMask; } void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggeredByAura) diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index b54061bc87d..e8a9a1dc95e 100755 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -400,7 +400,7 @@ class Spell void InitExplicitTargets(SpellCastTargets const& targets); void SelectSpellTargets(); - void SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur); + uint32 SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur); void SelectTrajTargets(); template<typename T> WorldObject* FindCorpseUsing(); @@ -588,10 +588,10 @@ class Spell }; std::list<ItemTargetInfo> m_UniqueItemInfo; - void AddUnitTarget(Unit* target, uint32 effIndex, bool checkIfValid = true); - void AddGOTarget(GameObject* target, uint32 effIndex); - void AddGOTarget(uint64 goGUID, uint32 effIndex); - void AddItemTarget(Item* target, uint32 effIndex); + void AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid = true); + void AddGOTarget(GameObject* target, uint32 effectMask); + void AddGOTarget(uint64 goGUID, uint32 effectMask); + void AddItemTarget(Item* item, uint32 effectMask); void DoAllEffectOnTarget(TargetInfo* target); SpellMissInfo DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleAura); void DoTriggersOnSpellHit(Unit* unit, uint8 effMask); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index a42b32a4c44..f798e43a7d2 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1374,7 +1374,7 @@ void Spell::EffectDummy(SpellEffIndex effIndex) for (uint32 i = 0; i < maxTargets; ++i) { Unit* attacker = SelectRandomContainerElement(attackers); - AddUnitTarget(attacker, 1); + AddUnitTarget(attacker, 1 << 1); attackers.erase(attacker); } |