fix: Fixes crash with combatant and mobs facing each other (#1644)

### Summary
- Fixes crash bugs with combatant checks in AI
- Fixes mobs not facing each other while in combat. (Old RunUO bug)
- Fixes predators not actually going into guard when their combatant dies.
- Adds missing checks for combatant in various AI.

Note: Much easier to understand changes if whitespace is off - https://github.com/modernuo/ModernUO/pull/1644/files?diff=split&w=1
This commit is contained in:
Kamron Batman 2023-12-20 14:48:24 -08:00 committed by GitHub
parent 1e73802d1e
commit d4282367ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 89 additions and 87 deletions

View file

@ -52,11 +52,12 @@ public class AnimalAI : BaseAI
{
var combatant = m_Mobile.Combatant;
if (combatant?.Deleted != false || combatant.Map != m_Mobile.Map)
if (combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map || !combatant.Alive ||
combatant.IsDeadBondedPet)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("My combatant is gone..");
m_Mobile.DebugSay("My combatant is gone!");
}
Action = ActionType.Wander;
@ -98,6 +99,7 @@ public class AnimalAI : BaseAI
}
}
m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant))
{
if (m_Mobile.Debug)

View file

@ -36,55 +36,53 @@ public class ArcherAI : BaseAI
public override bool DoActionCombat()
{
if (m_Mobile.Combatant?.Deleted != false || !m_Mobile.Combatant.Alive ||
m_Mobile.Combatant.IsDeadBondedPet)
var combatant = m_Mobile.Combatant;
if (combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map || !combatant.Alive ||
combatant.IsDeadBondedPet)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("My combatant is deleted");
m_Mobile.DebugSay("My combatant is gone, so my guard is up");
}
Action = ActionType.Guard;
return true;
}
if (Core.TickCount - m_Mobile.LastMoveTime > 1000)
{
if (
m_Mobile.Combatant != null &&
!WalkMobileRange(
m_Mobile.Combatant,
1,
true,
m_Mobile.RangeFight,
m_Mobile.Weapon.MaxRange
)
)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I am still not in range of {m_Mobile.Combatant.Name}");
}
if ((int)m_Mobile.GetDistanceToSqrt(m_Mobile.Combatant) > m_Mobile.RangePerception + 1)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I have lost {m_Mobile.Combatant.Name}");
}
m_Mobile.Combatant = null;
Action = ActionType.Guard;
return true;
}
}
}
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, m_Mobile.Combatant))
if (Core.TickCount - m_Mobile.LastMoveTime > 1000 &&
!WalkMobileRange(
m_Mobile.Combatant,
1,
true,
m_Mobile.RangeFight,
m_Mobile.Weapon.MaxRange
))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I used my abilities on {m_Mobile.Combatant.Name}!");
m_Mobile.DebugSay($"I am still not in range of {combatant.Name}");
}
if ((int)m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I have lost {combatant.Name}");
}
m_Mobile.Combatant = null;
Action = ActionType.Guard;
return true;
}
}
m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I used my abilities on {combatant.Name}!");
}
return true;

View file

