[7801] Apply damage mods from scripts or target state not in DealDamage but in new function before send data to client.

* Fixed bug with health decrease (client side visual bug) at spell damage by target with AI::DamageTaken damage set to 0
* Fixed bug with ignore .die command and instant kill damage in some cases.
This commit is contained in:
VladimirMangos 2009-05-08 16:43:52 +04:00
parent b9cd3ffd0d
commit f53d06ad70
8 changed files with 80 additions and 31 deletions

View file

@ -3418,31 +3418,34 @@ bool ChatHandler::HandleDamageCommand(const char * args)
Unit* target = getSelectedUnit(); Unit* target = getSelectedUnit();
if(!target || !m_session->GetPlayer()->GetSelection()) if (!target || !m_session->GetPlayer()->GetSelection())
{ {
SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE);
SetSentErrorMessage(true); SetSentErrorMessage(true);
return false; return false;
} }
if( !target->isAlive() ) if (!target->isAlive())
return true; return true;
char* damageStr = strtok((char*)args, " "); char* damageStr = strtok((char*)args, " ");
if(!damageStr) if (!damageStr)
return false; return false;
int32 damage = atoi((char*)damageStr); int32 damage_int = atoi((char*)damageStr);
if(damage <=0) if(damage_int <=0)
return true; return true;
uint32 damage = damage_int;
char* schoolStr = strtok((char*)NULL, " "); char* schoolStr = strtok((char*)NULL, " ");
// flat melee damage without resistence/etc reduction // flat melee damage without resistence/etc reduction
if(!schoolStr) if (!schoolStr)
{ {
m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); if (target != m_session->GetPlayer())
m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0);
return true; return true;
} }
@ -3458,7 +3461,7 @@ bool ChatHandler::HandleDamageCommand(const char * args)
char* spellStr = strtok((char*)NULL, " "); char* spellStr = strtok((char*)NULL, " ");
// melee damage by specific school // melee damage by specific school
if(!spellStr) if (!spellStr)
{ {
uint32 absorb = 0; uint32 absorb = 0;
uint32 resist = 0; uint32 resist = 0;
@ -3470,6 +3473,7 @@ bool ChatHandler::HandleDamageCommand(const char * args)
damage -= absorb + resist; damage -= absorb + resist;
m_session->GetPlayer()->DealDamageMods(target,damage,&absorb);
m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false);
m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, schoolmask, damage, absorb, resist, VICTIMSTATE_NORMAL, 0); m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, schoolmask, damage, absorb, resist, VICTIMSTATE_NORMAL, 0);
return true; return true;
@ -3479,7 +3483,7 @@ bool ChatHandler::HandleDamageCommand(const char * args)
// number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form
uint32 spellid = extractSpellIdFromLink((char*)args); uint32 spellid = extractSpellIdFromLink((char*)args);
if(!spellid || !sSpellStore.LookupEntry(spellid)) if (!spellid || !sSpellStore.LookupEntry(spellid))
return false; return false;
m_session->GetPlayer()->SpellNonMeleeDamageLog(target, spellid, damage); m_session->GetPlayer()->SpellNonMeleeDamageLog(target, spellid, damage);

View file

@ -846,6 +846,8 @@ void Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
damage-=absorb+resist; damage-=absorb+resist;
DealDamageMods(this,damage,&absorb);
WorldPacket data(SMSG_ENVIRONMENTALDAMAGELOG, (21)); WorldPacket data(SMSG_ENVIRONMENTALDAMAGELOG, (21));
data << uint64(GetGUID()); data << uint64(GetGUID());
data << uint8(type!=DAMAGE_FALL_TO_VOID ? type : DAMAGE_FALL); data << uint8(type!=DAMAGE_FALL_TO_VOID ? type : DAMAGE_FALL);

View file

@ -1056,6 +1056,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
// Add bonuses and fill damageInfo struct // Add bonuses and fill damageInfo struct
caster->CalculateSpellDamage(&damageInfo, m_damage, m_spellInfo); caster->CalculateSpellDamage(&damageInfo, m_damage, m_spellInfo);
caster->DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb);
// Send log damage message to client // Send log damage message to client
caster->SendSpellNonMeleeDamageLog(&damageInfo); caster->SendSpellNonMeleeDamageLog(&damageInfo);

View file

