예제 #1
0
        public static void Postfix(ref float __result, Pawn initiator, Pawn recipient)
        {
            // one in mental break OR is already lover of the initiator can't be targeted
            if (recipient.InMentalState || LovePartnerRelationUtility.LovePartnerRelationExists(initiator, recipient))
            {
                __result = 0f;
                return;
            }

            // one can't perform romance atempt if recently rebuffed
            if (initiator.needs.mood.thoughts.memories.NumMemoriesOfDef(ThoughtDefOf.RebuffedMyRomanceAttempt) > 0)
            {
                __result = 0f;
                return;
            }

            // one can't target other people if current lover is good enough
            var initiator_partner = LovePartnerRelationUtility.ExistingMostLikedLovePartner(initiator, false);

            if (initiator_partner != null && initiator.relations.OpinionOf(initiator_partner) >= 25)
            {
                __result = 0f;
                return;
            }

            // one can't be targeted if current lover is good enough
            var recipient_partner = LovePartnerRelationUtility.ExistingMostLikedLovePartner(recipient, false);

            if (recipient_partner != null && recipient.relations.OpinionOf(recipient_partner) >= 25)
            {
                __result = 0f;
            }
        }
예제 #2
0
        internal static float _RandomSelectionWeight(this InteractionWorker_RomanceAttempt _this, Pawn initiator, Pawn recipient)
        {
            PsychologyPawn realInitiator = initiator as PsychologyPawn;

            //Lovers won't romance each other
            if (LovePartnerRelationUtility.LovePartnerRelationExists(initiator, recipient))
            {
                return(0f);
            }
            //Codependents won't romance anyone if they are in a relationship
            if (LovePartnerRelationUtility.HasAnyLovePartner(initiator) && initiator.story.traits.HasTrait(TraitDefOfPsychology.Codependent))
            {
                return(0f);
            }
            //No one will romance someone they find less than 25% attractive
            float num = initiator.relations.SecondaryRomanceChanceFactor(recipient);

            if (num < 0.25f)
            {
                return(0f);
            }
            //No one will romance someone they have less than +5 opinion of
            int num2 = initiator.relations.OpinionOf(recipient);

            if (num2 < 5)
            {
                return(0f);
            }
            //Only lechers will romance someone that has less than +5 opinion of them
            if (recipient.relations.OpinionOf(initiator) < 5 && !initiator.story.traits.HasTrait(TraitDefOfPsychology.Lecher))
            {
                return(0f);
            }
            //A pawn with +50 or more opinion of their lover will not hit on other pawns unless they are lecherous or polygamous (and their lover is also polygamous).
            float num3 = 1f;
            Pawn  pawn = LovePartnerRelationUtility.ExistingMostLikedLovePartner(initiator, false);

            if (pawn != null && !initiator.story.traits.HasTrait(TraitDefOfPsychology.Lecher) && (!initiator.story.traits.HasTrait(TraitDefOfPsychology.Polygamous) && !pawn.story.traits.HasTrait(TraitDefOfPsychology.Polygamous)))
            {
                float value = (float)initiator.relations.OpinionOf(pawn);
                num3 = Mathf.InverseLerp(50f, -50f, value);
            }
            //Straight women are 15% as likely to romance anyone.
            float num4 = (!initiator.story.traits.HasTrait(TraitDefOf.Gay)) ? ((initiator.gender != Gender.Female) ? 1f : 0.15f) : 1f;
            float num5 = Mathf.InverseLerp(0.25f, 1f, num);
            float num6 = Mathf.InverseLerp(5f, 100f, (float)num2);
            //People who have hit on someone in the past and been rejected because of their sexuality will rarely attempt to hit on them again.
            float num7 = (realInitiator != null && realInitiator.sexuality.IncompatibleSexualityKnown(recipient)) ? 0.05f : 1f;
            //Only lechers will try to romance someone in a stable relationship.
            float num8  = 1f;
            Pawn  pawn2 = LovePartnerRelationUtility.ExistingMostLikedLovePartner(recipient, false);

            if (pawn2 != null && !initiator.story.traits.HasTrait(TraitDefOfPsychology.Lecher))
            {
                int value = recipient.relations.OpinionOf(pawn2);
                num8 = Mathf.InverseLerp(5f, -100f, (float)value);
            }
            return(1.15f * num3 * num4 * num5 * num6 * num3 * num7 * num8);
        }
 private bool TryFindBetrothed(out Pawn betrothed)
 {
     return((from potentialPartners in PawnsFinder
             .AllMapsCaravansAndTravelingTransportPods_Alive_FreeColonistsAndPrisoners_NoCryptosleep
             where !LovePartnerRelationUtility.HasAnyLovePartner(potentialPartners) ||
             LovePartnerRelationUtility.ExistingMostLikedLovePartner(potentialPartners, false) ==
             marriageSeeker
             select potentialPartners).TryRandomElementByWeight(
                marriageSeeker2 => marriageSeeker.relations.SecondaryLovinChanceFactor(marriageSeeker2), out betrothed));
 }
 private static bool TryFindMarriageSeeker(out Pawn marriageSeeker)
 {
     return((from x in Find.WorldPawns.AllPawnsAlive
             where x.Faction != null && !x.Faction.def.hidden && !x.Faction.def.permanentEnemy && !x.Faction.IsPlayer &&
             x.Faction.PlayerGoodwill <= 50 && !x.Faction.defeated &&
             x.Faction.def.techLevel <= TechLevel.Medieval &&
             x.Faction.leader != null && !x.Faction.leader.IsPrisoner && !x.Faction.leader.Spawned &&
             !x.IsPrisoner && !x.Spawned && x.relations != null && x.RaceProps.Humanlike &&
             !SettlementUtility.IsPlayerAttackingAnySettlementOf(x.Faction) && !PeaceTalksExist(x.Faction) &&
             (!LovePartnerRelationUtility.HasAnyLovePartner(x) ||
              LovePartnerRelationUtility.ExistingMostLikedLovePartner(x, false)?.Faction ==
              Faction.OfPlayer)
             select x).TryRandomElement(out marriageSeeker)); //todo: make more likely to select hostile.
 }
예제 #5
0
        // Token: 0x06000C7E RID: 3198 RVA: 0x0003DCB8 File Offset: 0x0003BEB8
        internal static float _RandomSelectionWeight(this InteractionWorker_RomanceAttempt _this, Pawn initiator, Pawn recipient)
        {
            if (LovePartnerRelationUtility.LovePartnerRelationExists(initiator, recipient))
            {
                return(0f);
            }
            if (LovePartnerRelationUtility.HasAnyLovePartner(initiator) && initiator.story.traits.HasTrait(TraitDefOfPsychology.Codependent))
            {
                return(0f);
            }
            float num  = initiator.relations.AttractionTo(recipient);
            int   num2 = initiator.relations.OpinionOf(recipient);

            if (!initiator.story.traits.HasTrait(TraitDefOfPsychology.Lecher))
            {
                if (num < 0.25f)
                {
                    return(0f);
                }
                if (num2 < 5)
                {
                    return(0f);
                }
                if (recipient.relations.OpinionOf(initiator) < 5)
                {
                    return(0f);
                }
            }
            else
            {
                num  = 0.25f;
                num2 = 5;
            }
            float num3 = 1f;
            Pawn  pawn = LovePartnerRelationUtility.ExistingMostLikedLovePartner(initiator, false);

            if (pawn != null)
            {
                float value = (float)initiator.relations.OpinionOf(pawn);
                num3 = Mathf.InverseLerp(50f, -50f, value);
            }
            float num4 = (initiator.gender != Gender.Female) ? 1f : 0.125f;
            float num5 = Mathf.InverseLerp(0.25f, 1f, num);
            float num6 = Mathf.InverseLerp(5f, 100f, (float)num2);
            float num7 = (initiator.story.traits.HasTrait(TraitDefOfPsychology.Lecher)) ? 0.25f : 0f;

            return(1.15f * num4 * num5 * num6 * num3 + num7);
        }
