feat: Adds monster abilities to combat actions (#1266)

This commit is contained in:
Kamron Batman 2022-11-22 20:05:19 -08:00 committed by GitHub
parent efaf2e947a
commit 8b5bd9ec13
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 173 additions and 127 deletions

View file

@ -60,7 +60,6 @@ public class AnimalAI : BaseAI
}
Action = ActionType.Wander;
return true;
}
@ -74,7 +73,6 @@ public class AnimalAI : BaseAI
}
Action = ActionType.Wander;
return true;
}
@ -96,6 +94,15 @@ public class AnimalAI : BaseAI
}
Action = ActionType.Flee;
return true;
}
}
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I used my abilities on {combatant.Name}!");
}
}

View file

@ -80,6 +80,16 @@ public class ArcherAI : BaseAI
}
}
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, m_Mobile.Combatant))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I used my abilities on {m_Mobile.Combatant.Name}!");
}
return true;
}
// When we have no ammo, we flee
var pack = m_Mobile.Backpack;
@ -123,4 +133,4 @@ public class ArcherAI : BaseAI
return true;
}
}
}

View file

@ -993,18 +993,24 @@ public abstract class BaseAI
{
m_Mobile.DebugSay("Praise the shepherd!");
}
}
else
{
var c = m_Mobile.Combatant;
if (c?.Deleted != false || c.Map != m_Mobile.Map || !c.Alive || c.IsDeadBondedPet)
return true;
}
var c = m_Mobile.Combatant;
if (c?.Deleted != false || c.Map != m_Mobile.Map || !c.Alive || c.IsDeadBondedPet)
{
Action = ActionType.Wander;
return true;
}
m_Mobile.Direction = m_Mobile.GetDirectionTo(c);
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, c))
{
if (m_Mobile.Debug)
{
Action = ActionType.Wander;
}
else
{
m_Mobile.Direction = m_Mobile.GetDirectionTo(c);
m_Mobile.DebugSay($"I used my abilities on {c.Name}!");
}
}

View file

@ -72,6 +72,14 @@ public class BerserkAI : BaseAI
}
}
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, m_Mobile.Combatant))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I used my abilities on {m_Mobile.Combatant.Name}!");
}
}
return true;
}
@ -94,4 +102,4 @@ public class BerserkAI : BaseAI
return true;
}
}
}

View file

@ -49,54 +49,65 @@ public class HealerAI : BaseAI
{
targ.Cancel(m_Mobile, TargetCancelType.Canceled);
}
return true;
}
else
var toHelp = Find(m_All);
if (toHelp != null)
{
var toHelp = Find(m_All);
if (toHelp != null)
if (NeedCure(toHelp))
{
if (NeedCure(toHelp))
if (m_Mobile.Debug)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"{toHelp.Name} needs a cure");
}
if (!new CureSpell(m_Mobile).Cast())
{
new CureSpell(m_Mobile).Cast();
}
m_Mobile.DebugSay($"{toHelp.Name} needs a cure");
}
else if (NeedGHeal(toHelp))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("{toHelp.Name} needs a greater heal");
}
if (!new GreaterHealSpell(m_Mobile).Cast())
{
new HealSpell(m_Mobile).Cast();
}
if (!new CureSpell(m_Mobile).Cast())
{
new CureSpell(m_Mobile).Cast();
}
else if (NeedLHeal(toHelp))
}
else if (NeedGHeal(toHelp))
{
if (m_Mobile.Debug)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("{toHelp.Name} needs a lesser heal");
}
m_Mobile.DebugSay($"{toHelp.Name} needs a greater heal");
}
if (!new GreaterHealSpell(m_Mobile).Cast())
{
new HealSpell(m_Mobile).Cast();
}
}
else if (AcquireFocusMob(m_Mobile.RangePerception, FightMode.Weakest, false, true, false))
else if (NeedLHeal(toHelp))
{
WalkMobileRange(m_Mobile.FocusMob, 1, false, 4, 7);
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"{toHelp.Name} needs a lesser heal");
}
new HealSpell(m_Mobile).Cast();
}
else
return true;
}
if (!AcquireFocusMob(m_Mobile.RangePerception, FightMode.Weakest, false, true, false))
{
WalkRandomInHome(3, 2, 1);
return true;
}
WalkMobileRange(m_Mobile.FocusMob, 1, false, 4, 7);
// TODO: Should it be able to do this?
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, m_Mobile.Combatant))
{
if (m_Mobile.Debug)
{
WalkRandomInHome(3, 2, 1);
m_Mobile.DebugSay($"I used my abilities on {m_Mobile.Combatant.Name}!");
}
}