@ -5806,6 +5806,8 @@ void Aura::PeriodicTick()
sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
pCaster->DealDamageMods(m_target,pdamage,&absorb);
WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
data.append(m_target->GetPackGUID()); data.append(m_target->GetPackGUID());
data.appendPackGUID(GetCasterGUID()); data.appendPackGUID(GetCasterGUID());
@ -5984,10 +5986,13 @@ void Aura::PeriodicTick()
} }
else else
{ {
pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false); uint32 damage = gain;
uint32 absorb = 0;
pCaster->DealDamageMods(pCaster,damage,&absorb);
pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true); pCaster->DealDamage(pCaster, damage, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
} }
} }
@ -6169,6 +6174,9 @@ void Aura::PeriodicTick()
//maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
SpellNonMeleeDamage damageInfo(pCaster, m_target, spellProto->Id, spellProto->SchoolMask); SpellNonMeleeDamage damageInfo(pCaster, m_target, spellProto->Id, spellProto->SchoolMask);
pCaster->CalculateSpellDamage(&damageInfo, gain, spellProto); pCaster->CalculateSpellDamage(&damageInfo, gain, spellProto);
pCaster->DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb);
pCaster->SendSpellNonMeleeDamageLog(&damageInfo); pCaster->SendSpellNonMeleeDamageLog(&damageInfo);
// Set trigger flag // Set trigger flag

View file

@ -279,8 +279,7 @@ void Spell::EffectInstaKill(uint32 /*i*/)
if(m_caster==unitTarget) // prevent interrupt message if(m_caster==unitTarget) // prevent interrupt message
finish(); finish();
uint32 health = unitTarget->GetHealth(); m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
} }
void Spell::EffectEnvirinmentalDMG(uint32 i) void Spell::EffectEnvirinmentalDMG(uint32 i)

View file

