Code:
//send damage packet...
if(!iBuffTic) { //buff ticks do not send damage, instead they just call SendHPUpdate(), which is done below
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct));
CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer;
a->target = GetID();
if (attacker == NULL)
a->source = 0;
else if (attacker->IsClient() && attacker->CastToClient()->GMHideMe())
a->source = 0;
else
a->source = attacker->GetID();
a->type = SkillDamageTypes[skill_used]; // was 0x1c
a->damage = damage;
// if (attack_skill != 231)
// a->spellid = SPELL_UNKNOWN;
// else
a->spellid = spell_id;
//Note: if players can become pets, they will not receive damage messages of their own
//this was done to simplify the code here (since we can only effectively skip one mob on queue)
eqFilterType filter;
Mob *skip = attacker;
if(attacker && attacker->GetOwnerID()) {
//attacker is a pet, let pet owners see their pet's damage
Mob* owner = attacker->GetOwner();
if (owner && owner->IsClient()) {
if ((spell_id != SPELL_UNKNOWN) && damage>0) {
//special crap for spell damage, looks hackish to me
char val1[20]={0};
owner->Message_StringID(4,OTHER_HIT_NONMELEE,GetCleanName(),ConvertArray(damage,val1));
} else {
if(damage > 0) {
if(spell_id != SPELL_UNKNOWN)
filter = iBuffTic ? FilterDOT : FilterSpellDamage;
else
filter = FILTER_MYPETHITS;
} else if(damage == -5)
filter = FilterNone; //cant filter invulnerable
else
filter = FILTER_MYPETMISSES;
owner->CastToClient()->QueuePacket(outapp,true,CLIENT_CONNECTED,filter);
}
}
skip = owner;
} else {
//attacker is not a pet, send to the attacker
//if the attacker is a client, try them with the correct filter
if(attacker && attacker->IsClient()) {
if ((spell_id != SPELL_UNKNOWN) && damage>0) {
//special crap for spell damage, looks hackish to me
char val1[20]={0};
attacker->Message_StringID(4,OTHER_HIT_NONMELEE,GetCleanName(),ConvertArray(damage,val1));
} else {
if(damage > 0) {
if(spell_id != SPELL_UNKNOWN)
filter = iBuffTic ? FilterDOT : FilterSpellDamage;
else
filter = FilterNone; //cant filter our own hits
} else if(damage == -5)
filter = FilterNone; //cant filter invulnerable
else
filter = FILTER_MYMISSES;
attacker->CastToClient()->QueuePacket(outapp, true, CLIENT_CONNECTED, filter);
}
}
skip = attacker;
}
//send damage to all clients around except the specified skip mob (attacker or the attacker's owner) and ourself
if(damage > 0) {
if(spell_id != SPELL_UNKNOWN)
filter = iBuffTic ? FilterDOT : FilterSpellDamage;
else
filter = FILTER_OTHERHITS;
} else if(damage == -5)
filter = FilterNone; //cant filter invulnerable
else
filter = FILTER_OTHERMISSES;
//make attacker (the attacker) send the packet so we can skip them and the owner
//this call will send the packet to `this` as well (using the wrong filter) (will not happen until PC charm works)
//LogFile->write(EQEMuLog::Debug, "Queue damage to all except %s with filter %d (%d), type %d", skip->GetName(), filter, IsClient()?CastToClient()->GetFilter(filter):-1, a->type);
entity_list.QueueCloseClients(this, outapp, true, 200, skip, true, filter);
//send the damage to ourself if we are a client
if(IsClient()) {
//I dont think any filters apply to damage affecting us
CastToClient()->QueuePacket(outapp);
}
safe_delete(outapp);
} else {
//else, it is a buff tic...
// Everhood - So we can see our dot dmg like live shows it.
if(spell_id != SPELL_UNKNOWN && damage > 0 && attacker && attacker != this && attacker->IsClient()) {
//might filter on (attack_skill>200 && attack_skill<250), but I dont think we need it
if(attacker->CastToClient()->GetFilter(FilterDOT) != FilterHide) {
attacker->Message_StringID(MT_DoTDamage, OTHER_HIT_DOT, GetCleanName(),itoa(damage),spells[spell_id].name);
}
}
} //end packet sending
if(damage > 0) {
//check for death conditions
if(IsClient()) {
if((GetHP() - damage) <= -10) {
Death(attacker, damage, spell_id, skill_used);
return;
}
} else {
if (damage >= GetHP()) {
//killed...
SetHP(-100);
Death(attacker, damage, spell_id, skill_used);
return;
}
}
//not killed. Apply the damage
SetHP(GetHP() - damage);
//fade mez if we are mezzed
if (IsMezzed()) {
mlog(COMBAT__HITS, "Breaking mez due to attack.");
BuffFadeByEffect(SE_Mez);
}
//check stun chances if bashing
if ((skill_used == BASH || skill_used == KICK && (attacker && attacker->GetLevel() >= 55)) && GetLevel() < 56) {
int stun_resist = itembonuses.StunResist+spellbonuses.StunResist;
if(this->GetBaseRace() == OGRE && this->IsClient() && !attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) {
mlog(COMBAT__HITS, "Stun Resisted. Ogres are immune to frontal melee stuns.");
} else {
if(stun_resist <= 0 || MakeRandomInt(0,99) >= stun_resist) {
mlog(COMBAT__HITS, "Stunned. We had %dpercent resist chance.");
Stun(0);
} else {
mlog(COMBAT__HITS, "Stun Resisted. We had %dpercent resist chance.");
}
}
}
if(spell_id != SPELL_UNKNOWN) {
//see if root will break
if (IsRooted()) { // neotoyko: only spells cancel root
if(GetAA(aaEnhancedRoot))
{
if (MakeRandomInt(0, 99) < 10) {
mlog(COMBAT__HITS, "Spell broke root! 10percent chance");
BuffFadeByEffect(SE_Root, buffslot); // buff slot is passed through so a root w/ dam doesnt cancel itself
} else {
mlog(COMBAT__HITS, "Spell did not break root. 10 percent chance");
}
}
else
{
if (MakeRandomInt(0, 99) < 20) {
mlog(COMBAT__HITS, "Spell broke root! 20percent chance");
BuffFadeByEffect(SE_Root, buffslot); // buff slot is passed through so a root w/ dam doesnt cancel itself
} else {
mlog(COMBAT__HITS, "Spell did not break root. 20 percent chance");
}
}
}
}
else{
//increment chances of interrupting
if(IsCasting() && damage > 0) { //shouldnt interrupt on regular spell damage
attacked_count++;
mlog(COMBAT__HITS, "Melee attack while casting. Attack count %d", attacked_count);
}
}
//send an HP update if we are hurt
if(GetHP() < GetMaxHP())
SendHPUpdate();
}
}