public override void Reset() { base.Reset(); getWeldingTool = null; refuelObjective = null; gotoObjective = null; operateObjective = null; }
public override bool IsDuplicate(AIObjective otherObjective) { AIObjectiveOperateItem operateItem = otherObjective as AIObjectiveOperateItem; if (operateItem == null) { return(false); } return(operateItem.component == component); }
public AIObjective CreateObjective(Order order, string option, Character orderGiver, float priorityModifier = 1) { if (order == null) { return(null); } AIObjective newObjective; switch (order.AITag.ToLowerInvariant()) { case "follow": if (orderGiver == null) { return(null); } newObjective = new AIObjectiveGoTo(orderGiver, character, this, repeat: true, priorityModifier: priorityModifier) { CloseEnough = 100, AllowGoingOutside = true, IgnoreIfTargetDead = true, followControlledCharacter = orderGiver == character, mimic = true }; break; case "wait": newObjective = new AIObjectiveGoTo(character, character, this, repeat: true, priorityModifier: priorityModifier) { AllowGoingOutside = true }; break; case "fixleaks": newObjective = new AIObjectiveFixLeaks(character, this, priorityModifier); break; case "chargebatteries": newObjective = new AIObjectiveChargeBatteries(character, this, option, priorityModifier); break; case "rescue": newObjective = new AIObjectiveRescueAll(character, this, priorityModifier); break; case "repairsystems": newObjective = new AIObjectiveRepairItems(character, this, priorityModifier) { RequireAdequateSkills = option == "jobspecific" }; break; case "pumpwater": newObjective = new AIObjectivePumpWater(character, this, option, priorityModifier: priorityModifier); break; case "extinguishfires": newObjective = new AIObjectiveExtinguishFires(character, this, priorityModifier); break; case "fightintruders": newObjective = new AIObjectiveFightIntruders(character, this, priorityModifier); break; case "steer": var steering = (order?.TargetEntity as Item)?.GetComponent <Steering>(); if (steering != null) { steering.PosToMaintain = steering.Item.Submarine?.WorldPosition; } if (order.TargetItemComponent == null) { return(null); } newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, priorityModifier: priorityModifier) { IsLoop = true }; break; default: if (order.TargetItemComponent == null) { return(null); } newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, priorityModifier: priorityModifier) { IsLoop = true }; break; } return(newObjective); }
public AIObjective CreateObjective(Order order, string option, Character orderGiver, bool isAutonomous, float priorityModifier = 1) { if (order == null || order.Identifier == "dismissed") { return(null); } AIObjective newObjective; switch (order.Identifier.ToLowerInvariant()) { case "follow": if (orderGiver == null) { return(null); } newObjective = new AIObjectiveGoTo(orderGiver, character, this, repeat: true, priorityModifier: priorityModifier) { CloseEnough = Rand.Range(90, 100) + Rand.Range(50, 70) * Math.Min(HumanAIController.CountCrew(c => c.ObjectiveManager.CurrentOrder is AIObjectiveGoTo gotoOrder && gotoOrder.Target == orderGiver, onlyBots: true), 4), extraDistanceOutsideSub = 100, extraDistanceWhileSwimming = 100, AllowGoingOutside = true, IgnoreIfTargetDead = true, followControlledCharacter = true, mimic = true, DialogueIdentifier = "dialogcannotreachplace" }; break; case "wait": newObjective = new AIObjectiveGoTo(order.TargetSpatialEntity ?? character, character, this, repeat: true, priorityModifier: priorityModifier) { AllowGoingOutside = character.Submarine == null || (order.TargetSpatialEntity != null && character.Submarine != order.TargetSpatialEntity.Submarine) }; break; case "fixleaks": newObjective = new AIObjectiveFixLeaks(character, this, priorityModifier: priorityModifier, prioritizedHull: order.TargetEntity as Hull); break; case "chargebatteries": newObjective = new AIObjectiveChargeBatteries(character, this, option, priorityModifier); break; case "rescue": newObjective = new AIObjectiveRescueAll(character, this, priorityModifier); break; case "repairsystems": case "repairmechanical": case "repairelectrical": newObjective = new AIObjectiveRepairItems(character, this, priorityModifier: priorityModifier, prioritizedItem: order.TargetEntity as Item) { RelevantSkill = order.AppropriateSkill, RequireAdequateSkills = isAutonomous }; break; case "pumpwater": if (order.TargetItemComponent is Pump targetPump) { if (!order.TargetItemComponent.Item.IsInteractable(character)) { return(null); } newObjective = new AIObjectiveOperateItem(targetPump, character, this, option, false, priorityModifier: priorityModifier) { IsLoop = true, Override = orderGiver != null && orderGiver.IsPlayer }; // ItemComponent.AIOperate() returns false by default -> We'd have to set IsLoop = false and implement a custom override of AIOperate for the Pump.cs, // if we want that the bot just switches the pump on/off and continues doing something else. // If we want that the bot does the objective and then forgets about it, I think we could do the same plus dismiss when the bot is done. } else { newObjective = new AIObjectivePumpWater(character, this, option, priorityModifier: priorityModifier); } break; case "extinguishfires": newObjective = new AIObjectiveExtinguishFires(character, this, priorityModifier); break; case "fightintruders": newObjective = new AIObjectiveFightIntruders(character, this, priorityModifier); break; case "steer": var steering = (order?.TargetEntity as Item)?.GetComponent <Steering>(); if (steering != null) { steering.PosToMaintain = steering.Item.Submarine?.WorldPosition; } if (order.TargetItemComponent == null) { return(null); } if (!order.TargetItemComponent.Item.IsInteractable(character)) { return(null); } newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, controller: order.ConnectedController, priorityModifier: priorityModifier) { IsLoop = true, // Don't override unless it's an order by a player Override = orderGiver != null && orderGiver.IsPlayer }; break; case "setchargepct": newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, false, priorityModifier: priorityModifier) { IsLoop = false, Override = !character.IsDismissed, completionCondition = () => { if (float.TryParse(option, out float pct)) { var targetRatio = Math.Clamp(pct, 0f, 1f); var currentRatio = (order.TargetItemComponent as PowerContainer).RechargeRatio; return(Math.Abs(targetRatio - currentRatio) < 0.05f); } return(true); } }; break; case "getitem": newObjective = new AIObjectiveGetItem(character, order.TargetEntity as Item ?? order.TargetItemComponent?.Item, this, false, priorityModifier: priorityModifier) { MustBeSpecificItem = true }; break; case "cleanupitems": if (order.TargetEntity is Item targetItem) { if (targetItem.HasTag("allowcleanup") && targetItem.ParentInventory == null && targetItem.OwnInventory != null) { // Target all items inside the container newObjective = new AIObjectiveCleanupItems(character, this, targetItem.OwnInventory.AllItems, priorityModifier); } else { newObjective = new AIObjectiveCleanupItems(character, this, targetItem, priorityModifier); } } else { newObjective = new AIObjectiveCleanupItems(character, this, priorityModifier: priorityModifier); } break; default: if (order.TargetItemComponent == null) { return(null); } if (!order.TargetItemComponent.Item.IsInteractable(character)) { return(null); } newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, controller: order.ConnectedController, priorityModifier: priorityModifier) { IsLoop = true, // Don't override unless it's an order by a player Override = orderGiver != null && orderGiver.IsPlayer }; if (newObjective.Abandon) { return(null); } break; } return(newObjective); }
public AIObjective CreateObjective(Order order, string option, Character orderGiver, bool isAutonomous, float priorityModifier = 1) { if (order == null) { return(null); } AIObjective newObjective; switch (order.Identifier.ToLowerInvariant()) { case "follow": if (orderGiver == null) { return(null); } newObjective = new AIObjectiveGoTo(orderGiver, character, this, repeat: true, priorityModifier: priorityModifier) { CloseEnough = 100, AllowGoingOutside = true, IgnoreIfTargetDead = true, followControlledCharacter = orderGiver == character, mimic = true, DialogueIdentifier = "dialogcannotreachplace" }; break; case "wait": newObjective = new AIObjectiveGoTo(order.TargetEntity ?? character, character, this, repeat: true, priorityModifier: priorityModifier) { AllowGoingOutside = character.CurrentHull == null }; break; case "fixleaks": newObjective = new AIObjectiveFixLeaks(character, this, priorityModifier: priorityModifier, prioritizedHull: order.TargetEntity as Hull); break; case "chargebatteries": newObjective = new AIObjectiveChargeBatteries(character, this, option, priorityModifier); break; case "rescue": newObjective = new AIObjectiveRescueAll(character, this, priorityModifier); break; case "repairsystems": case "repairmechanical": case "repairelectrical": newObjective = new AIObjectiveRepairItems(character, this, priorityModifier: priorityModifier, prioritizedItem: order.TargetEntity as Item) { RelevantSkill = order.AppropriateSkill, RequireAdequateSkills = isAutonomous }; break; case "pumpwater": if (order.TargetItemComponent is Pump targetPump) { if (order.TargetItemComponent.Item.NonInteractable) { return(null); } newObjective = new AIObjectiveOperateItem(targetPump, character, this, option, false, priorityModifier: priorityModifier) { IsLoop = true, Override = orderGiver != null && orderGiver.IsPlayer }; // ItemComponent.AIOperate() returns false by default -> We'd have to set IsLoop = false and implement a custom override of AIOperate for the Pump.cs, // if we want that the bot just switches the pump on/off and continues doing something else. // If we want that the bot does the objective and then forgets about it, I think we could do the same plus dismiss when the bot is done. } else { newObjective = new AIObjectivePumpWater(character, this, option, priorityModifier: priorityModifier); } break; case "extinguishfires": newObjective = new AIObjectiveExtinguishFires(character, this, priorityModifier); break; case "fightintruders": newObjective = new AIObjectiveFightIntruders(character, this, priorityModifier); break; case "steer": var steering = (order?.TargetEntity as Item)?.GetComponent <Steering>(); if (steering != null) { steering.PosToMaintain = steering.Item.Submarine?.WorldPosition; } if (order.TargetItemComponent == null) { return(null); } if (order.TargetItemComponent.Item.NonInteractable) { return(null); } newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, controller: order.ConnectedController, priorityModifier: priorityModifier) { IsLoop = true, // Don't override unless it's an order by a player Override = orderGiver != null && orderGiver.IsPlayer }; break; default: if (order.TargetItemComponent == null) { return(null); } if (order.TargetItemComponent.Item.NonInteractable) { return(null); } newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, controller: order.ConnectedController, priorityModifier: priorityModifier) { IsLoop = true, // Don't override unless it's an order by a player Override = orderGiver != null && orderGiver.IsPlayer }; if (newObjective.Abandon) { return(null); } break; } return(newObjective); }
public void SetOrder(Order order, string option, Character orderGiver) { CurrentOrder = null; if (order == null) { return; } switch (order.AITag.ToLowerInvariant()) { case "follow": CurrentOrder = new AIObjectiveGoTo(orderGiver, character, true) { CloseEnough = 1.5f, AllowGoingOutside = true, IgnoreIfTargetDead = true, FollowControlledCharacter = orderGiver == character }; break; case "wait": CurrentOrder = new AIObjectiveGoTo(character, character, true) { AllowGoingOutside = true }; break; case "fixleaks": CurrentOrder = new AIObjectiveFixLeaks(character); break; case "chargebatteries": CurrentOrder = new AIObjectiveChargeBatteries(character, option); break; case "rescue": CurrentOrder = new AIObjectiveRescueAll(character); break; case "repairsystems": CurrentOrder = new AIObjectiveRepairItems(character) { RequireAdequateSkills = option != "all" }; break; case "pumpwater": CurrentOrder = new AIObjectivePumpWater(character, option); break; case "extinguishfires": CurrentOrder = new AIObjectiveExtinguishFires(character); break; case "steer": var steering = (order?.TargetEntity as Item)?.GetComponent <Steering>(); if (steering != null) { steering.PosToMaintain = steering.Item.Submarine?.WorldPosition; } if (order.TargetItemComponent == null) { return; } CurrentOrder = new AIObjectiveOperateItem(order.TargetItemComponent, character, option, false, null, order.UseController); break; default: if (order.TargetItemComponent == null) { return; } CurrentOrder = new AIObjectiveOperateItem(order.TargetItemComponent, character, option, false, null, order.UseController); break; } }
protected override void Act(float deltaTime) { if (!leak.IsRoomToRoom) { if (findDivingGear == null) { findDivingGear = new AIObjectiveFindDivingGear(character, true); AddSubObjective(findDivingGear); } else if (!findDivingGear.CanBeCompleted) { abandon = true; return; } } var weldingTool = character.Inventory.FindItemByTag("weldingtool"); if (weldingTool == null) { AddSubObjective(new AIObjectiveGetItem(character, "weldingtool", true)); return; } else { var containedItems = weldingTool.ContainedItems; if (containedItems == null) { return; } var fuelTank = containedItems.FirstOrDefault(i => i.HasTag("weldingfueltank") && i.Condition > 0.0f); if (fuelTank == null) { AddSubObjective(new AIObjectiveContainItem(character, "weldingfueltank", weldingTool.GetComponent <ItemContainer>())); return; } } var repairTool = weldingTool.GetComponent <RepairTool>(); if (repairTool == null) { return; } Vector2 gapDiff = leak.WorldPosition - character.WorldPosition; // TODO: use the collider size/reach? if (!character.AnimController.InWater && Math.Abs(gapDiff.X) < 100 && gapDiff.Y < 0.0f && gapDiff.Y > -150) { HumanAIController.AnimController.Crouching = true; } //float reach = HumanAIController.AnimController.ArmLength + ConvertUnits.ToSimUnits(repairTool.Range); float reach = ConvertUnits.ToSimUnits(repairTool.Range); bool cannotReach = ConvertUnits.ToSimUnits(gapDiff.Length()) > reach; if (cannotReach) { if (gotoObjective != null) { // Check if the objective is already removed -> completed/impossible if (!subObjectives.Contains(gotoObjective)) { if (!gotoObjective.CanBeCompleted) { abandon = true; } gotoObjective = null; return; } } else { gotoObjective = new AIObjectiveGoTo(ConvertUnits.ToSimUnits(GetStandPosition()), character) { CloseEnough = reach }; if (!subObjectives.Contains(gotoObjective)) { AddSubObjective(gotoObjective); } } } if (gotoObjective == null || gotoObjective.IsCompleted()) { if (operateObjective == null) { operateObjective = new AIObjectiveOperateItem(repairTool, character, "", true, leak); AddSubObjective(operateObjective); } else if (!subObjectives.Contains(operateObjective)) { operateObjective = null; } } }
public AIObjective CreateObjective(Order order, string option, Character orderGiver, float priorityModifier = 1) { if (order == null) { return(null); } AIObjective newObjective; switch (order.Identifier.ToLowerInvariant()) { case "follow": if (orderGiver == null) { return(null); } newObjective = new AIObjectiveGoTo(orderGiver, character, this, repeat: true, priorityModifier: priorityModifier) { CloseEnough = 100, AllowGoingOutside = true, IgnoreIfTargetDead = true, followControlledCharacter = orderGiver == character, mimic = true, DialogueIdentifier = "dialogcannotreachplace" }; break; case "wait": newObjective = new AIObjectiveGoTo(order.TargetEntity ?? character, character, this, repeat: true, priorityModifier: priorityModifier) { AllowGoingOutside = character.CurrentHull == null }; break; case "fixleaks": newObjective = new AIObjectiveFixLeaks(character, this, priorityModifier: priorityModifier, prioritizedHull: order.TargetEntity as Hull); break; case "chargebatteries": newObjective = new AIObjectiveChargeBatteries(character, this, option, priorityModifier); break; case "rescue": newObjective = new AIObjectiveRescueAll(character, this, priorityModifier); break; case "repairsystems": case "repairmechanical": case "repairelectrical": newObjective = new AIObjectiveRepairItems(character, this, priorityModifier: priorityModifier, prioritizedItem: order.TargetEntity as Item) { RelevantSkill = order.AppropriateSkill, RequireAdequateSkills = option == "jobspecific" }; break; case "pumpwater": if (order.TargetItemComponent is Pump targetPump) { newObjective = new AIObjectiveOperateItem(targetPump, character, this, option, false, priorityModifier: priorityModifier); // newObjective.Completed += DismissSelf; } else { newObjective = new AIObjectivePumpWater(character, this, option, priorityModifier: priorityModifier); } break; case "extinguishfires": newObjective = new AIObjectiveExtinguishFires(character, this, priorityModifier); break; case "fightintruders": newObjective = new AIObjectiveFightIntruders(character, this, priorityModifier); break; case "steer": var steering = (order?.TargetEntity as Item)?.GetComponent <Steering>(); if (steering != null) { steering.PosToMaintain = steering.Item.Submarine?.WorldPosition; } if (order.TargetItemComponent == null) { return(null); } newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, priorityModifier: priorityModifier) { IsLoop = true, // Don't override unless it's an order by a player Override = orderGiver != null && orderGiver.IsPlayer }; break; default: if (order.TargetItemComponent == null) { return(null); } newObjective = new AIObjectiveOperateItem(order.TargetItemComponent, character, this, option, requireEquip: false, useController: order.UseController, priorityModifier: priorityModifier) { IsLoop = true, // Don't override unless it's an order by a player Override = orderGiver != null && orderGiver.IsPlayer }; break; } return(newObjective); }