Core/Creatures: Implemented CREATURE_STATIC_FLAG_4_NO_MELEE_APPROACH and fixed CREATURE_STATIC_FLAG_NO_MELEE_FLEE implementation (should cause fleeing from melee range)
Port From (https://github.com/TrinityCore/TrinityCore/commit/a748fddfa47216e1f516303e3bca9b5a86823748)
This commit is contained in:
@@ -290,7 +290,7 @@ namespace Framework.Constants
|
|||||||
CombatPing = 0x00020000,
|
CombatPing = 0x00020000,
|
||||||
Aquatic = 0x00040000, // Aka Water Only, CreatureTemplateMovement.Ground = 0
|
Aquatic = 0x00040000, // Aka Water Only, CreatureTemplateMovement.Ground = 0
|
||||||
Amphibious = 0x00080000, // CreatureTemplateMovement.Swim = 1
|
Amphibious = 0x00080000, // CreatureTemplateMovement.Swim = 1
|
||||||
NoMelee = 0x00100000, // Prevents Melee(Does Not Prevent Chasing, Does Not Make Creature Passive). Not Sure What 'Flee' Means But Another Flag Is Named NoMeleeApproach
|
NoMeleeFlee = 0x00100000, // "No Melee (Flee)" Prevents melee (moves as-if feared, does not make creature passive)
|
||||||
VisibleToGhosts = 0x00200000, // CreatureTypeFlagVisibleToGhosts
|
VisibleToGhosts = 0x00200000, // CreatureTypeFlagVisibleToGhosts
|
||||||
PvpEnabling = 0x00400000, // Old UnitFlagPvpEnabling, Now UnitBytes2OffsetPvpFlag From UnitFieldBytes2
|
PvpEnabling = 0x00400000, // Old UnitFlagPvpEnabling, Now UnitBytes2OffsetPvpFlag From UnitFieldBytes2
|
||||||
DoNotPlayWoundAnim = 0x00800000, // CreatureTypeFlagDoNotPlayWoundAnim
|
DoNotPlayWoundAnim = 0x00800000, // CreatureTypeFlagDoNotPlayWoundAnim
|
||||||
@@ -390,7 +390,7 @@ namespace Framework.Constants
|
|||||||
DealsTripleDamageToPcControlledPets = 0x00000040,
|
DealsTripleDamageToPcControlledPets = 0x00000040,
|
||||||
NoNpcDamageBelow85ptc = 0x00000080,
|
NoNpcDamageBelow85ptc = 0x00000080,
|
||||||
ObeysTauntDiminishingReturns = 0x00000100, // CreatureFlagExtraObeysTauntDiminishingReturns
|
ObeysTauntDiminishingReturns = 0x00000100, // CreatureFlagExtraObeysTauntDiminishingReturns
|
||||||
NoMeleeApproach = 0x00000200,
|
NoMeleeApproach = 0x00000200, // "No Melee (Approach)" Prevents melee (chases into melee range, does not make creature passive)
|
||||||
UpdateCreatureRecordWhenInstanceChangesDifficulty = 0x00000400, // Used Only By Snobold Vassal
|
UpdateCreatureRecordWhenInstanceChangesDifficulty = 0x00000400, // Used Only By Snobold Vassal
|
||||||
CannotDaze = 0x00000800, // "Cannot Daze (Combat Stun)"
|
CannotDaze = 0x00000800, // "Cannot Daze (Combat Stun)"
|
||||||
FlatHonorAward = 0x00001000,
|
FlatHonorAward = 0x00001000,
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ namespace Game.AI
|
|||||||
protected TaskScheduler _scheduler = new();
|
protected TaskScheduler _scheduler = new();
|
||||||
protected InstanceScript _instanceScript;
|
protected InstanceScript _instanceScript;
|
||||||
|
|
||||||
public CreatureAI(Creature _creature) : base(_creature)
|
public CreatureAI(Creature creature) : base(creature)
|
||||||
{
|
{
|
||||||
me = _creature;
|
me = creature;
|
||||||
_moveInLOSLocked = false;
|
_moveInLOSLocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,6 +514,21 @@ namespace Game.AI
|
|||||||
// called when the corpse of this creature gets removed
|
// called when the corpse of this creature gets removed
|
||||||
public virtual void CorpseRemoved(long respawnDelay) { }
|
public virtual void CorpseRemoved(long respawnDelay) { }
|
||||||
|
|
||||||
|
public override void AttackStart(Unit victim)
|
||||||
|
{
|
||||||
|
if (victim != null && me.Attack(victim, true))
|
||||||
|
{
|
||||||
|
// Clear distracted state on attacking
|
||||||
|
if (me.HasUnitState(UnitState.Distracted))
|
||||||
|
{
|
||||||
|
me.ClearUnitState(UnitState.Distracted);
|
||||||
|
me.GetMotionMaster().Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
me.StartDefaultCombatMovement(victim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// == Gossip system ================================
|
/// == Gossip system ================================
|
||||||
|
|
||||||
// Called when the dialog status between a player and the creature is requested.
|
// Called when the dialog status between a player and the creature is requested.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
using Framework.Constants;
|
using Framework.Constants;
|
||||||
using Game.Entities;
|
using Game.Entities;
|
||||||
using Game.Spells;
|
using Game.Spells;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Game.AI
|
namespace Game.AI
|
||||||
{
|
{
|
||||||
@@ -92,28 +93,34 @@ namespace Game.AI
|
|||||||
|
|
||||||
public class CritterAI : PassiveAI
|
public class CritterAI : PassiveAI
|
||||||
{
|
{
|
||||||
public CritterAI(Creature c) : base(c)
|
TimeTracker _evadeTimer;
|
||||||
|
|
||||||
|
public CritterAI(Creature creature) : base(creature)
|
||||||
{
|
{
|
||||||
me.SetReactState(ReactStates.Passive);
|
_evadeTimer = new();
|
||||||
|
me.SetCanMelee(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void JustEngagedWith(Unit who)
|
public override void JustEngagedWith(Unit who)
|
||||||
{
|
{
|
||||||
if (!me.HasUnitState(UnitState.Fleeing))
|
me.StartDefaultCombatMovement(who);
|
||||||
me.SetControlled(true, UnitState.Fleeing);
|
_evadeTimer.Reset(TimeSpan.FromMilliseconds(WorldConfig.GetIntValue(WorldCfg.CreatureFamilyFleeDelay)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void MovementInform(MovementGeneratorType type, uint id)
|
public override void UpdateAI(uint diff)
|
||||||
{
|
{
|
||||||
if (type == MovementGeneratorType.TimedFleeing)
|
if (me.IsEngaged())
|
||||||
EnterEvadeMode(EvadeReason.Other);
|
{
|
||||||
}
|
if (!me.IsInCombat())
|
||||||
|
{
|
||||||
|
EnterEvadeMode(EvadeReason.NoHostiles);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
public override void EnterEvadeMode(EvadeReason why)
|
_evadeTimer.Update(diff);
|
||||||
{
|
if (_evadeTimer.Passed())
|
||||||
if (me.HasUnitState(UnitState.Fleeing))
|
EnterEvadeMode(EvadeReason.Other);
|
||||||
me.SetControlled(false, UnitState.Fleeing);
|
}
|
||||||
base.EnterEvadeMode(why);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace Game.AI
|
|||||||
public void DoStartMovement(Unit target, float distance = 0.0f, float angle = 0.0f)
|
public void DoStartMovement(Unit target, float distance = 0.0f, float angle = 0.0f)
|
||||||
{
|
{
|
||||||
if (target != null)
|
if (target != null)
|
||||||
me.GetMotionMaster().MoveChase(target, distance, angle);
|
me.StartDefaultCombatMovement(target, distance, angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Start no movement on victim
|
//Start no movement on victim
|
||||||
|
|||||||
@@ -618,7 +618,7 @@ namespace Game.AI
|
|||||||
if (_canCombatMove)
|
if (_canCombatMove)
|
||||||
{
|
{
|
||||||
SetRun(_run);
|
SetRun(_run);
|
||||||
me.GetMotionMaster().MoveChase(who);
|
me.StartDefaultCombatMovement(who);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -830,7 +830,7 @@ namespace Game.AI
|
|||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
SetRun(_run);
|
SetRun(_run);
|
||||||
me.GetMotionMaster().MoveChase(me.GetVictim());
|
me.StartDefaultCombatMovement(me.GetVictim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1515,7 +1515,7 @@ namespace Game.AI
|
|||||||
if (creature != null)
|
if (creature != null)
|
||||||
if (IsSmart(creature) && creature.GetVictim() != null)
|
if (IsSmart(creature) && creature.GetVictim() != null)
|
||||||
if (((SmartAI)creature.GetAI()).CanCombatMove())
|
if (((SmartAI)creature.GetAI()).CanCombatMove())
|
||||||
creature.GetMotionMaster().MoveChase(creature.GetVictim(), attackDistance, attackAngle);
|
creature.StartDefaultCombatMovement(creature.GetVictim(), attackDistance, attackAngle);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2602,6 +2602,47 @@ namespace Game.Entities
|
|||||||
Global.WorldMgr.SendGlobalMessage(packet, null, (enemy_team == Team.Alliance ? Team.Horde : Team.Alliance));
|
Global.WorldMgr.SendGlobalMessage(packet, null, (enemy_team == Team.Alliance ? Team.Horde : Team.Alliance));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetCanMelee(bool canMelee, bool fleeFromMelee = false)
|
||||||
|
{
|
||||||
|
bool wasFleeingFromMelee = HasFlag(CreatureStaticFlags.NoMeleeFlee);
|
||||||
|
|
||||||
|
_staticFlags.ApplyFlag(CreatureStaticFlags.NoMeleeFlee, !canMelee && fleeFromMelee);
|
||||||
|
_staticFlags.ApplyFlag(CreatureStaticFlags4.NoMeleeApproach, !canMelee && !fleeFromMelee);
|
||||||
|
|
||||||
|
if (wasFleeingFromMelee == HasFlag(CreatureStaticFlags.NoMeleeFlee))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Unit victim = GetVictim();
|
||||||
|
if (victim == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var currentMovement = GetMotionMaster().GetCurrentMovementGenerator();
|
||||||
|
if (currentMovement == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var canChangeMovement = new Func<bool>(() =>
|
||||||
|
{
|
||||||
|
if (wasFleeingFromMelee)
|
||||||
|
return currentMovement.GetMovementGeneratorType() == MovementGeneratorType.Fleeing && !HasUnitFlag(UnitFlags.Fleeing);
|
||||||
|
|
||||||
|
return currentMovement.GetMovementGeneratorType() == MovementGeneratorType.Chase;
|
||||||
|
})();
|
||||||
|
|
||||||
|
if (!canChangeMovement)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GetMotionMaster().Remove(currentMovement);
|
||||||
|
StartDefaultCombatMovement(victim);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartDefaultCombatMovement(Unit victim, float? range = null, float? angle = null)
|
||||||
|
{
|
||||||
|
if (!HasFlag(CreatureStaticFlags.NoMeleeFlee) || IsSummon())
|
||||||
|
GetMotionMaster().MoveChase(victim, range.GetValueOrDefault(0), angle.GetValueOrDefault(0));
|
||||||
|
else
|
||||||
|
GetMotionMaster().MoveFleeing(victim);
|
||||||
|
}
|
||||||
|
|
||||||
public override bool HasSpell(uint spellId)
|
public override bool HasSpell(uint spellId)
|
||||||
{
|
{
|
||||||
return m_spells.Contains(spellId);
|
return m_spells.Contains(spellId);
|
||||||
@@ -3376,9 +3417,7 @@ namespace Game.Entities
|
|||||||
public override SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType attackType = WeaponAttackType.BaseAttack) { return m_meleeDamageSchoolMask; }
|
public override SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType attackType = WeaponAttackType.BaseAttack) { return m_meleeDamageSchoolMask; }
|
||||||
public void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = (SpellSchoolMask)(1 << (int)school); }
|
public void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = (SpellSchoolMask)(1 << (int)school); }
|
||||||
|
|
||||||
public bool CanMelee() { return !_staticFlags.HasFlag(CreatureStaticFlags.NoMelee); }
|
public bool CanMelee() { return !_staticFlags.HasFlag(CreatureStaticFlags.NoMeleeFlee) && !_staticFlags.HasFlag(CreatureStaticFlags4.NoMeleeApproach); }
|
||||||
|
|
||||||
public void SetCanMelee(bool canMelee) { _staticFlags.ApplyFlag(CreatureStaticFlags.NoMelee, !canMelee); }
|
|
||||||
|
|
||||||
public bool CanIgnoreLineOfSightWhenCastingOnMe() { return _staticFlags.HasFlag(CreatureStaticFlags4.IgnoreLosWhenCastingOnMe); }
|
public bool CanIgnoreLineOfSightWhenCastingOnMe() { return _staticFlags.HasFlag(CreatureStaticFlags4.IgnoreLosWhenCastingOnMe); }
|
||||||
|
|
||||||
|
|||||||
@@ -1391,14 +1391,17 @@ namespace Game.Entities
|
|||||||
if (caster == null)
|
if (caster == null)
|
||||||
caster = GetAttackerForHelper();
|
caster = GetAttackerForHelper();
|
||||||
GetMotionMaster().MoveFleeing(caster, TimeSpan.FromMilliseconds(fearAuras.Empty() ? WorldConfig.GetIntValue(WorldCfg.CreatureFamilyFleeDelay) : 0)); // caster == NULL processed in MoveFleeing
|
GetMotionMaster().MoveFleeing(caster, TimeSpan.FromMilliseconds(fearAuras.Empty() ? WorldConfig.GetIntValue(WorldCfg.CreatureFamilyFleeDelay) : 0)); // caster == NULL processed in MoveFleeing
|
||||||
|
SetUnitFlag(UnitFlags.Fleeing);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
RemoveUnitFlag(UnitFlags.Fleeing);
|
||||||
if (IsAlive())
|
if (IsAlive())
|
||||||
{
|
{
|
||||||
GetMotionMaster().Remove(MovementGeneratorType.Fleeing);
|
GetMotionMaster().Remove(MovementGeneratorType.Fleeing);
|
||||||
if (GetVictim() != null)
|
Unit victim = GetVictim();
|
||||||
SetTarget(GetVictim().GetGUID());
|
if (victim != null)
|
||||||
|
SetTarget(victim.GetGUID());
|
||||||
if (!IsPlayer() && !IsInCombat())
|
if (!IsPlayer() && !IsInCombat())
|
||||||
GetMotionMaster().MoveTargetedHome();
|
GetMotionMaster().MoveTargetedHome();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ namespace Game.Movement
|
|||||||
if (owner == null || !owner.IsAlive())
|
if (owner == null || !owner.IsAlive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: UNIT_FIELD_FLAGS should not be handled by generators
|
|
||||||
owner.SetUnitFlag(UnitFlags.Fleeing);
|
|
||||||
_path = null;
|
_path = null;
|
||||||
SetTargetLocation(owner);
|
SetTargetLocation(owner);
|
||||||
}
|
}
|
||||||
@@ -83,16 +81,15 @@ namespace Game.Movement
|
|||||||
{
|
{
|
||||||
if (owner.IsPlayer())
|
if (owner.IsPlayer())
|
||||||
{
|
{
|
||||||
owner.RemoveUnitFlag(UnitFlags.Fleeing);
|
|
||||||
owner.ClearUnitState(UnitState.FleeingMove);
|
owner.ClearUnitState(UnitState.FleeingMove);
|
||||||
owner.StopMoving();
|
owner.StopMoving();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
owner.RemoveUnitFlag(UnitFlags.Fleeing);
|
|
||||||
owner.ClearUnitState(UnitState.FleeingMove);
|
owner.ClearUnitState(UnitState.FleeingMove);
|
||||||
if (owner.GetVictim() != null)
|
Unit victim = owner.GetVictim();
|
||||||
owner.SetTarget(owner.GetVictim().GetGUID());
|
if (victim != null)
|
||||||
|
owner.SetTarget(victim.GetGUID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,7 +217,6 @@ namespace Game.Movement
|
|||||||
if (!active)
|
if (!active)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
owner.RemoveUnitFlag(UnitFlags.Fleeing);
|
|
||||||
Unit victim = owner.GetVictim();
|
Unit victim = owner.GetVictim();
|
||||||
if (victim != null)
|
if (victim != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -563,7 +563,6 @@ namespace Game.Movement
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void MoveChase(Unit target, float dist, float angle = 0.0f) { MoveChase(target, new ChaseRange(dist), new ChaseAngle(angle)); }
|
public void MoveChase(Unit target, float dist, float angle = 0.0f) { MoveChase(target, new ChaseRange(dist), new ChaseAngle(angle)); }
|
||||||
public void MoveChase(Unit target, float dist) { MoveChase(target, new ChaseRange(dist)); }
|
|
||||||
public void MoveChase(Unit target, ChaseRange? dist = null, ChaseAngle? angle = null)
|
public void MoveChase(Unit target, ChaseRange? dist = null, ChaseAngle? angle = null)
|
||||||
{
|
{
|
||||||
// Ignore movement request if target not exist
|
// Ignore movement request if target not exist
|
||||||
|
|||||||
Reference in New Issue
Block a user