示例#1
0
        public static BTStatus SleepNearLeader(Animal agent)
        {
            var leader = GetLeader(agent);

            if (leader == null || leader == agent)
            {
                return(BTStatus.Failure);
            }

            if (leader.AnimationState == AnimalAnimationState.Sleeping)
            {
                // sleep near alpha
                if (Vector3.WrappedDistance(agent.Position, leader.Position) < agent.Species.HeadDistance * 3)
                {
                    agent.SetState(AnimalAnimationState.LyingDown, 10f);
                    agent.Hunger = Math.Min(agent.Hunger, 50);
                    return(BTStatus.Success);
                }

                // TODO: avoid overlapping with other herd members, make the leader pick a spot to sleep that can accomidate the herd
                var route = AIUtilities.GetRouteFacingTarget(agent.Position, leader.Position, agent.Species.WanderingSpeed, agent.Species.HeadDistance * 2);
                agent.Target.SetPath(route);
                agent.NextTick       = agent.Target.TargetTime;
                agent.AnimationState = AnimalAnimationState.Wander;
                return(BTStatus.Success);
            }
            return(BTStatus.Failure);
        }
示例#2
0
    void Update()
    {
        if (projectile != null && !LevelManager.instance.paused && sr.isVisible)
        {
            shootTimer += Time.deltaTime;

            if (shootTimer >= SHOOT_COOLDOWN)
            {
                // Find closest player and shoot at them.
                GameObject player = AIUtilities.getClosestPlayer(transform.position);

                // only shoot if player is approximately on our y-level
                if (Mathf.Abs(player.transform.position.y - transform.position.y) < 2f)
                {
                    // shoot
                    float       direction     = Mathf.Sign(player.transform.position.x - transform.position.x);
                    GameObject  newProjectile = LevelManager.instance.placeSpawnedObject((Vector2)gameObject.transform.position + new Vector2(direction, 0f), projectile, transform.parent);
                    Rigidbody2D rb            = newProjectile.GetComponent <Rigidbody2D>();
                    if (rb != null)
                    {
                        rb.velocity = new Vector2(projectileSpeed * direction, rb.velocity.y);
                    }
                    Vector3 scale = newProjectile.transform.localScale;
                    scale.x = Mathf.Abs(scale.x) * direction;
                    newProjectile.transform.localScale = scale;
                    shootTimer = 0f;
                }
            }
        }
    }
示例#3
0
        public static IEnumerator <BTStatus> Hunt(Animal agent, Func <Animal, BTStatus> noNearbyFoodBehavior)
        {
            while (agent.Hunger > Brain.HungerSatiated)
            {
                var agentRegion = RouteRegions.GetRegion(agent.Position.WorldPosition3i);
                var nearPrey    = NetObjectManager.GetObjectsWithin(agent.Position.XZ, agent.DetectionRange).OfType <Animal>()
                                  .Where(x => agent.ShouldFleeUs(x) && RouteRegions.GetRegion(x.Position.WorldPosition3i) == agentRegion)
                                  .OrderBy(x => Vector3.WrappedDistanceSq(x.Position, agent.Position) + (x.AnimationState == AnimalAnimationState.Sleeping ? -200 : 0));
                foreach (var prey in nearPrey)
                {
                    var i = 0;
                    while (prey.Active)
                    {
                        Eco.Simulation.ExternalInputs.PredatorTracker.AddPredator(agent);
                        var route = AIUtilities.GetRoute(agent.Position, prey.Position, prey.Alertness < 50 ? agent.Species.WanderingSpeed : agent.Species.Speed);
                        agent.Target.SetPath(route);
                        agent.Target.Set(prey);
                        agent.NextTick = Math.Min(agent.Target.TargetTime, WorldTime.Seconds + 3);
                        i++;
                        yield return(BTStatus.Running);

                        if (Vector3.WrappedDistance(agent.Position, prey.Position) < 2f || i > 4)
                        {
                            // making this look good will require a lot of work, for now just let it go
                            agent.Hunger = 0;
                            Eco.Simulation.ExternalInputs.PredatorTracker.RemovePredator(agent);
                            yield break;
                        }
                    }
                }
                yield return(noNearbyFoodBehavior(agent));
            }
        }
