Ejemplo n.º 1
0
        protected override void Act(float deltaTime)
        {
            if (followControlledCharacter)
            {
                if (Character.Controlled == null)
                {
                    Abandon = true;
                    return;
                }
                Target = Character.Controlled;
            }
            if (Target == character)
            {
                // Wait
                character.AIController.SteeringManager.Reset();
                return;
            }
            waitUntilPathUnreachable -= deltaTime;
            if (!character.IsClimbing)
            {
                character.SelectedConstruction = null;
            }
            if (Target is Entity e)
            {
                if (e.Removed)
                {
                    Abandon = true;
                }
                else
                {
                    character.AIController.SelectTarget(e.AiTarget);
                }
            }
            var targetHull = Target is Hull h ? h : Target is Item i ? i.CurrentHull : Target is Character c ? c.CurrentHull : character.CurrentHull;

            if (!followControlledCharacter)
            {
                // Abandon if going through unsafe paths. Note ignores unsafe nodes when following an order or when the objective is set to ignore unsafe hulls.
                bool containsUnsafeNodes = HumanAIController.CurrentOrder == null && !HumanAIController.ObjectiveManager.CurrentObjective.IgnoreUnsafeHulls &&
                                           PathSteering != null && PathSteering.CurrentPath != null &&
                                           PathSteering.CurrentPath.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull));
                if (containsUnsafeNodes || HumanAIController.UnreachableHulls.Contains(targetHull))
                {
                    Abandon = true;
                    SteeringManager.Reset();
                    return;
                }
            }
            bool insideSteering  = SteeringManager == PathSteering && PathSteering.CurrentPath != null && !PathSteering.IsPathDirty;
            bool isInside        = character.CurrentHull != null;
            bool targetIsOutside = (Target != null && targetHull == null) || (insideSteering && PathSteering.CurrentPath.HasOutdoorsNodes);

            if (isInside && targetIsOutside && !AllowGoingOutside)
            {
                Abandon = true;
            }
            else if (waitUntilPathUnreachable < 0)
            {
                if (SteeringManager == PathSteering && PathSteering.CurrentPath != null && PathSteering.CurrentPath.Unreachable && !PathSteering.IsPathDirty)
                {
                    if (repeat)
                    {
                        SteeringManager.Reset();
                    }
                    else
                    {
                        Abandon = true;
                    }
                }
            }
            if (Abandon)
            {
#if DEBUG
                DebugConsole.NewMessage($"{character.Name}: Cannot reach the target: {Target.ToString()}", Color.Yellow);
#endif
                if (objectiveManager.CurrentOrder != null && objectiveManager.CurrentOrder.ReportFailures)
                {
                    character.Speak(TextManager.Get("DialogCannotReach"), identifier: "cannotreach", minDurationBetweenSimilar: 10.0f);
                }
                SteeringManager.Reset();
            }
            else
            {
                if (getDivingGearIfNeeded && !character.LockHands)
                {
                    Character followTarget    = Target as Character;
                    bool      needsDivingSuit = targetIsOutside;
                    bool      needsDivingGear = needsDivingSuit || HumanAIController.NeedsDivingGear(character, targetHull, out needsDivingSuit);
                    if (!needsDivingGear && mimic)
                    {
                        if (HumanAIController.HasDivingSuit(followTarget))
                        {
                            needsDivingGear = true;
                            needsDivingSuit = true;
                        }
                        else if (HumanAIController.HasDivingMask(followTarget))
                        {
                            needsDivingGear = true;
                        }
                    }
                    bool needsEquipment = false;
                    if (needsDivingSuit)
                    {
                        needsEquipment = !HumanAIController.HasDivingSuit(character, AIObjectiveFindDivingGear.lowOxygenThreshold);
                    }
                    else if (needsDivingGear)
                    {
                        needsEquipment = !HumanAIController.HasDivingGear(character, AIObjectiveFindDivingGear.lowOxygenThreshold);
                    }
                    if (needsEquipment)
                    {
                        TryAddSubObjective(ref findDivingGear, () => new AIObjectiveFindDivingGear(character, needsDivingSuit, objectiveManager),
                                           onAbandon: () => Abandon = true,
                                           onCompleted: () => RemoveSubObjective(ref findDivingGear));
                        return;
                    }
                }
                if (repeat && IsCloseEnough)
                {
                    OnCompleted();
                    return;
                }
                if (SteeringManager == PathSteering)
                {
                    Func <PathNode, bool> nodeFilter = null;
                    if (isInside && !AllowGoingOutside)
                    {
                        nodeFilter = node => node.Waypoint.CurrentHull != null;
                    }
                    PathSteering.SteeringSeek(character.GetRelativeSimPosition(Target), 1, startNodeFilter, endNodeFilter, nodeFilter);
                }
                else
                {
                    SteeringManager.SteeringSeek(character.GetRelativeSimPosition(Target), 10);
                }
                if (!insideSteering)
                {
                    SteeringManager.SteeringAvoid(deltaTime, lookAheadDistance: 5, weight: 1);
                }
            }
        }
Ejemplo n.º 2
0
        protected override void Act(float deltaTime)
        {
            if (followControlledCharacter)
            {
                if (Character.Controlled == null)
                {
                    abandon = true;
                    return;
                }
                Target = Character.Controlled;
            }
            if (Target == character)
            {
                character.AIController.SteeringManager.Reset();
                abandon = true;
                return;
            }
            waitUntilPathUnreachable -= deltaTime;
            if (!character.IsClimbing)
            {
                character.SelectedConstruction = null;
            }
            if (Target is Entity e)
            {
                if (e.Removed)
                {
                    abandon = true;
                }
                else
                {
                    character.AIController.SelectTarget(e.AiTarget);
                }
            }
            bool isInside        = character.CurrentHull != null;
            bool insideSteering  = SteeringManager == PathSteering && PathSteering.CurrentPath != null && !PathSteering.IsPathDirty;
            var  targetHull      = Target is Hull h ? h : Target is Item i ? i.CurrentHull : Target is Character c ? c.CurrentHull : character.CurrentHull;
            bool targetIsOutside = (Target != null && targetHull == null) || (insideSteering && PathSteering.CurrentPath.HasOutdoorsNodes);

            if (isInside && targetIsOutside && !AllowGoingOutside)
            {
                abandon = true;
            }
            else if (waitUntilPathUnreachable < 0)
            {
                if (SteeringManager == PathSteering && PathSteering.CurrentPath != null && PathSteering.CurrentPath.Unreachable)
                {
                    if (repeat)
                    {
                        SteeringManager.Reset();
                    }
                    else
                    {
                        abandon = true;
                    }
                }
            }
            if (abandon)
            {
#if DEBUG
                DebugConsole.NewMessage($"{character.Name}: Cannot reach the target: {Target.ToString()}", Color.Yellow);
#endif
                if (objectiveManager.CurrentOrder != null)
                {
                    character.Speak(TextManager.Get("DialogCannotReach"), identifier: "cannotreach", minDurationBetweenSimilar: 10.0f);
                }
                character.AIController.SteeringManager.Reset();
            }
            else
            {
                Vector2 currTargetSimPos = Vector2.Zero;
                currTargetSimPos = Target.SimPosition;
                // Take the sub position into account in the sim pos
                if (SteeringManager != PathSteering && character.Submarine == null && Target.Submarine != null)
                {
                    currTargetSimPos += Target.Submarine.SimPosition;
                }
                else if (character.Submarine != null && Target.Submarine == null)
                {
                    currTargetSimPos -= character.Submarine.SimPosition;
                }
                else if (character.Submarine != Target.Submarine)
                {
                    if (character.Submarine != null && Target.Submarine != null)
                    {
                        Vector2 diff = character.Submarine.SimPosition - Target.Submarine.SimPosition;
                        currTargetSimPos -= diff;
                    }
                }
                if (PathSteering != null)
                {
                    PathSteering.startNodeFilter = startNodeFilter;
                    PathSteering.endNodeFilter   = endNodeFilter;
                }
                SteeringManager.SteeringSeek(currTargetSimPos);
                if (SteeringManager != PathSteering)
                {
                    SteeringManager.SteeringAvoid(deltaTime, lookAheadDistance: 5, weight: 1, heading: VectorExtensions.Forward(character.AnimController.Collider.Rotation));
                }
                if (getDivingGearIfNeeded)
                {
                    Character followTarget    = Target as Character;
                    bool      needsDivingGear = HumanAIController.NeedsDivingGear(targetHull) || mimic && HumanAIController.HasDivingMask(followTarget);
                    bool      needsDivingSuit = needsDivingGear && (targetHull == null || targetIsOutside || targetHull.WaterPercentage > 90) || mimic && HumanAIController.HasDivingSuit(followTarget);
                    bool      needsEquipment  = false;
                    if (needsDivingSuit)
                    {
                        needsEquipment = !HumanAIController.HasDivingSuit(character);
                    }
                    else if (needsDivingGear)
                    {
                        needsEquipment = !HumanAIController.HasDivingMask(character);
                    }
                    if (needsEquipment)
                    {
                        TryAddSubObjective(ref findDivingGear, () => new AIObjectiveFindDivingGear(character, needsDivingSuit, objectiveManager));
                    }
                }
            }
        }
