private static bool roll_to_skip(Pawn pawn, Pawn target, out float fuckability)
        {
            fuckability = SexAppraiser.would_fuck(pawn, target);             // 0.0 to 1.0
            if (fuckability < RJWHookupSettings.MinimumFuckabilityToHookup)
            {
                if (RJWSettings.DebugLogJoinInBed)
                {
                    Log.Message($"[RJWQ] roll_to_skip(I, {xxx.get_pawnname(pawn)} won't f**k {xxx.get_pawnname(target)}), ({fuckability})");
                }
                return(false);
            }

            float reciprocity = xxx.is_animal(target) ? 1.0f : SexAppraiser.would_fuck(target, pawn);

            if (reciprocity < RJWHookupSettings.MinimumFuckabilityToHookup)
            {
                if (RJWSettings.DebugLogJoinInBed)
                {
                    Log.Message($"[RJWQ] roll_to_skip({xxx.get_pawnname(target)} won't f**k me, {xxx.get_pawnname(pawn)}), ({reciprocity})");
                }
                return(false);
            }

            float chance_to_skip = 0.9f - 0.7f * fuckability;

            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());
            return(Rand.Value < chance_to_skip);
        }
 public virtual float GetFuckability(Pawn rapist, Pawn target)
 {
     //Log.Message("[RJW]JobDriver_RapeEnemy::GetFuckability(" + rapist.ToString() + "," + target.ToString() + ")");
     if (target.health.hediffSet.HasHediff(is_submitting))            //it's not about attractiveness anymore, it's about showing who's whos bitch
     {
         return(2 * SexAppraiser.would_fuck(rapist, target, invert_opinion: true, ignore_bleeding: true, ignore_gender: true));
     }
     return(!SexAppraiser.would_rape(rapist, target) ? 0f
                         : SexAppraiser.would_fuck(rapist, target, invert_opinion: true, ignore_bleeding: true, ignore_gender: true));
 }
Example #3
0
        public override bool MoreChecks(Pawn pawn, Thing t, bool forced = false)
        {
            //Log.Message("[RJW]" + this.GetType().ToString() + " base checks: pass");
            if (!RJWSettings.necrophilia_enabled)
            {
                return(false);
            }

            //Pawn target = (t as Corpse).InnerPawn;
            if (!pawn.CanReserve(t, xxx.max_rapists_per_prisoner, 0))
            {
                return(false);
            }

            if (!(pawn.IsDesignatedHero() || RJWSettings.override_control))
            {
                if (!RJWSettings.WildMode)
                {
                    if (xxx.is_necrophiliac(pawn) && !xxx.is_hornyorfrustrated(pawn))
                    {
                        if (RJWSettings.DevMode)
                        {
                            JobFailReason.Is("not horny enough");
                        }
                        return(false);
                    }
                    if (!xxx.is_necrophiliac(pawn))
                    {
                        if ((t as Corpse).CurRotDrawMode != RotDrawMode.Fresh)
                        {
                            if (RJWSettings.DevMode)
                            {
                                JobFailReason.Is("refuse to rape rotten");
                            }
                            return(false);
                        }
                        else if (!xxx.is_frustrated(pawn))
                        {
                            if (RJWSettings.DevMode)
                            {
                                JobFailReason.Is("not horny enough");
                            }
                            return(false);
                        }
                    }
                    //Log.Message("[RJW]WorkGiver_ViolateCorpse::" + SexAppraiser.would_fuck(pawn, t as Corpse));
                    if (SexAppraiser.would_fuck(pawn, t as Corpse) > 0.1f)
                    {
                        return(false);
                    }
                }
            }
            //Log.Message("[RJW]" + this.GetType().ToString() + " extended checks: can start sex");
            return(true);
        }
        private static bool Roll_to_skip(Pawn client, Pawn w***e)
        {
            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());
            float fuckability = SexAppraiser.would_fuck(client, w***e);             // 0.0 to 1.

            // More likely to skip other w****s, because they're supposed to be working.
            if (client.IsDesignatedService())
            {
                fuckability *= 0.6f;
            }
            return(fuckability >= 0.1f && xxx.need_some_sex(client) >= 1f && Rand.Chance(0.5f));
        }
        // Gives the wanted information of the selected thing
        public static void info_on_select(Map m)
        {
            Pawn p = Find.Selector.SingleSelectedThing as Pawn;

            if (p != null)
            {
                //--Log.Message("[RJW]TestInc2::info_on_select is called");
                foreach (var q in m.mapPawns.AllPawns)
                {
                    SexAppraiser.would_fuck(p, q, true);
                }
            }
        }
        public static Corpse find_corpse(Pawn pawn, Map m)
        {
            float  min_fuckability = 0.10f;                                       // Don't rape pawns with <10% fuckability
            float  avg_fuckability = 0f;                                          // Average targets fuckability, choose target higher than that
            var    valid_targets   = new Dictionary <Corpse, float>();            // Valid pawns and their fuckability
            Corpse chosentarget    = null;                                        // Final target pawn

            IEnumerable <Thing> targets = m.spawnedThings.Where(x
                                                                => x is Corpse &&
                                                                pawn.CanReserveAndReach(x, PathEndMode.OnCell, Danger.Some) &&
                                                                !x.IsForbidden(pawn)
                                                                );

            foreach (Corpse target in targets)
            {
                if (!xxx.can_path_to_target(pawn, target.Position))
                {
                    continue;                    // too far
                }
                // Filter out rotters if not necrophile.
                if (!xxx.is_necrophiliac(pawn) && target.CurRotDrawMode != RotDrawMode.Fresh)
                {
                    continue;
                }

                float fuc = SexAppraiser.would_fuck(pawn, target, false, false);
                if (fuc > min_fuckability)
                {
                    valid_targets.Add(target, fuc);
                }
            }

            if (valid_targets.Any())
            {
                avg_fuckability = valid_targets.Average(x => x.Value);

                // choose pawns to f**k with above average fuckability
                var valid_targetsFilteredAnimals = valid_targets.Where(x => x.Value >= avg_fuckability);

                if (valid_targetsFilteredAnimals.Any())
                {
                    chosentarget = valid_targetsFilteredAnimals.RandomElement().Key;
                }
            }

            return(chosentarget);
        }
Example #7
0
        public static Pawn find_victim(Pawn pawn, Map m)
        {
            float min_fuckability = 0.10f;                                      // Don't rape pawns with <10% fuckability
            float avg_fuckability = 0f;                                         // Average targets fuckability, choose target higher than that
            var   valid_targets   = new Dictionary <Pawn, float>();             // Valid pawns and their fuckability
            Pawn  chosentarget    = null;                                       // Final target pawn

            IEnumerable <Pawn> targets = m.mapPawns.AllPawns.Where(x
                                                                   => x != pawn &&
                                                                   IsPrisonerOf(x, pawn.Faction) &&
                                                                   xxx.can_get_raped(x) &&
                                                                   pawn.CanReserveAndReach(x, PathEndMode.Touch, Danger.Some, xxx.max_rapists_per_prisoner, 0) &&
                                                                   !x.Position.IsForbidden(pawn)
                                                                   );

            foreach (Pawn target in targets)
            {
                if (!xxx.can_path_to_target(pawn, target.Position))
                {
                    continue;                    // too far
                }
                float fuc = SexAppraiser.would_fuck(pawn, target, true, true);

                if (fuc > min_fuckability)
                {
                    valid_targets.Add(target, fuc);
                }
            }

            if (valid_targets.Any())
            {
                avg_fuckability = valid_targets.Average(x => x.Value);

                // choose pawns to f**k with above average fuckability
                var valid_targetsFiltered = valid_targets.Where(x => x.Value >= avg_fuckability);

                if (valid_targetsFiltered.Any())
                {
                    chosentarget = valid_targetsFiltered.RandomElement().Key;
                }
            }

            return(chosentarget);
        }
        public Pawn find_victim(Pawn pawn, Map m)
        {
            float min_fuckability = 0.10f;                                      // Don't rape pawns with <10% fuckability
            float avg_fuckability = 0f;                                         // Average targets fuckability, choose target higher than that
            var   valid_targets   = new Dictionary <Pawn, float>();             // Valid pawns and their fuckability
            Pawn  chosentarget    = null;                                       // Final target pawn

            // could be prisoner, colonist, or non-hostile outsider
            IEnumerable <Pawn> targets = m.mapPawns.AllPawnsSpawned.Where(x
                                                                          => x != pawn &&
                                                                          xxx.is_not_dying(x) &&
                                                                          xxx.can_get_raped(x) &&
                                                                          !x.Suspended &&
                                                                          !x.Drafted &&
                                                                          !x.IsForbidden(pawn) &&
                                                                          pawn.CanReserveAndReach(x, PathEndMode.Touch, Danger.Some, xxx.max_rapists_per_prisoner, 0) &&
                                                                          !x.HostileTo(pawn)
                                                                          );


            //Zoo rape Animal
            if (xxx.is_zoophile(pawn) && RJWSettings.bestiality_enabled)
            {
                foreach (Pawn target in targets.Where(x => xxx.is_animal(x)))
                {
                    if (!xxx.can_path_to_target(pawn, target.Position))
                    {
                        continue;                        // too far
                    }
                    float fuc = SexAppraiser.would_fuck(pawn, target, true, true);

                    if (fuc > min_fuckability)
                    {
                        valid_targets.Add(target, fuc);
                    }
                }

                if (valid_targets.Any())
                {
                    avg_fuckability = valid_targets.Average(x => x.Value);

                    // choose pawns to f**k with above average fuckability
                    var valid_targetsFilteredAnimals = valid_targets.Where(x => x.Value >= avg_fuckability);

                    if (valid_targetsFilteredAnimals.Any())
                    {
                        chosentarget = valid_targetsFilteredAnimals.RandomElement().Key;
                    }

                    return(chosentarget);
                }
            }

            valid_targets = new Dictionary <Pawn, float>();
            // rape Humanlike
            foreach (Pawn target in targets.Where(x => !xxx.is_animal(x)))
            {
                if (!xxx.can_path_to_target(pawn, target.Position))
                {
                    continue;                    // too far
                }
                float fuc = SexAppraiser.would_fuck(pawn, target, true, true);

                if (fuc > min_fuckability)
                {
                    valid_targets.Add(target, fuc);
                }
            }

            if (valid_targets.Any())
            {
                avg_fuckability = valid_targets.Average(x => x.Value);

                // choose pawns to f**k with above average fuckability
                var valid_targetsFilteredAnimals = valid_targets.Where(x => x.Value >= avg_fuckability);

                if (valid_targetsFilteredAnimals.Any())
                {
                    chosentarget = valid_targetsFilteredAnimals.RandomElement().Key;
                }
            }

            return(chosentarget);
        }
        public override bool MoreChecks(Pawn pawn, Thing t, bool forced = false)
        {
            //Log.Message("[RJW]" + this.GetType().ToString() + ":: base checks: pass");
            if (!RJWSettings.bestiality_enabled)
            {
                return(false);
            }

            Pawn target = t as Pawn;

            if (!WorkGiverChecks(pawn, t, forced))
            {
                return(false);
            }

            if (!xxx.can_be_fucked(pawn))
            {
                if (RJWSettings.DevMode)
                {
                    JobFailReason.Is("pawn cant be f****d");
                }
                return(false);
            }

            if (!(pawn.IsDesignatedHero() || RJWSettings.override_control))
            {
                if (!RJWSettings.WildMode)
                {
                    if (!xxx.is_zoophile(pawn) && !xxx.is_frustrated(pawn))
                    {
                        if (RJWSettings.DevMode)
                        {
                            JobFailReason.Is("not willing to have sex with animals");
                        }
                        return(false);
                    }
                    if (!xxx.is_hornyorfrustrated(pawn))
                    {
                        if (RJWSettings.DevMode)
                        {
                            JobFailReason.Is("not horny enough");
                        }
                        return(false);
                    }
                    if (!xxx.is_healthy_enough(target))
                    {
                        if (RJWSettings.DevMode)
                        {
                            JobFailReason.Is("target not healthy enough");
                        }
                        return(false);
                    }

                    //Log.Message("[RJW]WorkGiver_BestialityForFemale::" + SexAppraiser.would_fuck_animal(pawn, target));
                    if (SexAppraiser.would_fuck_animal(pawn, target) < 0.1f)
                    {
                        return(false);
                    }
                    //add some more fancy conditions from JobGiver_Bestiality?
                }
            }

            //Log.Message("[RJW]" + this.GetType().ToString() + ":: extended checks: can start sex");
            return(true);
        }
Example #10
0
        public static Pawn find_breeder_animal(Pawn pawn, Map m)
        {
            DebugText("BreederHelper::find_breeder_animal( " + xxx.get_pawnname(pawn) + " ) called");

            float min_fuckability = 0.10f;                                      // Don't rape pawns with <10% fuckability
            float avg_fuckability = 0f;                                         // Average targets fuckability, choose target higher than that
            var   valid_targets   = new Dictionary <Pawn, float>();             // Valid pawns and their fuckability
            Pawn  chosentarget    = null;                                       // Final target pawn

            //Pruning initial pawn list.
            IEnumerable <Pawn> targets = m.mapPawns.AllPawnsSpawned.Where(x
                                                                          => x != pawn &&
                                                                          xxx.is_animal(x) &&
                                                                          xxx.can_get_raped(x) &&
                                                                          !x.IsForbidden(pawn) &&
                                                                          !x.Suspended &&
                                                                          !x.HostileTo(pawn) &&
                                                                          pawn.CanReserveAndReach(x, PathEndMode.Touch, Danger.Some, max_animals_at_once)
                                                                          //&& SameRace ? pawn.kindDef.race == x.kindDef.race : true
                                                                          );

            if (targets.Any())
            {
                var partBPR = Genital_Helper.get_genitalsBPR(pawn);
                var parts   = Genital_Helper.get_PartsHediffList(pawn, partBPR);

                //filter pawns for female, who can f**k her
                //not sure if faction check should be but w/e
                if (!Genital_Helper.has_penis_fertile(pawn, parts) && !Genital_Helper.has_penis_infertile(pawn, parts) && (Genital_Helper.has_vagina(pawn, parts) || Genital_Helper.has_anus(pawn)))
                {
                    targets = targets.Where(x => xxx.can_fuck(x) && x.Faction == pawn.Faction);
                }

                //for humans, animals dont have need - always = 3f
                //if not horny, seek only targets with safe temp
                if (xxx.need_some_sex(pawn) < 3.0f)
                {
                    targets = targets.Where(x => pawn.CanReach(x, PathEndMode.Touch, Danger.None));
                }

                //Used for interspecies animal-on-animal.
                //Animals will only go for targets they can see.
                if (xxx.is_animal(pawn))
                {
                    targets = targets.Where(x => pawn.CanSee(x) && pawn.def.defName != x.def.defName);
                }
                else
                {
                    // Pickier about the targets if the pawn has no prior experience.
                    if (pawn.records.GetValue(xxx.CountOfSexWithAnimals) < 3 && !xxx.is_zoophile(pawn))
                    {
                        min_fuckability *= 2f;
                    }

                    if (xxx.is_frustrated(pawn))
                    {                       // Less picky when frustrated...
                        min_fuckability *= 0.6f;
                    }
                    else if (!xxx.is_hornyorfrustrated(pawn))
                    {                       // ...and far more picky when satisfied.
                        min_fuckability *= 2.5f;
                    }
                }
            }

            DebugText("[RJW]BreederHelper::find_breeder_animal::" + targets.Count() + " targets found on map.");

            if (!targets.Any())
            {
                return(null);                //None found.
            }

            foreach (Pawn target in targets)
            {
                DebugText("[RJW]BreederHelper::find_breeder_animal::Checking target " + target.kindDef.race.defName.ToLower());

                if (!xxx.can_path_to_target(pawn, target.Position))
                {
                    continue;                                             // too far
                }
                float fuc = SexAppraiser.would_fuck_animal(pawn, target); // 0.0 to ~3.0, orientation checks etc.

                if (!(fuc > min_fuckability))
                {
                    continue;
                }
                DebugText("Adding target" + target.kindDef.race.defName.ToLower());
                valid_targets.Add(target, fuc);
            }

            DebugText(valid_targets.Count() + " valid targets found on map.");
            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());
            if (valid_targets.Any())
            {
                avg_fuckability = valid_targets.Average(x => x.Value);

                // choose pawns to f**k with above average fuckability
                var valid_targetsFilteredAnimals = valid_targets.Where(x => x.Value >= avg_fuckability);

                if (valid_targetsFilteredAnimals.Any())
                {
                    chosentarget = valid_targetsFilteredAnimals.RandomElement().Key;
                }
            }

            return(chosentarget);
        }