예제 #6
0
        public static bool WillPawnTryHookup(Pawn target)
        {
            if (target.story.traits.HasTrait(TraitDefOf.Asexual))
            {
                return(false);
            }
            Pawn lover = LovePartnerRelationUtility.ExistingMostLikedLovePartner(target, false);

            if (lover == null)
            {
                return(true);
            }
            float num  = target.relations.OpinionOf(lover);
            float num2 = Mathf.InverseLerp(30f, -80f, num);

            if (xxx.is_prude(target))
            {
                num2 = 0f;
            }
            else if (xxx.is_lecher(target))
            {
                //Lechers are always up for it.
                num2 = Mathf.InverseLerp(100f, 50f, num);
            }
            else if (target.Map == lover.Map)
            {
                //Less likely to cheat if the lover is on the same map.
                num2 = Mathf.InverseLerp(70f, 15f, num);
            }
            //else default values

            if (xxx.is_frustrated(target))
            {
                num2 *= 1.8f;
            }
            else if (xxx.is_hornyorfrustrated(target))
            {
                num2 *= 1.4f;
            }
            num2 /= 1.5f;
            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());
            return(Rand.Range(0f, 1f) < num2);
        }
예제 #7
0
        public override float RandomSelectionWeight(Pawn initiator, Pawn recipient)
        {
            if (LovePartnerRelationUtility.LovePartnerRelationExists(initiator, recipient))
            {
                return(0f);
            }

            var num = initiator.relations.SecondaryRomanceChanceFactor(recipient);

            if (num < 0.25f)
            {
                return(0f);
            }

            var num2 = initiator.relations.OpinionOf(recipient);

            if (num2 < 5)
            {
                return(0f);
            }

            if (recipient.relations.OpinionOf(initiator) < 5)
            {
                return(0f);
            }

            var num3 = 1f;
            var pawn = LovePartnerRelationUtility.ExistingMostLikedLovePartner(initiator, false);

            if (pawn != null)
            {
                float value = initiator.relations.OpinionOf(pawn);
                num3 = Mathf.InverseLerp(50f, -50f, value);
            }

            var num5 = Mathf.InverseLerp(0.25f, 1f, num);
            var num6 = Mathf.InverseLerp(5f, 100f, num2);

            return(1.15f * num5 * num6 * num3);
        }
