Exemple #1
0
        public static BTResult Swim(Animal agent, Vector2 direction, bool wandering, AnimalState state, bool surface, int tries = 10)
        {
            var targetPos = AIUtil.FindTargetSwimPosition(agent.Position, 5.0f, 20.0f, direction, 90, 360, tries, surface).XYZi;

            if (targetPos == agent.Position)
            {
                return(BTResult.Failure("target position is current position."));
            }

            // Avoid fish swimming too close to coast line
            // TODO: Avoid building routes near coast, cache available points far away from coast
            if (!agent.Species.CanSwimNearCoast)
            {
                var waterHeight = World.World.GetWaterHeight(targetPos.XZ);
                var isNearCoast = ((WorldPosition3i)targetPos).SpiralOutXZIter(3).Any(groundPos => World.World.GetBlock((WrappedWorldPosition3i)groundPos.X_Z(waterHeight)).Is <Solid>());
                if (isNearCoast)
                {
                    return(BTResult.Failure("target position is too close to coast line"));
                }
            }

            var targetBlock = World.World.GetBlock(targetPos);

            // If an animal can't float on water surface - move it a block below highest water block TODO: make them move on underwater ground
            // TODO: Remove after pathfinder improvements
            if (!agent.Species.FloatOnSurface && targetBlock is WaterBlock && World.World.GetBlock(targetPos + Vector3i.Up).Is <Empty>())
            {
                targetPos += Vector3i.Down;
            }
            //if (targetBlock.Is<Solid>()) targetPos += Vector3i.Up;
            if (targetBlock.Is <Empty>())
            {
                targetPos += Vector3i.Down;
                // Fail if target position is too shallow
                if (World.World.GetBlock(targetPos).Is <Solid>())
                {
                    return(BTResult.Failure("target position is too thin"));
                }
            }
            // Clamp current position to ground or water, if can't float on water surface - stay below water height TODO: make them move on underwater ground
            var pos = World.World.ClampToWaterHeight(agent.Position.XYZi);

            // TODO: Remove after pathfinder improvements
            if (!agent.Species.FloatOnSurface && pos.y == World.World.GetWaterHeight(agent.Position.XZi))
            {
                pos += Vector3i.Down;
            }

            var route     = Route.Basic(agent.Species.GetTraversalData(wandering), agent.FacingDir, pos + Vector3i.Down, targetPos); //For fish, we need to compensate, since route is built from positions of the ground below
            var routeTime = route.IsValid ? agent.SetRoute(route, state, null) : 0f;

            return(routeTime < float.Epsilon ? BTResult.Failure("route not set") : BTResult.Success($"swimming path"));
        }