Esempio n. 1
0
        protected override void Act(float deltaTime)
        {
            var weldingTool = character.Inventory.FindItem("Welding Tool");

            if (weldingTool == null)
            {
                AddSubObjective(new AIObjectiveGetItem(character, "Welding Tool", true));
                return;
            }
            else
            {
                var containedItems = weldingTool.ContainedItems;
                if (containedItems == null)
                {
                    return;
                }

                var fuelTank = Array.Find(containedItems, i => i.Prefab.NameMatches("Welding Fuel Tank") && i.Condition > 0.0f);

                if (fuelTank == null)
                {
                    AddSubObjective(new AIObjectiveContainItem(character, "Welding Fuel Tank", weldingTool.GetComponent <ItemContainer>()));
                    return;
                }
            }

            var repairTool = weldingTool.GetComponent <RepairTool>();

            if (repairTool == null)
            {
                return;
            }

            Vector2 standPosition = GetStandPosition();

            if (Vector2.DistanceSquared(character.WorldPosition, leak.WorldPosition) > 100.0f * 100.0f)
            {
                var gotoObjective = new AIObjectiveGoTo(ConvertUnits.ToSimUnits(standPosition), character);
                if (!gotoObjective.IsCompleted())
                {
                    AddSubObjective(gotoObjective);
                    return;
                }
            }

            AddSubObjective(new AIObjectiveOperateItem(repairTool, character, "", true, leak));
        }
Esempio n. 2
0
        protected override void Act(float deltaTime)
        {
            var  currentHull     = character.AnimController.CurrentHull;
            bool needsDivingGear = HumanAIController.NeedsDivingGear(currentHull);
            bool needsDivingSuit = needsDivingGear && (currentHull == null || currentHull.WaterPercentage > 90);
            bool needsEquipment  = false;

            if (needsDivingSuit)
            {
                needsEquipment = !HumanAIController.HasDivingSuit(character);
            }
            else if (needsDivingGear)
            {
                needsEquipment = !HumanAIController.HasDivingMask(character);
            }
            if (needsEquipment)
            {
                TryAddSubObjective(ref divingGearObjective,
                                   () => new AIObjectiveFindDivingGear(character, needsDivingSuit, objectiveManager),
                                   onAbandon: () => searchHullTimer = Math.Min(1, searchHullTimer));
            }
            else
            {
                if (divingGearObjective != null && divingGearObjective.IsCompleted())
                {
                    // Reset the devotion.
                    Priority            = 0;
                    divingGearObjective = null;
                }
                if (currenthullSafety < HumanAIController.HULL_SAFETY_THRESHOLD)
                {
                    searchHullTimer = Math.Min(1, searchHullTimer);
                }
                if (searchHullTimer > 0.0f)
                {
                    searchHullTimer -= deltaTime;
                }
                else
                {
                    searchHullTimer  = SearchHullInterval;
                    previousSafeHull = currentSafeHull;
                    currentSafeHull  = FindBestHull();
                    if (currentSafeHull == null)
                    {
                        currentSafeHull = previousSafeHull;
                    }
                    if (currentSafeHull != null && currentSafeHull != currentHull)
                    {
                        if (goToObjective?.Target != currentSafeHull)
                        {
                            goToObjective = null;
                        }
                        TryAddSubObjective(ref goToObjective,
                                           constructor: () => new AIObjectiveGoTo(currentSafeHull, character, objectiveManager, getDivingGearIfNeeded: true)
                        {
                            AllowGoingOutside = HumanAIController.HasDivingSuit(character)
                        },
                                           onAbandon: () => unreachable.Add(goToObjective.Target as Hull));
                    }
                    else
                    {
                        goToObjective = null;
                    }
                }
                if (goToObjective != null)
                {
                    if (goToObjective.IsCompleted())
                    {
                        objectiveManager.GetObjective <AIObjectiveIdle>()?.Wander(deltaTime);
                    }
                    Priority = 0;
                    return;
                }
                if (currentHull == null)
                {
                    return;
                }
                //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;
                // TODO: optimize
                foreach (FireSource fireSource in HumanAIController.VisibleHulls.SelectMany(h => h.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)
                {
                    if (enemy.IsDead || enemy.IsUnconscious || enemy.Removed || HumanAIController.IsFriendly(enemy))
                    {
                        continue;
                    }
                    if (HumanAIController.VisibleHulls.Contains(enemy.CurrentHull))
                    {
                        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)
                {
                    float left  = currentHull.Rect.X + 50;
                    float right = currentHull.Rect.Right - 50;
                    //only move if we haven't reached the edge of the room
                    if (escapeVel.X < 0 && character.Position.X > left || escapeVel.X > 0 && character.Position.X < right)
                    {
                        character.AIController.SteeringManager.SteeringManual(deltaTime, escapeVel);
                    }
                    else
                    {
                        character.AnimController.TargetDir = escapeVel.X < 0.0f ? Direction.Right : Direction.Left;
                        character.AIController.SteeringManager.Reset();
                    }
                }
                else
                {
                    Priority = 0;
                    objectiveManager.GetObjective <AIObjectiveIdle>()?.Wander(deltaTime);
                }
            }
        }
Esempio n. 3
0
        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;
                }
            }
        }