示例#4
0
    // Update is called once per frame
    void Update()
    {
        if (sr == null)
        {
            sr = GetComponent <SpriteRenderer>();
        }

        if (!sr.isVisible)
        {
            return;
        }

        if (rb == null)
        {
            rb = GetComponent <Rigidbody2D>();
        }

        // Find closest player and move toward it
        GameObject player = AIUtilities.getClosestPlayer(transform.position);

        if (player != null && rb != null)
        {
            float direction = Mathf.Sign(player.transform.position.x - transform.position.x);

            Vector2 position = transform.position;
            position.x        += (direction * moveSpeed) * Time.deltaTime;
            transform.position = position;
            Vector3 scale = transform.localScale;
            scale.x = Mathf.Abs(scale.x) * -direction;
            transform.localScale = scale;
        }
    }
示例#5
0
    // Update is called once per frame
    void Update()
    {
        // If we dont have a target do nothing
        if (target == null)
        {
            return;
        }

        AIUtilities.LookAtTarget(transform, target.position, maxRotation);
        AIUtilities.ClampTurretRotation(transform, minRotationAngle, maxRotationAngle);

        float angleToPosition = AIUtilities.GetAngleToTarget(transform, target.position);

        if (Vector3.Distance(transform.position, target.position) < 600)
        {
            if (Mathf.Abs(angleToPosition) < 1)
            {
                if ((_shotCounter += Time.deltaTime) > fireRate)
                {
                    _shotCounter = 0.0f;
                    Shoot();
                }
            }
        }
    }
    private void Update()
    {
        if (Placed)
        {
            GameObject enemy = AIUtilities.GetNearestGameObject(VisionCheck, EnemyTag, Range);

            if (enemy != null)
            {
                Barrel.transform.LookAt(enemy.transform.position + Vector3.up);
                if (WaitTime <= 0)
                {
                    GameObject shot       = Instantiate(Projectile, Barrel.transform.position + Barrel.transform.forward, Barrel.transform.rotation);
                    Projectile projectile = shot.GetComponent <Projectile>();
                    projectile.WeaponDamage = Damage;
                    projectile.EnemyTag     = EnemyTag;
                    Rigidbody rb = shot.GetComponent <Rigidbody>();
                    rb.AddForce(Barrel.transform.forward * (ShotSpeed * 10));
                    rb.useGravity = false;
                    WaitTime      = Rate;
                }
                else
                {
                    WaitTime -= Time.deltaTime;
                }
            }
        }
    }
示例#7
0
    // Update is called once per frame
    void Update()
    {
        if (_target == null)
        {
            GameObject target = targetArea.GetObstacle();
            if (target)
            {
                _target = target.transform;
            }
        }
        else
        {
            AIUtilities.LookAtTarget(transform, _target.position, maxRotation);
            AIUtilities.ClampTurretRotation(transform, minRotationAngle, maxRotationAngle);

            float angleToPosition = AIUtilities.GetAngleToTarget(transform, _target.position);

            if (Mathf.Abs(angleToPosition) < 1)
            {
                if (coRunning == false)
                {
                    StartCoroutine(coShoot());
                }
            }
        }
    }