예제 #8
0
        public override float RandomSelectionWeight(Pawn initiator, Pawn recipient)
        {
            if (LovePartnerRelationUtility.LovePartnerRelationExists(initiator, recipient))
            {
                return(0f);
            }
            float num = initiator.relations.SecondaryRomanceChanceFactor(recipient);

            if (num < 0.25f)
            {
                return(0f);
            }
            int num2 = initiator.relations.OpinionOf(recipient);

            if (num2 < 5)
            {
                return(0f);
            }
            if (recipient.relations.OpinionOf(initiator) < 5)
            {
                return(0f);
            }
            float num3 = 1f;
            Pawn  pawn = LovePartnerRelationUtility.ExistingMostLikedLovePartner(initiator, false);

            if (pawn != null)
            {
                float value = initiator.relations.OpinionOf(pawn);
                num3 = Mathf.InverseLerp(50f, -50f, value);
            }
            float num4 = (!initiator.story.traits.HasTrait(TraitDefOf.Gay)) ? ((initiator.gender != Gender.Female) ? 1f : 0.15f) : 1f;
            float num5 = Mathf.InverseLerp(0.25f, 1f, num);
            float num6 = Mathf.InverseLerp(5f, 100f, num2);
            float num7 = initiator.gender != recipient.gender || (initiator.story.traits.HasTrait(TraitDefOf.Gay) && recipient.story.traits.HasTrait(TraitDefOf.Gay)) ? 1f : 0.15f;

            return(1.15f * num4 * num5 * num6 * num3 * num7);
        }
        public static void PsychologyException(ref float __result, Pawn initiator, Pawn recipient)
        {
            //Don't hit on people in mental breaks... unless you're really freaky.
            if (recipient.InMentalState && PsycheHelper.PsychologyEnabled(initiator) && PsycheHelper.Comp(initiator).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Experimental) < 0.8f)
            {
                __result = 0f;
                return;
            }
            //Pawns won't hit on their spouses.
            if (LovePartnerRelationUtility.LovePartnerRelationExists(initiator, recipient))
            {
                __result = 0f;
                return;
            }
            //Codependents won't romance anyone if they are in a relationship
            if (LovePartnerRelationUtility.HasAnyLovePartner(initiator) && initiator.story.traits.HasTrait(TraitDefOfPsychology.Codependent))
            {
                __result = 0f;
                return;
            }
            //Only lechers will romance someone that has less than +5 opinion of them
            if (recipient.relations.OpinionOf(initiator) < 5 && !initiator.story.traits.HasTrait(TraitDefOfPsychology.Lecher))
            {
                __result = 0f;
                return;
            }
            float attractiveness = initiator.relations.SecondaryRomanceChanceFactor(recipient);
            int   opinion        = initiator.relations.OpinionOf(recipient);
            float romanceChance  = 1.15f;

            if (!PsycheHelper.PsychologyEnabled(initiator))
            {
                //Vanilla: Straight women are 15% as likely to romance anyone.
                romanceChance = (!initiator.story.traits.HasTrait(TraitDefOf.Gay)) ? ((initiator.gender != Gender.Female) ? romanceChance : romanceChance * 0.15f) : romanceChance;
            }
            else
            {
                //Psychology: A pawn's likelihood to romance is based on how Aggressive and Romantic they are.
                float personalityFactor = Mathf.Pow(20f, PsycheHelper.Comp(initiator).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Aggressive)) * Mathf.Pow(12f, (1f - PsycheHelper.Comp(initiator).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Romantic)));
                romanceChance = personalityFactor * 0.02f;
            }
            //A pawn with +50 or more opinion of their lover will not hit on other pawns unless they are lecherous or polygamous (and their lover is also polygamous).
            float existingLovePartnerFactor = 1f;
            Pawn  pawn = LovePartnerRelationUtility.ExistingMostLikedLovePartner(initiator, false);

            if (pawn != null && !initiator.story.traits.HasTrait(TraitDefOfPsychology.Lecher) && (!initiator.story.traits.HasTrait(TraitDefOfPsychology.Polygamous) && !pawn.story.traits.HasTrait(TraitDefOfPsychology.Polygamous)))
            {
                float value = (float)initiator.relations.OpinionOf(pawn);
                existingLovePartnerFactor = Mathf.InverseLerp(50f, -50f, value);
            }
            float attractivenessFactor = Mathf.InverseLerp(0.25f, 1f, attractiveness);
            float opinionFactor        = Mathf.InverseLerp(-5f, 100f, (float)opinion) * 2f;
            //People who have hit on someone in the past and been rejected because of their sexuality will rarely attempt to hit on them again.
            float knownSexualityFactor = (PsycheHelper.PsychologyEnabled(initiator) && PsychologyBase.ActivateKinsey() && PsycheHelper.Comp(initiator).Sexuality.IncompatibleSexualityKnown(recipient) && !initiator.story.traits.HasTrait(TraitDefOfPsychology.Lecher)) ? 0.05f : (PsycheHelper.PsychologyEnabled(initiator) ? (initiator.gender == recipient.gender ? (initiator.story.traits.HasTrait(TraitDefOf.Gay) && recipient.story.traits.HasTrait(TraitDefOf.Gay) ? 1f : 0.15f) : (!initiator.story.traits.HasTrait(TraitDefOf.Gay) && !recipient.story.traits.HasTrait(TraitDefOf.Gay) ? 1f : 0.15f)) : 1f);
            //Only lechers will try to romance someone in a stable relationship.
            float recipientLovePartnerFactor = 1f;
            Pawn  pawn2 = LovePartnerRelationUtility.ExistingMostLikedLovePartner(recipient, false);

            if (pawn2 != null && !initiator.story.traits.HasTrait(TraitDefOfPsychology.Lecher))
            {
                int value = recipient.relations.OpinionOf(pawn2);
                recipientLovePartnerFactor = Mathf.InverseLerp(5f, -100f, (float)value);
            }
            __result = romanceChance * existingLovePartnerFactor * attractivenessFactor * opinionFactor * knownSexualityFactor * recipientLovePartnerFactor;
            return;
        }
            public static bool Listener(Map map, ref bool __result)
            {
                try
                {
                    if (!map.IsPlayerHome)
                    {
                        return(false);
                    }

                    var num  = 0;
                    var num2 = 0;
                    var allBuildingsColonist = map.listerBuildings.allBuildingsColonist;
                    foreach (var building_Bed in allBuildingsColonist.Select(building => building as Building_Bed).Where(building_Bed =>
                                                                                                                         building_Bed != null && !building_Bed.ForPrisoners && !building_Bed.Medical && building_Bed.def.building.bed_humanlike))
                    {
                        if (building_Bed.SleepingSlotsCount == 1)
                        {
                            num++;
                        }
                        else
                        {
                            num2++;
                        }
                    }

                    var num3 = 0;
                    var num4 = 0;
                    foreach (var current in map.mapPawns.FreeColonistsSpawned)
                    {
                        if (Utils.ExceptionAndroidList.Contains(current.def.defName))
                        {
                            continue;
                        }

                        var pawn = LovePartnerRelationUtility.ExistingMostLikedLovePartner(current, false);
                        if (pawn == null || !pawn.Spawned || pawn.Map != current.Map || pawn.Faction != Faction.OfPlayer || pawn.HostFaction != null)
                        {
                            num3++;
                        }
                        else
                        {
                            num4++;
                        }
                    }

                    if (num4 % 2 != 0)
                    {
                    }

                    for (var j = 0; j < num4 / 2; j++)
                    {
                        if (num2 > 0)
                        {
                            num2--;
                        }
                        else
                        {
                            num -= 2;
                        }
                    }
                    for (var k = 0; k < num3; k++)
                    {
                        if (num2 > 0)
                        {
                            num2--;
                        }
                        else
                        {
                            num--;
                        }
                    }
                    __result = num < 0 || num2 < 0;

                    return(false);
                }
                catch (Exception e)
                {
                    Log.Message("[ATPP] ALert_NeedColonistBeds.NeedColonistBeds :" + e.Message + " - " + e.StackTrace);
                    return(true);
                }
            }
            public static bool Listener(Map map, ref bool __result)
            {
                try
                {
                    if (!map.IsPlayerHome)
                    {
                        return(false);
                    }
                    int             num  = 0;
                    int             num2 = 0;
                    List <Building> allBuildingsColonist = map.listerBuildings.allBuildingsColonist;
                    for (int i = 0; i < allBuildingsColonist.Count; i++)
                    {
                        Building_Bed building_Bed = allBuildingsColonist[i] as Building_Bed;
                        if (building_Bed != null && !building_Bed.ForPrisoners && !building_Bed.Medical && building_Bed.def.building.bed_humanlike)
                        {
                            if (building_Bed.SleepingSlotsCount == 1)
                            {
                                num++;
                            }
                            else
                            {
                                num2++;
                            }
                        }
                    }
                    int num3 = 0;
                    int num4 = 0;
                    foreach (Pawn current in map.mapPawns.FreeColonistsSpawned)
                    {
                        //On ignore les androis dans la comptabilisation
                        if (Utils.ExceptionAndroidList.Contains(current.def.defName))
                        {
                            continue;
                        }

                        Pawn pawn = LovePartnerRelationUtility.ExistingMostLikedLovePartner(current, false);
                        if (pawn == null || !pawn.Spawned || pawn.Map != current.Map || pawn.Faction != Faction.OfPlayer || pawn.HostFaction != null)
                        {
                            num3++;
                        }
                        else
                        {
                            num4++;
                        }
                    }
                    if (num4 % 2 != 0)
                    {
                        //Log.ErrorOnce("partneredCols % 2 != 0", 743211, false);
                    }
                    for (int j = 0; j < num4 / 2; j++)
                    {
                        if (num2 > 0)
                        {
                            num2--;
                        }
                        else
                        {
                            num -= 2;
                        }
                    }
                    for (int k = 0; k < num3; k++)
                    {
                        if (num2 > 0)
                        {
                            num2--;
                        }
                        else
                        {
                            num--;
                        }
                    }
                    __result = num < 0 || num2 < 0;

                    return(false);
                }
                catch (Exception e)
                {
                    Log.Message("[ATPP] ALert_NeedColonistBeds.NeedColonistBeds :" + e.Message + " - " + e.StackTrace);
                    return(true);
                }
            }
