Пример #1
0
        private Toil dismount()
        {
            ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage();

            Toil toil = new Toil();

            toil.defaultCompleteMode = ToilCompleteMode.Never;
            toil.initAction          = delegate {
                if (store == null)
                {
                    ReadyForNextToil();
                    return;
                }
                ExtendedPawnData pawnData = store.GetExtendedDataFor(pawn);
                if (pawnData.mount != null)
                {
                    pawnData.mount.jobs.EndCurrentJob(JobCondition.InterruptForced);
                }
                ReadyForNextToil();
            };
            return(toil);
        }
Пример #2
0
        public static void RemoveAllLinks(this Pawn pawn)
        {
            ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage();

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

            pawnData.isActive = false;
            pawn.RemoveRemoteControlLink();
            if (pawn.ControllingAI() != null)
            {
                pawn.ControllingAI().controlledMechs.Remove(pawn);
                pawn.ControllingAI().hackedMechs.Remove(pawn);
                if (pawnData.originalFaction != null)
                {
                    pawn.RevertToFaction(pawnData.originalFaction);
                }
            }
        }
Пример #3
0
 static bool Prefix(Pawn __instance, ref List <WorkTypeDef> __result)
 {
     if (__instance.IsHacked())
     {
         List <WorkTypeDef>  shouldForbid = new List <WorkTypeDef>();
         ExtendedDataStorage store        = Base.Instance.GetExtendedDataStorage();
         if (store != null)
         {
             ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(__instance);
             foreach (WorkTypeDef def in DefDatabase <WorkTypeDef> .AllDefs)
             {
                 if (pawnData.workTypes == null || !pawnData.workTypes.Contains(def))
                 {
                     shouldForbid.Add(def);
                 }
             }
             __result = shouldForbid;
             return(false);
         }
     }
     return(true);
 }
Пример #4
0
        public static void InitWorkTypesAndSkills(Pawn pawn, ExtendedPawnData pawnData)
        {
            if (pawnData.workTypes == null)
            {
                pawnData.workTypes = new List <WorkTypeDef>();
            }
            if (pawn.skills == null)
            {
                pawn.skills = new Pawn_SkillTracker(pawn);
            }
            if (pawn.workSettings == null)
            {
                pawn.workSettings = new Pawn_WorkSettings(pawn);
                pawn.workSettings.EnableAndInitialize();
            }

            if (pawn.skills != null)
            {
                if (pawn.skills.GetSkill(SkillDefOf.Shooting).Level == 0)
                {
                    pawn.skills.GetSkill(SkillDefOf.Shooting).Level = 8;
                }
                if (pawn.skills.GetSkill(SkillDefOf.Melee).Level == 0)
                {
                    pawn.skills.GetSkill(SkillDefOf.Melee).Level = 4;
                }
            }
            if (pawn.workSettings != null)
            {
                var huntingWorkType = WorkTypeDefOf.Hunting;
                if (pawnData.workTypes == null)
                {
                    // Log.Message("WTHACK: " + pawn.Name);
                    pawnData.workTypes = new List <WorkTypeDef>();
                }
                pawnData.workTypes.Add(huntingWorkType);
                pawn.workSettings.SetPriority(huntingWorkType, 3);
            }
        }
        static void Postfix(TransferableOneWayWidget __instance, ref bool anythingChanged)
        {
            //Reflection is needed here to access the private struct inside TransferableOneWayWidget
            Type  sectionType = Traverse.Create(__instance).Type("Section").GetValue <Type>();
            IList sections    = Traverse.Create(__instance).Field("sections").GetValue <IList>();

            foreach (object s in sections)
            {
                List <TransferableOneWay> tf = sectionType.GetField("cachedTransferables").GetValue(s) as List <TransferableOneWay>;
            }
            if (sections.Count < 4)
            {
                return;
            }
            object section = sections[3]; //section 3 only yields animals, which are needed in this case

            List <TransferableOneWay> cachedTransferables = sectionType.GetField("cachedTransferables").GetValue(section) as List <TransferableOneWay>;

            if (cachedTransferables != null)
            {
                foreach (TransferableOneWay tow in cachedTransferables)
                {
                    Pawn towPawn = tow.AnyThing as Pawn;
                    if (towPawn == null)
                    {
                        continue;
                    }
                    if (tow.CountToTransfer == -1)
                    {
                        ExtendedPawnData PawnData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(towPawn);
                        if (PawnData.selectedForCaravan == true)
                        {
                            anythingChanged = true;
                            Traverse.Create(tow).Property("CountToTransfer").SetValue(1);
                        }
                    }
                }
            }
        }
