aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.cpp13
-rw-r--r--src/server/game/DataStores/DBCEnums.h1
-rw-r--r--src/server/game/DataStores/DBCStructure.h1
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp48
-rw-r--r--src/server/game/Entities/Unit/Unit.h20
5 files changed, 70 insertions, 13 deletions
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp
index fbb79426bb8..a2967dc7391 100644
--- a/src/server/game/AI/CoreAI/UnitAI.cpp
+++ b/src/server/game/AI/CoreAI/UnitAI.cpp
@@ -56,16 +56,25 @@ void UnitAI::DoMeleeAttackIfReady()
if (!me->IsWithinMeleeRange(victim))
return;
+ bool sparAttack = me->GetFactionTemplateEntry()->ShouldSparAttack() && victim->GetFactionTemplateEntry()->ShouldSparAttack();
//Make sure our attack is ready and we aren't currently casting before checking distance
if (me->isAttackReady())
{
- me->AttackerStateUpdate(victim);
+ if (sparAttack)
+ me->FakeAttackerStateUpdate(victim);
+ else
+ me->AttackerStateUpdate(victim);
+
me->resetAttackTimer();
}
if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK))
{
- me->AttackerStateUpdate(victim, OFF_ATTACK);
+ if (sparAttack)
+ me->FakeAttackerStateUpdate(victim, OFF_ATTACK);
+ else
+ me->AttackerStateUpdate(victim, OFF_ATTACK);
+
me->resetAttackTimer(OFF_ATTACK);
}
}
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index cb2f26e567f..99d7b49f82f 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -312,6 +312,7 @@ enum SpawnMask
enum FactionTemplateFlags
{
+ FACTION_TEMPLATE_ENEMY_SPAR = 0x00000020, // guessed, sparring with enemies?
FACTION_TEMPLATE_FLAG_PVP = 0x00000800, // flagged for PvP
FACTION_TEMPLATE_FLAG_CONTESTED_GUARD = 0x00001000, // faction will attack players that were involved in PvP combats
FACTION_TEMPLATE_FLAG_HOSTILE_BY_DEFAULT= 0x00002000
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index c85344b9bd1..a6445b27a44 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -673,6 +673,7 @@ struct FactionTemplateEntry
return hostileMask == 0 && friendlyMask == 0;
}
bool IsContestedGuardFaction() const { return (factionFlags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD) != 0; }
+ bool ShouldSparAttack() const { return (factionFlags & FACTION_TEMPLATE_ENEMY_SPAR) != 0; }
};
struct GameObjectDisplayInfoEntry
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index e270789c281..46d5ab5bf05 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -2086,6 +2086,50 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr
}
}
+void Unit::FakeAttackerStateUpdate(Unit* victim, WeaponAttackType attType /*= BASE_ATTACK*/)
+{
+ if (HasUnitState(UNIT_STATE_CANNOT_AUTOATTACK) || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED))
+ return;
+
+ if (!victim->IsAlive())
+ return;
+
+ if ((attType == BASE_ATTACK || attType == OFF_ATTACK) && !IsWithinLOSInMap(victim))
+ return;
+
+ CombatStart(victim);
+ RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MELEE_ATTACK);
+
+ if (attType != BASE_ATTACK && attType != OFF_ATTACK)
+ return; // ignore ranged case
+
+ if (GetTypeId() == TYPEID_UNIT && !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
+ SetFacingToObject(victim); // update client side facing to face the target (prevents visual glitches when casting untargeted spells)
+
+ CalcDamageInfo damageInfo;
+ damageInfo.attacker = this;
+ damageInfo.target = victim;
+ damageInfo.damageSchoolMask = GetMeleeDamageSchoolMask();
+ damageInfo.attackType = attType;
+ damageInfo.damage = 0;
+ damageInfo.cleanDamage = 0;
+ damageInfo.absorb = 0;
+ damageInfo.resist = 0;
+ damageInfo.blocked_amount = 0;
+
+ damageInfo.TargetState = VICTIMSTATE_HIT;
+ damageInfo.HitInfo = HITINFO_AFFECTS_VICTIM | HITINFO_NORMALSWING | HITINFO_FAKE_DAMAGE;
+ if (attType == OFF_ATTACK)
+ damageInfo.HitInfo |= HITINFO_OFFHAND;
+
+ damageInfo.procAttacker = PROC_FLAG_NONE;
+ damageInfo.procVictim = PROC_FLAG_NONE;
+ damageInfo.procEx = PROC_EX_NONE;
+ damageInfo.hitOutCome = MELEE_HIT_NORMAL;
+
+ SendAttackStateUpdate(&damageInfo);
+}
+
void Unit::HandleProcExtraAttackFor(Unit* victim)
{
while (m_extraAttacks)
@@ -5292,8 +5336,8 @@ void Unit::SendAttackStateUpdate(CalcDamageInfo* damageInfo)
{
TC_LOG_DEBUG("entities.unit", "WORLD: Sending SMSG_ATTACKERSTATEUPDATE");
- uint32 count = 1;
- size_t maxsize = 4+5+5+4+4+1+4+4+4+4+4+1+4+4+4+4+4*12;
+ uint32 const count = 1;
+ size_t const maxsize = 4+5+5+4+4+1+4+4+4+4+4+1+4+4+4+4+4*12;
WorldPacket data(SMSG_ATTACKERSTATEUPDATE, maxsize); // we guess size
data << uint32(damageInfo->HitInfo);
data << damageInfo->attacker->GetPackGUID();
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 525d0d54ecb..06aa2db8e0b 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -324,20 +324,21 @@ enum HitInfo
HITINFO_FULL_RESIST = 0x00000080,
HITINFO_PARTIAL_RESIST = 0x00000100,
HITINFO_CRITICALHIT = 0x00000200, // critical hit
- // 0x00000400
- // 0x00000800
- // 0x00001000
+ HITINFO_UNK10 = 0x00000400,
+ HITINFO_UNK11 = 0x00000800,
+ HITINFO_UNK12 = 0x00001000,
HITINFO_BLOCK = 0x00002000, // blocked damage
- // 0x00004000 // Hides worldtext for 0 damage
- // 0x00008000 // Related to blood visual
+ HITINFO_UNK14 = 0x00004000, // set only if meleespellid is present// no world text when victim is hit for 0 dmg(HideWorldTextForNoDamage?)
+ HITINFO_UNK15 = 0x00008000, // player victim?// something related to blod sprut visual (BloodSpurtInBack?)
HITINFO_GLANCING = 0x00010000,
HITINFO_CRUSHING = 0x00020000,
HITINFO_NO_ANIMATION = 0x00040000,
- // 0x00080000
- // 0x00100000
+ HITINFO_UNK19 = 0x00080000,
+ HITINFO_UNK20 = 0x00100000,
HITINFO_SWINGNOHITSOUND = 0x00200000, // unused?
- // 0x00400000
- HITINFO_RAGE_GAIN = 0x00800000
+ HITINFO_UNK22 = 0x00400000,
+ HITINFO_RAGE_GAIN = 0x00800000,
+ HITINFO_FAKE_DAMAGE = 0x01000000 // enables damage animation even if no damage done, set only if no damage
};
//i would like to remove this: (it is defined in item.h
@@ -1447,6 +1448,7 @@ class TC_GAME_API Unit : public WorldObject
void HandleEmoteCommand(uint32 anim_id);
void AttackerStateUpdate (Unit* victim, WeaponAttackType attType = BASE_ATTACK, bool extra = false);
+ void FakeAttackerStateUpdate(Unit* victim, WeaponAttackType attType = BASE_ATTACK);
void CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType = BASE_ATTACK);
void DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss);