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 | |
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
-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); } |