Пример #6
0
        private static void parkAnimal(Pawn_JobTracker __instance, Pawn pawn, ExtendedPawnData pawnData)
        {
            Area_Stable areaFound = (Area_Stable)pawn.Map.areaManager.GetLabeled(Base.STABLE_LABEL);
            IntVec3     targetLoc = pawn.Position;

            if (areaFound != null)
            {
                targetLoc = DistanceUtility.getClosestAreaLoc(pawn, areaFound);
            }

            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 (animalDuty != null)
            {
                animalDuty.focus = new LocalTargetInfo(targetLoc);
            }
        }
Пример #7
0
        private static Gizmo GetRemoteControlActivateGizmo(Pawn pawn)
        {
            Command_Target command_Target = new Command_Target();

            command_Target.defaultLabel    = "WTH_Gizmo_RemoteControlActivate_Label".Translate();
            command_Target.defaultDesc     = "WTH_Gizmo_RemoteControlActivate_Description".Translate();
            command_Target.targetingParams = GetTargetingParametersForHacking();
            command_Target.hotKey          = KeyBindingDefOf.Misc5;
            if (pawn.Drafted)
            {
                command_Target.Disable("WTH_Reason_PawnCannotBeDrafted".Translate());
            }
            command_Target.icon = ContentFinder <Texture2D> .Get(("Things/MechControllerBelt"));

            command_Target.action = delegate(Thing target)
            {
                if (target is Pawn)
                {
                    pawn.jobs.EndCurrentJob(JobCondition.InterruptForced, false);
                    Pawn             mech     = (Pawn)target;
                    ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn);
                    ExtendedPawnData mechData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(mech);
                    pawnData.remoteControlLink = mech;
                    mechData.remoteControlLink = pawn;
                    mechData.isActive          = true;
                    mech.drafter.Drafted       = true;
                    Find.Selector.ClearSelection();
                    Find.Selector.Select(mech);
                    if (pawn.GetLord() == null || pawn.GetLord().LordJob == null)
                    {
                        LordMaker.MakeNewLord(Faction.OfPlayer, new LordJob_ControlMechanoid(), pawn.Map, new List <Pawn> {
                            pawn
                        });
                        pawn.mindState.duty.focus = mech;
                    }
                }
            };
            return(command_Target);
        }
        public override bool TryMakePreToilReservations(bool errorOnFailed)
        {
            //For automatic mounting, reserve the mount aswell as targets of the job the pawn is riding to (target B and possibly C).

            bool result = true;

            ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage();

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

            if (pawnData.targetJob == null)
            {
                return(true);
            }
            result             = ReserveUtility.ReserveEveryThingOfJob(pawnData.targetJob, this);
            pawnData.targetJob = null;
            return(result);
        }
        static bool Prefix(ShieldBelt __instance)
        {
            bool             ShouldDisplay = Traverse.Create(__instance).Property("ShouldDisplay").GetValue <bool>();
            ExtendedPawnData pawnData      = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(__instance.Wearer);
            Pawn             mount         = pawnData.mount;

            if (mount == null)
            {
                return(true);
            }

            if (__instance.ShieldState == ShieldState.Active && ShouldDisplay)
            {
                float    energy = Traverse.Create(__instance).Field("energy").GetValue <float>();
                int      lastAbsorbDamageTick = Traverse.Create(__instance).Field("lastAbsorbDamageTick").GetValue <int>();
                Vector3  impactAngleVect      = Traverse.Create(__instance).Field("impactAngleVect").GetValue <Vector3>();
                Material BubbleMat            = MaterialPool.MatFrom("Other/ShieldBubble", ShaderDatabase.Transparent);
                ;

                float   num    = Mathf.Lerp(1.2f, 1.55f, energy);
                Vector3 vector = __instance.Wearer.Drawer.DrawPos;
                vector.z += pawnData.drawOffset;
                vector.y  = Altitudes.AltitudeFor(AltitudeLayer.MoteOverhead);
                int num2 = Find.TickManager.TicksGame - lastAbsorbDamageTick;
                if (num2 < 8)
                {
                    float num3 = (float)(8 - num2) / 8f * 0.05f;
                    vector += impactAngleVect * num3;
                    num    -= num3;
                }
                float     angle  = (float)Rand.Range(0, 360);
                Vector3   s      = new Vector3(num, 1f, num);
                Matrix4x4 matrix = default(Matrix4x4);
                matrix.SetTRS(vector, Quaternion.AngleAxis(angle, Vector3.up), s);
                Graphics.DrawMesh(MeshPool.plane10, matrix, BubbleMat, 0);
            }
            return(false);
        }
