Skip to content

Commit

Permalink
fix: Fixes crash with combatant and mobs facing each other (#1644)
Browse files Browse the repository at this point in the history
### 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
  • Loading branch information
kamronbatman authored Dec 20, 2023
1 parent 1e73802 commit d428236
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 76 deletions.
6 changes: 4 additions & 2 deletions Projects/UOContent/Mobiles/AI/AnimalAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@ public override bool DoActionCombat()
{
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;
Expand Down Expand Up @@ -98,6 +99,7 @@ public override bool DoActionCombat()
}
}

m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant))
{
if (m_Mobile.Debug)
Expand Down
54 changes: 26 additions & 28 deletions Projects/UOContent/Mobiles/AI/ArcherAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,55 +36,53 @@ public override bool DoActionWander()

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 (Core.TickCount - m_Mobile.LastMoveTime > 1000 &&
!WalkMobileRange(
m_Mobile.Combatant,
1,
true,
m_Mobile.RangeFight,
m_Mobile.Weapon.MaxRange
))
{
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 {combatant.Name}");
}

if ((int)m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I am still not in range of {m_Mobile.Combatant.Name}");
m_Mobile.DebugSay($"I have lost {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;
}
m_Mobile.Combatant = null;
Action = ActionType.Guard;
return true;
}
}

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}!");
}

return true;
Expand Down
53 changes: 28 additions & 25 deletions Projects/UOContent/Mobiles/AI/BaseAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -998,20 +998,26 @@ public virtual bool DoActionCombat()
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}!");
}
}

Expand Down Expand Up @@ -1949,31 +1955,28 @@ public virtual bool DoBardProvoked()
m_Mobile.Combatant = null;
m_Mobile.Warmode = false;
}
else
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.BardTarget?.Deleted != false || m_Mobile.BardTarget.Map != m_Mobile.Map ||
m_Mobile.GetDistanceToSqrt(m_Mobile.BardTarget) > m_Mobile.RangePerception)
if (m_Mobile.Debug)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("I have lost my provoke target");
}
m_Mobile.DebugSay("I have lost my provoke target");
}

m_Mobile.BardProvoked = false;
m_Mobile.BardMaster = null;
m_Mobile.BardTarget = null;
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.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;
Expand Down
29 changes: 12 additions & 17 deletions Projects/UOContent/Mobiles/AI/BerserkAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,50 +33,45 @@ public override bool DoActionWander()

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;
return true;
}
}

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}!");
}
}

Expand Down
1 change: 1 addition & 0 deletions Projects/UOContent/Mobiles/AI/MageAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,7 @@ public override bool DoActionCombat()
}
}

m_Mobile.Direction = m_Mobile.GetDirectionTo(c);
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, c))
{
if (m_Mobile.Debug)
Expand Down
3 changes: 2 additions & 1 deletion Projects/UOContent/Mobiles/AI/MeleeAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public override bool DoActionCombat()
{
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)
Expand Down Expand Up @@ -128,6 +128,7 @@ public override bool DoActionCombat()
}
}

m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant);
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant))
{
if (m_Mobile.Debug)
Expand Down
5 changes: 3 additions & 2 deletions Projects/UOContent/Mobiles/AI/PredatorAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,15 @@ public override bool DoActionCombat()
{
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;
}

Expand Down
3 changes: 2 additions & 1 deletion Projects/UOContent/Mobiles/AI/ThiefAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public override bool DoActionCombat()
{
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)
{
Expand Down

0 comments on commit d428236

Please sign in to comment.