View file

@ -685,14 +685,15 @@ public class MageAI : BaseAI
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.Combatant = c = m_Mobile.FocusMob!;
if (m_Mobile.Debug)
{
m_Mobile.DebugSay(
$"Something happened to my combatant, so I am going to fight {m_Mobile.FocusMob.Name}"
$"Something happened to my combatant, so I am going to fight {c.Name}"
);
}
m_Mobile.Combatant = c = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
else
@ -716,12 +717,13 @@ public class MageAI : BaseAI
if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true))
{
m_Mobile.Combatant = c = m_Mobile.FocusMob!;
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I will switch to {m_Mobile.FocusMob.Name}");
m_Mobile.DebugSay($"I will switch to {c.Name}");
}
m_Mobile.Combatant = c = m_Mobile.FocusMob;
m_Mobile.FocusMob = null;
}
}
@ -778,7 +780,14 @@ public class MageAI : BaseAI
}
}
if (m_Mobile.Spell == null && Core.TickCount - m_NextCastTime >= 0 && m_Mobile.InRange(c, Core.ML ? 10 : 12))
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, c))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("I used my abilities!");
}
}
else if (m_Mobile.Spell == null && Core.TickCount - m_NextCastTime >= 0 && m_Mobile.InRange(c, Core.ML ? 10 : 12))
{
// We are ready to cast a spell
Spell spell;

View file

@ -46,7 +46,6 @@ public class MeleeAI : BaseAI
}
Action = ActionType.Guard;
return true;
}
@ -74,7 +73,6 @@ public class MeleeAI : BaseAI
}
Action = ActionType.Guard;
return true;
}
}
@ -90,7 +88,6 @@ public class MeleeAI : BaseAI
m_Mobile.Combatant = m_Mobile.FocusMob;
Action = ActionType.Combat;
return true;
}
@ -102,7 +99,6 @@ public class MeleeAI : BaseAI
}
Action = ActionType.Guard;
return true;
}
@ -127,10 +123,19 @@ public class MeleeAI : BaseAI
}
Action = ActionType.Flee;
return true;
}
}
}
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("I used my abilities!");
}
}
return true;
}
@ -173,4 +178,4 @@ public class MeleeAI : BaseAI
return true;
}
}
}

View file

@ -68,6 +68,14 @@ public class PredatorAI : BaseAI
}
}
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, combatant))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I used my abilities on {combatant.Name}!");
}
}
return true;
}
@ -101,4 +109,4 @@ public class PredatorAI : BaseAI
return true;
}
}
}

View file

