protected override Job TryGiveJob(Pawn pawn)
        {
            // Most checks are done in ThinkNode_ConditionalNecro.

            // filter out necro for nymphs
            if (!RJWSettings.necrophilia_enabled)
            {
                return(null);
            }

            if (pawn.Drafted)
            {
                return(null);
            }

            //--Log.Message("[RJW] JobGiver_ViolateCorpse::TryGiveJob for ( " + xxx.get_pawnname(pawn) + " )");
            if (SexUtility.ReadyForLovin(pawn) || xxx.is_hornyorfrustrated(pawn))
            {
                //--Log.Message("[RJW] JobGiver_ViolateCorpse::TryGiveJob, can love ");
                if (!xxx.can_rape(pawn))
                {
                    return(null);
                }

                var target = find_corpse(pawn, pawn.Map);
                //--Log.Message("[RJW] JobGiver_ViolateCorpse::TryGiveJob - target is " + (target == null ? "NULL" : "Found"));
                if (target != null)
                {
                    return(JobMaker.MakeJob(xxx.RapeCorpse, target));
                }
                // Ticks should only be increased after successful sex.
            }

            return(null);
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            //--Log.Message("[RJW] JobGiver_DoFappin::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called");

            if (pawn.Drafted)
            {
                return(null);
            }

            if (!xxx.can_be_fucked(pawn) && !xxx.can_fuck(pawn))
            {
                return(null);
            }

            // W****s only fap if frustrated, unless imprisoned.
            if ((SexUtility.ReadyForLovin(pawn) && (!xxx.is_whore(pawn) || pawn.IsPrisoner)) || xxx.is_frustrated(pawn))
            {
                if (pawn.jobs.curDriver is JobDriver_LayDown && RJWPreferenceSettings.FapInBed)
                {
                    Building_Bed bed = ((JobDriver_LayDown)pawn.jobs.curDriver).Bed;
                    if (bed != null)
                    {
                        return(new Job(xxx.fappin, bed));
                    }
                }
                else if ((xxx.is_frustrated(pawn) || xxx.has_quirk(pawn, "Exhibitionist")) && RJWPreferenceSettings.FapEverywhere)
                {
                    return(new Job(xxx.quickfap, FindFapLocation(pawn)));
                }
            }
            return(null);
        }
示例#3
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            //Log.Message("[RJW] JobGiver_AIRapePrisoner::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called ");

            if (!xxx.can_rape(pawn))
            {
                return(null);
            }

            if (SexUtility.ReadyForLovin(pawn) || xxx.is_hornyorfrustrated(pawn))
            {
                // don't allow pawns marked as comfort prisoners to rape others
                if (xxx.is_healthy(pawn))
                {
                    Pawn prisoner = find_victim(pawn, pawn.Map);

                    if (prisoner != null)
                    {
                        //--Log.Message("[RJW] JobGiver_RandomRape::TryGiveJob( " + xxx.get_pawnname(p) + " ) - found victim " + xxx.get_pawnname(prisoner));
                        return(JobMaker.MakeJob(xxx.RapeRandom, prisoner));
                    }
                }
            }

            return(null);
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            //Log.Message("[RJW] JobGiver_ComfortPrisonerRape::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called0");

            if (!RJWSettings.WildMode)
            {
                // don't allow pawns marked as comfort prisoners to rape others
                if (!xxx.is_healthy(pawn) || pawn.IsDesignatedComfort() || (!SexUtility.ReadyForLovin(pawn) && !xxx.is_frustrated(pawn)))
                {
                    return(null);
                }
            }

            if (pawn.Drafted)
            {
                return(null);
            }

            //Log.Message("[RJW] JobGiver_ComfortPrisonerRape::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called1");
            if (!xxx.can_rape(pawn))
            {
                return(null);
            }

            // It's unnecessary to include other job checks. Pawns seem to only look for new jobs when between jobs or layind down idle.
            if (!(pawn.jobs.curJob == null || pawn.jobs.curJob.def == JobDefOf.LayDown))
            {
                return(null);
            }

            //--Log.Message("[RJW] JobGiver_ComfortPrisonerRape::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called2");
            // Faction check.
            if (!(pawn.Faction?.IsPlayer ?? false) && !pawn.IsPrisonerOfColony)
            {
                return(null);
            }

            Pawn target = find_prisoner_to_rape(pawn, pawn.Map);

            //--Log.Message("[RJW] JobGiver_ComfortPrisonerRape::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called3 - (" + ((target == null) ? "no target found" : xxx.get_pawnname(target))+") is the prisoner");

            if (target == null)
            {
                return(null);
            }

            //Log.Message("giving job to " + pawner + " with target " + target);
            if (xxx.is_animal(target))
            {
                return(new Job(xxx.bestiality, target));
            }
            else
            {
                return(new Job(xxx.comfort_prisoner_rapin, target));
            }
        }
