diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 54 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 252 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 22 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 64 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 13 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 6 | ||||
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp | 1 | ||||
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp | 4 |
8 files changed, 257 insertions, 159 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 1dfb3a42154..3e125a57448 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -2320,7 +2320,7 @@ void Unit::CalcHealAbsorb(Unit *pVictim, const SpellEntry *healSpell, uint32 &he healAmount = RemainingHeal; } -void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool /*extra*/) +void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool extra) { if (hasUnitState(UNIT_STAT_CANNOT_AUTOATTACK) || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) return; @@ -2339,36 +2339,46 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool /* else return; // ignore ranged case - // melee attack spell casted at main hand attack only + // melee attack spell casted at main hand attack only - no normal melee dmg dealt if (attType == BASE_ATTACK && m_currentSpells[CURRENT_MELEE_SPELL]) { m_currentSpells[CURRENT_MELEE_SPELL]->cast(); - return; } + else + { + // attack can be redirected to another target + pVictim = SelectMagnetTarget(pVictim); - // attack can be redirected to another target - pVictim = SelectMagnetTarget(pVictim); - - CalcDamageInfo damageInfo; - CalculateMeleeDamage(pVictim, 0, &damageInfo, attType); - // Send log damage message to client - DealDamageMods(pVictim, damageInfo.damage, &damageInfo.absorb); - SendAttackStateUpdate(&damageInfo); + CalcDamageInfo damageInfo; + CalculateMeleeDamage(pVictim, 0, &damageInfo, attType); + // Send log damage message to client + DealDamageMods(pVictim, damageInfo.damage, &damageInfo.absorb); + SendAttackStateUpdate(&damageInfo); - ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage, damageInfo.attackType); - DealMeleeDamage(&damageInfo,true); + ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage, damageInfo.attackType); + DealMeleeDamage(&damageInfo,true); - if (GetTypeId() == TYPEID_PLAYER) - sLog.outStaticDebug("AttackerStateUpdate: (Player) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.", - GetGUIDLow(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist); - else - sLog.outStaticDebug("AttackerStateUpdate: (NPC) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.", - GetGUIDLow(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist); + if (GetTypeId() == TYPEID_PLAYER) + sLog.outStaticDebug("AttackerStateUpdate: (Player) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.", + GetGUIDLow(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist); + else + sLog.outStaticDebug("AttackerStateUpdate: (NPC) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.", + GetGUIDLow(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist); - // if damage pVictim call AI reaction - //if (pVictim->GetTypeId() == TYPEID_UNIT && pVictim->ToCreature()->AI()) - // pVictim->ToCreature()->AI()->AttackedBy(this); + // if damage pVictim call AI reaction + //if (pVictim->GetTypeId() == TYPEID_UNIT && pVictim->ToCreature()->AI()) + // pVictim->ToCreature()->AI()->AttackedBy(this); + } + if(!extra && m_extraAttacks) + { + while(m_extraAttacks) + { + AttackerStateUpdate(pVictim, BASE_ATTACK, true); + if(m_extraAttacks > 0) + --m_extraAttacks; + } + } } MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit *pVictim, WeaponAttackType attType) const diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index f9a39618207..c6616d0625b 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -532,6 +532,7 @@ m_caster(Caster), m_spellValue(new SpellValue(m_spellInfo)) } CleanupTargetList(); + CleanupEffectExecuteData(); } Spell::~Spell() @@ -555,6 +556,8 @@ Spell::~Spell() if (m_caster && m_caster->GetTypeId() == TYPEID_PLAYER) ASSERT(m_caster->ToPlayer()->m_spellModTakingSpell != this); delete m_spellValue; + + CheckEffectExecuteData(); } template<typename T> @@ -2218,7 +2221,7 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) Unit *target = m_targets.getUnitTarget(); if (!target) { - sLog.outError("SPELL: no unit target for spell ID %u\n", m_spellInfo->Id); + sLog.outError("SPELL: no unit target for spell ID %u", m_spellInfo->Id); break; } @@ -2261,7 +2264,7 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) { if (!m_targets.HasDst()) { - sLog.outError("SPELL: no destination for spell ID %u\n", m_spellInfo->Id); + sLog.outError("SPELL: no destination for spell ID %u", m_spellInfo->Id); break; } @@ -3360,6 +3363,8 @@ void Spell::handle_immediate() } } + PrepareTargetProcessing(); + // process immediate effects (items, ground, etc.) also initialize some variables _handle_immediate_phase(); @@ -3369,6 +3374,8 @@ void Spell::handle_immediate() for (std::list<GOTargetInfo>::iterator ihit= m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit) DoAllEffectOnTarget(&(*ihit)); + FinishTargetProcessing(); + // spell is finished, perform some last features of the spell here _handle_finish_phase(); @@ -3388,6 +3395,8 @@ uint64 Spell::handle_delayed(uint64 t_offset) uint64 next_time = 0; + PrepareTargetProcessing(); + if (!m_immediateHandled) { _handle_immediate_phase(); @@ -3420,6 +3429,8 @@ uint64 Spell::handle_delayed(uint64 t_offset) } } + FinishTargetProcessing(); + if (m_caster->GetTypeId() == TYPEID_PLAYER) m_caster->ToPlayer()->SetSpellModTakingSpell(this, false); @@ -3449,7 +3460,6 @@ void Spell::_handle_immediate_phase() PrepareScriptHitHandlers(); - m_needSpellLog = IsNeedSendToClient(); for (uint32 j = 0; j < 3; ++j) { if (m_spellInfo->Effect[j] == 0) @@ -3461,10 +3471,6 @@ void Spell::_handle_immediate_phase() HandleEffects(NULL, NULL, NULL, j); continue; } - - // Don't do spell log, if is school damage spell - if (m_spellInfo->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE || m_spellInfo->Effect[j] == 0) - m_needSpellLog = false; } // initialize Diminishing Returns Data @@ -3543,10 +3549,6 @@ void Spell::_handle_finish_phase() if (m_comboPointGain) m_caster->m_movedPlayer->GainSpellComboPoints(m_comboPointGain); } - - // spell log - if (m_needSpellLog) - SendLogExecute(); } void Spell::SendSpellCooldown() @@ -3713,10 +3715,6 @@ void Spell::finish(bool ok) } } - // Okay to remove extra attacks - if (IsSpellHaveEffect(m_spellInfo, SPELL_EFFECT_ADD_EXTRA_ATTACKS)) - m_caster->m_extraAttacks = 0; - if (IsMeleeAttackResetSpell()) { bool found = false; @@ -4119,112 +4117,105 @@ void Spell::WriteSpellGoTargets(WorldPacket * data) void Spell::SendLogExecute() { - Unit *target = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster; - WorldPacket data(SMSG_SPELLLOGEXECUTE, (8+4+4+4+4+8)); - if (m_caster->GetTypeId() == TYPEID_PLAYER) - data.append(m_caster->GetPackGUID()); - else - data.append(target->GetPackGUID()); + data.append(m_caster->GetPackGUID()); data << uint32(m_spellInfo->Id); - uint32 count1 = 1; - data << uint32(count1); // count1 (effect count?) - for (uint32 i = 0; i < count1; ++i) + + uint8 effCount = 0; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - data << uint32(m_spellInfo->Effect[0]); // spell effect - uint32 count2 = 1; - data << uint32(count2); // count2 (target count?) - for (uint32 j = 0; j < count2; ++j) - { - switch(m_spellInfo->Effect[0]) - { - case SPELL_EFFECT_POWER_DRAIN: - if (Unit *unit = m_targets.getUnitTarget()) - data.append(unit->GetPackGUID()); - else - data << uint8(0); - data << uint32(0); - data << uint32(0); - data << float(0); - break; - case SPELL_EFFECT_ADD_EXTRA_ATTACKS: - if (Unit *unit = m_targets.getUnitTarget()) - data.append(unit->GetPackGUID()); - else - data << uint8(0); - data << uint32(m_caster->m_extraAttacks); - break; - case SPELL_EFFECT_INTERRUPT_CAST: - if (Unit *unit = m_targets.getUnitTarget()) - data.append(unit->GetPackGUID()); - else - data << uint8(0); - data << uint32(0); // spellid - break; - case SPELL_EFFECT_DURABILITY_DAMAGE: - if (Unit *unit = m_targets.getUnitTarget()) - data.append(unit->GetPackGUID()); - else - data << uint8(0); - data << uint32(0); - data << uint32(0); - break; - case SPELL_EFFECT_OPEN_LOCK: - if (Item *item = m_targets.getItemTarget()) - data.append(item->GetPackGUID()); - else - data << uint8(0); - break; - case SPELL_EFFECT_CREATE_ITEM: - case SPELL_EFFECT_CREATE_ITEM_2: - data << uint32(m_spellInfo->EffectItemType[0]); - break; - case SPELL_EFFECT_SUMMON: - case SPELL_EFFECT_TRANS_DOOR: - case SPELL_EFFECT_SUMMON_PET: - case SPELL_EFFECT_SUMMON_OBJECT_WILD: - case SPELL_EFFECT_CREATE_HOUSE: - case SPELL_EFFECT_DUEL: - case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: - case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: - case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: - case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: - if (Unit *unit = m_targets.getUnitTarget()) - data.append(unit->GetPackGUID()); - else if (m_targets.getItemTargetGUID()) - data.appendPackGUID(m_targets.getItemTargetGUID()); - else if (GameObject *go = m_targets.getGOTarget()) - data.append(go->GetPackGUID()); - else - data << uint8(0); // guid - break; - case SPELL_EFFECT_FEED_PET: - data << uint32(m_targets.getItemTargetEntry()); - break; - case SPELL_EFFECT_DISMISS_PET: - if (Unit *unit = m_targets.getUnitTarget()) - data.append(unit->GetPackGUID()); - else - data << uint8(0); - break; - case SPELL_EFFECT_RESURRECT: - case SPELL_EFFECT_RESURRECT_NEW: - if (Unit *unit = m_targets.getUnitTarget()) - data.append(unit->GetPackGUID()); - else - data << uint8(0); - break; - default: - return; - } - } + if (m_effectExecuteData[i]) + ++effCount; } + if (!effCount) + return; + + data << uint32(effCount); + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if (!m_effectExecuteData[i]) + continue; + + data << uint32(m_spellInfo->Effect[i]); // spell effect + + data.append(*m_effectExecuteData[i]); + + delete m_effectExecuteData[i]; + m_effectExecuteData[i] = NULL; + } m_caster->SendMessageToSet(&data, true); } +void Spell::ExecuteLogEffectTakeTargetPower(uint8 effIndex, Unit * target, uint32 powerType, uint32 powerTaken, float gainMultiplier) +{ + InitEffectExecuteData(effIndex); + m_effectExecuteData[effIndex]->append(target->GetPackGUID()); + *m_effectExecuteData[effIndex] << uint32(powerType); + *m_effectExecuteData[effIndex] << uint32(powerTaken); + *m_effectExecuteData[effIndex] << float(gainMultiplier); +} + +void Spell::ExecuteLogEffectExtraAttacks(uint8 effIndex, Unit * victim, uint32 attCount) +{ + InitEffectExecuteData(effIndex); + m_effectExecuteData[effIndex]->append(victim->GetPackGUID()); + *m_effectExecuteData[effIndex] << uint32(attCount); +} + +void Spell::ExecuteLogEffectInterruptCast(uint8 effIndex, Unit * victim, uint32 spellId) +{ + InitEffectExecuteData(effIndex); + m_effectExecuteData[effIndex]->append(victim->GetPackGUID()); + *m_effectExecuteData[effIndex] << uint32(spellId); +} + +void Spell::ExecuteLogEffectDurabilityDamage(uint8 effIndex, Unit * victim, uint32 itemslot, uint32 damage) +{ + InitEffectExecuteData(effIndex); + m_effectExecuteData[effIndex]->append(victim->GetPackGUID()); + *m_effectExecuteData[effIndex] << uint32(itemslot); + *m_effectExecuteData[effIndex] << uint32(damage); +} + +void Spell::ExecuteLogEffectOpenLock(uint8 effIndex, Object * obj) +{ + InitEffectExecuteData(effIndex); + m_effectExecuteData[effIndex]->append(obj->GetPackGUID()); +} + +void Spell::ExecuteLogEffectCreateItem(uint8 effIndex, uint32 entry) +{ + InitEffectExecuteData(effIndex); + *m_effectExecuteData[effIndex] << uint32(entry); +} + +void Spell::ExecuteLogEffectDestroyItem(uint8 effIndex, uint32 entry) +{ + InitEffectExecuteData(effIndex); + *m_effectExecuteData[effIndex] << uint32(entry); +} + +void Spell::ExecuteLogEffectSummonObject(uint8 effIndex, WorldObject * obj) +{ + InitEffectExecuteData(effIndex); + m_effectExecuteData[effIndex]->append(obj->GetPackGUID()); +} + +void Spell::ExecuteLogEffectUnsummonObject(uint8 effIndex, WorldObject * obj) +{ + InitEffectExecuteData(effIndex); + m_effectExecuteData[effIndex]->append(obj->GetPackGUID()); +} + +void Spell::ExecuteLogEffectResurrect(uint8 effIndex, Unit * target) +{ + InitEffectExecuteData(effIndex); + m_effectExecuteData[effIndex]->append(target->GetPackGUID()); +} + void Spell::SendInterrupted(uint8 result) { WorldPacket data(SMSG_SPELL_FAILURE, (8+4+1)); @@ -7263,6 +7254,45 @@ void Spell::SelectTrajTargets() } } +void Spell::PrepareTargetProcessing() +{ + CheckEffectExecuteData(); +} + +void Spell::FinishTargetProcessing() +{ + SendLogExecute(); +} + +void Spell::InitEffectExecuteData(uint8 effIndex) +{ + ASSERT(effIndex < MAX_SPELL_EFFECTS); + if (!m_effectExecuteData[effIndex]) + { + m_effectExecuteData[effIndex] = new ByteBuffer(); + // first dword - target counter + *m_effectExecuteData[effIndex] << uint32(1); + } + else + { + // increase target counter by one + uint32 count = (*m_effectExecuteData[effIndex]).read<uint32>(0); + (*m_effectExecuteData[effIndex]).put<uint32>(0, ++count); + } +} + +void Spell::CleanupEffectExecuteData() +{ + for(uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + m_effectExecuteData[i] = NULL; +} + +void Spell::CheckEffectExecuteData() +{ + for(uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + ASSERT(!m_effectExecuteData[i]); +} + void Spell::LoadScripts() { sLog.outDebug("Spell::LoadScripts"); diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index f6e037a7de8..6fe627b6ca2 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -32,6 +32,7 @@ class DynamicObject; class WorldObject; class Aura; class SpellScript; +class ByteBuffer; struct SpellEntry; @@ -475,6 +476,16 @@ class Spell void SendSpellGo(); void SendSpellCooldown(); void SendLogExecute(); + void ExecuteLogEffectTakeTargetPower(uint8 effIndex, Unit * target, uint32 powerType, uint32 powerTaken, float gainMultiplier); + void ExecuteLogEffectExtraAttacks(uint8 effIndex, Unit * victim, uint32 attCount); + void ExecuteLogEffectInterruptCast(uint8 effIndex, Unit * victim, uint32 spellId); + void ExecuteLogEffectDurabilityDamage(uint8 effIndex, Unit * victim, uint32 itemslot, uint32 damage); + void ExecuteLogEffectOpenLock(uint8 effIndex, Object * obj); + void ExecuteLogEffectCreateItem(uint8 effIndex, uint32 entry); + void ExecuteLogEffectDestroyItem(uint8 effIndex, uint32 entry); + void ExecuteLogEffectSummonObject(uint8 effIndex, WorldObject * obj); + void ExecuteLogEffectUnsummonObject(uint8 effIndex, WorldObject * obj); + void ExecuteLogEffectResurrect(uint8 effIndex, Unit * target); void SendInterrupted(uint8 result); void SendChannelUpdate(uint32 time); void SendChannelStart(uint32 duration); @@ -573,7 +584,6 @@ class Spell // These vars are used in both delayed spell system and modified immediate spell system bool m_referencedFromCurrentSpell; // mark as references to prevent deleted and access by dead pointers bool m_executedCurrently; // mark as executed to prevent deleted and access by dead pointers - bool m_needSpellLog; // need to send spell log? bool m_needComboPoints; // Current targets, to be used in SpellEffects (MUST BE USED ONLY IN SPELL EFFECTS) @@ -662,6 +672,14 @@ class Spell void SpellDamageWeaponDmg(uint32 i); void SpellDamageHeal(uint32 i); + void PrepareTargetProcessing(); + void FinishTargetProcessing(); + + // spell execution log + void InitEffectExecuteData(uint8 effIndex); + void CleanupEffectExecuteData(); + void CheckEffectExecuteData(); + // Scripting system void LoadScripts(); void PrepareScriptHitHandlers(); @@ -698,6 +716,8 @@ class Spell uint32 m_effectMask; uint8 m_auraScaleMask; + ByteBuffer * m_effectExecuteData[MAX_SPELL_EFFECTS]; + #ifdef MAP_BASED_RAND_GEN int32 irand(int32 min, int32 max) { return int32 (m_caster->GetMap()->mtRand.randInt(max - min)) + min; } uint32 urand(uint32 min, uint32 max) { return m_caster->GetMap()->mtRand.randInt(max - min) + min; } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index dbabd957c1c..eee2e7c6dc2 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -260,6 +260,7 @@ void Spell::EffectResurrectNew(uint32 i) uint32 health = damage; uint32 mana = m_spellInfo->EffectMiscValue[i]; + ExecuteLogEffectResurrect(i, pTarget); pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana); SendResurrectRequest(pTarget); } @@ -2352,15 +2353,18 @@ void Spell::EffectPowerDrain(uint32 i) int32 newDamage = unitTarget->ModifyPower(powerType, -int32(power)); + float gainMultiplier = 0.0f; + // Don`t restore from self drain if (m_caster != unitTarget) { - float gainMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(m_spellInfo, i, m_originalCaster, this); + gainMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(m_spellInfo, i, m_originalCaster, this); int32 gain = int32(newDamage * gainMultiplier); m_caster->EnergizeBySpell(m_caster, m_spellInfo->Id, gain, powerType); } + ExecuteLogEffectTakeTargetPower(i, unitTarget, powerType, newDamage, gainMultiplier); } void Spell::EffectSendEvent(uint32 EffectIndex) @@ -2413,7 +2417,8 @@ void Spell::EffectPowerBurn(uint32 i) newDamage = int32(newDamage * dmgMultiplier); - //TODO: no log + ExecuteLogEffectTakeTargetPower(i,unitTarget, powerType, newDamage, dmgMultiplier); + if (m_originalCaster) m_originalCaster->DealDamage(unitTarget, newDamage); } @@ -2714,6 +2719,7 @@ void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype) void Spell::EffectCreateItem(uint32 i) { DoCreateItem(i,m_spellInfo->EffectItemType[i]); + ExecuteLogEffectCreateItem(i, m_spellInfo->EffectItemType[i]); } void Spell::EffectCreateItem2(uint32 i) @@ -2745,6 +2751,7 @@ void Spell::EffectCreateItem2(uint32 i) else player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell); // create some random items } + // TODO: ExecuteLogEffectCreateItem(i, m_spellInfo->EffectItemType[i]); } void Spell::EffectCreateRandomItem(uint32 /*i*/) @@ -2755,6 +2762,7 @@ void Spell::EffectCreateRandomItem(uint32 /*i*/) // create some random items player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell); + // TODO: ExecuteLogEffectCreateItem(i, m_spellInfo->EffectItemType[i]); } void Spell::EffectPersistentAA(uint32 i) @@ -3069,6 +3077,7 @@ void Spell::EffectOpenLock(uint32 effIndex) } } } + ExecuteLogEffectOpenLock(effIndex, gameObjTarget ? (Object*)gameObjTarget : (Object*)itemTarget); } void Spell::EffectSummonChangeItem(uint32 i) @@ -3328,8 +3337,9 @@ void Spell::EffectSummonType(uint32 i) summon->setFaction(m_originalCaster->getFaction()); summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); } + ExecuteLogEffectSummonObject(i, summon); } - break; + return; } }//switch break; @@ -3363,6 +3373,7 @@ void Spell::EffectSummonType(uint32 i) { summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); summon->SetCreatorGUID(m_originalCaster->GetGUID()); + ExecuteLogEffectSummonObject(i, summon); } } @@ -4032,6 +4043,8 @@ void Spell::EffectSummonPet(uint32 i) std::string new_name=sObjectMgr.GeneratePetName(petentry); if (!new_name.empty()) pet->SetName(new_name); + + ExecuteLogEffectSummonObject(i, pet); } void Spell::EffectLearnPetSpell(uint32 i) @@ -4438,7 +4451,7 @@ void Spell::EffectHealMaxHealth(uint32 /*i*/) } } -void Spell::EffectInterruptCast(uint32 /*i*/) +void Spell::EffectInterruptCast(uint32 effIndex) { if (!unitTarget) return; @@ -4462,6 +4475,7 @@ void Spell::EffectInterruptCast(uint32 /*i*/) int32 duration = m_originalCaster->ModSpellDuration(m_spellInfo, unitTarget, m_originalCaster->CalcSpellDuration(m_spellInfo), false); unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(curSpellInfo), duration/*GetSpellDuration(m_spellInfo)*/); } + ExecuteLogEffectInterruptCast(effIndex, unitTarget, curSpellInfo->Id); unitTarget->InterruptSpell(CurrentSpellTypes(i), false); } } @@ -4498,6 +4512,8 @@ void Spell::EffectSummonObjectWild(uint32 i) pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0); pGameObj->SetSpellId(m_spellInfo->Id); + ExecuteLogEffectSummonObject(i, pGameObj); + // Wild object not have owner and check clickable by players map->Add(pGameObj); @@ -4541,6 +4557,8 @@ void Spell::EffectSummonObjectWild(uint32 i) linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0); linkedGO->SetSpellId(m_spellInfo->Id); + ExecuteLogEffectSummonObject(i, linkedGO); + // Wild object not have owner and check clickable by players map->Add(linkedGO); } @@ -5705,6 +5723,8 @@ void Spell::EffectDuel(uint32 i) pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0); pGameObj->SetSpellId(m_spellInfo->Id); + ExecuteLogEffectSummonObject(i, pGameObj); + m_caster->AddGameObject(pGameObj); map->Add(pGameObj); //END @@ -5940,10 +5960,12 @@ void Spell::EffectFeedPet(uint32 i) _player->DestroyItemCount(foodItem,count,true); // TODO: fix crash when a spell has two effects, both pointed at the same item target + ExecuteLogEffectDestroyItem(i, foodItem->GetEntry()); + m_caster->CastCustomSpell(pet, m_spellInfo->EffectTriggerSpell[i], &benefit, NULL, NULL, true); } -void Spell::EffectDismissPet(uint32 /*i*/) +void Spell::EffectDismissPet(uint32 i) { if (m_caster->GetTypeId() != TYPEID_PLAYER) return; @@ -5954,6 +5976,7 @@ void Spell::EffectDismissPet(uint32 /*i*/) if (!pet||!pet->isAlive()) return; + ExecuteLogEffectUnsummonObject(i, pet); m_caster->ToPlayer()->RemovePet(pet, PET_SAVE_NOT_IN_SLOT); } @@ -6012,12 +6035,14 @@ void Spell::EffectSummonObject(uint32 i) pGameObj->SetSpellId(m_spellInfo->Id); m_caster->AddGameObject(pGameObj); + ExecuteLogEffectSummonObject(i, pGameObj); + map->Add(pGameObj); m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID(); } -void Spell::EffectResurrect(uint32 /*effIndex*/) +void Spell::EffectResurrect(uint32 effIndex) { if (!unitTarget) return; @@ -6066,32 +6091,23 @@ void Spell::EffectResurrect(uint32 /*effIndex*/) uint32 health = pTarget->CountPctFromMaxHealth(damage); uint32 mana = pTarget->GetMaxPower(POWER_MANA) * damage / 100; + ExecuteLogEffectResurrect(effIndex, pTarget); + pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana); SendResurrectRequest(pTarget); } -void Spell::EffectAddExtraAttacks(uint32 /*i*/) +void Spell::EffectAddExtraAttacks(uint32 i) { - if (!unitTarget || !unitTarget->isAlive()) + if (!unitTarget || !unitTarget->isAlive() || !unitTarget->getVictim()) return; if (unitTarget->m_extraAttacks) return; - Unit *victim = unitTarget->getVictim(); - - // attack prevented - // fixme, some attacks may not target current victim, this is right now not handled - if (!victim || !unitTarget->IsWithinMeleeRange(victim) || !unitTarget->HasInArc(static_cast<float>(2*M_PI/3), victim)) - return; - - // Only for proc/log informations unitTarget->m_extraAttacks = damage; - // Need to send log before attack is made - SendLogExecute(); - m_needSpellLog = false; - unitTarget->AttackerStateUpdate(victim, BASE_ATTACK, true); + ExecuteLogEffectExtraAttacks(i, unitTarget->getVictim(), damage); } void Spell::EffectParry(uint32 /*i*/) @@ -6500,6 +6516,8 @@ void Spell::EffectDurabilityDamage(uint32 i) if (Item* item = unitTarget->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) unitTarget->ToPlayer()->DurabilityPointsLoss(item, damage); + + ExecuteLogEffectDurabilityDamage(i, unitTarget, slot, damage); } void Spell::EffectDurabilityDamagePCT(uint32 i) @@ -6646,6 +6664,8 @@ void Spell::EffectTransmitted(uint32 effIndex) //pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()); pGameObj->SetSpellId(m_spellInfo->Id); + ExecuteLogEffectSummonObject(effIndex, pGameObj); + sLog.outStaticDebug("AddObject at SpellEfects.cpp EffectTransmitted"); //m_caster->AddGameObject(pGameObj); //m_ObjToDel.push_back(pGameObj); @@ -6663,6 +6683,8 @@ void Spell::EffectTransmitted(uint32 effIndex) linkedGO->SetSpellId(m_spellInfo->Id); linkedGO->SetOwnerGUID(m_caster->GetGUID()); + ExecuteLogEffectSummonObject(effIndex, linkedGO); + linkedGO->GetMap()->Add(linkedGO); } else @@ -7086,6 +7108,8 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const * summon->SetDisplayId(1126); summon->AI()->EnterEvadeMode(); + + ExecuteLogEffectSummonObject(i, summon); } } diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 01cb2d6d243..6b3ec145b2e 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3862,6 +3862,19 @@ void SpellMgr::LoadSpellCustomAttr() mSpellCustomAttr[i] |= SPELL_ATTR_CU_IGNORE_ARMOR; count++; break; + // THESE SPELLS ARE WORKING CORRECTLY EVEN WITHOUT THIS HACK + // THE ONLY REASON ITS HERE IS THAT CURRENT GRID SYSTEM + // DOES NOT ALLOW FAR OBJECT SELECTION (dist > 333) + case 70781: // Light's Hammer Teleport + case 70856: // Oratory of the Damned Teleport + case 70857: // Rampart of Skulls Teleport + case 70858: // Deathbringer's Rise Teleport + case 70859: // Upper Spire Teleport + case 70860: // Frozen Throne Teleport + case 70861: // Sindragosa's Lair Teleport + spellInfo->EffectImplicitTargetA[0] = TARGET_DST_DB; + count++; + break; default: break; } diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 8a47cbdcc93..cc5391fc9a9 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1449,15 +1449,15 @@ void World::SetInitialWorldSettings() sLog.outString("Loading Graveyard-zone links..."); sObjectMgr.LoadGraveyardZones(); - sLog.outString("Loading Spell target coordinates..."); - sSpellMgr.LoadSpellTargetPositions(); - sLog.outString("Loading spell pet auras..."); sSpellMgr.LoadSpellPetAuras(); sLog.outString("Loading spell extra attributes..."); sSpellMgr.LoadSpellCustomAttr(); + sLog.outString("Loading Spell target coordinates..."); + sSpellMgr.LoadSpellTargetPositions(); + sLog.outString("Loading enchant custom attributes..."); sSpellMgr.LoadEnchantCustomAttr(); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp index 2eaaf96820d..100440237bb 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp @@ -63,6 +63,7 @@ class icecrown_citadel_teleport : public GameObjectScript bool OnGossipSelect(Player* player, GameObject* go, uint32 sender, uint32 action) { + player->CLOSE_GOSSIP_MENU(); SpellEntry const* spell = sSpellStore.LookupEntry(action); if (!spell) return false; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index 236642e414c..dbf8ced0c48 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -207,8 +207,8 @@ class instance_icecrown_citadel : public InstanceMapScript switch (data) { case DONE: - // TEMPORARY, UNCOMMMENT IF YOU WANT TO DO SAURFANG AND SKIP GUNSHIP - //uiEncounterState[DATA_GUNSHIP_EVENT] = DONE; + // TEMPORARY, SKIP GUNSHIP + uiEncounterState[DATA_GUNSHIP_EVENT] = DONE; HandleGameObject(uiOratoryDoor, true); if (GameObject* elevator = instance->GetGameObject(uiLadyDeathwisperElevator)) { |