*Fix combat logging of many spell effects - thanks to kiper, Ssp, Cyrax, and manuel for providing data and to Zor for inspecting opcodes.

--HG--
branch : trunk
This commit is contained in:
QAston
2010-08-27 17:49:32 +02:00
parent e2dc4c3a66
commit f1d4933dcb
4 changed files with 240 additions and 156 deletions
+36 -26
View File
@@ -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);
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);
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);
}
// 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);
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 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
+139 -109
View File
@@ -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>
@@ -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");
+21 -1
View File
@@ -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; }
+44 -20
View File
@@ -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);
}
}