示例#5
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            // Most things are now checked in the ThinkNode_ConditionalWhore.

            if (pawn.Drafted)
            {
                return(null);
            }
            if (MP.IsInMultiplayer)
            {
                return(null);                                //fix error someday, maybe
            }
            //Log.Message("[RJW] JobGiver_WhoreInvitingVisitors::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called");
            if (!SexUtility.ReadyForLovin(pawn))
            {
                //W****s need rest too, but this'll reduxe the wait a bit every it triggers.
                pawn.mindState.canLovinTick -= 40;
                return(null);
            }

            Building_Bed whorebed = xxx.FindBed(pawn);

            if (whorebed == null || !xxx.CanUse(pawn, whorebed))
            {
                return(null);
            }

            int  price;
            Pawn client = FindAttractivePawn(pawn, out price);

            if (client == null)
            {
                return(null);
            }

            if (!client.CanReach(whorebed, PathEndMode.OnCell, Danger.Some))
            {
                return(null);
            }
            //Log.Message("[RJW] JobGiver_WhoreInvitingVisitors::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) is w***e, " + xxx.get_pawnname(client) + " is client.");
            //whorebed.priceOfWhore = price;
            return(new Job(xxx.whore_inviting_visitors, client, whorebed));
        }
示例#6
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (pawn.Drafted)
            {
                return(null);
            }

            // Most checks are now done in ThinkNode_ConditionalBestiality
            DebugText("[RJW] JobGiver_Bestiality::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called");

            if (!SexUtility.ReadyForLovin(pawn) && !xxx.is_frustrated(pawn))
            {
                return(null);
            }

            Pawn target = BreederHelper.find_breeder_animal(pawn, pawn.Map);

            DebugText("[RJW] JobGiver_Bestiality::TryGiveJob - target is " + (target == null ? "no target found" : xxx.get_pawnname(target)));

            if (target == null)
            {
                return(null);
            }

            if (xxx.can_rape(pawn))
            {
                return(new Job(xxx.bestiality, target));
            }

            Building_Bed bed = pawn.ownership.OwnedBed;

            if (!xxx.can_be_fucked(pawn) || bed == null || !target.CanReach(bed, PathEndMode.OnCell, Danger.Some) || target.Downed)
            {
                return(null);
            }

            // TODO: Should rename this to BestialityInBed or somesuch, since it's not limited to females.
            return(new Job(xxx.bestialityForFemale, target, bed, bed.SleepPosOfAssignedPawn(pawn)));
        }
        protected override Job TryGiveJob(Pawn animal)
        {
            //Log.Message("[RJW] JobGiver_Breed::TryGiveJob( " + xxx.get_pawnname(animal) + " ) called0" + (SexUtility.ReadyForLovin(animal)));

            if (!SexUtility.ReadyForLovin(animal))
            {
                return(null);
            }

            if (xxx.is_healthy(animal) && xxx.can_rape(animal))
            {
                //search for desiganted target to sex
                if (animal.IsDesignatedBreedingAnimal())
                {
                    Pawn designated_target = BreederHelper.find_designated_breeder(animal, animal.Map);
                    if (designated_target != null)
                    {
                        return(JobMaker.MakeJob(xxx.animalBreed, designated_target));
                    }
                }
            }
            return(null);
        }
