using System; using System.Collections.Generic; using System.Linq; using Barotrauma.Items.Components; using Microsoft.Xna.Framework; namespace Barotrauma.MapCreatures.Behavior { class GrowToTargetState: GrowIdleState { public readonly List TargetBranches = new List(); public readonly Item Target; private bool isFinished; public GrowToTargetState(BallastFloraBehavior behavior, BallastFloraBranch starter, Item target) : base(behavior) { Target = target; TargetBranches.Add(starter); } // do nothing public override void Enter() { } public override ExitState GetState() => isFinished ? ExitState.Terminate : ExitState.Running; protected override void Grow() { if (TargetBranches.Any(b => b.Removed)) { if (!Behavior.IgnoredTargets.ContainsKey(Target)) { Behavior.IgnoredTargets.Add(Target, 10); } isFinished = true; return; } if (Target == null || Target.Removed) { isFinished = true; return; } GrowTowardsTarget(); } private void GrowTowardsTarget() { bool succeeded = false; List newList = new List(TargetBranches); foreach (BallastFloraBranch branch in newList) { if (branch.FailedGrowthAttempts > 8 || branch.DisconnectedFromRoot || !branch.CanGrowMore()) { continue; } // Get what side gets us closest to the target TileSide side = GetClosestSide(branch, Target.WorldPosition); if (branch.IsSideBlocked(side)) { continue; } succeeded |= Behavior.TryGrowBranch(branch, side, out List newBranches); TargetBranches.AddRange(newBranches); foreach (BallastFloraBranch newBranch in newBranches) { Rectangle worldRect = newBranch.Rect; worldRect.Location = Behavior.GetWorldPosition().ToPoint() + worldRect.Location; if (Behavior.BranchContainsTarget(newBranch, Target)) { Behavior.ClaimTarget(Target, newBranch); isFinished = true; return; } } } if (!succeeded) { if (!Behavior.IgnoredTargets.ContainsKey(Target)) { Behavior.IgnoredTargets.Add(Target, 1); } isFinished = true; } } private TileSide GetClosestSide(VineTile tile, Vector2 targetPos) { var (distX, distY) = tile.Position + Behavior.GetWorldPosition() - targetPos; int absDistX = (int) Math.Abs(distX), absDistY = (int) Math.Abs(distY); return absDistX > absDistY ? distX > 0 ? TileSide.Left : TileSide.Right : distY > 0 ? TileSide.Bottom : TileSide.Top; } } }