示例#8
0
    private void Update()
    {
        GameObject go = AIUtilities.GetNearestGameObject(gameObject, "Monster", Range, xray: true);

        target = go;
        if (target != null && Placed)
        {
            if (projectile.GetComponent <TowerProjectile>())
            {
                projectile.GetComponent <TowerProjectile>().target = target;
            }
            else if (projectile.GetComponent <TowerRapidProjectile>())
            {
                projectile.GetComponent <TowerRapidProjectile>().target = target;
            }
            //Debug.Log(target.name);
            AimBarrel(target);
            Fire(target);
            //Debug.Log((target.transform.position - rangeFinder.transform.position).magnitude);
            if (!CheckEnemyRange(target))
            {
                target = null;
            }
        }
    }
    bool CanPieceMove(int piece)
    {
        Vector2Int pieceLocation = AIUtilities.FindTargetLocation(piece);

        bool canMove = false;

        if (piece == 20 || piece == 21)
        {
            return(true);
        }
        else
        {
            for (int y = Mathf.Max(0, pieceLocation.y - 1); y <= Mathf.Min(7, pieceLocation.y + 1); y++)
            {
                for (int x = Mathf.Max(0, pieceLocation.x - 1); x <= Mathf.Min(7, pieceLocation.x + 1); x++)
                {
                    if (!(x == pieceLocation.x && y == pieceLocation.y))
                    {
                        ChessPiece p = Utilities.chessBoard[pieceLocation.x, pieceLocation.y].GetComponent <ChessPiece>();

                        if (p.IsMovePossible(x, y, Utilities.chessBoard[x, y]))
                        {
                            canMove = true;
                        }
                    }
                }
            }
        }

        return(canMove);
    }
示例#10
0
    public override void Act(StateController controller)
    {
        AIUtilities.AIMove = Vector2.zero;

        List <Vector2Int> possibleMoves = controller.bm.redSelectedPiece.PossibleMoves();

        if (possibleMoves.Count == 0)
        {
            return;
        }

        Vector2Int bestMove       = possibleMoves[0];
        Vector2Int targetLocation = AIUtilities.FindTargetLocation(controller.shortTermTarget);

        foreach (Vector2Int move in possibleMoves)
        {
            if ((targetLocation - move).magnitude <= (targetLocation - bestMove).magnitude)
            {
                bestMove = move;
            }
        }

        Vector2 direction = bestMove - controller.bm.redSelection;

        direction.Normalize();

        AIUtilities.AIMove = direction;
    }
示例#11
0
        public static BTStatus TryEatNearbyCorpses(Animal agent)
        {
            Animal targetCorpse = null;

            if (agent.TryGetMemory <Animal>("targetCorpse", out targetCorpse) && !targetCorpse.Active)
            {
                targetCorpse = null;
                agent.Brain.Memory.Remove("targetCorpse");
            }

            if (targetCorpse == null)
            {
                foreach (var corpse in Animal.Corpses.Shuffle())
                {
                    if (!corpse.Active)
                    {
                        Animal.Corpses.Remove(corpse);
                    }
                    else if (Vector3.WrappedDistance(corpse.Position, agent.Position) < 40 && agent.Species.Eats(corpse.Species))
                    {
                        targetCorpse = corpse;
                        agent.Brain.Memory["targetCorpse"] = targetCorpse;
                        break;
                    }
                }
            }

            if (targetCorpse != null)
            {
                if (agent.AnimationState == AnimalAnimationState.Eating)
                {
                    // finished eating, go do something else
                    agent.Hunger = 0;
                    agent.Brain.Memory.Remove("targetCorpse");
                    return(BTStatus.Failure);
                }
                // eat or walk then eat
                agent.AnimationState = AnimalAnimationState.Eating;
                if (Vector3.WrappedDistance(targetCorpse.Position, agent.Position) < 3)
                {
                    agent.NextTick = WorldTime.Seconds + 10f;
                    agent.Target.Set(targetCorpse);
                    return(BTStatus.Success);
                }
                else
                {
                    var route = AIUtilities.GetRouteFacingTarget(agent.Position, targetCorpse.Position, agent.Species.WanderingSpeed, agent.Species.HeadDistance);
                    agent.Target.SetPath(route);
                    agent.Target.Set(targetCorpse);
                    agent.NextTick = agent.Target.TargetTime + 20f;
                    return(BTStatus.Success);
                }
            }
            return(BTStatus.Failure);
        }
 private void Update()
 {
     if (attack != null)
     {
         GameObject target = AIUtilities.GetNearestGameObject(spawner.gameObject, attack.Target, xray: true);
         if (target != null)
         {
             spawner.gameObject.transform.LookAt(target.transform);
         }
     }
 }
        public static BTStatus Swim(Animal agent, Vector2 direction, float speed, AnimalAnimationState state, bool surface, int tries = 10)
        {
            var targetPos = AIUtilities.FindTargetSwimPosition(agent.Position, 5.0f, 20.0f, direction, 90, 360, tries, surface);
            if (targetPos == agent.Position)
                return BTStatus.Failure;

            agent.AnimationState = state;
            agent.Target.Set(agent.Position, targetPos, speed);
            agent.NextTick = agent.Target.TargetTime;

            return BTStatus.Success;
        }
    public override bool Decide(StateController controller)
    {
        Vector2Int targetLocation = AIUtilities.FindTargetLocation(controller.shortTermPieceToControl);

        if (targetLocation == controller.bm.redSelection)
        {
            AIUtilities.AIPressed = false;
            return(true);
        }

        return(false);
    }
示例#15
0
    public override void Act(StateController controller)
    {
        AIUtilities.AIMove = new Vector2(0, 0);

        Vector2Int targetLocation = AIUtilities.FindTargetLocation(controller.shortTermPieceToControl);

        Vector2 move = targetLocation - controller.bm.redSelection;

        move.Normalize();

        AIUtilities.AIPressed = true;
        AIUtilities.AIMove    = move;
    }
示例#16
0
 void Update()
 {
     GameObject[] gameObjects = AIUtilities.GetGameObjects(gameObject, monster, range);
     if (gameObjects.Length > 0)
     {
         foreach (GameObject monster in gameObjects)
         {
             TravelNav tn = monster.GetComponent <TravelNav>();
             Game.game.CoreHealth -= tn.Value;
             Destroy(monster);
         }
     }
 }
 public static BTStatus LandMovement(Animal agent, Vector2 direction, float speed, AnimalAnimationState state, float minDistance = 2f, float maxDistance = 20f, float minDirectionOffsetDegrees = 0, float maxDirectionOffsetDegrees = 360, int tryCount = 10)
 {
     var search = AIUtilities.FindRoute(agent.Position, 2f, 20f, direction);
     if (search != null)
     {
         var smoothed = search.LineOfSightSmooth(agent.Position);
         PiecewiseLinearFunction route = AIUtilities.ProjectRoute(smoothed, speed);
         agent.NextTick = WorldTime.Seconds + route.EndTime;
         agent.Target.SetPath(route);
         agent.AnimationState = state;
         return BTStatus.Success;
     }
     else
         return LandAnimalUnStuckOrDie(agent, speed, state);
 }
        public static BTStatus AmphibiousMovement(Animal agent, Vector2 generalDirection, float speed, AnimalAnimationState state, float minDistance = 2f, float maxDistance = 20f)
        {
            var start = agent.Position.WorldPosition3i;
            if (!World.World.IsUnderwater(start))
                start = RouteManager.NearestWalkableY(agent.Position.WorldPosition3i);

            if (!start.IsValid)
                return LandMovement(agent, generalDirection, speed, state, minDistance, maxDistance);

            if (generalDirection == Vector2.zero)
                generalDirection = Vector2.right.Rotate(RandomUtil.Range(0f, 360));
            else
                generalDirection = generalDirection.Normalized;

            var target = (agent.Position + (generalDirection * RandomUtil.Range(minDistance, maxDistance)).X_Z()).WorldPosition3i;
            if (World.World.IsUnderwater(target))
                target.y = World.World.MaxWaterHeight[target];
            else
                target = RouteManager.NearestWalkableXYZ(target, 5);

            // This is a low-effort search that includes water surface and should occasionally fail, just pick a semi-random node that was visited when it fails
            var allowWaterSearch = new AStarSearch(RouteCacheData.NeighborsIncludeWater, start, target, 30);
            if (allowWaterSearch.Status != SearchStatus.PathFound)
            {
                target = allowWaterSearch.Nodes.Last().Key;
                allowWaterSearch.GetPath(target);
            }

            if (allowWaterSearch.Path.Count < 2)
                return BTStatus.Failure;
            else if (allowWaterSearch.Status == SearchStatus.Unpathable && allowWaterSearch.Nodes.Count < RouteRegions.MinimumRegionSize && !World.World.IsUnderwater(agent.Position.WorldPosition3i))
            {
                // Search region was unexpectedly small and agent is on land, might be trapped by player construction. 
                // Try regular land movement so region checks can apply & the agent can get unstuck (or die)
                return LandMovement(agent, generalDirection, speed, state, minDistance, maxDistance);
            }

            var smoothed = allowWaterSearch.LineOfSightSmooth(agent.Position);
            PiecewiseLinearFunction route = AIUtilities.ProjectRoute(smoothed, speed);
            agent.AnimationState = state;
            agent.NextTick = WorldTime.Seconds + route.EndTime;
            agent.Target.SetPath(route);

            return BTStatus.Success;
        }
 void Update()
 {
     if (ResetTime <= 0)
     {
         GameObject enemy = AIUtilities.GetNearestGameObject(gameObject, EnemyTag, TriggerRange, xray: true);
         if (enemy != null)
         {
             ResetTime = Rate;
             Particles.Play();
             GameObject[] monsters = AIUtilities.GetGameObjects(gameObject, EnemyTag, Range);
             monsters.ToList().ForEach(m => m.GetComponent <Damagable>().ApplyDamage(Damage));
         }
     }
     else
     {
         ResetTime -= Time.deltaTime;
     }
 }
    private void Update()
    {
        GameObject go = AIUtilities.GetNearestGameObject(gameObject, attack.Target, 0, attack.Nc.Fov, attack.Nc.SeeThroughWalls);

        if (go != null && !hit)
        {
            hit = true;
            Damagable health = go.GetComponent <Damagable>();
            if (health != null)
            {
                health.ApplyDamage(Damage);
            }
            if (DestroyOnHit)
            {
                Destroy(gameObject);
            }
        }
    }
示例#21
0
    void Update()
    {
        bool hasLOSToPlayer = AIUtilities.HasLineOfSight(transform.position, player.transform.position, player);

        if (hasLOSToPlayer)
        {
            lastKnownPlayerLocation            = player.transform.position;
            lastKnownVisual.transform.position = lastKnownPlayerLocation;
        }

        var aimPos = lastKnownPlayerLocation;

        aimPos.y = 0;
        aiming.LookAt(aimPos);

        if (!hasLOSToPlayer)
        {
            confidence += confidenceRegen * Time.deltaTime;
        }

        // DEBUG INPUTS
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            AffectConfidence(100f);
            movement.StopMoving();
        }
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            AffectConfidence(-100f);
            movement.StopMoving();
        }

        Vector3 moveToPoint = Vector3.down;

        // Getting in cover
        if (confidence < 50f)
        {
            if (hasLOSToPlayer /*&& lastPlayerPos != player.transform.position*/)
            {
                moveToPoint = AIUtilities.GetClosestLOSPoint(this, transform.position, player.transform.position, false, player);
            }

            // Attacking player
        }
        else
        {
            if (hasLOSToPlayer)
            {
                shooting.Shoot(transform.forward);
            }
            else
            {
                if (AIUtilities.HasLineOfSight(transform.position, lastKnownPlayerLocation))
                {
                    print("has los");
                    moveToPoint = lastKnownPlayerLocation;
                }
                else
                {
                    print("no los");
                    moveToPoint = AIUtilities.GetClosestLOSPoint(this, transform.position, lastKnownPlayerLocation, true);
                }
            }
        }

        if (moveToPoint != Vector3.down && moveToPoint != lastMoveToPoint)
        {
            print("<color=red>Moving</color>");
            movement.MoveToPoint(moveToPoint);
            moveToVisual.transform.position = moveToPoint;
            lastMoveToPoint = moveToPoint;
            movingToNode    = Grid.GetNodeWorldPoint(moveToPoint);
        }
    }