示例#8
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (pawn.Drafted)
            {
                return(null);
            }

            // Most checks are now done in ThinkNode_ConditionalBestiality

            if (!SexUtility.ReadyForLovin(pawn) && !xxx.is_frustrated(pawn))
            {
                return(null);
            }

            Pawn target = BreederHelper.find_breeder_animal(pawn, pawn.Map);

            if (target == null)
            {
                return(null);
            }

            if (xxx.can_rape(pawn))
            {
                return(JobMaker.MakeJob(xxx.bestiality, target));
            }

            Building_Bed bed = pawn.ownership.OwnedBed;

            if (!xxx.can_be_fucked(pawn) || bed == null || !target.CanReach(bed, PathEndMode.OnCell, Danger.Some) || target.Downed)
            {
                return(null);
            }

            // TODO: Should rename this to BestialityInBed or somesuch, since it's not limited to females.
            return(JobMaker.MakeJob(xxx.bestialityForFemale, target, bed));
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            // Most things are now checked in the ThinkNode_ConditionalWhore.

            if (pawn.Drafted)
            {
                return(null);
            }
            if (MP.IsInMultiplayer)
            {
                return(null);                                //fix error someday, maybe
            }
            if (!SexUtility.ReadyForLovin(pawn))
            {
                //W****s need rest too, but this'll reduxe the wait a bit every it triggers.
                pawn.mindState.canLovinTick -= 40;
                return(null);
            }

            if (RJWSettings.DebugWhoring)
            {
                Log.Message($"[RJW] JobGiver_WhoreInvitingVisitors.TryGiveJob:({xxx.get_pawnname(pawn)})");
            }
            Building_Bed whorebed = xxx.FindBed(pawn);

            if (whorebed == null || !xxx.CanUse(pawn, whorebed))
            {
                if (RJWSettings.DebugWhoring)
                {
                    Log.Message($" {xxx.get_pawnname(pawn)} has no bed or can use it");
                }
                return(null);
            }

            int  price;
            Pawn client = FindAttractivePawn(pawn, out price);

            if (client == null)
            {
                if (RJWSettings.DebugWhoring)
                {
                    Log.Message($" no clients found");
                }
                return(null);
            }

            if (RJWSettings.DebugWhoring)
            {
                Log.Message($" {xxx.get_pawnname(client)} is client");
            }

            if (!client.CanReach(whorebed, PathEndMode.OnCell, Danger.Some))
            {
                if (RJWSettings.DebugWhoring)
                {
                    Log.Message($" {xxx.get_pawnname(client)} cant reach bed");
                }
                return(null);
            }
            //whorebed.priceOfWhore = price;
            return(JobMaker.MakeJob(xxx.whore_inviting_visitors, client, whorebed));
        }
示例#10
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called0");
            //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) 0 " + SexUtility.ReadyForLovin(pawn));
            //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) 1 " + (xxx.need_some_sex(pawn) <= 1f));
            //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) 2 " + !(SexUtility.ReadyForLovin(pawn) || xxx.need_some_sex(pawn) <= 1f));
            //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) 1 " + Find.TickManager.TicksGame);
            //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) 2 " + pawn.mindState.canLovinTick);

            if (pawn.Drafted)
            {
                return(null);
            }

            if (pawn.health.hediffSet.HasHediff(HediffDef.Named("Hediff_RapeEnemyCD")) || !pawn.health.capacities.CanBeAwake || !(SexUtility.ReadyForLovin(pawn) || xxx.need_some_sex(pawn) <= 1f))
            {
                //if (pawn.health.hediffSet.HasHediff(HediffDef.Named("Hediff_RapeEnemyCD")) || !pawn.health.capacities.CanBeAwake || (SexUtility.ReadyForLovin(pawn) || xxx.is_human(pawn) ? xxx.need_some_sex(pawn) <= 1f : false))
                return(null);
            }

            if (!xxx.can_rape(pawn))
            {
                return(null);
            }
            //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) can rape");

            JobDef_RapeEnemy rapeEnemyJobDef = null;
            int?highestPriority = null;

            foreach (JobDef_RapeEnemy job in DefDatabase <JobDef_RapeEnemy> .AllDefs)
            {
                if (job.CanUseThisJobForPawn(pawn))
                {
                    if (highestPriority == null)
                    {
                        rapeEnemyJobDef = job;
                        highestPriority = job.priority;
                    }
                    else if (job.priority > highestPriority)
                    {
                        rapeEnemyJobDef = job;
                        highestPriority = job.priority;
                    }
                }
            }

            //Log.Message("[RJW] JobGiver_RapeEnemy::ChoosedJobDef( " + xxx.get_pawnname(pawn) + " ) - " + rapeEnemyJobDef.ToString() + " choosed");
            Pawn victim = rapeEnemyJobDef?.FindVictim(pawn, pawn.Map);

            //Log.Message("[RJW] JobGiver_RapeEnemy::FoundVictim( " + xxx.get_pawnname(victim) + " )");

            //prevents 10 job stacks error, no idea whats the prob with JobDriver_Rape
            //if (victim != null)
            pawn.health.AddHediff(HediffDef.Named("Hediff_RapeEnemyCD"), null, null, null);

            return(victim != null ? new Job(rapeEnemyJobDef, victim) : null);

            /*
             * else
             * {
             *      //--Log.Message("[RJW]" + this.GetType().ToString() + "::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) - unable to find victim");
             *      pawn.mindState.canLovinTick = Find.TickManager.TicksGame + Rand.Range(75, 150);
             * }
             */
            //else {  //--Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) - too fast to play next"); }
        }
