public override void Update(float deltaTime) { if (DisableCrewAI || Character.IsUnconscious) { return; } float maxDistanceToSub = 3000; if (Character.Submarine != null || SelectedAiTarget?.Entity?.Submarine != null && Vector2.DistanceSquared(Character.WorldPosition, SelectedAiTarget.Entity.Submarine.WorldPosition) < maxDistanceToSub * maxDistanceToSub) { if (steeringManager != insideSteering) { insideSteering.Reset(); } steeringManager = insideSteering; } else { if (steeringManager != outsideSteering) { outsideSteering.Reset(); } steeringManager = outsideSteering; } AnimController.Crouching = shouldCrouch; CheckCrouching(deltaTime); Character.ClearInputs(); if (hullVisibilityTimer > 0) { hullVisibilityTimer--; } else { hullVisibilityTimer = hullVisibilityInterval; VisibleHulls = Character.GetVisibleHulls(); } objectiveManager.UpdateObjectives(deltaTime); if (sortTimer > 0.0f) { sortTimer -= deltaTime; } else { objectiveManager.SortObjectives(); sortTimer = sortObjectiveInterval; } if (reactTimer > 0.0f) { reactTimer -= deltaTime; } else { if (Character.CurrentHull != null) { VisibleHulls.ForEach(h => PropagateHullSafety(Character, h)); } if (Character.SpeechImpediment < 100.0f) { ReportProblems(); UpdateSpeaking(); } reactTimer = reactionTime * Rand.Range(0.75f, 1.25f); } if (objectiveManager.CurrentObjective == null) { return; } objectiveManager.DoCurrentObjective(deltaTime); bool run = objectiveManager.CurrentObjective.ForceRun || objectiveManager.GetCurrentPriority() > AIObjectiveManager.RunPriority; if (ObjectiveManager.CurrentObjective is AIObjectiveGoTo goTo && goTo.Target != null) { if (Character.CurrentHull == null) { run = Vector2.DistanceSquared(Character.WorldPosition, goTo.Target.WorldPosition) > 300 * 300; } else { float yDiff = goTo.Target.WorldPosition.Y - Character.WorldPosition.Y; if (Math.Abs(yDiff) > 100) { run = true; } else { float xDiff = goTo.Target.WorldPosition.X - Character.WorldPosition.X; run = Math.Abs(xDiff) > 300; } } } if (run) { run = !AnimController.Crouching && !AnimController.IsMovingBackwards; } float currentSpeed = Character.AnimController.GetCurrentSpeed(run); steeringManager.Update(currentSpeed); bool ignorePlatforms = Character.AnimController.TargetMovement.Y < -0.5f && (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X)); if (steeringManager == insideSteering) { var currPath = PathSteering.CurrentPath; if (currPath != null && currPath.CurrentNode != null) { if (currPath.CurrentNode.SimPosition.Y < Character.AnimController.GetColliderBottom().Y) { // Don't allow to jump from too high. The formula might require tweaking. float allowedJumpHeight = Character.AnimController.ImpactTolerance / 2; float height = Math.Abs(currPath.CurrentNode.SimPosition.Y - Character.SimPosition.Y); ignorePlatforms = height < allowedJumpHeight; } } if (Character.IsClimbing && PathSteering.IsNextLadderSameAsCurrent) { Character.AnimController.TargetMovement = new Vector2(0.0f, Math.Sign(Character.AnimController.TargetMovement.Y)); } } Character.AnimController.IgnorePlatforms = ignorePlatforms; Vector2 targetMovement = AnimController.TargetMovement; if (!Character.AnimController.InWater) { targetMovement = new Vector2(Character.AnimController.TargetMovement.X, MathHelper.Clamp(Character.AnimController.TargetMovement.Y, -1.0f, 1.0f)); } float maxSpeed = Character.ApplyTemporarySpeedLimits(currentSpeed); targetMovement.X = MathHelper.Clamp(targetMovement.X, -maxSpeed, maxSpeed); targetMovement.Y = MathHelper.Clamp(targetMovement.Y, -maxSpeed, maxSpeed); //apply speed multiplier if // a. it's boosting the movement speed and the character is trying to move fast (= running) // b. it's a debuff that decreases movement speed float speedMultiplier = Character.SpeedMultiplier; if (run || speedMultiplier <= 0.0f) { targetMovement *= speedMultiplier; } Character.ResetSpeedMultiplier(); // Reset, items will set the value before the next update Character.AnimController.TargetMovement = targetMovement; if (!NeedsDivingGear(Character.CurrentHull)) { bool oxygenLow = Character.OxygenAvailable < CharacterHealth.LowOxygenThreshold; bool highPressure = Character.CurrentHull == null || Character.CurrentHull.LethalPressure > 0 && Character.PressureProtection <= 0; bool shouldKeepTheGearOn = !ObjectiveManager.IsCurrentObjective <AIObjectiveIdle>(); bool removeDivingSuit = oxygenLow && !highPressure; if (!removeDivingSuit) { bool targetHasNoSuit = objectiveManager.CurrentOrder is AIObjectiveGoTo gtObj && gtObj.mimic && !HasDivingSuit(gtObj.Target as Character); bool canDropTheSuit = Character.CurrentHull.WaterPercentage < 1 && !Character.IsClimbing && steeringManager == insideSteering && !PathSteering.InStairs; removeDivingSuit = (!shouldKeepTheGearOn || targetHasNoSuit) && canDropTheSuit; } if (removeDivingSuit) { var divingSuit = Character.Inventory.FindItemByIdentifier("divingsuit") ?? Character.Inventory.FindItemByTag("divingsuit"); if (divingSuit != null) { // TODO: take the item where it was taken from? divingSuit.Drop(Character); } } bool targetHasNoMask = objectiveManager.CurrentOrder is AIObjectiveGoTo gotoObjective && gotoObjective.mimic && !HasDivingMask(gotoObjective.Target as Character); bool takeMaskOff = oxygenLow || (!shouldKeepTheGearOn && Character.CurrentHull.WaterPercentage < 20) || targetHasNoMask; if (takeMaskOff) { var mask = Character.Inventory.FindItemByIdentifier("divingmask"); if (mask != null && Character.Inventory.IsInLimbSlot(mask, InvSlotType.Head)) { // Try to put the mask in an Any slot, and drop it if that fails if (!mask.AllowedSlots.Contains(InvSlotType.Any) || !Character.Inventory.TryPutItem(mask, Character, new List <InvSlotType>() { InvSlotType.Any })) { mask.Drop(Character); } } } } if (!ObjectiveManager.IsCurrentObjective <AIObjectiveExtinguishFires>() && !ObjectiveManager.IsCurrentObjective <AIObjectiveExtinguishFire>()) { var extinguisherItem = Character.Inventory.FindItemByIdentifier("extinguisher") ?? Character.Inventory.FindItemByTag("extinguisher"); if (extinguisherItem != null && Character.HasEquippedItem(extinguisherItem)) { // TODO: take the item where it was taken from? extinguisherItem.Drop(Character); } } foreach (var item in Character.Inventory.Items) { if (item == null) { continue; } if (ObjectiveManager.CurrentObjective is AIObjectiveIdle) { if (item.AllowedSlots.Contains(InvSlotType.RightHand | InvSlotType.LeftHand) && Character.HasEquippedItem(item)) { // Try to put the weapon in an Any slot, and drop it if that fails if (!item.AllowedSlots.Contains(InvSlotType.Any) || !Character.Inventory.TryPutItem(item, Character, new List <InvSlotType>() { InvSlotType.Any })) { item.Drop(Character); } } } } if (Character.IsKeyDown(InputType.Aim)) { var cursorDiffX = Character.CursorPosition.X - Character.Position.X; if (cursorDiffX > 10.0f) { Character.AnimController.TargetDir = Direction.Right; } else if (cursorDiffX < -10.0f) { Character.AnimController.TargetDir = Direction.Left; } if (Character.SelectedConstruction != null) { Character.SelectedConstruction.SecondaryUse(deltaTime, Character); } } else if (Math.Abs(Character.AnimController.TargetMovement.X) > 0.1f && !Character.AnimController.InWater) { Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left; } }
public override void Update(float deltaTime) { if (DisableCrewAI || Character.IsUnconscious) { return; } Character.ClearInputs(); //steeringManager = Character.AnimController.CurrentHull == null ? outdoorsSteeringManager : indoorsSteeringManager; if (updateObjectiveTimer > 0.0f) { updateObjectiveTimer -= deltaTime; } else { objectiveManager.UpdateObjectives(); updateObjectiveTimer = UpdateObjectiveInterval; } objectiveManager.DoCurrentObjective(deltaTime); float currObjectivePriority = objectiveManager.GetCurrentPriority(Character); float moveSpeed = 1.0f; if (currObjectivePriority > 30.0f) { moveSpeed *= Character.AnimController.InWater ? Character.AnimController.SwimSpeedMultiplier : Character.AnimController.RunSpeedMultiplier; } steeringManager.Update(moveSpeed); bool ignorePlatforms = Character.AnimController.TargetMovement.Y < -0.5f && (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X)); var currPath = (steeringManager as IndoorsSteeringManager).CurrentPath; if (currPath != null && currPath.CurrentNode != null) { if (currPath.CurrentNode.SimPosition.Y < Character.AnimController.GetColliderBottom().Y) { ignorePlatforms = true; } } Character.AnimController.IgnorePlatforms = ignorePlatforms; (Character.AnimController as HumanoidAnimController).Crouching = false; if (!Character.AnimController.InWater) { Character.AnimController.TargetMovement = new Vector2( Character.AnimController.TargetMovement.X, MathHelper.Clamp(Character.AnimController.TargetMovement.Y, -1.0f, 1.0f)) * Character.SpeedMultiplier; Character.SpeedMultiplier = 1.0f; } if (Character.SelectedConstruction != null && Character.SelectedConstruction.GetComponent <Items.Components.Ladder>() != null) { if (currPath != null && currPath.CurrentNode != null && currPath.CurrentNode.Ladders != null) { Character.AnimController.TargetMovement = new Vector2(0.0f, Math.Sign(Character.AnimController.TargetMovement.Y)); } } //suit can be taken off if there character is inside a hull and there's air in the room bool canTakeOffSuit = Character.AnimController.CurrentHull != null && Character.AnimController.CurrentHull.OxygenPercentage > 30.0f && Character.AnimController.CurrentHull.Volume < Character.AnimController.CurrentHull.FullVolume * 0.3f; //the suit can be taken off and the character is running out of oxygen (couldn't find a tank for the suit?) or idling //-> take the suit off if (canTakeOffSuit && (Character.Oxygen < 50.0f || objectiveManager.CurrentObjective is AIObjectiveIdle)) { var divingSuit = Character.Inventory.FindItem("Diving Suit"); if (divingSuit != null) { divingSuit.Drop(Character); } } if (Character.IsKeyDown(InputType.Aim)) { var cursorDiffX = Character.CursorPosition.X - Character.Position.X; if (cursorDiffX > 10.0f) { Character.AnimController.TargetDir = Direction.Right; } else if (cursorDiffX < -10.0f) { Character.AnimController.TargetDir = Direction.Left; } if (Character.SelectedConstruction != null) { Character.SelectedConstruction.SecondaryUse(deltaTime, Character); } } else if (Math.Abs(Character.AnimController.TargetMovement.X) > 0.1f && !Character.AnimController.InWater) { Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left; } }
public override void Update(float deltaTime) { if (DisableCrewAI || Character.IsUnconscious) { return; } float maxDistanceToSub = 3000; if (Character.Submarine != null || SelectedAiTarget?.Entity?.Submarine != null && Vector2.DistanceSquared(Character.WorldPosition, SelectedAiTarget.Entity.Submarine.WorldPosition) < maxDistanceToSub * maxDistanceToSub) { if (steeringManager != insideSteering) { insideSteering.Reset(); } steeringManager = insideSteering; } else { if (steeringManager != outsideSteering) { outsideSteering.Reset(); } steeringManager = outsideSteering; } AnimController.Crouching = shouldCrouch; CheckCrouching(deltaTime); Character.ClearInputs(); if (hullVisibilityTimer > 0) { hullVisibilityTimer--; } else { hullVisibilityTimer = hullVisibilityInterval; VisibleHulls = Character.GetVisibleHulls(); } objectiveManager.UpdateObjectives(deltaTime); if (sortTimer > 0.0f) { sortTimer -= deltaTime; } else { objectiveManager.SortObjectives(); sortTimer = sortObjectiveInterval; } if (reactTimer > 0.0f) { reactTimer -= deltaTime; } else { if (Character.CurrentHull != null) { VisibleHulls.ForEach(h => PropagateHullSafety(Character, h)); } if (Character.SpeechImpediment < 100.0f) { ReportProblems(); UpdateSpeaking(); } reactTimer = reactionTime * Rand.Range(0.75f, 1.25f); } if (objectiveManager.CurrentObjective == null) { return; } objectiveManager.DoCurrentObjective(deltaTime); bool run = objectiveManager.CurrentObjective.ForceRun || objectiveManager.GetCurrentPriority() > AIObjectiveManager.RunPriority; if (ObjectiveManager.CurrentObjective is AIObjectiveGoTo goTo && goTo.Target != null) { if (Character.CurrentHull == null) { run = Vector2.DistanceSquared(Character.WorldPosition, goTo.Target.WorldPosition) > 300 * 300; } else { float yDiff = goTo.Target.WorldPosition.Y - Character.WorldPosition.Y; if (Math.Abs(yDiff) > 100) { run = true; } else { float xDiff = goTo.Target.WorldPosition.X - Character.WorldPosition.X; run = Math.Abs(xDiff) > 300; } } } if (run) { run = !AnimController.Crouching && !AnimController.IsMovingBackwards; } float currentSpeed = Character.AnimController.GetCurrentSpeed(run); steeringManager.Update(currentSpeed); bool ignorePlatforms = Character.AnimController.TargetMovement.Y < -0.5f && (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X)); if (steeringManager == insideSteering) { var currPath = PathSteering.CurrentPath; if (currPath != null && currPath.CurrentNode != null) { if (currPath.CurrentNode.SimPosition.Y < Character.AnimController.GetColliderBottom().Y) { // Don't allow to jump from too high. The formula might require tweaking. float allowedJumpHeight = Character.AnimController.ImpactTolerance / 2; float height = Math.Abs(currPath.CurrentNode.SimPosition.Y - Character.SimPosition.Y); ignorePlatforms = height < allowedJumpHeight; } } if (Character.IsClimbing && PathSteering.IsNextLadderSameAsCurrent) { Character.AnimController.TargetMovement = new Vector2(0.0f, Math.Sign(Character.AnimController.TargetMovement.Y)); } } Character.AnimController.IgnorePlatforms = ignorePlatforms; Vector2 targetMovement = AnimController.TargetMovement; if (!Character.AnimController.InWater) { targetMovement = new Vector2(Character.AnimController.TargetMovement.X, MathHelper.Clamp(Character.AnimController.TargetMovement.Y, -1.0f, 1.0f)); } float maxSpeed = Character.ApplyTemporarySpeedLimits(currentSpeed); targetMovement.X = MathHelper.Clamp(targetMovement.X, -maxSpeed, maxSpeed); targetMovement.Y = MathHelper.Clamp(targetMovement.Y, -maxSpeed, maxSpeed); //apply speed multiplier if // a. it's boosting the movement speed and the character is trying to move fast (= running) // b. it's a debuff that decreases movement speed float speedMultiplier = Character.SpeedMultiplier; if (run || speedMultiplier <= 0.0f) { targetMovement *= speedMultiplier; } Character.ResetSpeedMultiplier(); // Reset, items will set the value before the next update Character.AnimController.TargetMovement = targetMovement; if (!Character.LockHands) { DropUnnecessaryItems(); } if (Character.IsKeyDown(InputType.Aim)) { var cursorDiffX = Character.CursorPosition.X - Character.Position.X; if (cursorDiffX > 10.0f) { Character.AnimController.TargetDir = Direction.Right; } else if (cursorDiffX < -10.0f) { Character.AnimController.TargetDir = Direction.Left; } if (Character.SelectedConstruction != null) { Character.SelectedConstruction.SecondaryUse(deltaTime, Character); } } else if (Math.Abs(Character.AnimController.TargetMovement.X) > 0.1f && !Character.AnimController.InWater) { Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left; } }
public override void Update(float deltaTime) { if (DisableCrewAI || Character.IsUnconscious) { return; } if (Character.Submarine != null || SelectedAiTarget?.Entity?.Submarine != null) { if (steeringManager != insideSteering) { insideSteering.Reset(); } steeringManager = insideSteering; } else { if (steeringManager != outsideSteering) { outsideSteering.Reset(); } steeringManager = outsideSteering; } AnimController.Crouching = shouldCrouch; CheckCrouching(deltaTime); Character.ClearInputs(); objectiveManager.UpdateObjectives(deltaTime); if (updateObjectiveTimer > 0.0f) { updateObjectiveTimer -= deltaTime; } else { objectiveManager.SortObjectives(); updateObjectiveTimer = UpdateObjectiveInterval; } if (Character.SpeechImpediment < 100.0f) { ReportProblems(); UpdateSpeaking(); } objectiveManager.DoCurrentObjective(deltaTime); bool run = objectiveManager.GetCurrentPriority() > AIObjectiveManager.OrderPriority; if (ObjectiveManager.CurrentObjective is AIObjectiveGoTo goTo && goTo.Target != null) { if (Vector2.DistanceSquared(Character.SimPosition, goTo.Target.SimPosition) > 3 * 3) { run = true; } } if (!run) { run = objectiveManager.CurrentObjective.ForceRun; } if (run) { run = !AnimController.Crouching && !AnimController.IsMovingBackwards; } float currentSpeed = Character.AnimController.GetCurrentSpeed(run); steeringManager.Update(currentSpeed); bool ignorePlatforms = Character.AnimController.TargetMovement.Y < -0.5f && (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X)); if (steeringManager == insideSteering) { var currPath = PathSteering.CurrentPath; if (currPath != null && currPath.CurrentNode != null) { if (currPath.CurrentNode.SimPosition.Y < Character.AnimController.GetColliderBottom().Y) { ignorePlatforms = true; } } if (Character.IsClimbing && PathSteering.InLadders && PathSteering.IsNextLadderSameAsCurrent) { Character.AnimController.TargetMovement = new Vector2(0.0f, Math.Sign(Character.AnimController.TargetMovement.Y)); } } Character.AnimController.IgnorePlatforms = ignorePlatforms; Vector2 targetMovement = AnimController.TargetMovement; if (!Character.AnimController.InWater) { targetMovement = new Vector2(Character.AnimController.TargetMovement.X, MathHelper.Clamp(Character.AnimController.TargetMovement.Y, -1.0f, 1.0f)); } float maxSpeed = Character.ApplyTemporarySpeedLimits(currentSpeed); targetMovement.X = MathHelper.Clamp(targetMovement.X, -maxSpeed, maxSpeed); targetMovement.Y = MathHelper.Clamp(targetMovement.Y, -maxSpeed, maxSpeed); //apply speed multiplier if // a. it's boosting the movement speed and the character is trying to move fast (= running) // b. it's a debuff that decreases movement speed float speedMultiplier = Character.SpeedMultiplier; if (run || speedMultiplier <= 0.0f) { targetMovement *= speedMultiplier; } Character.ResetSpeedMultiplier(); // Reset, items will set the value before the next update Character.AnimController.TargetMovement = targetMovement; if (!NeedsDivingGear(Character.CurrentHull)) { bool oxygenLow = Character.OxygenAvailable < CharacterHealth.LowOxygenThreshold; bool highPressure = Character.CurrentHull == null || Character.CurrentHull.LethalPressure > 0 && Character.PressureProtection <= 0; bool shouldKeepTheGearOn = objectiveManager.CurrentObjective.KeepDivingGearOn; bool removeDivingSuit = (oxygenLow && !highPressure) || (!shouldKeepTheGearOn && Character.CurrentHull.WaterPercentage < 1 && !Character.IsClimbing && steeringManager == insideSteering && !PathSteering.InStairs); if (removeDivingSuit) { var divingSuit = Character.Inventory.FindItemByIdentifier("divingsuit") ?? Character.Inventory.FindItemByTag("divingsuit"); if (divingSuit != null) { // TODO: take the item where it was taken from? divingSuit.Drop(Character); } } bool takeMaskOff = oxygenLow || (!shouldKeepTheGearOn && Character.CurrentHull.WaterPercentage < 20); if (takeMaskOff) { var mask = Character.Inventory.FindItemByIdentifier("divingmask"); if (mask != null) { // Try to put the mask in an Any slot, and drop it if that fails if (!mask.AllowedSlots.Contains(InvSlotType.Any) || !Character.Inventory.TryPutItem(mask, Character, new List <InvSlotType>() { InvSlotType.Any })) { mask.Drop(Character); } } } } if (!(ObjectiveManager.CurrentOrder is AIObjectiveExtinguishFires) && !(ObjectiveManager.CurrentObjective is AIObjectiveExtinguishFire)) { var extinguisherItem = Character.Inventory.FindItemByIdentifier("extinguisher") ?? Character.Inventory.FindItemByTag("extinguisher"); if (extinguisherItem != null && Character.HasEquippedItem(extinguisherItem)) { // TODO: take the item where it was taken from? extinguisherItem.Drop(Character); } } if (Character.IsKeyDown(InputType.Aim)) { var cursorDiffX = Character.CursorPosition.X - Character.Position.X; if (cursorDiffX > 10.0f) { Character.AnimController.TargetDir = Direction.Right; } else if (cursorDiffX < -10.0f) { Character.AnimController.TargetDir = Direction.Left; } if (Character.SelectedConstruction != null) { Character.SelectedConstruction.SecondaryUse(deltaTime, Character); } } else if (Math.Abs(Character.AnimController.TargetMovement.X) > 0.1f && !Character.AnimController.InWater) { Character.AnimController.TargetDir = Character.AnimController.TargetMovement.X > 0.0f ? Direction.Right : Direction.Left; } if (Character.CurrentHull != null) { PropagateHullSafety(Character, Character.CurrentHull); } }