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);
            }
        }
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
    public override bool EndConditionsMet()
    {
        var  distance    = DistanceUtility.Get2d(SetPiece.transform, Target.transform);
        bool withinRange = distance <= 2;

        return(withinRange && base.EndConditionsMet());
    }
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;
            }
            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 #5
0
        static void Postfix(Pawn_JobTracker __instance, ref ThinkResult __result)
        {
            Pawn pawn = Traverse.Create(__instance).Field("pawn").GetValue <Pawn>();


            if (pawn.IsColonistPlayerControlled || pawn.RaceProps.Animal)
            {
                return;
            }

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

            if (!target.IsValid)
            {
                return;
            }

            ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage();

            if (store == null)
            {
                return;
            }

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

            if (lord == null)
            {
                return;
            }
            QueuedJob qJob = pawn.jobs.jobQueue.FirstOrFallback(null);

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

            Log.Message("curLordToil: " + pawn.GetLord().CurLordToil.ToString() + ", pawn name: " + pawn.Name);
            Log.Message("lordJob: " + pawn.GetLord().LordJob + ", pawn name: " + pawn.Name);
            Log.Message("lord.CurLordToil.GetType().Name" + lord.CurLordToil.GetType().Name);

            if (lord.CurLordToil is LordToil_ExitMapAndEscortCarriers)
            {
                if (PawnData.owning != null && PawnData.mount == null && !PawnData.owning.Downed && PawnData.owning.Spawned)
                {
                    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);
                }
            }
        }
Beispiel #6
0
    public override float GetProgress()
    {
        var distance = DistanceUtility.Get2d(SetPiece.transform, Target.transform);

        if (distance >= LargestDistance)
        {
            LargestDistance = distance;
        }
        return(1 - (distance / LargestDistance));
    }
    public override float GetProgress()
    {
        if (Target == null)
        {
            return(EndConditionsMet() ? 1f : 0f);
        }

        var distance = DistanceUtility.Get2d(TargetProp.transform, Target.transform);

        if (distance >= LargestDistance)
        {
            LargestDistance = distance;
        }
        return(1 - (distance / LargestDistance));
    }
    public override bool EndConditionsMet()
    {
        if (Target != null)
        {
            var distance = DistanceUtility.Get2d(TargetPropHolder.transform, Target.transform);
            if (distance >= 3)
            {
                return(false);
            }
        }

        bool correctHolder = TargetPropHolder == TargetProp.PropHolder;

        return(correctHolder && base.EndConditionsMet());
    }
Beispiel #9
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 CheckTargetDistance()
    {
        float dist;

        for (int i = 0; i < lookAtTargets.Length; i++)
        {
            dist = DistanceUtility.FlatDistance(lookAtTargets[i].position, characterLookAt.transform.position, Vector3.up);
            if (dist < lookRadius)
            {
                characterLookAt.target = lookAtTargets[i];
                return(true);
            }
        }

        return(false);
    }
Beispiel #11
0
    public virtual void DropProp()
    {
        if (PropHolder == null)
        {
            Logger.LogError($"DropProp called with PropHolder == null");
            return;
        }

        //find nearest prop holder
        PropHolder nearestPropHolder = null;
        float      smallestDistance  = float.MaxValue;

        foreach (var holder in PropHolder.PropHoldersList)
        {
            if (holder == PropHolder)
            {
                continue;
            }

            var distance = DistanceUtility.Get2d(transform, holder.transform);
            if (distance <= smallestDistance &&
                holder.CanHoldProp(this, distance:distance))
            {
                smallestDistance  = distance;
                nearestPropHolder = holder;
            }
        }

        //remove prop from old prop holder
        PropHolder.RemoveProp(this);

        PropHolder = null;

        if (nearestPropHolder == null)
        {
            //set pos to scene prop root
            transform.parent           = PlayerManger.MangerInstance.PropsRoot;
            transform.localEulerAngles = Vector3.zero;
            Rigidbody.isKinematic      = false;
            Collider.enabled           = true;
            SetRotateToCam(true);
        }
        else
        {
            PickUpProp(nearestPropHolder);
        }
    }
Beispiel #12
0
    public virtual bool CanHoldProp(Prop prop, float distance = -1)
    {
        if (prop == null)
        {
            return(false);
        }
        if (PropSlot != null)
        {
            return(false);
        }

        if (distance < 0)
        {
            distance = DistanceUtility.Get2d(prop.transform, transform);
        }
        return(distance <= prop.PropSize);
    }
Beispiel #13
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 #14
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);
            }
        }
Beispiel #15
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);
            }
        }
Beispiel #16
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 #17
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);
        }
        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);
                }
            }
        }
    protected override void Update()
    {
        var acceleration = Vector3.zero;

        if (CurrentTask == null && PropSlot == null)
        {
            acceleration = UpdateMovement();
            if (IsInputInState(eInput.Interact, eButtonState.Pressed))
            {
                float minDistance = float.MaxValue;
                Prop  closestProp = null;
                foreach (var prop in Prop.PropsList)
                {
                    var distance = DistanceUtility.Get2d(prop.transform, transform);
                    if (CanHoldProp(prop, distance:distance) &&
                        prop.CanMoveProp() &&
                        distance < minDistance)
                    {
                        closestProp = prop;
                        minDistance = distance;
                    }
                }

                if (closestProp != null)
                {
                    closestProp.PickUpProp(this);
                }


                if (PropSlot == null)
                {
                    foreach (var task in Interactable.Interactables)
                    {
                        var distance = (transform.position - task.transform.position).magnitude;
                        if (distance <= minDistance && task.CanInteract(transform.position))
                        {
                            CurrentTask = task;
                            minDistance = distance;
                            CurrentTask.StartInteraction(this);
                        }
                    }
                }
            }
        }
        else if (PropSlot != null)
        {
            acceleration = UpdateMovement();
            if (IsInputInState(eInput.Interact, eButtonState.Pressed))
            {
                PropSlot.DropProp();
            }
        }
        else if (CurrentTask != null)
        {
            Debug.DrawLine(transform.position, CurrentTask.transform.position, Color.green);

            var distance = (transform.position - CurrentTask.transform.position).magnitude;
            if (!CurrentTask.CanInteract(transform.position) ||
                IsInputInState(eInput.Interact, eButtonState.Pressed))
            {
                CurrentTask.EndInteraction();
                CurrentTask = null;
            }

            if (CurrentTask != null)
            {
                acceleration -= Velocity;
                Velocity      = Vector3.zero;
            }
        }
        UpdateVisuals(acceleration, Velocity);
        TryHideObjectsHiddingPlayer();
        base.Update();
    }
Beispiel #20
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;
                            }
                        }
                    });
                }
            }
        }