示例#22
0
 // Start is called before the first frame update
 private void Start()
 {
     Waypoints = AIUtilities.GenerateWaypoints(transform.position, 1000, 25);
 }
示例#23
0
    void FindShortTermTarget(int longTermTarget)
    {
        Vector2Int longTermTargetLocation = AIUtilities.FindTargetLocation(longTermTarget);
        bool       targetFound            = false;

        if (longTermTargetLocation.x < 0 || longTermTargetLocation.y < 0)
        {
            // target not found on board
        }

        for (int distance = 1; distance < 6; distance++)
        {
            for (int y = Mathf.Max(0, longTermTargetLocation.y - distance); y <= Mathf.Min(7, longTermTargetLocation.y + distance); y++)
            {
                for (int x = Mathf.Max(0, longTermTargetLocation.x - distance); x <= Mathf.Min(7, longTermTargetLocation.x + distance); x++)
                {
                    if (Mathf.Abs(longTermTargetLocation.x - x) == distance || Mathf.Abs(longTermTargetLocation.y - y) == distance)
                    {
                        if (Utilities.chessBoard[x, y] == null)
                        {
                            openingTarget = new Vector2Int(x, y);

                            Vector2Int checkShortTerm = Vector2Int.zero;

                            if (openingTarget.x > longTermTargetLocation.x)
                            {
                                checkShortTerm.x = -1;
                            }
                            else if (openingTarget.x < longTermTargetLocation.x)
                            {
                                checkShortTerm.x = 1;
                            }
                            else
                            {
                                checkShortTerm.x = 0;
                            }

                            if (openingTarget.y > longTermTargetLocation.y)
                            {
                                checkShortTerm.y = -1;
                            }
                            else if (openingTarget.y < longTermTargetLocation.y)
                            {
                                checkShortTerm.y = 1;
                            }
                            else
                            {
                                checkShortTerm.y = 0;
                            }

                            shortTermTarget = Utilities.chessBoard[openingTarget.x + checkShortTerm.x,
                                                                   openingTarget.y + checkShortTerm.y]
                                              .GetComponent <ChessPiece>().id;

                            targetFound = true;
                        }
                    }
                }
            }

            if (targetFound)
            {
                break;
            }
        }

        if (!targetFound)
        {
            shortTermTarget = longTermTarget;
        }
    }