Example #11
0
        public static Pawn find_designated_breeder(Pawn pawn, Map m)
        {
            if (!DesignatorsData.rjwBreeding.Any())
            {
                return(null);
            }

            DebugText("BreederHelper::find_designated_breeder( " + xxx.get_pawnname(pawn) + " ) called");

            float min_fuckability = 0.10f;                          // Don't rape pawns with <10% fuckability
            float avg_fuckability = 0f;                             // Average targets fuckability, choose target higher than that
            var   valid_targets   = new Dictionary <Pawn, float>(); // Valid pawns and their fuckability
            Pawn  chosentarget    = null;                           // Final target pawn

            if (pawn.Faction == null)                               // HostileTo causes error on fresh colony(w/o name)
            {
                return(null);
            }

            IEnumerable <Pawn> targets = DesignatorsData.rjwBreeding.Where(x
                                                                           => x != pawn &&
                                                                           xxx.is_not_dying(x) &&
                                                                           xxx.can_get_raped(x) &&
                                                                           !x.IsForbidden(pawn) &&
                                                                           !x.Suspended &&
                                                                           !x.HostileTo(pawn) &&
                                                                           !(x.IsPregnant() && xxx.is_animal(x)) &&
                                                                           pawn.CanReserveAndReach(x, PathEndMode.Touch, Danger.Some, max_animals_at_once) &&
                                                                           ((RJWSettings.bestiality_enabled && xxx.is_human(x)) || (RJWSettings.animal_on_animal_enabled && xxx.is_animal(x)))
                                                                           );

            foreach (Pawn target in targets)
            {
                if (!xxx.can_path_to_target(pawn, target.Position))
                {
                    continue;                    // too far
                }
                var partBPR = Genital_Helper.get_genitalsBPR(pawn);
                var parts   = Genital_Helper.get_PartsHediffList(pawn, partBPR);

                var fuc = SexAppraiser.would_fuck(pawn, target, invert_opinion: true, ignore_gender: (Genital_Helper.has_penis_fertile(pawn, parts) || Genital_Helper.has_penis_infertile(pawn, parts) || xxx.is_insect(pawn)));
                DebugText("BreederHelper::find_designated_breeder( " + xxx.get_pawnname(pawn) + " -> " + xxx.get_pawnname(target) + " (" + fuc.ToString() + " / " + min_fuckability.ToString() + ")");

                if (fuc > min_fuckability)
                {
                    valid_targets.Add(target, fuc);
                }
            }

            if (valid_targets.Any())
            {
                //avg_fuckability = valid_targets.Average(x => x.Value);

                // choose pawns to f**k with above average fuckability
                var valid_targetsFilteredAnimals = valid_targets.Where(x => x.Value >= avg_fuckability);

                if (valid_targetsFilteredAnimals.Any())
                {
                    chosentarget = valid_targetsFilteredAnimals.RandomElement().Key;
                }
            }

            return(chosentarget);
        }