Пример #10
0
        private static void Cleanup(Pawn pawn, HediffDef removedHediff)
        {
            if (removedHediff == WTH_DefOf.WTH_TurretModule && pawn.health.hediffSet.HasHediff(WTH_DefOf.WTH_MountedTurret))
            {
                pawn.health.RemoveHediff(pawn.health.hediffSet.hediffs.FirstOrDefault((Hediff h) => h.def == WTH_DefOf.WTH_MountedTurret));
            }
            ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn);

            if (removedHediff.GetModExtension <DefModExtension_Hediff_WorkModule>() is DefModExtension_Hediff_WorkModule ext)
            {
                pawnData.workTypes.RemoveAll((WorkTypeDef def) => ext.workTypes.Contains(def));
            }
            if (!pawn.health.hediffSet.hediffs.Exists((Hediff h) => h.def.HasModExtension <DefModExtension_Hediff_WorkModule>()))
            {
                pawnData.workTypes = null;
                pawn.skills        = null;
                pawn.workSettings  = null;
            }
            if (removedHediff == WTH_DefOf.WTH_RepairModule)
            {
                Base.RemoveComps(pawn);
            }
        }
        private Toil TalkToAnimal(TargetIndex tameeInd)
        {
            Toil toil = new Toil();

            toil.AddFailCondition(delegate { return(Mount.CurJob.def != BM_JobDefOf.Mounted_BattleMount); });
            toil.initAction = delegate
            {
                Pawn actor = toil.GetActor();
                actor.interactions.TryInteractWith(Mount, InteractionDefOf.AnimalChat);
            };
            toil.defaultCompleteMode = ToilCompleteMode.Delay;
            toil.defaultDuration     = 150;
            toil.AddFinishAction(delegate {
                if (Mount.CurJob != null && Mount.CurJob.def == BM_JobDefOf.Mounted_BattleMount)
                {
                    Pawn actor = toil.GetActor();
                    ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(actor);
                    pawnData.mount            = (Pawn)((Thing)actor.CurJob.GetTarget(tameeInd));
                    TextureUtility.setDrawOffset(pawnData);
                }
            });
            return(toil);
        }
        public static int adjustTicksPerMove(int num2, int index, List <Pawn> pawns)
        {
            ExtendedDataStorage store = GiddyUpCore.Base.Instance.GetExtendedDataStorage();

            if (store == null || pawns == null || pawns.Count == 0)
            {
                return(num2);
            }
            Pawn pawn = pawns[index];

            ExtendedPawnData pawnData = store.GetExtendedDataFor(pawn);

            if (pawnData != null && pawnData.caravanMount != null && pawn.ridingCaravanMount())
            {
                //Log.Message("Returning adjusted ticks per move: " + "TicsPerMove was: " + num2 + ", but now: " + TicksPerMoveUtility.adjustedTicksPerMove(pawn, pawnData.caravanMount, true));
                return(TicksPerMoveUtility.adjustedTicksPerMove(pawn, pawnData.caravanMount, true));
            }
            else
            {
                //Log.Message("Returning default ticks per move: " + num2);
                return(num2);
            }
        }