@ -48,7 +48,6 @@ public class ThiefAI : BaseAI
}
Action = ActionType.Guard;
return true;
}
@ -86,90 +85,69 @@ public class ThiefAI : BaseAI
}
else if (m_toDisarm == null && Core.TickCount - m_Mobile.NextSkillTime >= 0)
{
var cpack = combatant.Backpack;
if (cpack != null)
if (m_Mobile.Debug)
{
Item steala = cpack.FindItemByType<Bandage>();
if (steala != null)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("Trying to steal from combatant.");
}
m_Mobile.DebugSay($"Trying to steal from {combatant.Name}.");
}
m_Mobile.UseSkill(SkillName.Stealing);
m_Mobile.Target?.Invoke(m_Mobile, steala);
bool didSteal = TryStealFrom<Bandage>(combatant);
didSteal = TryStealFrom<Nightshade>(combatant) || didSteal;
didSteal = TryStealFrom<BlackPearl>(combatant) || didSteal;
didSteal = TryStealFrom<MandrakeRoot>(combatant) || didSteal;
if (!didSteal)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I am going to flee from {combatant.Name}");
}
Item stealb = cpack.FindItemByType<Nightshade>();
if (stealb != null)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("Trying to steal from combatant.");
}
m_Mobile.UseSkill(SkillName.Stealing);
m_Mobile.Target?.Invoke(m_Mobile, stealb);
}
Item stealc = cpack.FindItemByType<BlackPearl>();
if (stealc != null)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("Trying to steal from combatant.");
}
m_Mobile.UseSkill(SkillName.Stealing);
m_Mobile.Target?.Invoke(m_Mobile, stealc);
}
Item steald = cpack.FindItemByType<MandrakeRoot>();
if (steald != null)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay("Trying to steal from combatant.");
}
m_Mobile.UseSkill(SkillName.Stealing);
m_Mobile.Target?.Invoke(m_Mobile, steald);
}
else if (steala == null && stealb == null && stealc == null)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I am going to flee from {combatant.Name}");
}
Action = ActionType.Flee;
}
Action = ActionType.Flee;
return true;
}
}
}
if (m_Mobile.Hits >= m_Mobile.HitsMax * 20 / 100 || !m_Mobile.CanFlee)
// We are low on health, should we flee?
// (10 + diff)% chance to flee
if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100 && m_Mobile.CanFlee)
{
var fleeChance = 10 + Math.Max(0, combatant.Hits - m_Mobile.Hits);
if (Utility.Random(0, 100) > fleeChance)
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I am going to flee from {combatant.Name}");
}
Action = ActionType.Flee;
}
return true;
}
// We are low on health, should we flee?
// (10 + diff)% chance to flee
var fleeChance = 10 + Math.Max(0, combatant.Hits - m_Mobile.Hits);
if (Utility.Random(0, 100) > fleeChance)
if (m_Mobile.TriggerAbility(MonsterAbilityTrigger.CombatAction, m_Mobile.Combatant))
{
if (m_Mobile.Debug)
{
m_Mobile.DebugSay($"I am going to flee from {combatant.Name}");
m_Mobile.DebugSay($"I used my abilities on {m_Mobile.Combatant.Name}!");
}
}
return true;
}
Action = ActionType.Flee;
private bool TryStealFrom<T>(Mobile combatant) where T : Item
{
Item steal = combatant.Backpack?.FindItemByType<T>();
if (steal != null)
{
m_Mobile.UseSkill(SkillName.Stealing);
m_Mobile.Target?.Invoke(m_Mobile, steal);
return true;
}
return true;
return false;
}
public override bool DoActionGuard()
@ -211,4 +189,4 @@ public class ThiefAI : BaseAI
return true;
}
}
}

View file

@ -1159,23 +1159,27 @@ namespace Server.Mobiles
return false;
}
public virtual void TriggerAbility(MonsterAbilityTrigger trigger, Mobile defender)
public virtual bool TriggerAbility(MonsterAbilityTrigger trigger, Mobile defender)
{
var abilities = GetMonsterAbilities();
if (abilities == null)
{
return;
return false;
}
var triggered = false;
for (var i = 0; i < abilities.Length; i++)
{
var ability = abilities[i];
if (ability.WillTrigger(trigger) && ability.CanTrigger(this, trigger))
{
ability.Trigger(trigger, this, defender);
triggered = true;
}
}
return triggered;
}
public virtual void TriggerAbilityMove(MonsterAbilityTrigger trigger, Mobile defender, Direction d)