Ejemplo n.º 3
0
        public void Update(float deltaTime)
        {
            position += new Vector2(velocity.X, velocity.Y) * deltaTime;
            depth     = MathHelper.Clamp(depth + velocity.Z * deltaTime, 0.0f, MaxDepth);

            checkWallsTimer -= deltaTime;
            if (checkWallsTimer <= 0.0f && Level.Loaded != null)
            {
                checkWallsTimer = CheckWallsInterval;

                obstacleDiff = Vector2.Zero;
                if (position.Y > Level.Loaded.Size.Y)
                {
                    obstacleDiff = Vector2.UnitY;
                }
                else if (position.Y < 0.0f)
                {
                    obstacleDiff = -Vector2.UnitY;
                }
                else if (position.X < 0.0f)
                {
                    obstacleDiff = Vector2.UnitX;
                }
                else if (position.X > Level.Loaded.Size.X)
                {
                    obstacleDiff = -Vector2.UnitX;
                }
                else
                {
                    var cells = Level.Loaded.GetCells(position, 1);
                    if (cells.Count > 0)
                    {
                        int cellCount = 0;
                        foreach (Voronoi2.VoronoiCell cell in cells)
                        {
                            Vector2 diff = cell.Center - position;
                            if (diff.LengthSquared() > 5000.0f * 5000.0f)
                            {
                                continue;
                            }
                            obstacleDiff += diff;
                            cellCount++;
                        }
                        if (cellCount > 0)
                        {
                            obstacleDiff /= cellCount;
                            obstacleDist  = obstacleDiff.Length();
                            obstacleDiff  = Vector2.Normalize(obstacleDiff);
                        }
                    }
                }
            }

            if (Swarm != null)
            {
                Vector2 midPoint     = Swarm.MidPoint();
                float   midPointDist = Vector2.Distance(SimPosition, midPoint) * 100.0f;
                if (midPointDist > Swarm.MaxDistance)
                {
                    steeringManager.SteeringSeek(midPoint, ((midPointDist / Swarm.MaxDistance) - 1.0f) * prefab.Speed);
                }
                steeringManager.SteeringManual(deltaTime, Swarm.AvgVelocity() * Swarm.Cohesion);
            }

            if (prefab.WanderAmount > 0.0f)
            {
                steeringManager.SteeringWander(prefab.Speed);
            }

            if (obstacleDiff != Vector2.Zero)
            {
                steeringManager.SteeringManual(deltaTime, -obstacleDiff * (1.0f - obstacleDist / 5000.0f) * prefab.Speed);
            }

            steeringManager.Update(prefab.Speed);

            if (prefab.WanderZAmount > 0.0f)
            {
                wanderZPhase += Rand.Range(-prefab.WanderZAmount, prefab.WanderZAmount);
                velocity.Z    = (float)Math.Sin(wanderZPhase) * prefab.Speed;
            }

            velocity = Vector3.Lerp(velocity, new Vector3(Steering.X, Steering.Y, velocity.Z), deltaTime);
        }
Ejemplo n.º 4
0
        public void Update(float deltaTime)
        {
            position += new Vector2(velocity.X, velocity.Y) * deltaTime;
            depth     = MathHelper.Clamp(depth + velocity.Z * deltaTime, 0.0f, MaxDepth);

            checkWallsTimer -= deltaTime;
            if (checkWallsTimer <= 0.0f && Level.Loaded != null)
            {
                checkWallsTimer = CheckWallsInterval;

                obstacleDiff = Vector2.Zero;
                if (position.Y > Level.Loaded.Size.Y)
                {
                    obstacleDiff = Vector2.UnitY;
                }
                else if (position.Y < 0.0f)
                {
                    obstacleDiff = -Vector2.UnitY;
                }
                else if (position.X < 0.0f)
                {
                    obstacleDiff = Vector2.UnitX;
                }
                else if (position.X > Level.Loaded.Size.X)
                {
                    obstacleDiff = -Vector2.UnitX;
                }
                else
                {
                    var cells = Level.Loaded.GetCells(position, 1);
                    if (cells.Count > 0)
                    {
                        foreach (Voronoi2.VoronoiCell cell in cells)
                        {
                            obstacleDiff += cell.Center - position;
                        }
                        obstacleDiff /= cells.Count;

                        obstacleDiff = Vector2.Normalize(obstacleDiff) * prefab.Speed;
                    }
                }
            }



            if (Swarm != null)
            {
                Vector2 midPoint     = Swarm.MidPoint();
                float   midPointDist = Vector2.Distance(SimPosition, midPoint);

                if (midPointDist > Swarm.MaxDistance)
                {
                    steeringManager.SteeringSeek(midPoint, (midPointDist / Swarm.MaxDistance) * prefab.Speed);
                }
            }

            if (prefab.WanderAmount > 0.0f)
            {
                steeringManager.SteeringWander(prefab.Speed);
            }

            //Level.Loaded.Size


            if (obstacleDiff != Vector2.Zero)
            {
                steeringManager.SteeringSeek(SimPosition - obstacleDiff, prefab.Speed * 2.0f);
            }

            steeringManager.Update(prefab.Speed);

            if (prefab.WanderZAmount > 0.0f)
            {
                ang       += Rand.Range(-prefab.WanderZAmount, prefab.WanderZAmount);
                velocity.Z = (float)Math.Sin(ang) * prefab.Speed;
            }

            velocity = Vector3.Lerp(velocity, new Vector3(Steering.X, Steering.Y, velocity.Z), deltaTime);
        }
