diff options
| -rw-r--r-- | src/server/game/AI/CoreAI/UnitAI.cpp | 13 | ||||
| -rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 1 | ||||
| -rw-r--r-- | src/server/game/DataStores/DBCStructure.h | 1 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 48 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 20 | 
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);  | 
