private void Move(float deltaTime) { // Retreat to safety // TODO: aggressive behaviour, chasing? if (retreatTarget == null || (retreatObjective != null && !retreatObjective.CanBeCompleted)) { retreatTarget = HumanAIController.ObjectiveManager.GetObjective <AIObjectiveFindSafety>().FindBestHull(); } if (retreatTarget != null) { if (retreatObjective == null || retreatObjective.Target != retreatTarget) { retreatObjective = new AIObjectiveGoTo(retreatTarget, character, false, true); } retreatObjective.TryComplete(deltaTime); } }
private void Retreat(float deltaTime) { if (retreatTarget == null || (retreatObjective != null && !retreatObjective.CanBeCompleted)) { retreatTarget = HumanAIController.ObjectiveManager.GetObjective <AIObjectiveFindSafety>().FindBestHull(new List <Hull>() { character.CurrentHull }); } if (retreatTarget != null) { if (retreatObjective == null || retreatObjective.Target != retreatTarget) { retreatObjective = new AIObjectiveGoTo(retreatTarget, character, false, true); } retreatObjective.TryComplete(deltaTime); } }
protected override void Act(float deltaTime) { var currentHull = character.AnimController.CurrentHull; currenthullSafety = OverrideCurrentHullSafety == null? GetHullSafety(currentHull, character) : (float)OverrideCurrentHullSafety; if (NeedsDivingGear()) { if (!FindDivingGear(deltaTime)) { return; } } if (searchHullTimer > 0.0f) { searchHullTimer -= deltaTime; } else { var bestHull = FindBestHull(); if (bestHull != null) { goToObjective = new AIObjectiveGoTo(bestHull, character); } searchHullTimer = SearchHullInterval; } if (goToObjective != null) { var pathSteering = character.AIController.SteeringManager as IndoorsSteeringManager; if (pathSteering != null && pathSteering.CurrentPath != null && pathSteering.CurrentPath.Unreachable && !unreachable.Contains(goToObjective.Target)) { unreachable.Add(goToObjective.Target as Hull); } goToObjective.TryComplete(deltaTime); } }
protected override void Act(float deltaTime) { var currentHull = character.AnimController.CurrentHull; if (HumanAIController.NeedsDivingGear(currentHull) && divingGearObjective == null) { bool needsDivingSuit = currentHull == null || currentHull.WaterPercentage > 90; bool hasEquipment = needsDivingSuit ? HumanAIController.HasDivingSuit(character) : HumanAIController.HasDivingGear(character); if (!hasEquipment) { divingGearObjective = new AIObjectiveFindDivingGear(character, needsDivingSuit); } } if (divingGearObjective != null) { divingGearObjective.TryComplete(deltaTime); if (divingGearObjective.IsCompleted()) { divingGearObjective = null; Priority = 0; } else if (divingGearObjective.CanBeCompleted) { // If diving gear objective is active and can be completed, wait for it to complete. return; } else { divingGearObjective = null; // Reset the timer so that we get a safe hull target. searchHullTimer = 0; } } if (unreachableClearTimer > 0) { unreachableClearTimer -= deltaTime; } else { unreachableClearTimer = clearUnreachableInterval; unreachable.Clear(); } if (searchHullTimer > 0.0f) { searchHullTimer -= deltaTime; } else if (currenthullSafety < HumanAIController.HULL_SAFETY_THRESHOLD) { var bestHull = FindBestHull(); if (bestHull != null && bestHull != currentHull) { if (goToObjective != null) { if (goToObjective.Target != bestHull) { // If we need diving gear, we should already have it, if possible. goToObjective = new AIObjectiveGoTo(bestHull, character, getDivingGearIfNeeded: false) { AllowGoingOutside = HumanAIController.HasDivingSuit(character) }; } } else { goToObjective = new AIObjectiveGoTo(bestHull, character, getDivingGearIfNeeded: false) { AllowGoingOutside = HumanAIController.HasDivingSuit(character) }; } } searchHullTimer = SearchHullInterval; } if (goToObjective != null) { goToObjective.TryComplete(deltaTime); if (!goToObjective.CanBeCompleted) { if (!unreachable.Contains(goToObjective.Target)) { unreachable.Add(goToObjective.Target as Hull); } goToObjective = null; HumanAIController.ObjectiveManager.GetObjective <AIObjectiveIdle>().Wander(deltaTime); //SteeringManager.SteeringWander(); } } else if (currentHull != null) { //goto objective doesn't exist (a safe hull not found, or a path to a safe hull not found) // -> attempt to manually steer away from hazards Vector2 escapeVel = Vector2.Zero; foreach (FireSource fireSource in currentHull.FireSources) { Vector2 dir = character.Position - fireSource.Position; float distMultiplier = MathHelper.Clamp(100.0f / Vector2.Distance(fireSource.Position, character.Position), 0.1f, 10.0f); escapeVel += new Vector2(Math.Sign(dir.X) * distMultiplier, !character.IsClimbing ? 0 : Math.Sign(dir.Y) * distMultiplier); } foreach (Character enemy in Character.CharacterList) { //don't run from friendly NPCs if (enemy.TeamID == Character.TeamType.FriendlyNPC) { continue; } //friendly NPCs don't run away from anything but characters controlled by EnemyAIController (= monsters) if (character.TeamID == Character.TeamType.FriendlyNPC && !(enemy.AIController is EnemyAIController)) { continue; } if (enemy.CurrentHull == currentHull && !enemy.IsDead && !enemy.IsUnconscious && (enemy.AIController is EnemyAIController || enemy.TeamID != character.TeamID)) { Vector2 dir = character.Position - enemy.Position; float distMultiplier = MathHelper.Clamp(100.0f / Vector2.Distance(enemy.Position, character.Position), 0.1f, 10.0f); escapeVel += new Vector2(Math.Sign(dir.X) * distMultiplier, !character.IsClimbing ? 0 : Math.Sign(dir.Y) * distMultiplier); } } if (escapeVel != Vector2.Zero) { //only move if we haven't reached the edge of the room if ((escapeVel.X < 0 && character.Position.X > currentHull.Rect.X + 50) || (escapeVel.X > 0 && character.Position.X < currentHull.Rect.Right - 50)) { character.AIController.SteeringManager.SteeringManual(deltaTime, escapeVel); } else { character.AnimController.TargetDir = escapeVel.X < 0.0f ? Direction.Right : Direction.Left; character.AIController.SteeringManager.Reset(); } } else { character.AIController.SteeringManager.Reset(); } } }
protected override void Act(float deltaTime) { FindTargetItem(); if (targetItem == null || moveToTarget == null) { HumanAIController.ObjectiveManager.GetObjective <AIObjectiveIdle>().Wander(deltaTime); //SteeringManager.SteeringWander(); return; } if (moveToTarget.CurrentHull == character.CurrentHull && Vector2.DistanceSquared(character.Position, moveToTarget.Position) < MathUtils.Pow(targetItem.InteractDistance * 2, 2)) { int targetSlot = -1; if (equip) { var pickable = targetItem.GetComponent <Pickable>(); if (pickable == null) { canBeCompleted = false; return; } //check if all the slots required by the item are free foreach (InvSlotType slots in pickable.AllowedSlots) { if (slots.HasFlag(InvSlotType.Any)) { continue; } for (int i = 0; i < character.Inventory.Items.Length; i++) { //slot not needed by the item, continue if (!slots.HasFlag(character.Inventory.SlotTypes[i])) { continue; } targetSlot = i; //slot free, continue if (character.Inventory.Items[i] == null) { continue; } //try to move the existing item to LimbSlot.Any and continue if successful if (character.Inventory.TryPutItem(character.Inventory.Items[i], character, new List <InvSlotType>() { InvSlotType.Any })) { continue; } //if everything else fails, simply drop the existing item character.Inventory.Items[i].Drop(character); } } } targetItem.TryInteract(character, false, true); if (targetSlot > -1 && !character.HasEquippedItem(targetItem)) { character.Inventory.TryPutItem(targetItem, targetSlot, false, false, character); } } else { if (goToObjective == null || moveToTarget != goToObjective.Target) { //check if we're already looking for a diving gear bool gettingDivingGear = (targetItem != null && targetItem.Prefab.Identifier == "divingsuit" || targetItem.HasTag("diving")) || (itemIdentifiers != null && (itemIdentifiers.Contains("diving") || itemIdentifiers.Contains("divingsuit"))); //don't attempt to get diving gear to reach the destination if the item we're trying to get is diving gear goToObjective = new AIObjectiveGoTo(moveToTarget, character, false, !gettingDivingGear); } goToObjective.TryComplete(deltaTime); if (!goToObjective.CanBeCompleted) { targetItem = null; moveToTarget = null; ignoredItems.Add(targetItem); } } }
protected override void Act(float deltaTime) { FindTargetItem(); if (targetItem == null || moveToTarget == null) { character?.AIController?.SteeringManager?.Reset(); return; } if (Vector2.Distance(character.Position, moveToTarget.Position) < targetItem.InteractDistance * 2.0f) { int targetSlot = -1; if (equip) { var pickable = targetItem.GetComponent <Pickable>(); if (pickable == null) { canBeCompleted = false; return; } //check if all the slots required by the item are free foreach (InvSlotType slots in pickable.AllowedSlots) { if (slots.HasFlag(InvSlotType.Any)) { continue; } for (int i = 0; i < character.Inventory.Items.Length; i++) { //slot not needed by the item, continue if (!slots.HasFlag(CharacterInventory.limbSlots[i])) { continue; } targetSlot = i; //slot free, continue if (character.Inventory.Items[i] == null) { continue; } //try to move the existing item to LimbSlot.Any and continue if successful if (character.Inventory.TryPutItem(character.Inventory.Items[i], character, new List <InvSlotType>() { InvSlotType.Any })) { continue; } //if everything else fails, simply drop the existing item character.Inventory.Items[i].Drop(); } } } targetItem.TryInteract(character, false, true); if (targetSlot > -1 && character.Inventory.IsInLimbSlot(targetItem, InvSlotType.Any)) { character.Inventory.TryPutItem(targetItem, targetSlot, false, character); } } else { if (goToObjective == null || moveToTarget != goToObjective.Target) { //check if we're already looking for a diving gear bool gettingDivingGear = (targetItem != null && targetItem.Prefab.NameMatches("Diving Gear") || targetItem.HasTag("diving")) || (itemNames != null && (itemNames.Contains("diving") || itemNames.Contains("Diving Gear"))); //don't attempt to get diving gear to reach the destination if the item we're trying to get is diving gear goToObjective = new AIObjectiveGoTo(moveToTarget, character, false, !gettingDivingGear); } goToObjective.TryComplete(deltaTime); } }
protected override void Act(float deltaTime) { FindTargetItem(); if (targetItem == null || moveToTarget == null) { return; } if (Vector2.Distance(character.Position, moveToTarget.Position) < targetItem.PickDistance * 2.0f) { int targetSlot = -1; if (equip) { var pickable = targetItem.GetComponent <Pickable>(); if (pickable == null) { canBeCompleted = false; return; } //check if all the slots required by the item are free foreach (InvSlotType slots in pickable.AllowedSlots) { if (slots.HasFlag(InvSlotType.Any)) { continue; } for (int i = 0; i < character.Inventory.Items.Length; i++) { //slot not needed by the item, continue if (!slots.HasFlag(CharacterInventory.limbSlots[i])) { continue; } targetSlot = i; //slot free, continue if (character.Inventory.Items[i] == null) { continue; } //try to move the existing item to LimbSlot.Any and continue if successful if (character.Inventory.TryPutItem(character.Inventory.Items[i], new List <InvSlotType>() { InvSlotType.Any })) { continue; } //if everything else fails, simply drop the existing item character.Inventory.Items[i].Drop(); } } } targetItem.Pick(character, false, true); if (targetSlot > -1 && character.Inventory.IsInLimbSlot(targetItem, InvSlotType.Any)) { character.Inventory.TryPutItem(targetItem, targetSlot, false); } } else { if (goToObjective == null) { bool gettingDivingGear = itemName == "diving" || itemName == "Diving Gear"; goToObjective = new AIObjectiveGoTo(moveToTarget, character, false, !gettingDivingGear); } goToObjective.TryComplete(deltaTime); } }
protected override void Act(float deltaTime) { var extinguisherItem = character.Inventory.FindItemByIdentifier("extinguisher") ?? character.Inventory.FindItemByTag("extinguisher"); if (extinguisherItem == null || extinguisherItem.Condition <= 0.0f || !character.HasEquippedItem(extinguisherItem)) { if (getExtinguisherObjective == null) { character.Speak(TextManager.Get("DialogFindExtinguisher"), null, 2.0f, "findextinguisher", 30.0f); getExtinguisherObjective = new AIObjectiveGetItem(character, "extinguisher", true); } else { getExtinguisherObjective.TryComplete(deltaTime); } return; } var extinguisher = extinguisherItem.GetComponent <RepairTool>(); if (extinguisher == null) { DebugConsole.ThrowError("AIObjectiveExtinguishFire failed - the item \"" + extinguisherItem + "\" has no RepairTool component but is tagged as an extinguisher"); return; } foreach (FireSource fs in targetHull.FireSources) { bool inRange = fs.IsInDamageRange(character, MathHelper.Clamp(fs.DamageRange * 1.5f, extinguisher.Range * 0.5f, extinguisher.Range)); if (targetHull == character.CurrentHull && (inRange || useExtinquisherTimer > 0.0f)) { useExtinquisherTimer += deltaTime; if (useExtinquisherTimer > 2.0f) { useExtinquisherTimer = 0.0f; } character.CursorPosition = fs.Position; character.SetInput(InputType.Aim, false, true); if (!character.IsClimbing) { character.AIController.SteeringManager.Reset(); } extinguisher.Use(deltaTime, character); if (!targetHull.FireSources.Contains(fs)) { character.Speak(TextManager.Get("DialogPutOutFire").Replace("[roomname]", targetHull.Name), null, 0, "putoutfire", 10.0f); } return; } else { //go to the first firesource if (gotoObjective == null || !gotoObjective.CanBeCompleted || gotoObjective.IsCompleted()) { gotoObjective = new AIObjectiveGoTo(ConvertUnits.ToSimUnits(fs.Position), character); } else { gotoObjective.TryComplete(deltaTime); } break; } } }