Пример #13
0
        private static ThinkResult InsertMountingJobs(Pawn pawn, Pawn closestAnimal, LocalTargetInfo target, LocalTargetInfo secondTarget, ref ExtendedPawnData pawnData, ExtendedPawnData animalData, Pawn_JobTracker __instance, ThinkResult __result)
        {
            ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage();

            //__instance.jobQueue.EnqueueFirst(dismountJob);
            if (pawn.CanReserve(target) && pawn.CanReserve(closestAnimal))
            {
                Job oldJob = __result.Job;

                ExtendedPawnData pawnDataTest = store.GetExtendedDataFor(pawn);
                pawnDataTest.targetJob = oldJob;
                Job mountJob  = new Job(GUC_JobDefOf.Mount, closestAnimal);
                Job rideToJob = new Job(GU_RR_DefOf.RideToJob, closestAnimal, target);

                if (pawnData.mount != null)
                {
                    __instance.jobQueue.EnqueueFirst(oldJob);

                    if (__result.Job.def != JobDefOf.Hunt)//Don't ride to job when hunting.
                    {
                        __result = new ThinkResult(rideToJob, __result.SourceNode, __result.Tag, false);
                    }
                }
                else
                {
                    __instance.jobQueue.EnqueueFirst(oldJob);

                    if (__result.Job.def != JobDefOf.Hunt)//Don't ride to job when hunting.
                    {
                        __instance.jobQueue.EnqueueFirst(rideToJob);
                    }

                    __result = new ThinkResult(mountJob, __result.SourceNode, __result.Tag, false);
                }
            }
            return(__result);
        }
Пример #14
0
        static bool Prefix(Pawn_StoryTracker __instance, ref List <WorkTypeDef> __result)
        {
            Pawn pawn = Traverse.Create(__instance).Field("pawn").GetValue <Pawn>();

            if (pawn.RaceProps.IsMechanoid && pawn.IsHacked())
            {
                List <WorkTypeDef>  shouldForbid = new List <WorkTypeDef>();
                ExtendedDataStorage store        = Base.Instance.GetExtendedDataStorage();
                if (store != null)
                {
                    ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn);
                    foreach (WorkTypeDef def in DefDatabase <WorkTypeDef> .AllDefs)
                    {
                        if (pawnData.workTypes == null || !pawnData.workTypes.Contains(def))
                        {
                            shouldForbid.Add(def);
                        }
                    }
                    __result = shouldForbid;
                    return(false);
                }
            }
            return(true);
        }
        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);
            float           riderMountDistance = DistanceUtility.QuickDistance(pawnData.owning.Position, pawn.Position);

            if (riderMountDistance > 12 || pawnTargetDistance > 12 || __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;
            }
        }
Пример #16
0
        protected override void PostSuccessfulApply(Pawn pawn, BodyPartRecord part, Pawn billDoer, List <Thing> ingredients, Bill bill)
        {
            base.PostSuccessfulApply(pawn, part, billDoer, ingredients, bill);
            ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn);

            if (pawnData.workTypes == null)
            {
                pawnData.workTypes = new List <WorkTypeDef>();
            }
            if (pawn.skills == null)
            {
                pawn.skills = new Pawn_SkillTracker(pawn);
            }

            if (pawn.workSettings == null)
            {
                pawn.workSettings = new Pawn_WorkSettings(pawn);
                pawn.workSettings.EnableAndInitialize();
            }
            Utilities.InitWorkTypesAndSkills(pawn, pawnData);
            if (bill.recipe.addsHediff.GetModExtension <DefModExtension_Hediff_WorkModule>() is DefModExtension_Hediff_WorkModule modExt)
            {
                foreach (WorkTypeDef workType in modExt.workTypes)
                {
                    pawnData.workTypes.Add(workType);
                    pawn.workSettings.SetPriority(workType, 3);
                    if (modExt.skillLevel > 0)
                    {
                        foreach (SkillDef skillDef in workType.relevantSkills)
                        {
                            pawn.skills.GetSkill(skillDef).Level = modExt.skillLevel;
                        }
                    }
                }
            }
        }
Пример #17
0
        private static Gizmo CreateGizmo_Work(Pawn __instance, ExtendedPawnData pawnData)
        {
            string disabledReason = "";
            bool   disabled       = false;
            Gizmo  gizmo          = new Command_Toggle
            {
                defaultLabel   = "WTH_Gizmo_Work_Label".Translate(),
                defaultDesc    = "WTH_Gizmo_Work_Description".Translate(),
                disabled       = disabled,
                disabledReason = disabledReason,
                icon           = ContentFinder <Texture2D> .Get(("UI/" + "MechanoidWork"), true),
                isActive       = () => pawnData.canWorkNow,
                toggleAction   = () =>
                {
                    pawnData.canWorkNow = !pawnData.canWorkNow;
                    if (__instance.CurJob.def != WTH_DefOf.WTH_Mechanoid_Rest)
                    {
                        __instance.jobs.EndCurrentJob(JobCondition.InterruptForced);
                    }
                }
            };

            return(gizmo);
        }
Пример #18
0
        private Toil waitForRider()
        {
            Toil toil = new Toil();

            toil.defaultCompleteMode = ToilCompleteMode.Never;
            toil.tickAction          = delegate
            {
                //Log.Message("waiting for rider");

                riderData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(Rider);
                if (riderData.mount != null && riderData.mount == pawn)
                {
                    ReadyForNextToil();
                }
                if (Rider.CurJob.def != GUC_JobDefOf.Mount && Rider.CurJob.def != JobDefOf.Vomit && Rider.CurJob.def != JobDefOf.WaitMaintainPosture && Rider.CurJob.def != JobDefOf.SocialRelax && riderData.mount == null)
                {
                    Log.Message("cancel wait for rider, rider is not mounting, curJob: " + Rider.CurJob.def.defName);

                    shouldEnd = true;
                    ReadyForNextToil();
                }
            };
            return(toil);
        }
Пример #19
0
        static void Postfix(Pawn_HealthTracker __instance)
        {
            Pawn pawn = Traverse.Create(__instance).Field("pawn").GetValue <Pawn>();

            //If an enemy animal is downed, make it a wild animal so it can be rescued.
            if (pawn.RaceProps.Animal && pawn.Faction != null && !pawn.Faction.IsPlayer)
            {
                pawn.SetFaction(null);
            }

            //If the owner of an NPC mount is downed, let the animal flee
            if (pawn.RaceProps.Humanlike && pawn.Faction != null && !pawn.Faction.IsPlayer)
            {
                ExtendedDataStorage dataStorage = Base.Instance.GetExtendedDataStorage();
                if (dataStorage != null)
                {
                    ExtendedPawnData pawnData = dataStorage.GetExtendedDataFor(pawn);
                    if (pawnData != null && pawnData.owning != null && !pawnData.owning.Dead && pawnData.owning.Spawned && pawnData.owning.RaceProps.Animal)
                    {
                        pawnData.owning.mindState.mentalStateHandler.TryStartMentalState(MentalStateDefOf.PanicFlee);
                    }
                }
            }
        }
Пример #20
0
        private bool shouldCancelJob(ExtendedPawnData riderData)
        {
            if (interrupted)
            {
                //Log.Message("cancel job, shouldEnd called");
                return(true);
            }

            if (riderData == null || riderData.mount == null)
            {
                //Log.Message("riderData is null or riderData.mount is null");
                return(true);
            }

            Thing thing = pawn as Thing;

            if (Rider.Downed || Rider.Dead || pawn.Downed || pawn.Dead || pawn.IsBurning() || Rider.IsBurning())
            {
                //Log.Message("cancel job, rider downed or dead");
                return(true);
            }
            if (pawn.InMentalState || (Rider.InMentalState && Rider.MentalState.def != MentalStateDefOf.PanicFlee))
            {
                //Log.Message("cancel job, rider or mount in mental state");
                return(true);
            }
            if (!Rider.Spawned)
            {
                if (!Rider.IsColonist && !Rider.Dead)
                {
                    //Log.Message("rider not spawned, despawn");
                    pawn.ExitMap(false, CellRect.WholeMap(base.Map).GetClosestEdge(this.pawn.Position));
                    return(true);
                }
                else if (Rider.IsColonist && (Rider.CurJob == null || Rider.CurJob.def != JobDefOf.EnterTransporter))
                {
                    //Log.Message("rider moved to map, despawn");
                    pawn.ExitMap(true, CellRect.WholeMap(base.Map).GetClosestEdge(this.pawn.Position));
                    return(true);
                }
                else
                {
                    //Log.Message("rider died, dismount");
                    return(true);
                }
            }

            if (!Rider.Drafted && Rider.IsColonist) //TODO refactor this as a postfix in Giddy-up Caravan.
            {
                if ((Rider.mindState != null && Rider.mindState.duty != null && (Rider.mindState.duty.def == DutyDefOf.TravelOrWait || Rider.mindState.duty.def == DutyDefOf.TravelOrLeave)))
                {
                    if (riderData.caravanMount == pawn)
                    {
                        return(false);
                    }
                    return(true);
                    //if forming caravan, stay mounted.
                }
                else if (riderData.owning == pawn)
                {
                    //Log.Message("cancel job, rider not drafted while being colonist");
                    //Log.Message("riderData.owning: " + riderData.owning);
                    return(false);
                }
                else
                {
                    return(true);
                }
            }



            if (riderData.mount == null)
            {
                //Log.Message("cancel job, rider has no mount");
                return(true);
            }
            return(false);
        }
        protected override void SetValue(Pawn pawn, bool value)
        {
            ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn);

            pawnData.mountableByMaster = value;
        }
Пример #22
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);
            }
        }
