feat: Adds monster abilities to combat actions (#1266)
This commit is contained in:
parent
efaf2e947a
commit
8b5bd9ec13
10 changed files with 173 additions and 127 deletions
|
|
@ -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}!");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}!");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}!");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue