Beispiel #1
0
        static void Postfix(Pawn_JobTracker __instance, ref ThinkResult __result)
        {
            Pawn pawn = Traverse.Create(__instance).Field("pawn").GetValue <Pawn>();

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

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

            if (pawnData.owning == null || !pawnData.owning.Spawned || pawnData.owning.Downed || pawnData.owning.Dead || pawnData.mount != null)
            {
                return;
            }

            LocalTargetInfo target             = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A);
            float           pawnTargetDistance = DistanceUtility.QuickDistance(pawnData.owning.Position, target.Cell);

            if (pawnTargetDistance > 10 || __result.Job.def == JobDefOf.LayDown || __result.Job.def == JobDefOf.Research || pawn.InMentalState || pawn.Dead || pawn.Downed)
            {
                if (pawnData.owning.jobs.curJob != null && pawnData.owning.jobs.curJob.def == JobDefOf.Wait)
                {
                    pawnData.owning.jobs.EndCurrentJob(JobCondition.InterruptForced);
                }
                ExtendedPawnData animalData = store.GetExtendedDataFor(pawnData.owning);
                pawnData.owning    = null;
                animalData.ownedBy = null;
            }
        }
Beispiel #2
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);
        }
Beispiel #3
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);
        }
Beispiel #4
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);
            }
        }
Beispiel #5
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);
        }
Beispiel #6
0
        static void Postfix(Pawn_JobTracker __instance, ref ThinkResult __result, ref Pawn ___pawn)
        {
            if (!___pawn.IsColonistPlayerControlled || !___pawn.RaceProps.Humanlike)
            {
                return;
            }
            if (__result.Job == null)
            {
                return;
            }
            if (__result.Job.def == GUC_JobDefOf.Mount)
            {
                return;
            }
            if (___pawn.Drafted)
            {
                return;
            }
            if (___pawn.InMentalState)
            {
                return;
            }
            if (___pawn.IsBorrowedByAnyFaction())
            {
                return;
            }
            ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage();

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

            if (pawnData.mount != null)
            {
                return;
            }

            LocalTargetInfo firstTarget  = null;
            LocalTargetInfo secondTarget = null;

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

            if (Base.Instance == null)
            {
                return;
            }
            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 = null;

            float pawnTargetDistance          = DistanceUtility.QuickDistance(___pawn.Position, firstTarget.Cell);
            float firstToSecondTargetDistance = 0;

            if (__result.Job.def == JobDefOf.HaulToCell || __result.Job.def == JobDefOf.HaulToContainer)
            {
                if (secondTarget.IsValid)
                {
                    firstToSecondTargetDistance = DistanceUtility.QuickDistance(firstTarget.Cell, secondTarget.Cell);
                }
            }
            float totalDistance = pawnTargetDistance + firstToSecondTargetDistance;

            if (totalDistance > Base.minAutoMountDistance)
            {
                bestChoiceAnimal = GetBestChoiceAnimal(___pawn, firstTarget, secondTarget, pawnTargetDistance, firstToSecondTargetDistance, store);
                if (bestChoiceAnimal != null)
                {
                    __result = InsertMountingJobs(___pawn, bestChoiceAnimal, firstTarget, secondTarget, 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);
            }
        }