Пример #23
0
        private static void handleAnimal(float num, Rect buttonRect, Pawn animal, List <Pawn> pawns)
        {
            ExtendedPawnData animalData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animal);

            Text.Anchor = TextAnchor.MiddleLeft;

            List <FloatMenuOption> list = new List <FloatMenuOption>();

            string buttonText = "GU_Car_Set_Rider".Translate();

            bool canMount = true;

            if (!animalData.selectedForCaravan)
            {
                buttonText = "GU_Car_AnimalNotSelected".Translate();
                canMount   = false;
            }
            if (animal.ageTracker.CurLifeStageIndex != animal.RaceProps.lifeStageAges.Count - 1)
            {
                buttonText = "GU_Car_NotFullyGrown".Translate();
                canMount   = false;
            }
            if (!(animal.training != null && animal.training.IsCompleted(TrainableDefOf.Obedience)))
            {
                buttonText = "GU_Car_NeedsObedience".Translate();
                canMount   = false;
            }
            bool found = GiddyUpCore.Base.animalSelecter.Value.InnerList.TryGetValue(animal.def.defName, out AnimalRecord value);

            if (found && !value.isSelected)
            {
                buttonText = "GU_Car_NotInModOptions".Translate();
                canMount   = false;
            }

            if (animalData.caravanRider != null)
            {
                ExtendedPawnData riderData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animalData.caravanRider);
                if (riderData.selectedForCaravan)
                {
                    buttonText = animalData.caravanRider.Name.ToStringShort;
                }
            }
            if (!canMount)
            {
                Widgets.ButtonText(buttonRect, buttonText, false, false, false);
            }
            else if (Widgets.ButtonText(buttonRect, buttonText, true, false, true))
            {
                foreach (Pawn pawn in pawns)
                {
                    if (pawn.IsColonist)
                    {
                        ExtendedPawnData pawnData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn);
                        if (!pawnData.selectedForCaravan)
                        {
                            list.Add(new FloatMenuOption(pawn.Name.ToStringShort + " (" + "GU_Car_PawnNotSelected".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null));
                            continue;
                        }

                        if (pawnData.caravanMount != null)
                        {
                            continue;
                        }
                        list.Add(new FloatMenuOption(pawn.Name.ToStringShort, delegate
                        {
                            {
                                if (animalData.caravanRider != null)
                                {
                                    ExtendedPawnData riderData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animalData.caravanRider);
                                    riderData.caravanMount     = null;
                                }

                                pawnData.caravanMount   = animal;
                                animalData.caravanRider = pawn;
                            }
                        }, MenuOptionPriority.High, null, null, 0f, null, null));
                    }
                }
                list.Add(new FloatMenuOption("GU_Car_No_Rider".Translate(), delegate
                {
                    {
                        if (animalData.caravanRider != null)
                        {
                            ExtendedPawnData riderData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animalData.caravanRider);
                            riderData.caravanMount     = null;
                        }
                        animalData.caravanRider = null;
                    }
                }, MenuOptionPriority.Low, null, null, 0f, null, null));
                Find.WindowStack.Add(new FloatMenu(list));
            }
        }
        private static void handleAnimal(float num, Rect buttonRect, Pawn animal, List <Pawn> pawns, TransferableOneWay trad)
        {
            ExtendedPawnData animalData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animal);

            Text.Anchor = TextAnchor.MiddleLeft;

            List <FloatMenuOption> list = new List <FloatMenuOption>();

            string buttonText = "GU_Car_Set_Rider".Translate();

            bool canMount = true;



            if (!animalData.selectedForCaravan)
            {
                buttonText = "GU_Car_AnimalNotSelected".Translate();
                canMount   = false;
            }

            bool isMountable = IsMountableUtility.isMountable(animal, out IsMountableUtility.Reason reason);

            if (!isMountable)
            {
                if (reason == IsMountableUtility.Reason.NotFullyGrown)
                {
                    buttonText = "GU_Car_NotFullyGrown".Translate();
                    canMount   = false;
                }
                if (reason == IsMountableUtility.Reason.NeedsObedience)
                {
                    buttonText = "GU_Car_NeedsObedience".Translate();
                    canMount   = false;
                }
                if (reason == IsMountableUtility.Reason.NotInModOptions)
                {
                    buttonText = "GU_Car_NotInModOptions".Translate();
                    canMount   = false;
                }
            }

            if (animalData.caravanRider != null)
            {
                ExtendedPawnData riderData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animalData.caravanRider);
                if (riderData.selectedForCaravan)
                {
                    buttonText = animalData.caravanRider.Name.ToStringShort;
                }
            }
            if (!canMount)
            {
                Widgets.ButtonText(buttonRect, buttonText, false, false, false);
            }
            else if (Widgets.ButtonText(buttonRect, buttonText, true, false, true))
            {
                foreach (Pawn pawn in pawns)
                {
                    if (pawn.IsColonist)
                    {
                        ExtendedPawnData pawnData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn);
                        if (!pawnData.selectedForCaravan)
                        {
                            list.Add(new FloatMenuOption(pawn.Name.ToStringShort + " (" + "GU_Car_PawnNotSelected".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null));
                            continue;
                        }

                        if (pawnData.caravanMount != null)
                        {
                            continue;
                        }
                        list.Add(new FloatMenuOption(pawn.Name.ToStringShort, delegate
                        {
                            {
                                SelectMountRider(animalData, pawnData, animal, pawn);
                                Traverse.Create(trad).Property("CountToTransfer").SetValue(-1); //Setting this to -1 will make sure total weight is calculated again. it's set back to 1 shortly after
                                Log.Message("setting CountToTransfer to -1");
                                //if (animalData.caravanRider != null)
                                //{
                                //    ExtendedPawnData riderData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animalData.caravanRider);
                                //    riderData.caravanMount = null;
                                //}

                                //pawnData.caravanMount = animal;
                                //animalData.caravanRider = pawn;
                                //Traverse.Create(trad).Property("CountToTransfer").SetValue(-1); //Setting this to -1 will make sure total weight is calculated again. it's set back to 1 shortly after
                                //Log.Message("setting CountToTransfer to -1");
                                //animalData.selectedForCaravan = true;
                            }
                        }, MenuOptionPriority.High, null, null, 0f, null, null));
                    }
                }
                list.Add(new FloatMenuOption("GU_Car_No_Rider".Translate(), delegate
                {
                    {
                        ClearMountRider(animalData);
                        Traverse.Create(trad).Property("CountToTransfer").SetValue(-1); //Setting this to -1 will make sure total weight is calculated again. it's set back to 1 shortly after
                        Log.Message("setting CountToTransfer to -1");
                        //if (animalData.caravanRider != null)
                        //{
                        //    ExtendedPawnData riderData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animalData.caravanRider);
                        //    riderData.caravanMount = null;
                        //}
                        //animalData.caravanRider = null;
                        //Traverse.Create(trad).Property("CountToTransfer").SetValue(-1); //Setting this to -1 will make sure total weight is calculated again. it's set back to 1 shortly after
                        //Log.Message("setting CountToTransfer to -1");
                        //animalData.selectedForCaravan = true;
                    }
                }, MenuOptionPriority.Low, null, null, 0f, null, null));
                Find.WindowStack.Add(new FloatMenu(list));
            }
        }