示例#24
0
    void Update()
    {
        if (m_navAgent.isOnNavMesh)
        {
            var player = AIUtilities.GetNearestGameObject(gameObject, target, range, fov, SeeThroughWalls);
            //Debug.Log($"Player: {player}");
            if (player != null)
            {
                Attacking = ((transform.position - player.transform.position).magnitude <= attackRange && AttackTime <= 0);
                //Debug.Log($"Attacking: {Attacking}");
                if (Attacking)
                {
                    transform.LookAt(player.transform);
                    if (animator != null)
                    {
                        animator.SetTrigger("Attack");
                    }
                    AttackTime = attackCD; m_navAgent.isStopped = true;
                }
                else if ((transform.position - player.transform.position).magnitude <= attackRange)
                {
                    m_navAgent.isStopped = true;
                }
                else
                {
                    m_navAgent.SetDestination(player.transform.position); m_navAgent.isStopped = false;
                }
            }
            else if (MoveTime <= 0)
            {
                if (m_navAgent.isStopped && m_navAgent != null && m_navAgent.isOnNavMesh)
                {
                    m_navAgent.isStopped = false;
                }
                //Debug.Log("Moving");
                if (animator != null)
                {
                    animator.SetTrigger("StopAttack");
                }
                MoveTime = MoveCd;
                Vector3 target = Vector3.up;
                if (m_x && m_z)
                {
                    target = new Vector3(gameObject.transform.position.x + Random.Range(-searchDistance, searchDistance + 1), 0, gameObject.transform.position.z + Random.Range(-searchDistance, searchDistance + 1));
                }
                else if (!m_x && m_z)
                {
                    target = new Vector3(transform.position.x, 0, gameObject.transform.position.z + Random.Range(-searchDistance, searchDistance + 1));
                }
                else if (m_x && !m_z)
                {
                    target = new Vector3(gameObject.transform.position.x + Random.Range(-searchDistance, searchDistance + 1), 0, transform.position.z);
                }

                if (target != null && m_navAgent != null && m_navAgent.isOnNavMesh)
                {
                    m_navAgent.SetDestination(target);
                    if (m_weapon != null && !m_weapon.gameObject.activeSelf)
                    {
                        m_weapon.SetActive(true);
                    }
                }
            }

            if (MoveTime > 0 && m_navAgent.destination == transform.position)
            {
                MoveTime -= Time.deltaTime;
            }
            if (AttackTime > 0)
            {
                AttackTime -= Time.deltaTime;
            }

            if (animator != null)
            {
                animator.SetFloat("Speed", m_navAgent.velocity.magnitude);
            }
        }
    }
        public static IEnumerator <BTStatus> FoodFinder(Animal agent, Func <Animal, BTStatus> noNearbyFoodBehavior, float hungerRestored)
        {
            var             lastPos     = Vector3.Zero;
            Queue <Vector3> foodSources = new Queue <Vector3>();

            while (agent.Hunger > Brain.HungerSatiated)
            {
                foodSources.Clear();
                while (foodSources.Count == 0)
                {
                    if (Vector3.WrappedDistanceSq(lastPos, agent.Position) > 100)
                    {
                        var agentRegion = RouteRegions.GetRegion(agent.Position.WorldPosition3i);
                        foodSources.AddRange(EcoSim.PlantSim.PlantsWithinRange(agent.Position, 10, plant => agent.Species.Eats(plant.Species) &&
                                                                               RouteRegions.GetRegion(plant.Position.WorldPosition3i.Down()) == agentRegion).Shuffle().Select(plant => plant.Position + Vector3.Down));
                        lastPos = agent.Position;
                    }
                    else
                    {
                        yield return(noNearbyFoodBehavior(agent));
                    }
                }

                while (foodSources.Count > 0 && agent.Hunger > Brain.HungerSatiated && Vector3.WrappedDistanceSq(lastPos, agent.Position) < 100)
                {
                    // low-effort search for the first option or any other option visited while trying to hit the first
                    Vector3 targetPlantPosition;
                    PiecewiseLinearFunction route = AIUtilities.GetRouteToAny(agent.Position, foodSources, agent.Species.WanderingSpeed, out targetPlantPosition, 100, 20, agent.Species.HeadDistance);
                    if (route == null)
                    {
                        break;
                    }
                    agent.Target.SetPath(route);
                    agent.Target.LookPos = targetPlantPosition;
                    agent.AnimationState = AnimalAnimationState.LookingForFood;
                    var target = route.EndPosition;

                    // just in case something interrupts the path
                    while (agent.Target.TargetTime > WorldTime.Seconds && agent.Target.TargetPosition == target)
                    {
                        agent.NextTick = agent.Target.TargetTime;
                        yield return(BTStatus.Running);
                    }

                    if (Vector3.WrappedDistanceSq(target, agent.Position) < 4)
                    {
                        agent.AnimationState = AnimalAnimationState.Eating;
                        agent.NextTick       = WorldTime.Seconds + 10;
                        agent.Hunger        -= hungerRestored;
                        agent.Target.LookPos = targetPlantPosition;
                        yield return(BTStatus.Running);
                    }

                    // something interrupted eating, probably need to find new food
                    if (agent.Target.TargetPosition != target)
                    {
                        break;
                    }
                }
            }
        }
示例#26
0
 public void Die()
 {
     AIUtilities.EnemyDied(this);
 }