示例#11
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (!RJWHookupSettings.HookupsEnabled)
            {
                return(null);
            }

            if (pawn.Drafted)
            {
                return(null);
            }

            if (!SexUtility.ReadyForHookup(pawn))
            {
                return(null);
            }

            // We increase the time right away to prevent the fairly expensive check from happening too frequently
            SexUtility.IncreaseTicksToNextHookup(pawn);

            // If the pawn is a w***e, or recently had sex, skip the job unless they're really horny
            if (!xxx.is_frustrated(pawn) && (xxx.is_whore(pawn) || !SexUtility.ReadyForLovin(pawn)))
            {
                return(null);
            }

            // This check attempts to keep groups leaving the map, like guests or traders, from turning around to hook up
            if (pawn.mindState?.duty?.def == DutyDefOf.TravelOrLeave)
            {
                // TODO: Some guest pawns keep the TravelOrLeave duty the whole time, I think the ones assigned to guard the pack animals.
                // That's probably ok, though it wasn't the intention.
                if (RJWSettings.DebugLogJoinInBed)
                {
                    Log.Message($"[RJW] JoinInBed.TryGiveJob:({xxx.get_pawnname(pawn)}): has TravelOrLeave, no time for lovin!");
                }
                return(null);
            }

            if (pawn.CurJob == null || pawn.CurJob.def == JobDefOf.LayDown)
            {
                //--Log.Message("   checking pawn and abilities");
                if (xxx.can_fuck(pawn) || xxx.can_be_fucked(pawn))
                {
                    //--Log.Message("   finding partner");
                    Pawn partner = find_pawn_to_fuck(pawn, pawn.Map);

                    //--Log.Message("   checking partner");
                    if (partner == null)
                    {
                        return(null);
                    }

                    // Can never be null, since find checks for bed.
                    Building_Bed bed = partner.CurrentBed();

                    // Interrupt current job.
                    if (pawn.CurJob != null && pawn.jobs.curDriver != null)
                    {
                        pawn.jobs.curDriver.EndJobWith(JobCondition.InterruptForced);
                    }

                    //--Log.Message("   returning job");
                    return(new Job(DefDatabase <JobDef> .GetNamed("JoinInBed"), pawn, partner, bed));
                }
            }

            return(null);
        }
示例#12
0
        /// <summary> Checks all of our potential partners to see if anyone's eligible, returning the most attractive and convenient one. </summary>
        protected static Pawn FindBestPartner(Pawn pawn, List <Pawn> targets, bool pawnCanPickAnyone, bool pawnIsNympho)
        {
            string pawnName = xxx.get_pawnname(pawn);

            Pawn  best_fuckee            = null;
            float best_fuckability_score = 0;

            foreach (Pawn targetPawn in targets)
            {
                if (RJWSettings.DebugLogJoinInBed)
                {
                    Log.Message($"[RJW] FindBestPartner({pawnName}): checking hookup {xxx.get_pawnname(targetPawn)}");
                }

                // Check to see if the mod settings for hookups allow this pairing
                if (!pawnCanPickAnyone && !HookupAllowedViaSettings(pawn, targetPawn))
                {
                    continue;
                }

                // Check for homewrecking (banging a pawn who's in a relationship)
                if (!xxx.is_animal(targetPawn) &&
                    xxx.HasNonPolyPartnerOnCurrentMap(targetPawn))
                {
                    if (RJWHookupSettings.NymphosCanHomewreck && pawnIsNympho && xxx.is_frustrated(pawn))
                    {
                        // Hookup allowed... rip colony mood
                    }
                    else if (RJWHookupSettings.NymphosCanHomewreckReverse && xxx.is_nympho(targetPawn) && xxx.is_frustrated(targetPawn))
                    {
                        // Hookup allowed... rip colony mood
                    }
                    else
                    {
                        if (RJWSettings.DebugLogJoinInBed)
                        {
                            Log.Message($"[RJW] FindBestPartner({pawnName}): not hooking up with {xxx.get_pawnname(targetPawn)} to avoid homewrecking");
                        }
                        continue;
                    }
                }

                // If the pawn has had sex recently and isn't horny right now, skip them.
                if (!SexUtility.ReadyForLovin(targetPawn) && !xxx.is_horny(targetPawn))
                {
                    if (RJWSettings.DebugLogJoinInBed)
                    {
                        Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)} isn't ready for lovin'");
                    }
                    continue;
                }

                if (RJWSettings.DebugLogJoinInBed)
                {
                    Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)} is sufficiently single");
                }

                if (!xxx.is_animal(targetPawn))
                {
                    float relations = pawn.relations.OpinionOf(targetPawn);
                    if (relations < RJWHookupSettings.MinimumRelationshipToHookup)
                    {
                        if (!(relations > 0 && xxx.is_nympho(pawn)))
                        {
                            if (RJWSettings.DebugLogJoinInBed)
                            {
                                Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)}, i dont like them:({relations})");
                            }
                            continue;
                        }
                    }

                    relations = targetPawn.relations.OpinionOf(pawn);
                    if (relations < RJWHookupSettings.MinimumRelationshipToHookup)
                    {
                        if (!(relations > 0 && xxx.is_nympho(targetPawn)))
                        {
                            if (RJWSettings.DebugLogJoinInBed)
                            {
                                Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)}, dont like me:({relations})");
                            }
                            continue;
                        }
                    }

                    float attraction = pawn.relations.SecondaryRomanceChanceFactor(targetPawn);
                    if (attraction < RJWHookupSettings.MinimumAttractivenessToHookup)
                    {
                        if (!(attraction > 0 && xxx.is_nympho(pawn)))
                        {
                            if (RJWSettings.DebugLogJoinInBed)
                            {
                                Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)}, i dont find them attractive:({attraction})");
                            }
                            continue;
                        }
                    }
                    attraction = targetPawn.relations.SecondaryRomanceChanceFactor(pawn);
                    if (attraction < RJWHookupSettings.MinimumAttractivenessToHookup)
                    {
                        if (!(attraction > 0 && xxx.is_nympho(targetPawn)))
                        {
                            if (RJWSettings.DebugLogJoinInBed)
                            {
                                Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)}, doesnt find me attractive:({attraction})");
                            }
                            continue;
                        }
                    }
                }

                // Check to see if the two pawns are willing to bang, and if so remember how much attractive we find them
                float fuckability = 0f;
                if (pawn.CanReserveAndReach(targetPawn, PathEndMode.OnCell, Danger.Some, 1, 0) &&
                    targetPawn.CanReserve(pawn, 1, 0) &&
                    roll_to_skip(pawn, targetPawn, out fuckability))                     // do NOT check pawnIgnoresRules here - these checks, particularly roll_to_skip, are critical
                {
                    int dis = pawn.Position.DistanceToSquared(targetPawn.Position);

                    if (dis <= 4)
                    {
                        // Right next to me (in my bed)?  You'll do.
                        if (RJWSettings.DebugLogJoinInBed)
                        {
                            Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)} is right next to me.  we'll bang, ok?");
                        }
                        best_fuckability_score = 1.0e6f;
                        best_fuckee            = targetPawn;
                    }
                    else if (dis > MaxDistanceSquaredToFuck)
                    {
                        // too far
                        if (RJWSettings.DebugLogJoinInBed)
                        {
                            Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)} is too far... distance:{dis} max:{MaxDistanceSquaredToFuck}");
                        }
                        continue;
                    }
                    else
                    {
                        // scaling fuckability by distance may give us more varied results and give the less attractive folks a chance
                        float fuckability_score = fuckability / GenMath.Sqrt(GenMath.Sqrt(dis));
                        if (RJWSettings.DebugLogJoinInBed)
                        {
                            Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)} is totally bangable.  attraction: {fuckability}, score:{fuckability_score}");
                        }

                        if (fuckability_score > best_fuckability_score)
                        {
                            best_fuckee            = targetPawn;
                            best_fuckability_score = fuckability_score;
                        }
                    }
                }
            }

            if (best_fuckee == null)
            {
                if (RJWSettings.DebugLogJoinInBed)
                {
                    Log.Message($"[RJW] FindBestPartner({pawnName}): couldn't find anyone to bang");
                }
            }
            else
            {
                if (RJWSettings.DebugLogJoinInBed)
                {
                    Log.Message($"[RJW] FindBestPartner({pawnName}): found rando {xxx.get_pawnname(best_fuckee)} with score {best_fuckability_score}");
                }
            }

            return(best_fuckee);
        }
示例#13
0
        protected override Job TryGiveJob(Pawn animal)
        {
            //Log.Message("[RJW] JobGiver_Breed::TryGiveJob( " + xxx.get_pawnname(animal) + " ) called0" + (SexUtility.ReadyForLovin(animal)));

            if (!SexUtility.ReadyForLovin(animal))
            {
                return(null);
            }

            if (xxx.is_healthy(animal) && xxx.can_rape(animal))
            {
                //Log.Message("[RJW] JobGiver_Breed::TryGiveJob( " + xxx.get_pawnname(animal) + " ) called2");
                List <Pawn> valid_targets = new List <Pawn>();

                //search for desiganted target to sex
                if (animal.IsDesignatedBreedingAnimal())
                {
                    Pawn designated_target = BreederHelper.find_designated_breeder(animal, animal.Map);
                    if (designated_target != null)
                    {
                        valid_targets.Add(designated_target);
                    }
                }

                //some weird shit happens, animal tries to rape and fails, needs investigation someday

                /*
                 * //search for animal to sex
                 * if (RJWSettings.animal_on_animal_enabled)
                 * {
                 *      //Using bestiality target finder, since it works best for this.
                 *      //search for same race mate
                 *      if (!valid_targets.Any())
                 *      {
                 *              Pawn animal_target = BreederHelper.find_breeder_animal(animal, animal.Map);
                 *              if (animal_target != null)
                 *              {
                 *                      valid_targets.Add(animal_target);
                 *              }
                 *      }
                 *
                 *      //search for any other animal/human to sex
                 *      if (!valid_targets.Any())
                 *      {
                 *              Pawn animal_target = BreederHelper.find_breeder_animal(animal, animal.Map, false);
                 *              if (animal_target != null)
                 *              {
                 *                      valid_targets.Add(animal_target);
                 *              }
                 *      }
                 *
                 * }
                 */

                //Log.Message("[RJW] JobGiver_Breed::TryGiveJob( " + xxx.get_pawnname(animal) + " ) called3 - (" + ((target == null) ? "no target found" : xxx.get_pawnname(target))+") is the prisoner");

                if (valid_targets != null && valid_targets.Any())
                {
                    //Rand.PopState();
                    //Rand.PushState(RJW_Multiplayer.PredictableSeed());
                    var target = valid_targets.RandomElement();
                    //Log.Message("Target: " + xxx.get_pawnname(target));
                    return(new Job(DefDatabase <JobDef> .GetNamed("Breed"), target, animal));
                }
            }
            return(null);
        }