Пример #25
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;
                            }
                        }
                    });
                }
            }
        }
Пример #26
0
        public override void SetValue(Pawn pawn, bool value, PawnTable table)
        {
            ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn);

            pawnData.mountableByAnyone = value;
        }
Пример #27
0
        public override bool GetValue(Pawn pawn)
        {
            ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn);

            return(pawnData.mountableByAnyone);
        }
Пример #28
0
        static void Postfix(Pawn_JobTracker __instance, ref ThinkResult __result, ref Pawn ___pawn)
        {
            if (___pawn.RaceProps.Animal && ___pawn.Faction != Faction.OfPlayer && ___pawn.Faction != null)
            {
                if (___pawn.GetLord() != null && (___pawn.GetLord().CurLordToil is LordToil_DefendPoint || ___pawn.GetLord().CurLordToil.GetType().Name == "LordToil_DefendTraderCaravan"))
                {
                    if (__result.SourceNode is JobGiver_Wander)
                    {
                        JobGiver_Wander jgWander = (JobGiver_Wander)__result.SourceNode;
                        Traverse.Create(__result.SourceNode).Field("wanderRadius").SetValue(5f);
                    }
                }
            }


            if (___pawn.IsColonistPlayerControlled || ___pawn.RaceProps.Animal || ___pawn.Faction.HostileTo(Faction.OfPlayer))
            {
                return;
            }
            if (___pawn.IsPrisoner)
            {
                return;
            }

            LocalTargetInfo target = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A);

            if (!target.IsValid)
            {
                return;
            }

            ExtendedDataStorage store = Base.GetExtendedDataStorage();

            if (store == null)
            {
                return;
            }

            //Log.Message("wrong duty");
            ExtendedPawnData PawnData = store.GetExtendedDataFor(___pawn);
            Lord             lord     = ___pawn.GetLord();

            if (lord == null)
            {
                return;
            }
            if (__result.Job.def == GUC_JobDefOf.Dismount || __result.Job.def == GUC_JobDefOf.Mount)
            {
                return;
            }

            QueuedJob qJob = ___pawn.jobs.jobQueue.FirstOrFallback(null);

            if (qJob != null && (qJob.job.def == GUC_JobDefOf.Dismount || qJob.job.def == GUC_JobDefOf.Mount))
            {
                return;
            }

            if (lord.CurLordToil is LordToil_ExitMapAndEscortCarriers || lord.CurLordToil is LordToil_Travel || lord.CurLordToil is LordToil_ExitMap || lord.CurLordToil is LordToil_ExitMapTraderFighting)
            {
                if (PawnData.owning != null && PawnData.owning.Faction == ___pawn.Faction && PawnData.mount == null && !PawnData.owning.Downed && PawnData.owning.Spawned && !___pawn.IsBurning() && !___pawn.Downed)
                {
                    mountAnimal(__instance, ___pawn, PawnData, ref __result);
                }
            }
            else if (lord.CurLordToil.GetType().Name == "LordToil_DefendTraderCaravan" || lord.CurLordToil is LordToil_DefendPoint) //first option is internal class, hence this way of accessing.
            {
                if (PawnData.mount != null)
                {
                    parkAnimal(__instance, ___pawn, PawnData);
                }
            }
        }
Пример #29
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);
            }
        }
Пример #30
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);
        }