diff --git a/Projects/UOContent/Mobiles/AI/BehaviorTreeAI.cs b/Projects/UOContent/Mobiles/AI/BehaviorTreeAI.cs index 945604ce4..25426ab0a 100644 --- a/Projects/UOContent/Mobiles/AI/BehaviorTreeAI.cs +++ b/Projects/UOContent/Mobiles/AI/BehaviorTreeAI.cs @@ -12,7 +12,6 @@ namespace Server.Mobiles.AI { public class BehaviorTreeAI : BaseAI { - // private Blackboard blackboard; private Blackboard blackboard; private BehaviorTree behaviorTree; private BehaviorTreeContext behaviorTreeContext; @@ -23,11 +22,16 @@ namespace Server.Mobiles.AI behaviorTreeContext = new BehaviorTreeContext(m, blackboard); behaviorTree = new BehaviorTree(); behaviorTree.TryAddRoot( - new Sequence(behaviorTree) - .AddChild(new Condition(behaviorTree, (context) => context.Mobile.RawStr - context.Mobile.Str == 0)) - .AddChild(new CastSpell(behaviorTree, (context) => new BlessSpell(context.Mobile))) - .AddChild(new WaitForTarget(behaviorTree)) - .AddChild(new DynamicTarget(behaviorTree, (context) => context.Mobile)) + new Selector(behaviorTree) + .AddChild(new MageCombat(behaviorTree)) + .AddChild(new MagePassive(behaviorTree)) + /* + new Sequence(behaviorTree) + .AddChild(new Condition(behaviorTree, (context) => context.Mobile.RawStr - context.Mobile.Str == 0)) + .AddChild(new CastSpell(behaviorTree, (context) => new BlessSpell(context.Mobile))) + .AddChild(new WaitForTarget(behaviorTree)) + .AddChild(new DynamicTarget(behaviorTree, (context) => context.Mobile)) + */ ); behaviorTree.Start(behaviorTreeContext); @@ -42,7 +46,6 @@ namespace Server.Mobiles.AI // MageBehaviorTree.Instance.RunBehavior(m_Mobile, blackboard); - m_Mobile.DebugSay("Thinking..."); behaviorTree.Tick(behaviorTreeContext); return true; diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Composite/Selector.cs b/Projects/UOContent/Mobiles/BehaviorAI/Composite/Selector.cs index b57bfacdd..3d5f253fb 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Composite/Selector.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Composite/Selector.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Server.Mobiles.BehaviorAI { public class Selector : Composite @@ -19,8 +13,7 @@ namespace Server.Mobiles.BehaviorAI currentChildCache.Add(context.Mobile, currentChild); } - Behavior child = Children[currentChild]; - + currentChild++; if (lastResult == Result.Success) { currentChildCache[context.Mobile] = 0; @@ -28,23 +21,16 @@ namespace Server.Mobiles.BehaviorAI return; } - currentChild++; if (currentChild >= Children.Count) { currentChildCache[context.Mobile] = 0; SetResult(context, Result.Failure); return; } - else - { - currentChildCache[context.Mobile] = currentChild; - SetResult(context, Result.Running); - if (Children[currentChild] == null) - { - throw new NullReferenceException(); - } - Tree.Enqueue(context, Children[currentChild], OnChildComplete); - } + + currentChildCache[context.Mobile] = currentChild; + SetResult(context, Result.Running); + Tree.Enqueue(context, Children[currentChild], OnChildComplete); } } } diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Composite/Sequence.cs b/Projects/UOContent/Mobiles/BehaviorAI/Composite/Sequence.cs index aa38262cf..a1bc7473c 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Composite/Sequence.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Composite/Sequence.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Server.Mobiles.BehaviorAI { public class Sequence : Composite @@ -19,8 +13,7 @@ namespace Server.Mobiles.BehaviorAI currentChildCache.Add(context.Mobile, currentChild); } - Behavior child = Children[currentChild]; - + currentChild++; if (lastResult == Result.Failure) { currentChildCache[context.Mobile] = 0; @@ -28,23 +21,16 @@ namespace Server.Mobiles.BehaviorAI return; } - currentChild++; if (currentChild >= Children.Count) { currentChildCache[context.Mobile] = 0; SetResult(context, Result.Success); return; } - else - { - SetResult(context, Result.Running); - currentChildCache[context.Mobile] = currentChild; - if (Children[currentChild] == null) - { - throw new NullReferenceException(); - } - Tree.Enqueue(context, Children[currentChild], OnChildComplete); - } + + currentChildCache[context.Mobile] = currentChild; + SetResult(context, Result.Running); + Tree.Enqueue(context, Children[currentChild], OnChildComplete); } } } diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Core/Behavior.cs b/Projects/UOContent/Mobiles/BehaviorAI/Core/Behavior.cs index bc6683c3e..e0f6a2f21 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Core/Behavior.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Core/Behavior.cs @@ -1,8 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Server.Mobiles.BehaviorAI { diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Core/BehaviorQueueEntry.cs b/Projects/UOContent/Mobiles/BehaviorAI/Core/BehaviorQueueEntry.cs index 9b82b562d..90a352e59 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Core/BehaviorQueueEntry.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Core/BehaviorQueueEntry.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Server.Mobiles.BehaviorAI { diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Core/BehaviorTree.cs b/Projects/UOContent/Mobiles/BehaviorAI/Core/BehaviorTree.cs index b9136fa7e..b8a1bb08f 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Core/BehaviorTree.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Core/BehaviorTree.cs @@ -1,8 +1,8 @@ -using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Server.Items; +using Server.Engines.Spawners; +using MoveImpl = Server.Movement.MovementImpl; namespace Server.Mobiles.BehaviorAI { @@ -79,7 +79,7 @@ namespace Server.Mobiles.BehaviorAI queue.Enqueue(current); - return false; + return true; } public virtual void ExecutionFinished(BehaviorTreeContext context, Result result) { @@ -104,5 +104,336 @@ namespace Server.Mobiles.BehaviorAI return queue; } + public static void WalkRandomInHome(BehaviorTreeContext context, int steps) + { + BaseCreature mob = context.Mobile; + + if (mob.Deleted || mob.DisallowAllMoves) + { + return; + } + + if (mob.Home == Point3D.Zero) + { + if (mob.Spawner is RegionSpawner rs) + { + Region region = rs.SpawnRegion; + + if (mob.Region.AcceptsSpawnsFrom(region)) + { + mob.WalkRegion = region; + WalkRandom(context, steps); + mob.WalkRegion = null; + } + else + { + if (region.GoLocation != Point3D.Zero && Utility.RandomDouble() > 0.5) + { + DoMove(context, mob.GetDirectionTo(region.GoLocation)); + } + else + { + WalkRandom(context, steps); + } + } + } + else + { + WalkRandom(context, steps); + } + } + else + { + for (var i = 0; i < steps; i++) + { + if (mob.RangeHome != 0) + { + var currentDistance = (int)mob.GetDistanceToSqrt(mob.Home); + + if (currentDistance < mob.RangeHome * 2 / 3) + { + WalkRandom(context, 1); + } + else if (currentDistance > mob.RangeHome) + { + DoMove(context, mob.GetDirectionTo(mob.Home)); + } + else + { + if (Utility.RandomDouble() > 0.5) + { + DoMove(context, mob.GetDirectionTo(mob.Home)); + } + else + { + WalkRandom(context, 1); + } + } + } + else + { + if (mob.Location != mob.Home) + { + DoMove(context, mob.GetDirectionTo(mob.Home)); + } + } + } + } + } + public static MoveResult WalkRandom(BehaviorTreeContext context, int steps, bool run = false) + { + BaseCreature mob = context.Mobile; + + if (mob.Deleted || mob.DisallowAllMoves) + { + return MoveResult.BadState; + } + + for (var i = 0; i < steps; i++) + { + if (Utility.Random(8) <= 8) + { + var random = Utility.Random(0, 32); + + Direction direction; + + switch (random) + { + case 0: + direction = Direction.Up; + break; + case 1: + direction = Direction.North; + break; + case 2: + direction = Direction.Left; + break; + case 3: + direction = Direction.West; + break; + case 5: + direction = Direction.Down; + break; + case 6: + direction = Direction.South; + break; + case 7: + direction = Direction.Right; + break; + case 8: + direction = Direction.East; + break; + default: + direction = mob.Direction; + break; + } + + DoMove(context, direction, run); + } + } + return MoveResult.Success; + } + public static MoveResult DoMove(BehaviorTreeContext context, Direction d, bool run = false) + { + BaseCreature mob = context.Mobile; + + if (mob.Deleted || mob.Frozen || mob.Paralyzed || mob.Spell?.IsCasting == true || mob.DisallowAllMoves) + { + return MoveResult.BadState; + } + + Direction direction = d; + + if (run) + { + direction |= Direction.Running; + } + + mob.Pushing = false; + + MoveImpl.IgnoreMovableImpassables = mob.CanMoveOverObstacles && !mob.CanDestroyObstacles; + + if ((mob.Direction & Direction.Mask) != (direction & Direction.Mask)) + { + bool moved = mob.Move(direction); + + MoveImpl.IgnoreMovableImpassables = false; + return moved ? MoveResult.Success : MoveResult.Blocked; + } + + if (mob.Move(direction)) + { + MoveImpl.IgnoreMovableImpassables = false; + return MoveResult.Success; + } + + bool wasPushing = mob.Pushing; + + bool blocked = true; + + bool canOpenDoors = mob.CanOpenDoors; + bool canDestroyObstacles = mob.CanDestroyObstacles; + + if (canOpenDoors || canDestroyObstacles) + { + Map map = mob.Map; + + if (map != null) + { + int x = mob.X, y = mob.Y; + Movement.Movement.Offset(direction, ref x, ref y); + + int destroyables = 0; + List obstacles = new List(); + + var eable = map.GetItemsInRange(new Point3D(x, y, mob.Location.Z), 1); + + foreach (var item in eable) + { + if (canOpenDoors && item is BaseDoor door && door.Z + door.ItemData.Height > mob.Z && mob.Z + 16 > door.Z) + { + if (door.X != x || door.Y != y) + { + continue; + } + + if (!door.Locked || !door.UseLocks()) + { + obstacles.Add(item); + } + + if (!canDestroyObstacles) + { + break; + } + } + else if (canDestroyObstacles && item.Movable && item.ItemData.Impassable && item.Z + item.ItemData.Height > mob.Z && mob.Z + 16 > item.Z) + { + if (!mob.InRange(item.GetWorldLocation(), 1)) + { + continue; + } + + obstacles.Add(item); + ++destroyables; + } + } + + eable.Free(); + + if (destroyables > 0) + { + Effects.PlaySound(new Point3D(x, y, mob.Z), mob.Map, 0x3B3); + } + + if (obstacles.Count > 0) + blocked = true; + + while (obstacles.Count > 0) + { + Item item = obstacles.First(); + + if (item is BaseDoor door) + { + mob.DebugSay("Opening door..."); + if (!door.Open) + { + door.Use(mob); + } + obstacles.Remove(item); + } + else + { + if (item is Container container) + { + for (var i = 0; i < container.Items.Count; ++i) + { + Item check = container.Items[i]; + + if (check.Movable && check.ItemData.Impassable && container.Z + check.ItemData.Height > mob.Z) + { + obstacles.Add(check); + } + } + + obstacles.Remove(item); + container.Destroy(); + } + else + { + obstacles.Remove(item); + item.Delete(); + } + } + } + + if (!blocked) + { + blocked = !mob.Move(direction); + } + } + } + + if (blocked) + { + int offset = Utility.RandomDouble() >= 0.6 ? 1 : -1; + + for (var i = 0; i < 2; ++i) + { + mob.TurnInternal(offset); + + if (mob.Move(mob.Direction)) + { + MoveImpl.IgnoreMovableImpassables = false; + return MoveResult.SuccessAutoTurn; + } + } + + MoveImpl.IgnoreMovableImpassables = false; + return wasPushing ? MoveResult.BadState : MoveResult.Blocked; + } + + MoveImpl.IgnoreMovableImpassables = false; + return MoveResult.Success; + } + public static bool WalkMobileRange(BehaviorTreeContext context, BaseCreature target, int steps, bool run, int minRange, int maxRange) + { + BaseCreature mob = context.Mobile; + + if (mob.Deleted || mob.DisallowAllMoves) + { + return false; + } + + if (target == null) + { + return false; + } + + for (var i = 0; i < steps; i++) + { + // Get the current distance + var currentDistance = (int)mob.GetDistanceToSqrt(target); + + if (currentDistance < minRange || currentDistance > maxRange) + { + var needCloser = currentDistance > maxRange; + var direction = needCloser ? + mob.GetDirectionTo(target, run) : target.GetDirectionTo(mob, run); + + DoMove(context, direction, run); + } + else + { + WalkRandom(context, 2, run); + } + return true; + } + + // Get the current distance + var newDistance = (int)mob.GetDistanceToSqrt(target); + + return newDistance >= minRange && newDistance <= maxRange; + } } } diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Core/BehaviorTreeContext.cs b/Projects/UOContent/Mobiles/BehaviorAI/Core/BehaviorTreeContext.cs index 440613499..fd85cf512 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Core/BehaviorTreeContext.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Core/BehaviorTreeContext.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Server.Mobiles.BehaviorAI { public class BehaviorTreeContext diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Core/Blackboard.cs b/Projects/UOContent/Mobiles/BehaviorAI/Core/Blackboard.cs index c850af8c4..567da3600 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Core/Blackboard.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Core/Blackboard.cs @@ -1,8 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Server.Mobiles.BehaviorAI { diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Core/Composite.cs b/Projects/UOContent/Mobiles/BehaviorAI/Core/Composite.cs index f75dcc14f..163816218 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Core/Composite.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Core/Composite.cs @@ -1,8 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Server.Mobiles.BehaviorAI { @@ -36,10 +32,6 @@ namespace Server.Mobiles.BehaviorAI currentChild = 0; currentChildCache[context.Mobile] = currentChild; SetResult(context, Result.Running); - if (Children[currentChild] == null) - { - throw new NullReferenceException(); - } Tree.Enqueue(context, Children[currentChild], OnChildComplete); } } diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Core/Decorator.cs b/Projects/UOContent/Mobiles/BehaviorAI/Core/Decorator.cs index bedd27e61..feb48dedf 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Core/Decorator.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Core/Decorator.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Server.Mobiles.BehaviorAI { public class Decorator : Behavior @@ -16,14 +10,13 @@ namespace Server.Mobiles.BehaviorAI { Child = child; } - public virtual bool AddChild(Behavior child) + public virtual Decorator AddChild(Behavior child) { if (Child == null) { Child = child; - return true; } - return false; + return this; } public override void Tick(BehaviorTreeContext context) { @@ -34,9 +27,9 @@ namespace Server.Mobiles.BehaviorAI return; } } - public virtual void OnChildComplete(BehaviorTreeContext context, Result result) + public virtual void OnChildComplete(BehaviorTreeContext context, Result lastResult) { - SetResult(context, Child.GetResult(context)); + SetResult(context, lastResult); } } } diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/ConditionalLoop.cs b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/ConditionalLoop.cs index 0f92b43ee..24fa6e9ad 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/ConditionalLoop.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/ConditionalLoop.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Server.Mobiles.BehaviorAI { public delegate bool ConditionalLoopPredicate(BehaviorTreeContext context); diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/Cooldown.cs b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/Cooldown.cs index 13edfda87..9025210aa 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/Cooldown.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/Cooldown.cs @@ -1,8 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Server.Mobiles.BehaviorAI { diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/ForceSuccess.cs b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/ForceSuccess.cs index e6a8c9184..f4ad8b733 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/ForceSuccess.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/ForceSuccess.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Server.Mobiles.BehaviorAI { public class ForceSuccess : Decorator diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/Inverter.cs b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/Inverter.cs index a3d622e0e..478c64bb6 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/Inverter.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/Inverter.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Server.Mobiles.BehaviorAI { public class Inverter : Decorator diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/Loop.cs b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/Loop.cs index e93d623e5..304cbf452 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/Loop.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/Loop.cs @@ -1,8 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Server.Mobiles.BehaviorAI { diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/OwnerCondition.cs b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/OwnerCondition.cs index 2ee6948d2..5f5b9cd37 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/OwnerCondition.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/OwnerCondition.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Server.Mobiles.BehaviorAI { public delegate bool OwnerConditionPredicate(BehaviorTreeContext context); @@ -24,6 +18,7 @@ namespace Server.Mobiles.BehaviorAI { base.Tick(context); } + SetResult(context, Result.Failure); } } } diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/UntilFail.cs b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/UntilFail.cs index 44397f72e..b89a725f9 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Decorator/UntilFail.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Decorator/UntilFail.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Server.Mobiles.BehaviorAI { public class UntilFail : Decorator diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/AutoTarget.cs b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/AutoTarget.cs index d00c84d83..515aca0ef 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/AutoTarget.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/AutoTarget.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Server.Targeting; namespace Server.Mobiles.BehaviorAI diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/CancelTarget.cs b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/CancelTarget.cs new file mode 100644 index 000000000..515976197 --- /dev/null +++ b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/CancelTarget.cs @@ -0,0 +1,22 @@ +using Server.Targeting; + +namespace Server.Mobiles.BehaviorAI +{ + public class CancelTarget : Behavior + { + public CancelTarget(BehaviorTree tree) : base(tree) + { + } + public override void Tick(BehaviorTreeContext context) + { + Target target = context.Mobile.Target; + + if (target != null) + { + target.Cancel(context.Mobile, TargetCancelType.Canceled); + } + + SetResult(context, Result.Success); + } + } +} diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/CastSpell.cs b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/CastSpell.cs index f0a9aba49..29afb006b 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/CastSpell.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/CastSpell.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Server.Spells; namespace Server.Mobiles.BehaviorAI @@ -39,7 +34,7 @@ namespace Server.Mobiles.BehaviorAI if (!spell.Cast()) { - SetResult(context, Result.Running); + SetResult(context, Result.Failure); owner.DebugSay("Failed to cast..."); return; } @@ -57,7 +52,7 @@ namespace Server.Mobiles.BehaviorAI owner.DebugSay("Already casting {0}...", ((Spell)owner.Spell).Name); return; } - else if (!owner.Spell.IsCasting) + else if (!owner.Spell.IsCasting && ((Spell)owner.Spell).State == SpellState.Sequencing) { SetResult(context, Result.Success); owner.DebugSay("Finished casting {0}...", ((Spell)owner.Spell).Name); diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/Condition.cs b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/Condition.cs index bc0fea30c..faaba5283 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/Condition.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/Condition.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Server.Mobiles.BehaviorAI { public delegate bool ConditionPredicate(BehaviorTreeContext context); diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/DynamicTarget.cs b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/DynamicTarget.cs index 28560db26..f640db275 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/DynamicTarget.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/DynamicTarget.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Server.Targeting; namespace Server.Mobiles.BehaviorAI @@ -10,14 +5,14 @@ namespace Server.Mobiles.BehaviorAI public delegate object DynamicTargetCallback(BehaviorTreeContext context); public class DynamicTarget : Behavior { - public DynamicTargetCallback Transformation { get; private set; } + public DynamicTargetCallback Callback { get; private set; } public DynamicTarget(BehaviorTree tree, DynamicTargetCallback transformation) : base(tree) { - Transformation = transformation; + Callback = transformation; } public override void Tick(BehaviorTreeContext context) { - if (Transformation != null) + if (Callback == null) { SetResult(context, Result.Failure); return; @@ -31,7 +26,7 @@ namespace Server.Mobiles.BehaviorAI return; } - object targeted = Transformation(context); + object targeted = Callback(context); if (targeted == null) { diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/Tap.cs b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/Tap.cs index 338d4bc28..8bb3f1c5a 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/Tap.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/Tap.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Server.Mobiles.BehaviorAI { public delegate void TapAction(BehaviorTreeContext context); diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/WaitForTarget.cs b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/WaitForTarget.cs index e07d3a64e..87f767d79 100644 --- a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/WaitForTarget.cs +++ b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/WaitForTarget.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Server.Mobiles.BehaviorAI { public class WaitForTarget : Behavior diff --git a/Projects/UOContent/Mobiles/BehaviorAI/Leaf/Wander.cs b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/Wander.cs new file mode 100644 index 000000000..f1660518a --- /dev/null +++ b/Projects/UOContent/Mobiles/BehaviorAI/Leaf/Wander.cs @@ -0,0 +1,29 @@ +namespace Server.Mobiles.BehaviorAI +{ + public class Wander : Behavior + { + public int Range { get; } + public double Chance { get; } + public Wander(BehaviorTree tree) : this(tree, 2) + { + } + public Wander(BehaviorTree tree, int range) : this(tree, range, 1.0) + { + } + public Wander(BehaviorTree tree, int range, double chance) : base(tree) + { + Range = range; + Chance = chance; + } + public override void Tick(BehaviorTreeContext context) + { + if (!context.Mobile.CheckIdle() && Utility.RandomDouble() < Chance) + { + BehaviorTree.WalkRandomInHome(context, Range); + SetResult(context, Result.Success); + return; + } + SetResult(context, Result.Failure); + } + } +} diff --git a/Projects/UOContent/Mobiles/BehaviorAI/MageCombat.cs b/Projects/UOContent/Mobiles/BehaviorAI/MageCombat.cs new file mode 100644 index 000000000..24b9276be --- /dev/null +++ b/Projects/UOContent/Mobiles/BehaviorAI/MageCombat.cs @@ -0,0 +1,37 @@ +using Server.Spells; +using Server.Spells.First; +using Server.Spells.Second; +using Server.Spells.Third; +using Server.Spells.Sixth; + +namespace Server.Mobiles.BehaviorAI +{ + public class MageCombat : OwnerCondition + { + public MageCombat(BehaviorTree tree) : base(tree, canActivate) + { + AddChild( + new Sequence(tree) + .AddChild(new Condition(tree, (context) => context.Mobile.Mana >= 65)) + .AddChild(new CastSpell(tree, (context) => new ExplosionSpell(context.Mobile))) + .AddChild(new WaitForTarget(tree)) + .AddChild(new AutoTarget(tree)) + .AddChild( + new ForceSuccess(tree) + .AddChild( + new Selector(tree) + .AddChild(new OwnerCondition(tree, (context) => Utility.RandomBool(), new CastSpell(tree, (context) => new PoisonSpell(context.Mobile)))) + .AddChild(new OwnerCondition(tree, (context) => Utility.RandomBool(), new CastSpell(tree, (context) => new FireballSpell(context.Mobile)))) + .AddChild(new CastSpell(tree, (context) => new EnergyBoltSpell(context.Mobile))) + ) + ) + .AddChild(new WaitForTarget(tree)) + .AddChild(new AutoTarget(tree)) + ); + } + public static bool canActivate(BehaviorTreeContext context) + { + return context.Mobile.Combatant != null; + } + } +} diff --git a/Projects/UOContent/Mobiles/BehaviorAI/MagePassive.cs b/Projects/UOContent/Mobiles/BehaviorAI/MagePassive.cs new file mode 100644 index 000000000..c76b3b75b --- /dev/null +++ b/Projects/UOContent/Mobiles/BehaviorAI/MagePassive.cs @@ -0,0 +1,14 @@ +namespace Server.Mobiles.BehaviorAI +{ + public class MagePassive : OwnerCondition + { + public MagePassive(BehaviorTree tree) : base(tree, canActivate) + { + AddChild(new Wander(tree, 2, 0.5)); + } + public static bool canActivate(BehaviorTreeContext context) + { + return context.Mobile.Combatant == null; + } + } +} diff --git a/Projects/UOContent/Mobiles/BehaviorMage.cs b/Projects/UOContent/Mobiles/BehaviorMage.cs index f89566483..9236f4d82 100644 --- a/Projects/UOContent/Mobiles/BehaviorMage.cs +++ b/Projects/UOContent/Mobiles/BehaviorMage.cs @@ -11,9 +11,9 @@ namespace Server.Mobiles public class BehaviorMage : BaseCreature { [Constructible] - public BehaviorMage() : base(AIType.AI_BehaviorTree, FightMode.Evil, 2, 0, 0.01, 3) + public BehaviorMage() : base(AIType.AI_BehaviorTree, FightMode.Evil, 2, 0, 0.01, 1) { - Debug = true; + // Debug = true; InitBody(); diff --git a/Projects/UOContent/UOContent.csproj b/Projects/UOContent/UOContent.csproj index 16c2b724f..e0ef6c535 100755 --- a/Projects/UOContent/UOContent.csproj +++ b/Projects/UOContent/UOContent.csproj @@ -52,6 +52,9 @@ + + + true Generated