mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/AI: initial support for monster sparring (#17673)
(cherry picked from commit 303066509d)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -913,6 +913,7 @@ struct FactionTemplateEntry
|
||||
return EnemyMask == 0 && FriendMask == 0;
|
||||
}
|
||||
bool IsContestedGuardFaction() const { return (Flags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD) != 0; }
|
||||
bool ShouldSparAttack() const { return (Flags & FACTION_TEMPLATE_ENEMY_SPAR) != 0; }
|
||||
};
|
||||
|
||||
struct GameObjectsEntry
|
||||
|
||||
@@ -535,6 +535,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
|
||||
|
||||
@@ -1895,6 +1895,50 @@ void Unit::AttackerStateUpdate (Unit* victim, WeaponAttackType attType, bool ext
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -362,20 +362,21 @@ enum HitInfo
|
||||
HITINFO_FULL_RESIST = 0x00000080,
|
||||
HITINFO_PARTIAL_RESIST = 0x00000100,
|
||||
HITINFO_CRITICALHIT = 0x00000200, // critical hit
|
||||
// 0x00000400
|
||||
// 0x00000800
|
||||
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
|
||||
@@ -1549,6 +1550,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);
|
||||
|
||||
Reference in New Issue
Block a user