コード例 #1
0
        // If the animal is stuck somewhere it shouldn't be help it escape or die if its very far from walkable terrain
        public static BTResult LandAnimalUnStuckOrDie(Animal agent)
        {
            const int maxUnStuckDistance = 20;
            var       nearestValid       = RouteManager.NearestWalkableXYZ(agent.Position.XYZi, maxUnStuckDistance);

            if (nearestValid == agent.Position.WorldPosition3i)
            {
                agent.NextTick = WorldTime.Seconds + 10f;
                return(BTResult.Failure());
            }

            if (!nearestValid.IsValid)
            {
                // cheating failed? time to die!
                agent.Kill();
                return(BTResult.Success());
            }
            // ignore terrain, path directly to a valid area, but only if noone is around *shy* or if he's really trying
            if (agent.TryGetMemory(Animal.TriesToUnStuckMemory, out int tries))
            {
                tries += 1;
            }
            agent.SetMemory(Animal.TriesToUnStuckMemory, tries);
            if (!NetObjectManager.GetObjectsWithin(agent.Position.XZ, 20).OfType <Player>().Any() || tries >= 3)
            {
                var route = AIUtil.GetRoute(agent.FacingDir, agent.Position, (Vector3)nearestValid, agent.Species.GetTraversalData(true), null, null);
                if (!route.IsValid)
                {
                    agent.NextTick = WorldTime.Seconds + 10;
                    return(BTResult.Failure());
                }

                // Proceed with route with time length more than 0
                var timeToFinishRoute = agent.SetRoute(route, AnimalState.Wander);
                if (timeToFinishRoute > float.Epsilon)
                {
                    agent.RemoveMemory(Animal.TriesToUnStuckMemory);
                    return(BTResult.Success());
                }
            }

            agent.NextTick = WorldTime.Seconds + 10;
            return(BTResult.Failure());
        }