@ -367,10 +367,15 @@ void Unit::RemoveSpellbyDamageTaken(AuraType auraType, uint32 damage)
RemoveSpellsCausingAura(auraType); RemoveSpellsCausingAura(auraType);
} }
uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss) void Unit::DealDamageMods(Unit *pVictim, uint32 &damage, uint32* absorb)
{ {
if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
return 0; {
if(absorb)
absorb += damage;
damage = 0;
return;
}
//You don't lose health from damage taken from another player while in a sanctuary //You don't lose health from damage taken from another player while in a sanctuary
//You still see it in the combat log though //You still see it in the combat log though
@ -378,9 +383,28 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
{ {
const AreaTableEntry *area = GetAreaEntryByAreaID(pVictim->GetAreaId()); const AreaTableEntry *area = GetAreaEntryByAreaID(pVictim->GetAreaId());
if(area && area->flags & AREA_FLAG_SANCTUARY) //sanctuary if(area && area->flags & AREA_FLAG_SANCTUARY) //sanctuary
return 0; {
if(absorb)
absorb += damage;
damage = 0;
}
} }
uint32 originalDamage = damage;
//Script Event damage Deal
if( GetTypeId()== TYPEID_UNIT && ((Creature *)this)->AI())
((Creature *)this)->AI()->DamageDeal(pVictim, damage);
//Script Event damage taken
if( pVictim->GetTypeId()== TYPEID_UNIT && ((Creature *)pVictim)->AI() )
((Creature *)pVictim)->AI()->DamageTaken(this, damage);
if(absorb && originalDamage > damage)
absorb += (originalDamage - damage);
}
uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss)
{
// remove affects from victim (including from 0 damage and DoTs) // remove affects from victim (including from 0 damage and DoTs)
if(pVictim != this) if(pVictim != this)
pVictim->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); pVictim->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
@ -398,13 +422,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
pVictim->SetStandState(UNIT_STAND_STATE_STAND); pVictim->SetStandState(UNIT_STAND_STATE_STAND);
} }
//Script Event damage Deal
if( GetTypeId()== TYPEID_UNIT && ((Creature *)this)->AI())
((Creature *)this)->AI()->DamageDeal(pVictim, damage);
//Script Event damage taken
if( pVictim->GetTypeId()== TYPEID_UNIT && ((Creature *)pVictim)->AI() )
((Creature *)pVictim)->AI()->DamageTaken(this, damage);
if(!damage) if(!damage)
{ {
// Rage from physical damage received . // Rage from physical damage received .
@ -978,6 +995,7 @@ uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID);
SpellNonMeleeDamage damageInfo(this, pVictim, spellInfo->Id, spellInfo->SchoolMask); SpellNonMeleeDamage damageInfo(this, pVictim, spellInfo->Id, spellInfo->SchoolMask);
CalculateSpellDamage(&damageInfo, damage, spellInfo); CalculateSpellDamage(&damageInfo, damage, spellInfo);
DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb);
SendSpellNonMeleeDamageLog(&damageInfo); SendSpellNonMeleeDamageLog(&damageInfo);
DealSpellDamage(&damageInfo, true); DealSpellDamage(&damageInfo, true);
return damageInfo.damage; return damageInfo.damage;
@ -1507,6 +1525,8 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
//CalcAbsorbResist(pVictim, SpellSchools(spellProto->School), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); //CalcAbsorbResist(pVictim, SpellSchools(spellProto->School), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
//damage-=absorb + resist; //damage-=absorb + resist;
pVictim->DealDamageMods(this,damage,NULL);
WorldPacket data(SMSG_SPELLDAMAGESHIELD,(8+8+4+4+4+4)); WorldPacket data(SMSG_SPELLDAMAGESHIELD,(8+8+4+4+4+4));
data << uint64(pVictim->GetGUID()); data << uint64(pVictim->GetGUID());
data << uint64(GetGUID()); data << uint64(GetGUID());
@ -1802,8 +1822,12 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
int32 canabsorb = caster->GetHealth(); int32 canabsorb = caster->GetHealth();
if (canabsorb < absorbed) if (canabsorb < absorbed)
absorbed = canabsorb; absorbed = canabsorb;
DealDamage(caster, absorbed, NULL, damagetype, schoolMask, 0, false);
RemainingDamage -= absorbed; RemainingDamage -= absorbed;
uint32 ab_damage = absorbed;
DealDamageMods(caster,ab_damage,NULL);
DealDamage(caster, ab_damage, NULL, damagetype, schoolMask, 0, false);
continue; continue;
} }
break; break;
@ -1907,10 +1931,15 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
RemainingDamage -= currentAbsorb; RemainingDamage -= currentAbsorb;
SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, currentAbsorb, schoolMask, 0, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(currentAbsorb, BASE_ATTACK, MELEE_HIT_NORMAL); uint32 splitted = currentAbsorb;
DealDamage(caster, currentAbsorb, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); uint32 splitted_absorb = 0;
DealDamageMods(caster,splitted,&splitted_absorb);
SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, splitted_absorb, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL);
DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false);
} }
AuraList const& vSplitDamagePct = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT); AuraList const& vSplitDamagePct = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT);
@ -1927,11 +1956,14 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive()) if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive())
continue; continue;
int32 splitted = int32(RemainingDamage * (*i)->GetModifier()->m_amount / 100.0f); uint32 splitted = uint32(RemainingDamage * (*i)->GetModifier()->m_amount / 100.0f);
RemainingDamage -= splitted; RemainingDamage -= int32(splitted);
SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, 0, 0, false, 0, false); uint32 split_absorb = 0;
DealDamageMods(caster,splitted,&split_absorb);
SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, split_absorb, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL); CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL);
DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false);
@ -2021,6 +2053,7 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex
CalcDamageInfo damageInfo; CalcDamageInfo damageInfo;
CalculateMeleeDamage(pVictim, 0, &damageInfo, attType); CalculateMeleeDamage(pVictim, 0, &damageInfo, attType);
// Send log damage message to client // Send log damage message to client
DealDamageMods(pVictim,damageInfo.damage,&damageInfo.absorb);
SendAttackStateUpdate(&damageInfo); SendAttackStateUpdate(&damageInfo);
ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage, damageInfo.attackType); ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage, damageInfo.attackType);
DealMeleeDamage(&damageInfo,true); DealMeleeDamage(&damageInfo,true);
@ -10649,6 +10682,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
sLog.outDebug("ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", auraModifier->m_amount, spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); sLog.outDebug("ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", auraModifier->m_amount, spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
SpellNonMeleeDamage damageInfo(this, pTarget, spellInfo->Id, spellInfo->SchoolMask); SpellNonMeleeDamage damageInfo(this, pTarget, spellInfo->Id, spellInfo->SchoolMask);
CalculateSpellDamage(&damageInfo, auraModifier->m_amount, spellInfo); CalculateSpellDamage(&damageInfo, auraModifier->m_amount, spellInfo);
DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb);
SendSpellNonMeleeDamageLog(&damageInfo); SendSpellNonMeleeDamageLog(&damageInfo);
DealSpellDamage(&damageInfo, true); DealSpellDamage(&damageInfo, true);
break; break;

View file

@ -952,6 +952,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
void Unmount(); void Unmount();
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
void DealDamageMods(Unit *pVictim, uint32 &damage, uint32* absorb);
uint32 DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss); uint32 DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss);
int32 DealHeal(Unit *pVictim, uint32 addhealth, SpellEntry const *spellProto, bool critical = false); int32 DealHeal(Unit *pVictim, uint32 addhealth, SpellEntry const *spellProto, bool critical = false);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "7800" #define REVISION_NR "7801"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__