예제 #12
0
        private static float RandomSelectionWeight_Method(Pawn initiator, Pawn recipient)
        {
            CompIndividuality compOther = recipient.TryGetComp <CompIndividuality>();
            CompIndividuality comp      = initiator.TryGetComp <CompIndividuality>();

            if (LovePartnerRelationUtility.LovePartnerRelationExists(initiator, recipient))
            {
                return(0f);
            }
            float attractiveness = initiator.relations.SecondaryRomanceChanceFactor(recipient);

            if (attractiveness < 0.15f)
            {
                return(0f);
            }
            int opinionOfOther = initiator.relations.OpinionOf(recipient);

            if (opinionOfOther < 5)
            {
                return(0f);
            }
            if (recipient.relations.OpinionOf(initiator) < 5)
            {
                return(0f);
            }
            float existingLovePartnerFactor = 1f;
            Pawn  pawn = LovePartnerRelationUtility.ExistingMostLikedLovePartner(initiator, false);

            if (pawn != null)
            {
                float opinionOfSpouse = initiator.relations.OpinionOf(pawn);
                existingLovePartnerFactor = Mathf.InverseLerp(50f, -50f, opinionOfSpouse);
            }
            float romanceFactor;

            if (compOther != null)
            {
                romanceFactor = compOther.RomanceFactor * 2f;
            }
            else
            {
                romanceFactor = 1f;
            }
            float attractivenessFactor = Mathf.InverseLerp(0.15f, 1f, attractiveness);
            float opinionFactor        = Mathf.InverseLerp(5f, 100f, opinionOfOther);
            float genderFactor         = 1f;

            if (initiator.gender != recipient.gender && compOther != null && comp != null)
            {
                if (compOther.sexuality == CompIndividuality.Sexuality.Straight)
                {
                    genderFactor = 1.0f;
                }
                else if (compOther.sexuality == CompIndividuality.Sexuality.Bisexual)
                {
                    genderFactor = 0.75f;
                }
                else if (compOther.sexuality == CompIndividuality.Sexuality.Gay)
                {
                    genderFactor = 0.1f;
                }
                else if (compOther.sexuality == CompIndividuality.Sexuality.Asexual && comp.sexuality == CompIndividuality.Sexuality.Asexual)
                {
                    genderFactor = 1.0f;
                }
            }
            if (initiator.gender == recipient.gender && compOther != null && comp != null)
            {
                if (compOther.sexuality == CompIndividuality.Sexuality.Gay)
                {
                    genderFactor = 1.0f;
                }
                else if (compOther.sexuality == CompIndividuality.Sexuality.Bisexual)
                {
                    genderFactor = 0.75f;
                }
                else if (compOther.sexuality == CompIndividuality.Sexuality.Straight)
                {
                    genderFactor = 0.1f;
                }
                else if (compOther.sexuality == CompIndividuality.Sexuality.Asexual && comp.sexuality == CompIndividuality.Sexuality.Asexual)
                {
                    genderFactor = 0.5f;
                }
            }
            return(1.15f * romanceFactor * attractivenessFactor * opinionFactor * existingLovePartnerFactor * genderFactor);
        }
 private static bool TryFindMarriageSeeker(out Pawn marriageSeeker) => (from x in Find.WorldPawns.AllPawnsAlive
                                                                            where x.Faction != null && !x.Faction.def.hidden && !x.Faction.def.permanentEnemy && !x.Faction.IsPlayer && !x.Faction.defeated &&
                                                                        !SettlementUtility.IsPlayerAttackingAnySettlementOf(faction : x.Faction) && !PeaceTalksExist(faction : x.Faction) &&
                                                                        x.Faction.leader != null && !x.Faction.leader.IsPrisoner && !x.Faction.leader.Spawned &&
                                                                        (x.Faction.def.techLevel <= TechLevel.Medieval) && /*|| x.Faction.def.techLevel == TechLevel.Archotech*/ // not today space kitties
                                                                        !x.IsPrisoner && !x.Spawned &&
                                                                        (!LovePartnerRelationUtility.HasAnyLovePartner(pawn : x) || LovePartnerRelationUtility.ExistingMostLikedLovePartner(p : x, allowDead : false)?.Faction == Faction.OfPlayer)
                                                                        select x).TryRandomElement(result : out marriageSeeker); //todo: make more likely to select hostile.
        protected override float MtbHours(Pawn pawn)
        {
            float base_mtb = xxx.config.comfort_prisoner_rape_mtbh_mul;             // Default is 4.0

            float desire_factor;
            {
                Need_Sex need_sex = pawn.needs.TryGetNeed <Need_Sex>();

                if (need_sex != null)
                {
                    if (need_sex.CurLevel <= need_sex.thresh_frustrated())
                    {
                        desire_factor = 0.40f;
                    }
                    else if (need_sex.CurLevel <= need_sex.thresh_horny())
                    {
                        desire_factor = 0.80f;
                    }
                    else
                    {
                        desire_factor = 1.00f;
                    }
                }
                else
                {
                    desire_factor = 1.00f;
                }
            }

            float personality_factor;
            {
                personality_factor = 1.0f;

                if (xxx.is_nympho(pawn))
                {
                    personality_factor *= 0.5f;
                }
                else if (xxx.is_prude(pawn) || pawn.story.traits.HasTrait(TraitDefOf.BodyPurist))
                {
                    personality_factor *= 2f;
                }

                if (pawn.story.traits.HasTrait(TraitDefOf.Nudist))
                {
                    personality_factor *= 0.9f;
                }

                // Pawns with no zoophile trait should first try to find other outlets.
                if (!xxx.is_zoophile(pawn))
                {
                    personality_factor *= 8f;
                }

                // Less likely to engage in bestiality if the pawn has a lover... unless the lover is an animal (there's mods for that, so need to check).
                if (!xxx.isSingleOrPartnerNotHere(pawn) && !xxx.is_animal(LovePartnerRelationUtility.ExistingMostLikedLovePartner(pawn, false)) && !xxx.is_lecher(pawn) && !xxx.is_nympho(pawn))
                {
                    personality_factor *= 2.5f;
                }

                // Pawns with few or no prior animal encounters are more reluctant to engage in bestiality.
                if (pawn.records.GetValue(xxx.CountOfSexWithAnimals) < 3)
                {
                    personality_factor *= 3f;
                }
                else if (pawn.records.GetValue(xxx.CountOfSexWithAnimals) > 10)
                {
                    personality_factor *= 0.8f;
                }
            }

            float fun_factor;

            {
                if ((pawn.needs.joy != null) && (xxx.is_bloodlust(pawn)))
                {
                    fun_factor = Mathf.Clamp01(0.50f + pawn.needs.joy.CurLevel);
                }
                else
                {
                    fun_factor = 1.00f;
                }
            }

            return(base_mtb * desire_factor * personality_factor * fun_factor);
        }