Ejemplo n.º 5
0
        public void Update(float deltaTime)
        {
            position += new Vector2(velocity.X, velocity.Y) * deltaTime;
            depth     = MathHelper.Clamp(depth + velocity.Z * deltaTime, Prefab.MinDepth, Prefab.MaxDepth * 10);

            if (Prefab.FlashInterval > 0.0f)
            {
                flashTimer -= deltaTime;
                if (flashTimer > 0.0f)
                {
                    alpha = 0.0f;
                }
                else
                {
                    //value goes from 0 to 1 and back to 0 during the flash
                    alpha = (float)Math.Sin(-flashTimer / Prefab.FlashDuration * MathHelper.Pi) * PerlinNoise.GetPerlin((float)Timing.TotalTime * 0.1f, (float)Timing.TotalTime * 0.2f);
                    if (flashTimer < -Prefab.FlashDuration)
                    {
                        flashTimer = Prefab.FlashInterval;
                    }
                }
            }

            checkWallsTimer -= deltaTime;
            if (checkWallsTimer <= 0.0f && Level.Loaded != null)
            {
                checkWallsTimer = CheckWallsInterval;

                obstacleDiff = Vector2.Zero;
                if (position.Y > Level.Loaded.Size.Y)
                {
                    obstacleDiff = Vector2.UnitY;
                }
                else if (position.Y < 0.0f)
                {
                    obstacleDiff = -Vector2.UnitY;
                }
                else if (position.X < 0.0f)
                {
                    obstacleDiff = Vector2.UnitX;
                }
                else if (position.X > Level.Loaded.Size.X)
                {
                    obstacleDiff = -Vector2.UnitX;
                }
                else
                {
                    var cells = Level.Loaded.GetCells(position, 1);
                    if (cells.Count > 0)
                    {
                        int cellCount = 0;
                        foreach (Voronoi2.VoronoiCell cell in cells)
                        {
                            Vector2 diff = cell.Center - position;
                            if (diff.LengthSquared() > 5000.0f * 5000.0f)
                            {
                                continue;
                            }
                            obstacleDiff += diff;
                            cellCount++;
                        }
                        if (cellCount > 0)
                        {
                            obstacleDiff /= cellCount;
                            obstacleDist  = obstacleDiff.Length();
                            obstacleDiff  = Vector2.Normalize(obstacleDiff);
                        }
                    }
                }
            }

            if (Swarm != null)
            {
                Vector2 midPoint     = Swarm.MidPoint();
                float   midPointDist = Vector2.Distance(SimPosition, midPoint) * 100.0f;
                if (midPointDist > Swarm.MaxDistance)
                {
                    steeringManager.SteeringSeek(midPoint, ((midPointDist / Swarm.MaxDistance) - 1.0f) * Prefab.Speed);
                }
                steeringManager.SteeringManual(deltaTime, Swarm.AvgVelocity() * Swarm.Cohesion);
            }

            if (Prefab.WanderAmount > 0.0f)
            {
                steeringManager.SteeringWander(Prefab.Speed);
            }

            if (obstacleDiff != Vector2.Zero)
            {
                steeringManager.SteeringManual(deltaTime, -obstacleDiff * (1.0f - obstacleDist / 5000.0f) * Prefab.Speed);
            }

            steeringManager.Update(Prefab.Speed);

            if (Prefab.WanderZAmount > 0.0f)
            {
                wanderZPhase += Rand.Range(-Prefab.WanderZAmount, Prefab.WanderZAmount);
                velocity.Z    = (float)Math.Sin(wanderZPhase) * Prefab.Speed;
            }

            velocity = Vector3.Lerp(velocity, new Vector3(Steering.X, Steering.Y, velocity.Z), deltaTime);

            UpdateDeformations(deltaTime);
        }