Exemplo n.º 1
0
        private static void parkAnimal(Pawn_JobTracker __instance, Pawn pawn, ExtendedPawnData pawnData)
        {
            Area_GU areaFound = (Area_GU)pawn.Map.areaManager.GetLabeled(Base.DropAnimal_NPC_LABEL);
            IntVec3 targetLoc = pawn.Position;

            if (areaFound != null && areaFound.ActiveCells.Count() > 0)
            {
                targetLoc = DistanceUtility.getClosestAreaLoc(pawn, areaFound);
            }
            if (pawn.Map.reachability.CanReach(pawn.Position, targetLoc, PathEndMode.OnCell, TraverseParms.For(TraverseMode.PassDoors, Danger.Deadly, false)))
            {
                Job dismountJob = new Job(GUC_JobDefOf.Dismount);
                dismountJob.count = 1;
                __instance.jobQueue.EnqueueFirst(dismountJob);
                __instance.jobQueue.EnqueueFirst(new Job(JobDefOf.Goto, targetLoc));
                PawnDuty animalDuty = pawnData.mount.mindState.duty;
                //if(pawnData.mount.GetLord().CurLordToil is LordToil)

                if (animalDuty != null)
                {
                    animalDuty.focus = new LocalTargetInfo(targetLoc);
                }
            }
            else
            {
                Messages.Message("GU_Car_NotReachable_DropAnimal_NPC_Message".Translate(), new RimWorld.Planet.GlobalTargetInfo(targetLoc, pawn.Map), MessageTypeDefOf.NegativeEvent);
            }
        }
        private bool ShouldAlert()
        {
            List <Map> maps = Find.Maps;

            foreach (Map map in maps)
            {
                Area_GU areaNoMount    = (Area_GU)map.areaManager.GetLabeled(Base.NOMOUNT_LABEL);
                Area_GU areaDropAnimal = (Area_GU)map.areaManager.GetLabeled(Base.DROPANIMAL_LABEL);
                if (areaNoMount != null && areaDropAnimal != null && areaNoMount.ActiveCells.Count() > 0 && areaDropAnimal.ActiveCells.Count() == 0)
                {
                    return(true);
                }
            }
            return(false);
        }
Exemplo n.º 3
0
        public static IntVec3 getClosestAreaLoc(IntVec3 sourceLocation, Area_GU areaFound)
        {
            IntVec3 targetLoc   = new IntVec3();
            double  minDistance = double.MaxValue;

            foreach (IntVec3 loc in areaFound.ActiveCells)
            {
                double distance = DistanceUtility.QuickDistance(loc, sourceLocation);
                if (distance < minDistance)
                {
                    minDistance = distance;
                    targetLoc   = loc;
                }
            }
            return(targetLoc);
        }
Exemplo n.º 4
0
        private static bool TryParkAnimalDropSpot(Area_GU areaDropAnimal, ref IntVec3 parkLoc, Toil toil)
        {
            bool succeeded = false;

            parkLoc = DistanceUtility.getClosestAreaLoc(toil.actor.pather.Destination.Cell, areaDropAnimal);
            if (toil.actor.Map.reachability.CanReach(toil.actor.Position, parkLoc, PathEndMode.OnCell, TraverseParms.For(TraverseMode.PassDoors, Danger.Deadly, false)))
            {
                toil.actor.pather.StartPath(parkLoc, PathEndMode.OnCell);
                succeeded = true;
            }
            else
            {
                Messages.Message("GU_RR_NotReachable_DropAnimal_Message".Translate(), new RimWorld.Planet.GlobalTargetInfo(parkLoc, toil.actor.Map), MessageTypeDefOf.NegativeEvent);
            }
            return(succeeded);
        }
        private bool ShouldAlert()
        {
            List <Map> maps = Find.Maps;

            foreach (Map map in maps)
            {
                Area_GU areaNoMount            = (Area_GU)map.areaManager.GetLabeled(Base.NOMOUNT_LABEL);
                Area_GU areaDropAnimal         = (Area_GU)map.areaManager.GetLabeled(Base.DROPANIMAL_LABEL);
                var     unropablePlayerAnimals = map.mapPawns.SpawnedColonyAnimals.Where(animal => animal.Faction == Faction.OfPlayer && !AnimalPenUtility.NeedsToBeManagedByRope(animal));

                if (unropablePlayerAnimals.Count() > 0 && areaNoMount != null && areaDropAnimal != null && areaNoMount.ActiveCells.Count() > 0 && areaDropAnimal.ActiveCells.Count() == 0)
                {
                    return(true);
                }
            }
            return(false);
        }
Exemplo n.º 6
0
        //uses abstract unit of time. Real time values aren't needed, only relative values.
        private static float CalculateTimeNeeded(Pawn pawn, ref LocalTargetInfo target, LocalTargetInfo secondTarget, float firstToSecondTargetDistance, Pawn animal, bool firstTargetNoMount, bool secondTargetNoMount, Area_GU areaDropAnimal)
        {
            float walkDistance = DistanceUtility.QuickDistance(pawn.Position, animal.Position);
            float rideDistance = DistanceUtility.QuickDistance(animal.Position, target.Cell);

            if (firstTargetNoMount && areaDropAnimal != null)
            {
                rideDistance = 0;
                IntVec3 parkLoc = DistanceUtility.getClosestAreaLoc(animal.Position, areaDropAnimal);
                rideDistance += DistanceUtility.QuickDistance(animal.Position, parkLoc);
                walkDistance += DistanceUtility.QuickDistance(parkLoc, target.Cell);
                walkDistance += firstToSecondTargetDistance;
            }
            else if (secondTargetNoMount && secondTarget != null && secondTarget.IsValid && areaDropAnimal != null)
            {
                IntVec3 parkLoc = DistanceUtility.getClosestAreaLoc(target.Cell, areaDropAnimal);
                rideDistance += DistanceUtility.QuickDistance(target.Cell, parkLoc);
                walkDistance += DistanceUtility.QuickDistance(parkLoc, secondTarget.Cell);
            }
            else
            {
                rideDistance += firstToSecondTargetDistance;
            }
            Area_GU areaNoMount = (Area_GU)pawn.Map.areaManager.GetLabeled(Base.NOMOUNT_LABEL);

            if (areaNoMount != null)
            {
                if (areaNoMount.ActiveCells.Contains(target.Cell) || (secondTarget != null && secondTarget.IsValid && areaNoMount.ActiveCells.Contains(secondTarget.Cell)))
                {
                    walkDistance += 10; //apply a fixed 10 cell walk penalty when the animal has to be penned
                }
            }


            var animalBaseSpeed = animal.GetStatValue(StatDefOf.MoveSpeed);
            var pawnPaseSpeed   = pawn.GetStatValue(StatDefOf.MoveSpeed);

            var animalMountedSpeed = GiddyUpCore.Stats.StatPart_Riding.GetRidingSpeed(animalBaseSpeed, animal, pawn);


            float timeNeeded = walkDistance / pawnPaseSpeed + rideDistance / animalMountedSpeed;

            return(timeNeeded);
        }
Exemplo n.º 7
0
        //uses abstract unit of time. Real time values aren't needed, only relative values.
        private static float CalculateTimeNeeded(Pawn pawn, ref LocalTargetInfo target, LocalTargetInfo secondTarget, float firstToSecondTargetDistance, Pawn animal, bool firstTargetNoMount, bool secondTargetNoMount, Area_GU areaDropAnimal)
        {
            float walkDistance = DistanceUtility.QuickDistance(pawn.Position, animal.Position);
            float rideDistance = DistanceUtility.QuickDistance(animal.Position, target.Cell);

            if (firstTargetNoMount && areaDropAnimal != null)
            {
                rideDistance = 0;
                IntVec3 parkLoc = DistanceUtility.getClosestAreaLoc(animal.Position, areaDropAnimal);
                rideDistance += DistanceUtility.QuickDistance(animal.Position, parkLoc);
                walkDistance += DistanceUtility.QuickDistance(parkLoc, target.Cell);
                walkDistance += firstToSecondTargetDistance;
            }
            else if (secondTargetNoMount && secondTarget != null && secondTarget.IsValid && areaDropAnimal != null)
            {
                IntVec3 parkLoc = DistanceUtility.getClosestAreaLoc(target.Cell, areaDropAnimal);
                rideDistance += DistanceUtility.QuickDistance(target.Cell, parkLoc);
                walkDistance += DistanceUtility.QuickDistance(parkLoc, secondTarget.Cell);
            }
            else
            {
                rideDistance += firstToSecondTargetDistance;
            }

            int adjustedTicksPerMove = TicksPerMoveUtility.adjustedTicksPerMove(pawn, animal, true);

            float timeNeeded = walkDistance * pawn.TicksPerMoveDiagonal + rideDistance * adjustedTicksPerMove;

            return(timeNeeded);
        }
Exemplo n.º 8
0
        static void Postfix(Pawn_JobTracker __instance, ref ThinkResult __result)
        {
            Pawn pawn = Traverse.Create(__instance).Field("pawn").GetValue <Pawn>();

            if (!pawn.IsColonistPlayerControlled)
            {
                return;
            }
            if (__result.Job == null)
            {
                return;
            }
            if (__result.Job.def == GUC_JobDefOf.Mount)
            {
                return;
            }
            if (pawn.Drafted)
            {
                return;
            }
            if (pawn.InMentalState)
            {
                return;
            }

            LocalTargetInfo target  = null;
            LocalTargetInfo targetB = null;

            //For some jobs the first target is B, and the second A.
            if (__result.Job.def == JobDefOf.TendPatient || __result.Job.def == JobDefOf.Refuel)
            {
                target  = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.B);
                targetB = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A);
            }
            else if (__result.Job.def == JobDefOf.DoBill && !__result.Job.targetQueueB.NullOrEmpty())
            {
                target  = __result.Job.targetQueueB[0];
                targetB = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A);
            }
            else
            {
                target  = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A);
                targetB = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.B);
            }



            if (!target.IsValid)
            {
                return;
            }
            Area_GU area = (Area_GU)pawn.Map.areaManager.GetLabeled(Base.NOMOUNT_LABEL);

            //TODO: make sure mounts are parked of when pawn wants to enter area with mount.

            if (Base.Instance == null)
            {
                return;
            }
            ExtendedDataStorage store    = Base.Instance.GetExtendedDataStorage();
            ExtendedPawnData    pawnData = store.GetExtendedDataFor(pawn);

            if (store == null || pawnData == null)
            {
                return;
            }
            if (pawnData.wasRidingToJob)
            {
                pawnData.wasRidingToJob = false;
                return;
            }

            if (pawn.mindState != null && pawn.mindState.duty != null && (pawn.mindState.duty.def == DutyDefOf.TravelOrWait || pawn.mindState.duty.def == DutyDefOf.TravelOrLeave))
            {
                return;
            }

            Pawn bestChoiceAnimal = pawnData.mount;
            //Pawn bestChoiceAnimal = null;

            float pawnTargetDistance = DistanceUtility.QuickDistance(pawn.Position, target.Cell);
            //Log.Message("pawnTargetDistance: " + pawnTargetDistance);
            float firstToSecondTargetDistance = 0;

            if (__result.Job.def == JobDefOf.HaulToCell || __result.Job.def == JobDefOf.HaulToContainer)
            {
                if (targetB.IsValid)
                {
                    firstToSecondTargetDistance = DistanceUtility.QuickDistance(target.Cell, targetB.Cell);
                }
            }

            float totalDistance = pawnTargetDistance + firstToSecondTargetDistance;



            if (totalDistance > Base.minAutoMountDistance)
            {
                if (pawnData.mount == null)
                {
                    bestChoiceAnimal = GetBestChoiceAnimal(pawn, target, targetB, pawnTargetDistance, firstToSecondTargetDistance, store);
                }

                if (bestChoiceAnimal != null)
                {
                    __result = InsertMountingJobs(pawn, bestChoiceAnimal, target, targetB, ref pawnData, store.GetExtendedDataFor(bestChoiceAnimal), __instance, __result);
                }

                //Log.Message("timeNeededOriginal: " + timeNeededOriginal);
                //Log.Message("adjusted ticks per move: " + TicksPerMoveUtility.adjustedTicksPerMove(pawn, closestAnimal, true));
                //Log.Message("original ticks per move: " + pawn.TicksPerMoveDiagonal);
            }
        }
Exemplo n.º 9
0
        //Gets animal that'll get the pawn to the target the quickest. Returns null if no animal is found or if walking is faster.
        static Pawn GetBestChoiceAnimal(Pawn pawn, LocalTargetInfo target, LocalTargetInfo secondTarget, float pawnTargetDistance, float firstToSecondTargetDistance, ExtendedDataStorage store)
        {
            //float minDistance = float.MaxValue;
            Pawn             closestAnimal       = null;
            float            timeNeededMin       = (pawnTargetDistance + firstToSecondTargetDistance) * pawn.TicksPerMoveDiagonal;
            ExtendedPawnData pawnData            = store.GetExtendedDataFor(pawn);
            bool             firstTargetNoMount  = false;
            bool             secondTargetNoMount = false;

            Area_GU areaNoMount    = (Area_GU)pawn.Map.areaManager.GetLabeled(Base.NOMOUNT_LABEL);
            Area_GU areaDropAnimal = (Area_GU)pawn.Map.areaManager.GetLabeled(Base.DROPANIMAL_LABEL);

            if (areaNoMount != null && areaNoMount.ActiveCells.Contains(target.Cell))
            {
                firstTargetNoMount = true;
                if (pawnTargetDistance < Base.minAutoMountDistance)
                {
                    return(null);
                }
            }


            //If owning an animal, prefer this animal if it still gets you to the goal quicker than walking.
            //This'll make sure pawns prefer the animals they were already riding previously.
            if (pawnData.owning != null && pawnData.owning.Spawned && !AnimalNotAvailable(pawnData.owning) && pawn.CanReserve(pawnData.owning))
            {
                if (CalculateTimeNeeded(pawn, ref target, secondTarget, firstToSecondTargetDistance, pawnData.owning, firstTargetNoMount, secondTargetNoMount, areaDropAnimal) < timeNeededMin)
                {
                    return(pawnData.owning);
                }
            }
            //Otherwise search the animal on the map that gets you to the goal the quickest
            foreach (Pawn animal in from p in pawn.Map.mapPawns.AllPawnsSpawned
                     where p.RaceProps.Animal && IsMountableUtility.isMountable(p) && p.CurJob != null && p.CurJob.def != GUC_JobDefOf.Mounted
                     select p)
            {
                if (AnimalNotAvailable(animal) || !pawn.CanReserve(animal))
                {
                    continue;
                }
                float distanceFromAnimal = DistanceUtility.QuickDistance(animal.Position, target.Cell);
                if (!firstTargetNoMount)
                {
                    distanceFromAnimal += firstToSecondTargetDistance;
                }
                if (distanceFromAnimal < Base.minAutoMountDistanceFromAnimal)
                {
                    continue;
                }
                ExtendedPawnData animalData = store.GetExtendedDataFor(animal);
                if (animalData.ownedBy != null)
                {
                    continue;
                }
                if (!animalData.mountableByMaster && !animalData.mountableByAnyone)
                {
                    continue;
                }
                else if (!animalData.mountableByAnyone && animalData.mountableByMaster)
                {
                    if (animal.playerSettings != null && animal.playerSettings.master != pawn)
                    {
                        continue;
                    }
                }

                float timeNeeded = CalculateTimeNeeded(pawn, ref target, secondTarget, firstToSecondTargetDistance, animal, firstTargetNoMount, secondTargetNoMount, areaDropAnimal);

                if (timeNeeded < timeNeededMin)
                {
                    closestAnimal = animal;
                    timeNeededMin = timeNeeded;
                }
            }
            return(closestAnimal);
        }
Exemplo n.º 10
0
 public static IntVec3 getClosestAreaLoc(Pawn pawn, Area_GU areaFound)
 {
     return(getClosestAreaLoc(pawn.Position, areaFound));
 }
Exemplo n.º 11
0
        static void Postfix(JobDriver __instance)
        {
            if (__instance.pawn.Map == null)
            {
                return;
            }
            List <Toil> toils = Traverse.Create(__instance).Field("toils").GetValue <List <Toil> >();

            if (__instance.pawn.Faction != Faction.OfPlayer || __instance.pawn.Drafted)
            {
                return;
            }
            ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage();

            if (store == null)
            {
                return;
            }
            ExtendedPawnData pawnData = store.GetExtendedDataFor(__instance.pawn);


            Area_GU areaNoMount    = (Area_GU)__instance.pawn.Map.areaManager.GetLabeled(Base.NOMOUNT_LABEL);
            Area_GU areaDropAnimal = (Area_GU)__instance.pawn.Map.areaManager.GetLabeled(Base.DROPANIMAL_LABEL);
            bool    startedPark    = false;
            IntVec3 originalLoc    = new IntVec3();
            IntVec3 parkLoc        = new IntVec3();

            if (pawnData.mount != null && areaNoMount != null && areaDropAnimal != null)
            {
                foreach (Toil toil in toils)
                {
                    //checkedToil makes sure the ActiveCells.Contains is only called once, preventing performance impact.
                    bool checkedToil = false;
                    toil.AddPreTickAction(delegate
                    {
                        if (!checkedToil && pawnData.mount != null && areaDropAnimal.ActiveCells.Count() > 0 && areaNoMount.ActiveCells.Contains(toil.actor.pather.Destination.Cell))
                        {
                            //Toil parkToil = ParkToil(__instance, toils, pawnData, areaDropAnimal, toils[__instance.CurToilIndex]);
                            //toils.Add(parkToil);
                            parkLoc     = DistanceUtility.getClosestAreaLoc(toil.actor.pather.Destination.Cell, areaDropAnimal);
                            originalLoc = toil.actor.pather.Destination.Cell;
                            if (toil.actor.Map.reachability.CanReach(toil.actor.Position, parkLoc, PathEndMode.OnCell, TraverseParms.For(TraverseMode.PassDoors, Danger.Deadly, false)))
                            {
                                toil.actor.pather.StartPath(parkLoc, PathEndMode.OnCell);
                                startedPark = true;
                            }
                            else
                            {
                                Messages.Message("GU_RR_NotReachable_DropAnimal_Message".Translate(), new RimWorld.Planet.GlobalTargetInfo(parkLoc, toil.actor.Map), MessageTypeDefOf.NegativeEvent);
                            }
                        }
                        checkedToil = true;
                        if (startedPark && toil.actor.pather.nextCell == parkLoc)
                        {
                            pawnData.mount = null;
                            toil.actor.pather.StartPath(originalLoc, PathEndMode.ClosestTouch);
                            if (pawnData.owning != null)
                            {
                                ExtendedPawnData animalData = store.GetExtendedDataFor(pawnData.owning);
                                animalData.ownedBy          = null;
                                pawnData.owning             = null;
                            }
                        }
                    });
                }
            }
        }
Exemplo n.º 12
0
        static void Postfix(JobDriver __instance, ref List <Toil> ___toils)
        {
            if (__instance.pawn.Map == null)
            {
                return;
            }
            if (__instance.pawn.Faction != Faction.OfPlayer || __instance.pawn.Drafted)
            {
                return;
            }
            ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage();

            if (store == null)
            {
                return;
            }
            ExtendedPawnData pawnData = store.GetExtendedDataFor(__instance.pawn);


            Area_GU     areaNoMount    = (Area_GU)__instance.pawn.Map.areaManager.GetLabeled(Base.NOMOUNT_LABEL);
            Area_GU     areaDropAnimal = (Area_GU)__instance.pawn.Map.areaManager.GetLabeled(Base.DROPANIMAL_LABEL);
            bool        startedPark    = false;
            IntVec3     originalLoc    = new IntVec3();
            IntVec3     parkLoc        = new IntVec3();
            PathEndMode endMode;

            if (pawnData.mount != null && areaNoMount != null)
            {
                foreach (Toil toil in ___toils)
                {
                    //checkedToil makes sure the ActiveCells.Contains is only called once, preventing performance impact.
                    toil.AddPreTickAction(delegate
                    {
                        if (__instance.pawn.IsHashIntervalTick(60) && !startedPark && pawnData.mount != null && __instance.pawn.CurJobDef != JobDefOf.RopeToPen && areaNoMount.ActiveCells.Contains(toil.actor.pather.Destination.Cell))
                        {
                            originalLoc = toil.actor.pather.Destination.Cell;
                            if (AnimalPenUtility.NeedsToBeManagedByRope(pawnData.mount) || areaDropAnimal == null)
                            {
                                startedPark = TryParkAnimalPen(__instance, pawnData, ref parkLoc, toil);
                            }
                            else
                            {
                                startedPark = TryParkAnimalDropSpot(areaDropAnimal, ref parkLoc, toil);
                            }
                        }
                        //checkedToil = true;
                        if (startedPark && toil.actor.pather.nextCell == parkLoc)
                        {
                            pawnData.mount = null;
                            toil.actor.pather.StartPath(originalLoc, PathEndMode.OnCell);
                            if (pawnData.owning != null)
                            {
                                ExtendedPawnData animalData = store.GetExtendedDataFor(pawnData.owning);
                                animalData.ownedBy          = null;
                                pawnData.owning             = null;
                            }
                        }
                    });
                }
            }
        }