Example #12
0
            //Create a new menu option that will contain some of the relevant data for debugging RJW
            //Window space is limited, so keep to one line per pawn. Additional data may need a separate menu
            static FloatMenuOption newMenuOption(Pawn pawn)
            {
                return(new FloatMenuOption("RJW WouldFuck", () =>
                {
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.AppendLine();
                    stringBuilder.AppendLine("canFuck: " + xxx.can_fuck(pawn) + ", canBeFucked: " + xxx.can_be_fucked(pawn) + ", loving: " + xxx.can_do_loving(pawn));
                    stringBuilder.AppendLine("canRape: " + xxx.can_rape(pawn) + ", canBeRaped: " + xxx.can_get_raped(pawn));

                    if (!pawn.IsColonist)
                    {
                        if (pawn.Faction != null)
                        {
                            int pawnAmountOfSilvers = pawn.inventory.innerContainer.TotalStackCountOfDef(ThingDefOf.Silver);
                            int caravanAmountOfSilvers = 0;
                            Lord lord = pawn.GetLord();
                            List <Pawn> caravanMembers = pawn.Map.mapPawns.PawnsInFaction(pawn.Faction).Where(x => x.GetLord() == lord && x.inventory?.innerContainer?.TotalStackCountOfDef(ThingDefOf.Silver) > 0).ToList();

                            caravanAmountOfSilvers += caravanMembers.Sum(member => member.inventory.innerContainer.TotalStackCountOfDef(ThingDefOf.Silver));

                            stringBuilder.AppendLine("pawnSilvers: " + pawnAmountOfSilvers + ", caravanSilvers: " + caravanAmountOfSilvers);
                        }
                    }
                    stringBuilder.AppendLine();

                    stringBuilder.AppendLine("Humans - Colonists:");
                    List <Pawn> pawns = pawn.Map.mapPawns.AllPawnsSpawned.Where(x => x != pawn && x.RaceProps.Humanlike && x.IsColonist).OrderBy(x => xxx.get_pawnname(x)).ToList();
                    foreach (Pawn partner in pawns)
                    {
                        stringBuilder.AppendLine(partner.LabelShort + " (" + partner.gender.GetLabel() +
                                                 ", age: " + partner.ageTracker.AgeBiologicalYears +
                                                 ", " + CompRJW.Comp(partner).orientation +
                                                 "): (would f**k) " + SexAppraiser.would_fuck(pawn, partner).ToString("F3") +
                                                 "): (be f****d) " + SexAppraiser.would_fuck(partner, pawn).ToString("F3") +
                                                 ": (rape) " + SexAppraiser.would_rape(pawn, partner));
                    }
                    stringBuilder.AppendLine();

                    stringBuilder.AppendLine("Humans - Prisoners:");
                    pawns = pawn.Map.mapPawns.AllPawnsSpawned.Where(x => x != pawn && x.RaceProps.Humanlike && !x.IsColonist && x.IsPrisonerOfColony).OrderBy(x => xxx.get_pawnname(x)).ToList();
                    foreach (Pawn partner in pawns)
                    {
                        stringBuilder.AppendLine(partner.LabelShort + " (" + partner.gender.GetLabel() +
                                                 ", age: " + partner.ageTracker.AgeBiologicalYears +
                                                 ", " + CompRJW.Comp(partner).orientation +
                                                 "): (would f**k) " + SexAppraiser.would_fuck(pawn, partner).ToString("F3") +
                                                 "): (be f****d) " + SexAppraiser.would_fuck(partner, pawn).ToString("F3") +
                                                 ": (rape) " + SexAppraiser.would_rape(pawn, partner));
                    }
                    stringBuilder.AppendLine();

                    stringBuilder.AppendLine("Humans - non Colonists:");
                    pawns = pawn.Map.mapPawns.AllPawnsSpawned.Where(x => x != pawn && x.RaceProps.Humanlike && !x.IsColonist && !x.IsPrisonerOfColony).OrderBy(x => xxx.get_pawnname(x)).ToList();
                    foreach (Pawn partner in pawns)
                    {
                        stringBuilder.AppendLine(partner.LabelShort + " (" + partner.gender.GetLabel() +
                                                 ", age: " + partner.ageTracker.AgeBiologicalYears +
                                                 ", " + CompRJW.Comp(partner).orientation +
                                                 "): (would f**k) " + SexAppraiser.would_fuck(pawn, partner).ToString("F3") +
                                                 "): (be f****d) " + SexAppraiser.would_fuck(partner, pawn).ToString("F3") +
                                                 ": (rape) " + SexAppraiser.would_rape(pawn, partner));
                    }
                    stringBuilder.AppendLine();

                    stringBuilder.AppendLine("Animals - Colony:");
                    pawns = pawn.Map.mapPawns.AllPawnsSpawned.Where(x => x != pawn && x.RaceProps.Animal && x.Faction == Faction.OfPlayer).OrderBy(x => xxx.get_pawnname(x)).ToList();
                    foreach (Pawn partner in pawns)
                    {
                        stringBuilder.AppendLine(partner.LabelShort + " (" + partner.gender.GetLabel() +
                                                 ", age: " + partner.ageTracker.AgeBiologicalYears +
                                                 //", " + CompRJW.Comp(partner).orientation +
                                                 "): (would f**k) " + SexAppraiser.would_fuck(pawn, partner).ToString("F3") +
                                                 "): (be f****d) " + SexAppraiser.would_fuck(partner, pawn).ToString("F3") +
                                                 ": (rape) " + SexAppraiser.would_rape(pawn, partner));
                    }
                    stringBuilder.AppendLine();

                    stringBuilder.AppendLine("Animals - non Colony:");
                    pawns = pawn.Map.mapPawns.AllPawnsSpawned.Where(x => x != pawn && x.RaceProps.Animal && x.Faction != Faction.OfPlayer).OrderBy(x => xxx.get_pawnname(x)).ToList();
                    foreach (Pawn partner in pawns)
                    {
                        stringBuilder.AppendLine(partner.LabelShort + " (" + partner.gender.GetLabel() +
                                                 ", age: " + partner.ageTracker.AgeBiologicalYears +
                                                 //", " + CompRJW.Comp(partner).orientation +
                                                 "): (would f**k) " + SexAppraiser.would_fuck(pawn, partner).ToString("F3") +
                                                 "): (be f****d) " + SexAppraiser.would_fuck(partner, pawn).ToString("F3") +
                                                 ": (rape) " + SexAppraiser.would_rape(pawn, partner));
                    }
                    Find.WindowStack.Add(new Dialog_MessageBox(stringBuilder.ToString(), null, null, null, null, null, false, null, null));
                }, MenuOptionPriority.Default, null, null, 0.0f, null, null));
            }
        public static Pawn find_pawn_to_fuck(Pawn pawn, Map map)
        {
            string pawnName = xxx.get_pawnname(pawn);

            if (RJWSettings.DebugLogJoinInBed)
            {
                Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): starting.");
            }

            bool pawnIsNympho       = xxx.is_nympho(pawn);
            bool pawnCanPickAnyone  = RJWSettings.WildMode || (pawnIsNympho && RJWHookupSettings.NymphosCanPickAnyone);
            bool pawnCanPickAnimals = (pawnCanPickAnyone || xxx.is_zoophile(pawn)) && RJWSettings.bestiality_enabled;

            if (RJWSettings.DebugLogJoinInBed)
            {
                Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): nympho:{pawnIsNympho}, ignores rules:{pawnCanPickAnyone}, zoo:{pawnCanPickAnimals}");
            }

            if (!RJWHookupSettings.ColonistsCanHookup && pawn.IsFreeColonist && !pawnCanPickAnyone)
            {
                if (RJWSettings.DebugLogJoinInBed)
                {
                    Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): is a colonist and colonist hookups are disabled in mod settings");
                }
                return(null);
            }

            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());

            // Check AllPawns, not just colonists, to include guests.
            List <Pawn> targets = map.mapPawns.AllPawns.Where(x
                                                              => x != pawn &&
                                                              !x.InBed() &&
                                                              !x.IsForbidden(pawn) &&
                                                              xxx.IsTargetPawnOkay(x) &&
                                                              CanFuck(x) &&
                                                              x.Map == pawn.Map &&
                                                              !x.HostileTo(pawn)
                                                              //&& (pawnCanPickAnimals || !xxx.is_animal(x))
                                                              && !xxx.is_animal(x)
                                                              ).ToList();

            if (!targets.Any())
            {
                if (RJWSettings.DebugLogJoinInBed)
                {
                    Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): no eligible targets");
                }
                return(null);
            }

            if (RJWSettings.DebugLogJoinInBed)
            {
                Log.Message($"[RJWQ] find_pawn_to_fuck quickie({pawnName}): considering {targets.Count} targets");
            }

            // find lover/partner on same map
            List <Pawn> partners = targets.Where(x
                                                 => pawn.relations.DirectRelationExists(PawnRelationDefOf.Lover, x) ||
                                                 pawn.relations.DirectRelationExists(PawnRelationDefOf.Fiance, x) ||
                                                 pawn.relations.DirectRelationExists(PawnRelationDefOf.Spouse, x)
                                                 ).ToList();

            if (RJWSettings.DebugLogJoinInBed)
            {
                Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): considering {partners.Count} partners");
            }

            if (partners.Any())
            {
                partners.Shuffle();                 //Randomize order.
                foreach (Pawn target in partners)
                {
                    if (RJWSettings.DebugLogJoinInBed)
                    {
                        Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): checking lover {xxx.get_pawnname(target)}");
                    }

                    //interruptible jobs
                    if (target.jobs?.curJob != null &&
                        (target.jobs.curJob.playerForced ||
                         JobDriver_SexQuick.quickieAllowedJobs.Contains(target.jobs.curJob.def)
                        ))
                    {
                        if (RJWSettings.DebugLogJoinInBed)
                        {
                            Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): lover has important job, skipping");
                        }
                        continue;
                    }
                    if (pawn.Position.DistanceToSquared(target.Position) < MaxDistanceSquaredToFuck &&
                        pawn.CanReserveAndReach(target, PathEndMode.OnCell, Danger.Some, 1, 0) &&
                        target.CanReserve(pawn, 1, 0) &&
                        SexAppraiser.would_fuck(pawn, target) > 0.1f &&
                        SexAppraiser.would_fuck(target, pawn) > 0.1f)
                    {
                        if (RJWSettings.DebugLogJoinInBed)
                        {
                            Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): banging lover {xxx.get_pawnname(target)}");
                        }
                        return(target);
                    }
                }
            }

            // No lovers around... see if the pawn fancies a hookup.  Nymphos and frustrated pawns always do!
            if (RJWSettings.DebugLogJoinInBed)
            {
                Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): no partners available.  checking canHookup");
            }
            bool canHookup = pawnIsNympho || pawnCanPickAnyone || xxx.is_frustrated(pawn) || (xxx.is_horny(pawn) && Rand.Value < RJWHookupSettings.HookupChanceForNonNymphos);

            if (!canHookup)
            {
                if (RJWSettings.DebugLogJoinInBed)
                {
                    Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): no hookup today");
                }
                return(null);
            }

            // No cheating from casual hookups... would probably make colony relationship management too annoying
            if (RJWSettings.DebugLogJoinInBed)
            {
                Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): checking canHookupWithoutCheating");
            }
            bool hookupWouldBeCheating = xxx.HasNonPolyPartnerOnCurrentMap(pawn);

            if (hookupWouldBeCheating)
            {
                if (RJWHookupSettings.NymphosCanCheat && pawnIsNympho && xxx.is_frustrated(pawn))
                {
                    if (RJWSettings.DebugLogJoinInBed)
                    {
                        Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): I'm a nympho and I'm so frustrated that I'm going to cheat");
                    }
                    // No return here so they continue searching for hookup
                }
                else
                {
                    if (RJWSettings.DebugLogJoinInBed)
                    {
                        Log.Message($"[RJWQ] find_pawn_to_fuck({pawnName}): I want to bang but that's cheating");
                    }
                    return(null);
                }
            }

            Pawn best_fuckee = FindBestPartner(pawn, targets, pawnCanPickAnyone, pawnIsNympho);

            return(best_fuckee);
        }
        public static Pawn find_targetCP(Pawn pawn, Map m)
        {
            if (!DesignatorsData.rjwComfort.Any())
            {
                return(null);
            }

            float min_fuckability = 0.10f;                                              // Don't rape prisoners with <10% fuckability
            float avg_fuckability = 0f;                                                 // Average targets fuckability, choose target higher than that
            var   valid_targets   = new Dictionary <Pawn, float>();                     // Valid pawns and their fuckability
            Pawn  chosentarget    = null;                                               // Final target pawn

            IEnumerable <Pawn> targets = DesignatorsData.rjwComfort.Where(x
                                                                          => x != pawn &&
                                                                          xxx.can_get_raped(x) &&
                                                                          pawn.CanReserveAndReach(x, PathEndMode.Touch, Danger.Some, xxx.max_rapists_per_prisoner, 0) &&
                                                                          !x.IsForbidden(pawn) &&
                                                                          SexAppraiser.would_rape(pawn, x)
                                                                          );

            if (xxx.is_animal(pawn))
            {
                // Animals only consider targets they can see, instead of seeking them out.
                targets = targets.Where(x => pawn.CanSee(x)).ToList();
            }

            foreach (Pawn target in targets)
            {
                if (!xxx.can_path_to_target(pawn, target.Position))
                {
                    continue;                    // too far
                }
                float fuc = 0f;
                if (xxx.is_animal(target))
                {
                    fuc = SexAppraiser.would_fuck_animal(pawn, target, true);
                }
                else if (xxx.is_human(target))
                {
                    fuc = SexAppraiser.would_fuck(pawn, target, true);
                }

                if (fuc > min_fuckability)
                {
                    valid_targets.Add(target, fuc);
                }
            }

            if (valid_targets.Any())
            {
                // avg_fuckability = valid_targets.Average(x => x.Value); // disabled for CP

                // choose pawns to f**k with above average fuckability
                var valid_targetsFiltered = valid_targets.Where(x => x.Value >= avg_fuckability);

                if (valid_targetsFiltered.Any())
                {
                    chosentarget = valid_targetsFiltered.RandomElement().Key;
                }
            }

            return(chosentarget);
        }
        public override bool MoreChecks(Pawn pawn, Thing t, bool forced = false)
        {
            //Log.Message("[RJW]" + this.GetType().ToString() + " base checks: pass");

            Pawn target = t as Pawn;

            if (target == pawn)
            {
                //JobFailReason.Is("no self sex", null);
                return(false);
            }
            if (!WorkGiverChecks(pawn, t, forced))
            {
                return(false);
            }

            if (!xxx.is_human(target))
            {
                return(false);
            }
            if (!pawn.CanReserve(target, xxx.max_rapists_per_prisoner, 0))
            {
                return(false);
            }

            if (!(pawn.IsDesignatedHero() || RJWSettings.override_control))
            {
                if (!RJWSettings.WildMode)
                {
                    //check initiator
                    //fail for:
                    //satisfied non nymph pawns
                    if (xxx.need_some_sex(pawn) <= 1f && !xxx.is_nympho(pawn))
                    {
                        if (RJWSettings.DevMode)
                        {
                            JobFailReason.Is("not horny enough");
                        }
                        return(false);
                    }
                    if (!xxx.IsTargetPawnOkay(target))
                    {
                        if (RJWSettings.DevMode)
                        {
                            JobFailReason.Is("target not healthy enough");
                        }
                        return(false);
                    }
                    if (!xxx.is_lecher(pawn) && !xxx.is_psychopath(pawn) && !xxx.is_nympho(pawn))
                    {
                        if (!xxx.isSingleOrPartnerNotHere(pawn))
                        {
                            if (!LovePartnerRelationUtility.LovePartnerRelationExists(pawn, target))
                            {
                                if (RJWSettings.DevMode)
                                {
                                    JobFailReason.Is("cannot have sex while partner around");
                                }
                                return(false);
                            }
                        }
                    }

                    float relations  = 0;
                    float attraction = 0;
                    if (!xxx.is_animal(target))
                    {
                        relations = pawn.relations.OpinionOf(target);
                        if (relations < RJWHookupSettings.MinimumRelationshipToHookup)
                        {
                            if (!(relations > 0 && xxx.is_nympho(pawn)))
                            {
                                if (RJWSettings.DevMode)
                                {
                                    JobFailReason.Is($"i dont like them:({relations})");
                                }
                                return(false);
                            }
                        }

                        attraction = pawn.relations.SecondaryRomanceChanceFactor(target);
                        if (attraction < RJWHookupSettings.MinimumAttractivenessToHookup)
                        {
                            if (!(attraction > 0 && xxx.is_nympho(pawn)))
                            {
                                if (RJWSettings.DevMode)
                                {
                                    JobFailReason.Is($"i dont find them attractive:({attraction})");
                                }
                                return(false);
                            }
                        }
                    }
                    //Log.Message("[RJW]WorkGiver_Sex::" + SexAppraiser.would_fuck(pawn, target));
                    if (SexAppraiser.would_fuck(pawn, target) < 0.1f)
                    {
                        return(false);
                    }

                    if (!xxx.is_animal(target))
                    {
                        //check partner
                        if (xxx.need_some_sex(target) <= 1f && !xxx.is_nympho(target))
                        {
                            if (RJWSettings.DevMode)
                            {
                                JobFailReason.Is("partner not horny enough");
                            }
                            return(false);
                        }
                        if (!xxx.is_lecher(target) && !xxx.is_psychopath(target) && !xxx.is_nympho(target))
                        {
                            if (!xxx.isSingleOrPartnerNotHere(target))
                            {
                                if (!LovePartnerRelationUtility.LovePartnerRelationExists(pawn, target))
                                {
                                    if (RJWSettings.DevMode)
                                    {
                                        JobFailReason.Is("partner cannot have sex while their partner around");
                                    }
                                    return(false);
                                }
                            }
                        }

                        relations = target.relations.OpinionOf(pawn);
                        if (relations <= RJWHookupSettings.MinimumRelationshipToHookup)
                        {
                            if (!(relations > 0 && xxx.is_nympho(target)))
                            {
                                if (RJWSettings.DevMode)
                                {
                                    JobFailReason.Is($"dont like me:({relations})");
                                }
                                return(false);
                            }
                        }

                        attraction = target.relations.SecondaryRomanceChanceFactor(pawn);
                        if (attraction <= RJWHookupSettings.MinimumAttractivenessToHookup)
                        {
                            if (!(attraction > 0 && xxx.is_nympho(target)))
                            {
                                if (RJWSettings.DevMode)
                                {
                                    JobFailReason.Is($"doesnt find me attractive:({attraction})");
                                }
                                return(false);
                            }
                        }
                    }

                    //Log.Message("[RJW]WorkGiver_Sex::" + SexAppraiser.would_fuck(target, pawn));
                    if (SexAppraiser.would_fuck(target, pawn) < 0.1f)
                    {
                        return(false);
                    }
                }
            }

            //Log.Message("[RJW]" + this.GetType().ToString() + " extended checks: can start sex");
            return(true);
        }
        public override bool MoreChecks(Pawn pawn, Thing t, bool forced = false)
        {
            //Log.Message("[RJW]" + this.GetType().ToString() + " base checks: pass");
            if (!RJWSettings.rape_enabled)
            {
                return(false);
            }

            Pawn target = t as Pawn;

            if (target == pawn)
            {
                //JobFailReason.Is("no self rape", null);
                return(false);
            }
            if (!WorkGiverChecks(pawn, t, forced))
            {
                return(false);
            }

            if (!xxx.is_human(target))
            {
                return(false);
            }
            if (!pawn.CanReserve(target, xxx.max_rapists_per_prisoner, 0))
            {
                return(false);
            }

            if (!(pawn.IsDesignatedHero() || RJWSettings.override_control))
            {
                if (!RJWSettings.WildMode)
                {
                    if (xxx.is_kind(pawn) || xxx.is_masochist(pawn))
                    {
                        if (RJWSettings.DevMode)
                        {
                            JobFailReason.Is("refuses to rape");
                        }
                        return(false);
                    }
                    if (pawn.relations.OpinionOf(target) > 50 && !xxx.is_rapist(pawn) && !xxx.is_psychopath(pawn) && !xxx.is_masochist(target))
                    {
                        if (RJWSettings.DevMode)
                        {
                            JobFailReason.Is("refuses to rape a friend");
                        }
                        return(false);
                    }
                    if (!xxx.can_get_raped(target))
                    {
                        if (RJWSettings.DevMode)
                        {
                            JobFailReason.Is("cannot rape target");
                        }
                        return(false);
                    }
                    //fail for:
                    //satisfied pawns
                    //horny non rapists
                    if ((xxx.need_some_sex(pawn) <= 1f) ||
                        (xxx.need_some_sex(pawn) <= 2f && !(xxx.is_rapist(pawn) || xxx.is_psychopath(pawn) || xxx.is_nympho(pawn))))
                    {
                        if (RJWSettings.DevMode)
                        {
                            JobFailReason.Is("not horny enough");
                        }
                        return(false);
                    }
                    if (!xxx.can_rape(pawn))
                    {
                        if (RJWSettings.DevMode)
                        {
                            JobFailReason.Is("cannot rape");
                        }
                        return(false);
                    }
                    if (!xxx.is_healthy_enough(target) ||
                        !xxx.is_not_dying(target) && (xxx.is_bloodlust(pawn) || xxx.is_psychopath(pawn) || xxx.is_rapist(pawn) || xxx.has_quirk(pawn, "Somnophile")))
                    {
                        if (RJWSettings.DevMode)
                        {
                            JobFailReason.Is("target not healthy enough");
                        }
                        return(false);
                    }
                    if (!xxx.is_lecher(pawn) && !xxx.is_psychopath(pawn) && !xxx.is_nympho(pawn))
                    {
                        if (!xxx.isSingleOrPartnerNotHere(pawn))
                        {
                            if (!LovePartnerRelationUtility.LovePartnerRelationExists(pawn, target))
                            {
                                if (RJWSettings.DevMode)
                                {
                                    JobFailReason.Is("cannot rape while partner around");
                                }
                                return(false);
                            }
                        }
                    }
                    //Log.Message("[RJW]WorkGiver_RapeCP::" + SexAppraiser.would_fuck(pawn, target));
                    if (SexAppraiser.would_fuck(pawn, target) < 0.1f)
                    {
                        return(false);
                    }
                }
            }

            //Log.Message("[RJW]" + this.GetType().ToString() + " extended checks: can start sex");
            return(true);
        }