Esempio n. 4
0
 protected override void Act(float deltaTime)
 {
     if (goToObjective != null && !subObjectives.Contains(goToObjective))
     {
         if (!goToObjective.IsCompleted() && !goToObjective.CanBeCompleted)
         {
             abandon = true;
             character?.Speak(TextManager.Get("DialogCannotRepair").Replace("[itemname]", Item.Name), null, 0.0f, "cannotrepair", 10.0f);
         }
         goToObjective = null;
     }
     foreach (Repairable repairable in Item.Repairables)
     {
         if (!repairable.HasRequiredItems(character, false))
         {
             //make sure we have all the items required to fix the target item
             foreach (var kvp in repairable.requiredItems)
             {
                 foreach (RelatedItem requiredItem in kvp.Value)
                 {
                     AddSubObjective(new AIObjectiveGetItem(character, requiredItem.Identifiers, true));
                 }
             }
             return;
         }
     }
     if (character.CanInteractWith(Item))
     {
         if (repairTool == null)
         {
             FindRepairTool();
         }
         if (repairTool != null)
         {
             OperateRepairTool(deltaTime);
         }
         foreach (Repairable repairable in Item.Repairables)
         {
             if (repairable.CurrentFixer != null && repairable.CurrentFixer != character)
             {
                 // Someone else is repairing the target. Abandon the objective if the other is better at this then us.
                 abandon = repairable.DegreeOfSuccess(character) < repairable.DegreeOfSuccess(repairable.CurrentFixer);
             }
             if (!abandon)
             {
                 if (character.SelectedConstruction != Item)
                 {
                     Item.TryInteract(character, true, true);
                 }
                 if (previousCondition == -1)
                 {
                     previousCondition = Item.Condition;
                 }
                 else if (Item.Condition < previousCondition)
                 {
                     // If the current condition is less than the previous condition, we can't complete the task, so let's abandon it. The item is probably deteriorating at a greater speed than we can repair it.
                     abandon = true;
                     character?.Speak(TextManager.Get("DialogRepairFailed").Replace("[itemname]", Item.Name), null, 0.0f, "repairfailed", 10.0f);
                 }
             }
             repairable.CurrentFixer = abandon && repairable.CurrentFixer == character ? null : character;
             break;
         }
     }
     else if (goToObjective == null || goToObjective.Target != Item)
     {
         previousCondition = -1;
         if (goToObjective != null)
         {
             subObjectives.Remove(goToObjective);
         }
         goToObjective = new AIObjectiveGoTo(Item, character);
         if (repairTool != null)
         {
             goToObjective.CloseEnough = (HumanAIController.AnimController.ArmLength + ConvertUnits.ToSimUnits(repairTool.Range)) * 0.75f;
         }
         AddSubObjective(goToObjective);
     }
 }
        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;
                }
            }
        }