@ -998,20 +998,26 @@ public abstract class BaseAI
return true;
}
var c = m_Mobile.Combatant;
var combatant = m_Mobile.Combatant;
if (c?.Deleted != false || c.Map != m_Mobile.Map || !c.Alive || c.IsDeadBondedPet)
if (combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map || !combatant.Alive ||
combatant.IsDeadBondedPet)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("My combatant is gone!");
}
Action = ActionType.Wander;
return true;
}
m_Mobile.Direction = m_Mobile.GetDirectionTo(c);
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, c))
m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I used my abilities on {c.Name}!");
m_Mobile.DebugSay($"I used my abilities on {combatant.Name}!");
}
}
@ -1949,31 +1955,28 @@ public abstract class BaseAI
m_Mobile.Combatant = null;
m_Mobile.Warmode = false;
}
else if (m_Mobile.BardTarget?.Deleted != false || m_Mobile.BardTarget.Map != m_Mobile.Map ||
m_Mobile.GetDistanceToSqrt(m_Mobile.BardTarget) > m_Mobile.RangePerception)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("I have lost my provoke target");
}
m_Mobile.BardProvoked = false;
m_Mobile.BardMaster = null;
m_Mobile.BardTarget = null;
m_Mobile.Combatant = null;
m_Mobile.Warmode = false;
}
else
{
if (m_Mobile.BardTarget?.Deleted != false || m_Mobile.BardTarget.Map != m_Mobile.Map ||
m_Mobile.GetDistanceToSqrt(m_Mobile.BardTarget) > m_Mobile.RangePerception)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("I have lost my provoke target");
}
m_Mobile.Combatant = m_Mobile.BardTarget;
m_Action = ActionType.Combat;
m_Mobile.BardProvoked = false;
m_Mobile.BardMaster = null;
m_Mobile.BardTarget = null;
m_Mobile.Combatant = null;
m_Mobile.Warmode = false;
}
else
{
m_Mobile.Combatant = m_Mobile.BardTarget;
m_Action = ActionType.Combat;
m_Mobile.OnThink();
Think();
}
m_Mobile.OnThink();
Think();
}
return true;

View file

@ -33,38 +33,32 @@ public class BerserkAI : BaseAI
public override bool DoActionCombat()
{
if (m_Mobile.Combatant?.Deleted != false)
var combatant = m_Mobile.Combatant;
if (combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map || !combatant.Alive ||
combatant.IsDeadBondedPet)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("My combatant is deleted");
m_Mobile.DebugSay("My combatant is gone, so my guard is up");
}
Action = ActionType.Guard;
return true;
}
if (
m_Mobile.Combatant != null &&
!WalkMobileRange(
m_Mobile.Combatant,
1,
true,
m_Mobile.RangeFight,
m_Mobile.RangeFight
)
)
if (!WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I am still not in range of {m_Mobile.Combatant.Name}");
m_Mobile.DebugSay($"I am still not in range of {combatant.Name}");
}
if ((int)m_Mobile.GetDistanceToSqrt(m_Mobile.Combatant) > m_Mobile.RangePerception + 1)
if ((int)m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I have lost {m_Mobile.Combatant.Name}");
m_Mobile.DebugSay($"I have lost {combatant.Name}");
}
Action = ActionType.Guard;
@ -72,11 +66,12 @@ public class BerserkAI : BaseAI
}
}
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, m_Mobile.Combatant))
m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I used my abilities on {m_Mobile.Combatant.Name}!");
m_Mobile.DebugSay($"I used my abilities on {combatant.Name}!");
}
}

View file

@ -780,6 +780,7 @@ public class MageAI : BaseAI
}
}
m_Mobile.Direction = m_Mobile.GetDirectionTo(c);
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, c))
{
if (m_Mobile.Debug)

View file

@ -37,7 +37,7 @@ public class MeleeAI : BaseAI
{
var combatant = m_Mobile.Combatant;
if (combatant?.Deleted != false || combatant.Map != m_Mobile.Map || !combatant.Alive ||
if (combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map || !combatant.Alive ||
combatant.IsDeadBondedPet)
{
if (m_Mobile.Debug)
@ -128,6 +128,7 @@ public class MeleeAI : BaseAI
}
}
m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant))
{
if (m_Mobile.Debug)

View file

@ -38,14 +38,15 @@ public class PredatorAI : BaseAI
{
var combatant = m_Mobile.Combatant;
if (combatant?.Deleted != false || combatant.Map != m_Mobile.Map)
if (combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map || !combatant.Alive ||
combatant.IsDeadBondedPet)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("My combatant is gone, so my guard is up");
}
Action = ActionType.Wander;
Action = ActionType.Guard;
return true;
}

View file

@ -40,7 +40,8 @@ public class ThiefAI : BaseAI
{
var combatant = m_Mobile.Combatant;
if (combatant?.Deleted != false || combatant.Map != m_Mobile.Map)
if (combatant == null || combatant.Deleted || combatant.Map != m_Mobile.Map || !combatant.Alive ||
combatant.IsDeadBondedPet)
{
if (m_Mobile.Debug)
{