public override float RandomSelectionWeight(Pawn initiator, Pawn recipient)
        {
            if (!initiator.IsColonist || !recipient.IsColonist)
            {
                return(0f);
            }
            if (!PartyUtility.AcceptableGameConditionsToStartParty(initiator.Map))
            {
                return(0f);
            }
            PsychologyPawn realRecipient = recipient as PsychologyPawn;
            PsychologyPawn realInitiator = initiator as PsychologyPawn;

            if (realRecipient == null || realInitiator == null)
            {
                return(0f);
            }
            if (!LovePartnerRelationUtility.LovePartnerRelationExists(initiator, recipient))
            {
                return(0f);
            }
            if (realInitiator.psyche.lastDateTick >= Find.TickManager.TicksGame - GenDate.TicksPerDay * 7 || realRecipient.psyche.lastDateTick >= Find.TickManager.TicksGame - GenDate.TicksPerDay * 7)
            {
                return(0f);
            }
            if (initiator.health.summaryHealth.SummaryHealthPercent < 1f || recipient.health.summaryHealth.SummaryHealthPercent < 1f)
            {
                return(0f);
            }
            return(1.2f * realInitiator.psyche.GetPersonalityRating(PersonalityNodeDefOf.Romantic) * (1f - realInitiator.psyche.GetPersonalityRating(PersonalityNodeDefOf.Independent))
                   * realRecipient.psyche.GetPersonalityRating(PersonalityNodeDefOf.Romantic) * (1f - realRecipient.psyche.GetPersonalityRating(PersonalityNodeDefOf.Independent)) * RendezvousUtility.ColonySizeFactor(initiator));
        }
Exemple #2
0
        protected override ThoughtState CurrentSocialStateInternal(Pawn p, Pawn otherPawn)
        {
            if (!RelationsUtility.PawnsKnowEachOther(p, otherPawn))
            {
                return(false);
            }
            if (!LovePartnerRelationUtility.LovePartnerRelationExists(p, otherPawn))
            {
                return(false);
            }
            if (!PsycheHelper.PsychologyEnabled(p))
            {
                return(false);
            }
            if (p.Map == otherPawn.Map)
            {
                PsycheHelper.Comp(p).LDRTick = Find.TickManager.TicksAbs;
                return(false);
            }
            int tickSinceLastSeen = PsycheHelper.Comp(p).LDRTick;
            int ticksApart        = Find.TickManager.TicksAbs - tickSinceLastSeen;
            int quadrumsApart     = Mathf.FloorToInt((float)ticksApart / (float)GenDate.TicksPerQuadrum);
            int maxApart          = (p.relations.GetDirectRelation(PawnRelationDefOf.Spouse, otherPawn) == null ? 7 : 6);

            if (quadrumsApart > maxApart)
            {
                quadrumsApart = maxApart;
            }
            if (quadrumsApart > 1)
            {
                return(ThoughtState.ActiveAtStage(quadrumsApart - 1));
            }
            return(false);
        }
        public static bool NewSelectionWeight(InteractionWorker_Breakup __instance, ref float __result, Pawn initiator, Pawn recipient)
        {
            /* Also this one. */
            if (!LovePartnerRelationUtility.LovePartnerRelationExists(initiator, recipient))
            {
                __result = 0f;
                return(false);
            }
            else if (initiator.story.traits.HasTrait(TraitDefOfPsychology.Codependent))
            {
                __result = 0f;
                return(false);
            }
            float          chance         = 0.02f;
            float          romanticFactor = 1f;
            PsychologyPawn realInitiator  = initiator as PsychologyPawn;

            if (realInitiator != null)
            {
                chance         = 0.05f;
                romanticFactor = Mathf.InverseLerp(1.05f, 0f, realInitiator.psyche.GetPersonalityRating(PersonalityNodeDefOf.Romantic));
            }
            float opinionFactor = Mathf.InverseLerp(100f, -100f, (float)initiator.relations.OpinionOf(recipient));
            float spouseFactor  = 1f;

            if (initiator.relations.DirectRelationExists(PawnRelationDefOf.Spouse, recipient))
            {
                spouseFactor = 0.4f;
            }
            __result = chance * romanticFactor * opinionFactor * spouseFactor;
            return(false);
        }
Exemple #4
0
 public override void Tick()
 {
     base.Tick();
     if (!LovePartnerRelationUtility.LovePartnerRelationExists(this.pawn, this.partner))
     {
         this.pawn.health.RemoveHediff(this);
     }
     else if (Find.TickManager.TicksGame >= this.day && GenLocalDate.HourOfDay(this.pawn) == this.hour)
     {
         if (this.pawn.GetTimeAssignment() != TimeAssignmentDefOf.Work && this.partner.GetTimeAssignment() != TimeAssignmentDefOf.Work && !this.pawn.Drafted && !this.partner.Drafted &&
             PartyUtility.AcceptableGameConditionsToStartParty(this.pawn.Map) && this.pawn.Map == this.partner.Map)
         {
             pawn.jobs.StopAll();
             if (pawn.Awake() && partner.Awake())
             {
                 LordMaker.MakeNewLord(this.pawn.Faction, new LordJob_Date(this.pawn, this.partner), this.pawn.Map, new Pawn[] { this.pawn, this.partner });
             }
             else if (pawn.Awake())
             {
                 this.pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOfPsychology.MissedDate, this.partner);
             }
             else
             {
                 this.partner.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOfPsychology.MissedDate, this.pawn);
             }
         }
         else
         {
             this.pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOfPsychology.DateCancelled);
             this.partner.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOfPsychology.DateCancelled);
         }
         this.pawn.health.RemoveHediff(this);
     }
 }
Exemple #5
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;
            }
        }
 public override float RandomSelectionWeight(Pawn initiator, Pawn recipient)
 {
     if (!initiator.IsColonist || !recipient.IsColonist)
     {
         return(0f);
     }
     if (!RendezvousUtility.AcceptableGameConditionsToStartHangingOut(initiator.Map))
     {
         return(0f);
     }
     if (!PsycheHelper.PsychologyEnabled(initiator) || !PsycheHelper.PsychologyEnabled(recipient))
     {
         return(0f);
     }
     if (!LovePartnerRelationUtility.LovePartnerRelationExists(initiator, recipient))
     {
         return(0f);
     }
     if (PsycheHelper.Comp(initiator).Psyche.lastDateTick >= Find.TickManager.TicksGame - GenDate.TicksPerDay * 7 || PsycheHelper.Comp(recipient).Psyche.lastDateTick >= Find.TickManager.TicksGame - GenDate.TicksPerDay * 7)
     {
         return(0f);
     }
     if (!GatheringsUtility.ShouldGuestKeepAttendingGathering(initiator) || !GatheringsUtility.ShouldGuestKeepAttendingGathering(recipient))
     {
         return(0f);
     }
     return(1.2f * (1f + Mathf.InverseLerp(100f, 0f, initiator.needs.mood.thoughts.TotalOpinionOffset(recipient))) * PsycheHelper.Comp(initiator).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Romantic) * (1f - PsycheHelper.Comp(initiator).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Independent))
            * PsycheHelper.Comp(recipient).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Romantic) * (1f - PsycheHelper.Comp(recipient).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Independent)) * RendezvousUtility.ColonySizeFactor(initiator));
 }
Exemple #7
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);
        }
        public static void CurrentStateInternal(ref ThoughtState __result, Pawn p)
        {
            DirectPawnRelation directPawnRelation = LovePartnerRelationUtility.ExistingMostLikedLovePartnerRel(p, false);
            bool multiplePartners = (from r in p.relations.PotentiallyRelatedPawns
                                     where LovePartnerRelationUtility.LovePartnerRelationExists(p, r)
                                     select r).Count() > 1;
            bool partnerBedInRoom = (from t in p.ownership.OwnedBed.GetRoom().ContainedBeds
                                     where t.AssignedPawns.Contains(directPawnRelation.otherPawn)
                                     select t).Count() > 0;

            if (directPawnRelation != null && p.ownership.OwnedBed != null && p.story.traits.HasTrait(TraitDefOfPsychology.Polygamous) && multiplePartners && partnerBedInRoom)
            {
                __result = false;
            }
        }
            // Copied
            private static IEnumerable <Pawn> GetOwnersInternal(Room room)
            {
                // Extracted room types
                if (room.TouchesMapEdge || room.IsHuge || WrongRoomType(room))
                {
                    yield break;
                }

                Pawn pawn        = null;
                Pawn secondOwner = null;

                foreach (Building_Bed containedBed in room.ContainedBeds)
                {
                    if (containedBed.def.building.bed_humanlike)
                    {
                        foreach (var owner in containedBed.Owners())
                        {
                            if (pawn == null)
                            {
                                pawn = owner;
                            }
                            else
                            {
                                if (secondOwner != null)
                                {
                                    yield break;
                                }

                                secondOwner = owner;
                            }
                        }
                    }
                }

                if (pawn != null)
                {
                    if (secondOwner == null)
                    {
                        yield return(pawn);
                    }
                    else if (LovePartnerRelationUtility.LovePartnerRelationExists(pawn, secondOwner))
                    {
                        yield return(pawn);

                        yield return(secondOwner);
                    }
                }
            }
Exemple #10
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);
        }
Exemple #11
0
 // Token: 0x06000052 RID: 82 RVA: 0x00005688 File Offset: 0x00003888
 public static Pawn GetCondomPartnerInMyBed(Pawn pawn, Building_Bed LovinBed)
 {
     if (LovinBed.SleepingSlotsCount <= 1)
     {
         return(null);
     }
     if (!LovePartnerRelationUtility.HasAnyLovePartner(pawn))
     {
         return(null);
     }
     foreach (Pawn curOccupant in LovinBed.CurOccupants)
     {
         if (curOccupant != pawn && LovePartnerRelationUtility.LovePartnerRelationExists(pawn, curOccupant))
         {
             return(curOccupant);
         }
     }
     return(null);
 }
        internal static float _RandomSelectionWeight(this InteractionWorker_Breakup _this, Pawn initiator, Pawn recipient)
        {
            if (!LovePartnerRelationUtility.LovePartnerRelationExists(initiator, recipient))
            {
                return(0f);
            }
            else if (initiator.story.traits.HasTrait(TraitDefOfPsychology.Codependent))
            {
                return(0f);
            }
            float num  = Mathf.InverseLerp(100f, -100f, (float)initiator.relations.OpinionOf(recipient));
            float num2 = 1f;

            if (initiator.relations.DirectRelationExists(PawnRelationDefOf.Spouse, recipient))
            {
                num2 = 0.4f;
            }
            return(0.02f * num * num2);
        }
Exemple #13
0
        public static bool PawnIsInLoveBed(Pawn p)
        {
            Building_Bed Bed = p.CurrentBed();

            if (Bed == null)
            {
                return(false);
            }

            for (int i = 0; i < Bed.OwnersForReading.Count; i++)
            {
                if (LovePartnerRelationUtility.LovePartnerRelationExists(p, Bed.OwnersForReading[i]))
                {
                    return(true);
                }
            }

            return(false);
        }
 public override void Tick()
 {
     base.Tick();
     if (!LovePartnerRelationUtility.LovePartnerRelationExists(this.pawn, this.partner))
     {
         this.pawn.health.RemoveHediff(this);
     }
     else if (Find.TickManager.TicksAbs >= this.day && GenLocalDate.HourOfDay(this.pawn) == this.hour)
     {
         if (ShouldStartDate(pawn, partner) && ShouldStartDate(partner, pawn))
         {
             pawn.jobs.StopAll();
             partner.jobs.StopAll();
             if (pawn.GetLord() != null)
             {
                 pawn.GetLord().Notify_PawnLost(pawn, PawnLostCondition.ForcedToJoinOtherLord);
             }
             if (partner.GetLord() != null)
             {
                 partner.GetLord().Notify_PawnLost(partner, PawnLostCondition.ForcedToJoinOtherLord);
             }
             if (pawn.Awake() && partner.Awake())
             {
                 LordMaker.MakeNewLord(this.pawn.Faction, new LordJob_Date(this.pawn, this.partner), this.pawn.Map, new Pawn[] { this.pawn, this.partner });
             }
             else if (pawn.Awake())
             {
                 this.pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOfPsychology.MissedDate, this.partner);
             }
             else if (partner.Awake())
             {
                 this.partner.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOfPsychology.MissedDate, this.pawn);
             }
         }
         else
         {
             this.pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOfPsychology.DateCancelled);
             this.partner.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOfPsychology.DateCancelled);
         }
         this.pawn.health.RemoveHediff(this);
     }
 }
Exemple #15
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);
        }
Exemple #16
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);
        }
Exemple #17
0
        private ThoughtDef CreateSocialThought(out float opinionMod)
        {
            //We create a dynamic def to hold this thought so that the game won't worry about it being used anywhere else.
            ThoughtDef def = new ThoughtDef();

            def.defName          = this.pawn.GetHashCode() + "Conversation" + topic.defName;
            def.label            = topic.defName;
            def.durationDays     = PsychologyBase.ConvoDuration();
            def.nullifyingTraits = new List <TraitDef>();
            def.nullifyingTraits.Add(TraitDefOf.Psychopath);
            def.thoughtClass = typeof(Thought_MemorySocialDynamic);
            ThoughtStage stage = new ThoughtStage();

            /* Base opinion mod is 5 to the power of controversiality.
             * Controversiality varies from 0.7 (~3.09) to 1.5 (~11.18).
             */
            opinionMod = Mathf.Pow(5f, topic.controversiality);

            /* That opinion mod is weighted by the difference in their personality. 1 is identical, 0 is polar opposites.
             * Here's the math on how this works:
             *
             * The weighting is on a heavily customized cubic curve. It looks like this: https://www.wolframalpha.com/input/?i=(9.5((x-0.5)%5E3))%2B(2x%2F3)%5E2-0.3+from+0+to+1
             * The maximum positive weight is 1.27x. The maximum negative weight is -1.4875x. The neutral weight (0x) is at an opinion diff of 0.706.
             * This means that to have a positive thought from a conversation, pawns need to have a <31% difference in personality on that topic.
             * However, since it's a cubic curve, the negative modifier builds gradually. Pawns will need a >79% difference in personality to have a -0.5x weight.
             * But they'll also need a <23% difference to have a 0.5x weight. Normal agreement is at ~0.962, and normal disagreement is at ~0.073.
             * Pawns are unlikely to have huge differences in opinion. There are more ways for them to be close to each other than far apart. Here's the proof: https://anydice.com/program/1177b4
             * The approximate likelihood for them to agree on something with this weighting is 49.89%.
             *
             * Pawns' differences are exacerbated when they are in a relationship, but their similarities are also magnified.
             * The neutral conversation weight (0x) moves from 0.706 to 0.759, so the threshold for agreement is ~5% higher.
             * Normal disagreement moves from 0.073 to 0.127, and normal agreement moves from 0.962 to 0.946.
             * The maximum positive weight moves from 1.27x to 1.4986x. The maximum negative weight moves from -1.425x to -1.9875x.
             * The approximate likelihood for them to agree on something with this weighting is 42.63%.
             */
            float rawOpinionDiff = 1f - Mathf.Abs(PsycheHelper.Comp(pawn).Psyche.GetPersonalityRating(topic) - PsycheHelper.Comp(otherPawn).Psyche.GetPersonalityRating(topic));

            if (LovePartnerRelationUtility.LovePartnerRelationExists(this.pawn, this.otherPawn))
            {
                opinionMod *= (13.5f * (Mathf.Pow(rawOpinionDiff - 0.5f, 3))) + Mathf.Pow(((3f * rawOpinionDiff) / 9f), 2) - 0.3f;
            }
            else
            {
                opinionMod *= (9.5f * (Mathf.Pow(rawOpinionDiff - 0.5f, 3))) + Mathf.Pow(((2f * rawOpinionDiff) / 3f), 2) - 0.3f;
            }
            //Old cubic interpolation weighting.
            //opinionMod *= Mathf.Lerp((LovePartnerRelationUtility.LovePartnerRelationExists(pawn, otherPawn) ? -2f : -1.5f), (LovePartnerRelationUtility.LovePartnerRelationExists(pawn, otherPawn) ? 1.5f : 1.25f), weightedOpinionDiff);

            /* The Cool modifier ranges from 3^(0.7) ~ 2.16 to 3^(1.5) ~ 5.2.
             * If a pawn is Cool, that modifier is a positive one added to all conversational thoughts. Otherwise, it's subtracted.
             * On average, Cool pawns will be liked better, and non-Cool pawns will be disliked more.
             */
            opinionMod += Mathf.Pow(3f, topic.controversiality) * (PsycheHelper.Comp(otherPawn).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Cool) - 0.5f);

            /* The length of the talk has a large impact on how much the pawn cares.
             * A conversation is considered "full impact" at 1,125 ticks, or less than half an hour in-game.
             * A short talk (500 ticks or less) has a maximum 0.53x impact. The max opinion this could give (for non-lovers) is 7.5/-8.8.
             * A normal talk (half an hour or less) has a maximum 1.33x impact. The max opinion this could give is 18.9/-22.1.
             * A long talk (2.5 hours or less) has a maximum 6.67x impact. The max opinion this could give is 94.7/-110.9.
             * An epic talk (2.5+ hours) has no maximum impact, but after 2 hours the MTB to end the conversation becomes half an hour, so it's unlikely they will ever have an epic talk.
             * An average conversation is 1-2 hours, so on average the max opinion (not counting Cool modifier) is 37.9/-44.3 to 75.7/-88.7.
             * Again, it's unlikely the numbers will get that high. This is assuming identical or polar opposite personalities.
             */
            opinionMod *= 6f * ((float)this.ageTicks / (float)(GenDate.TicksPerHour * 2.25f));
            // Negative opinions are tempered by how Polite the other pawn is. An extremely impolite pawn will make a bad opinion 1.5x worse. A very polite pawn will make it half as bad.
            opinionMod *= (opinionMod < 0f ? 0.5f + (1f - PsycheHelper.Comp(otherPawn).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Polite)) : 1f);
            // Positive opinions are bolstered by how Friendly the other pawn is. An extremely friendly pawn will make a positive opinion 1.5x better. A very unfriendly pawn will halve it.
            opinionMod *= (opinionMod > 0f ? 0.5f + PsycheHelper.Comp(otherPawn).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Friendly) : 1f);
            // The more Judgmental the pawn, the more they're affected by all conversations.
            opinionMod *= 0.5f + PsycheHelper.Comp(pawn).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Judgmental);
            // In low-population colonies, pawns will put aside their differences.
            if (opinionMod < 0f)
            {
                opinionMod *= PopulationModifier;
            }
            else if (LovePartnerRelationUtility.LovePartnerRelationExists(this.pawn, this.otherPawn) && this.pawn.story.traits.HasTrait(TraitDefOfPsychology.Codependent))
            {
                //If it's a positive thought about their lover, Codependent pawns are always 1.25x as affected by it.
                opinionMod *= 1.25f;
            }
            stage.label             = "ConversationStage".Translate() + " " + convoTopic;
            stage.baseOpinionOffset = Mathf.RoundToInt(opinionMod);
            def.stages.Add(stage);
            return(def);
        }
Exemple #18
0
        // ReSharper disable once RedundantAssignment
        private static bool Prefix(Room __instance, ref IEnumerable <Pawn> __result)
        {
            __result = new List <Pawn>();
            if (__instance.TouchesMapEdge)
            {
                return(false);
            }

            if (__instance.IsHuge)
            {
                return(false);
            }

            if (__instance.Role != RoomRoleDefOf.Bedroom && __instance.Role != RoomRoleDefOf.PrisonCell &&
                __instance.Role != RoomRoleDefOf.Barracks && __instance.Role != RoomRoleDefOf.PrisonBarracks)
            {
                return(false);
            }

            foreach (var building_Bed in __instance.ContainedBeds)
            {
                if (!building_Bed.def.building.bed_humanlike)
                {
                    continue;
                }

                if (building_Bed.OwnersForReading.Count == 0)
                {
                    continue;
                }

                if (building_Bed.OwnersForReading.Count < 3)
                {
                    return(true);
                }

                var returnValue = new HashSet <Pawn>();
                for (var index = 0; index < building_Bed.OwnersForReading.Count; index++)
                {
                    var pawn = building_Bed.OwnersForReading[index];
                    if (pawn == null)
                    {
                        continue;
                    }

                    if (index == building_Bed.OwnersForReading.Count - 1)
                    {
                        returnValue.Add(pawn);
                    }

                    var pawnHasLover = false;
                    for (var otherIndex = 0; otherIndex < building_Bed.OwnersForReading.Count; otherIndex++)
                    {
                        if (otherIndex == index)
                        {
                            continue;
                        }

                        var otherPawn = building_Bed.OwnersForReading[otherIndex];
                        if (!LovePartnerRelationUtility.LovePartnerRelationExists(pawn, otherPawn))
                        {
                            continue;
                        }

                        pawnHasLover = true;
                        break;
                    }

                    if (!pawnHasLover)
                    {
                        return(false);
                    }

                    returnValue.Add(pawn);
                }

                __result = returnValue;
                break;
            }

            return(false);
        }
Exemple #19
0
        public static void BreakupRelations(Pawn pawn)
        {
            var relations = pawn.relations.DirectRelations.Where(r => !r.otherPawn.Dead && r.otherPawn.Faction != null && r.otherPawn.Faction.IsPlayer && LovePartnerRelationUtility.LovePartnerRelationExists(pawn, r.otherPawn)).ToArray();
            var breakup   = new InteractionWorker_Breakup();

            foreach (var relation in relations)
            {
                breakup.Interacted(relation.otherPawn, pawn, null);
            }
            Faction hostileFaction;

            if (
                Find.FactionManager.AllFactions.Where(f => f.def.humanlikeFaction && f.HostileTo(Faction.OfPlayer))
                .TryRandomElement(out hostileFaction))
            {
                pawn.SetFaction(hostileFaction);
            }
        }
        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())
            {
                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::" + xxx.would_fuck(pawn, target));
                    if (xxx.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::" + xxx.would_fuck(target, pawn));
                    if (xxx.would_fuck(target, pawn) < 0.1f)
                    {
                        return(false);
                    }
                }
            }

            //Log.Message("[RJW]" + this.GetType().ToString() + " extended checks: can start sex");
            return(true);
        }
        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;
        }
Exemple #22
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);
        }
Exemple #23
0
 private static bool BedClaimedByStranger(Building_Bed bed, Pawn guest)
 {
     return(bed.Owners().Any(p => p != guest && !p.RaceProps.Animal && !LovePartnerRelationUtility.LovePartnerRelationExists(p, guest)));
 }
        public static Building_AIPawnRechargeStation FindRechargeStationFor(AIPawn sleeper, AIPawn traveler, bool sleeperWillBePrisoner, bool checkSocialProperness, bool forceCheckMedBed = false)
        {
            Predicate <Thing> bedValidator = (Thing t) =>
            {
                Building_AIPawnRechargeStation foundRechargeStation = t as Building_AIPawnRechargeStation;
                if (foundRechargeStation == null)
                {
                    return(false);
                }

                if (!traveler.CanReserveAndReach(t, PathEndMode.OnCell, Danger.Some, foundRechargeStation.SleepingSlotsCount))
                {
                    return(false);
                }

                if (!foundRechargeStation.AnyUnoccupiedSleepingSlot && (!sleeper.InBed() || sleeper.CurrentBed() != foundRechargeStation))
                {
                    foreach (Pawn owner in foundRechargeStation.owners)
                    {
                        if (owner as AIPawn != null)
                        {
                            return(false);
                        }
                    }
                }

                if (sleeperWillBePrisoner)
                {
                    if (!foundRechargeStation.ForPrisoners)
                    {
                        return(false);
                    }

                    if (!foundRechargeStation.Position.IsInPrisonCell(sleeper.Map))
                    {
                        return(false);
                    }
                }
                else
                {
                    if (foundRechargeStation.Faction != traveler.Faction)
                    {
                        return(false);
                    }

                    if (foundRechargeStation.ForPrisoners)
                    {
                        return(false);
                    }
                }


                if (foundRechargeStation.Medical)
                {
                    if (!HealthAIUtility.ShouldEverReceiveMedicalCare(sleeper))
                    {
                        return(false);
                    }
                    if (!HealthAIUtility.ShouldSeekMedicalRest(sleeper))
                    {
                        return(false);
                    }
                    if (!foundRechargeStation.AnyUnoccupiedSleepingSlot && (!sleeper.InBed() || sleeper.CurrentBed() != foundRechargeStation))
                    {
                        return(false);
                    }
                }
                else if (foundRechargeStation.owners.Any <Pawn>() && !foundRechargeStation.owners.Contains(sleeper))
                {
                    // The pawn in the recharge station is not an AIPawn. UnassignPawn!
                    foreach (Pawn owner in foundRechargeStation.owners)
                    {
                        if (owner as AIPawn == null)
                        {
                            if (foundRechargeStation.owners.Find((Pawn x) => LovePartnerRelationUtility.LovePartnerRelationExists(sleeper, x)) == null)
                            {
                                foundRechargeStation.TryUnassignPawn(owner);
                                break;
                            }
                        }
                    }
                    // Now recheck if there is a free place
                    if (!foundRechargeStation.AnyUnownedSleepingSlot)
                    {
                        return(false);
                    }
                }

                return((!checkSocialProperness || foundRechargeStation.IsSociallyProper(sleeper, sleeperWillBePrisoner, false)) && !foundRechargeStation.IsForbidden(traveler) && !foundRechargeStation.IsBurning());
            };

            if (sleeper.ownership != null && sleeper.ownership.OwnedBed != null && bedValidator(sleeper.ownership.OwnedBed))
            {
                Building_AIPawnRechargeStation rStation = sleeper.ownership.OwnedBed as Building_AIPawnRechargeStation;

                if (rStation != null)
                {
                    return(rStation);
                }
                else
                {
                    sleeper.ownership.UnclaimBed();
                }
            }

            DirectPawnRelation directPawnRelation = LovePartnerRelationUtility.ExistingMostLikedLovePartnerRel(sleeper, false);

            if (directPawnRelation != null)
            {
                Building_AIPawnRechargeStation ownedBed = directPawnRelation.otherPawn.ownership.OwnedBed as Building_AIPawnRechargeStation;
                if (ownedBed != null && bedValidator(ownedBed))
                {
                    return(ownedBed);
                }
            }
            for (int j = 0; j < RestUtility.AllBedDefBestToWorst.Count; j++)
            {
                ThingDef thingDef = RestUtility.AllBedDefBestToWorst[j];
                if (RestUtility.CanUseBedEver(sleeper, thingDef))
                {
                    Predicate <Thing> validator = (Thing b) => bedValidator(b) && (b as Building_AIPawnRechargeStation != null) && !((Building_AIPawnRechargeStation)b).Medical;
                    Building_AIPawnRechargeStation building_Bed2 = GenClosest.ClosestThingReachable(sleeper.Position, sleeper.Map, ThingRequest.ForDef(thingDef), PathEndMode.OnCell, TraverseParms.For(traveler, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null, 0, -1, false)
                                                                   as Building_AIPawnRechargeStation;
                    if (building_Bed2 != null)
                    {
                        if (sleeper.ownership != null)
                        {
                            sleeper.ownership.UnclaimBed();
                        }
                        return(building_Bed2);
                    }
                }
            }
            return(null);
        }
        // Plundered and adapted from Psychology
        public override float RandomSelectionWeight(Pawn initiator, Pawn recipient)
        {
            if (!GRPawnRelationUtility.HasInformalRelationship(initiator, recipient) && !LovePartnerRelationUtility.LovePartnerRelationExists(initiator, recipient))
            {
                return(0f);
            }
            else if (initiator.story.traits.HasTrait(TraitDefOfPsychology.Codependent))
            {
                return(0f);
            }
            float chance         = 0.02f * GradualRomanceMod.BaseBreakupChance;
            float romanticFactor = 1f;

            if (PsycheHelper.PsychologyEnabled(initiator))
            {
                chance         = 0.05f * GradualRomanceMod.BaseBreakupChance;
                romanticFactor = Mathf.InverseLerp(1.05f, 0f, PsycheHelper.Comp(initiator).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Romantic));
            }
            float opinionFactor = Mathf.InverseLerp(100f, -100f, (float)initiator.relations.OpinionOf(recipient));
            float spouseFactor  = 1f;

            if (initiator.relations.DirectRelationExists(PawnRelationDefOf.Spouse, recipient))
            {
                spouseFactor = 0.4f;
            }
            return(chance * romanticFactor * opinionFactor * spouseFactor);
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            LordToil_HangOut toil   = pawn.GetLord().CurLordToil as LordToil_HangOut;
            Pawn             friend = (pawn == toil.friends[0] ? toil.friends[1] : toil.friends[0]);

            if (friend == null)
            {
                return(null);
            }
            /* If they are partners, possibly send them to lay down together so they'll do lovin'. */
            if (LovePartnerRelationUtility.LovePartnerRelationExists(pawn, friend) && pawn.ownership.OwnedBed != null && !pawn.GetPosture().Laying() && (pawn.IsHashIntervalTick(GenDate.TicksPerHour) || friend.IsHashIntervalTick(GenDate.TicksPerHour)))
            {
                return(new Job(JobDefOf.LayDown, pawn.ownership.OwnedBed, GenDate.TicksPerHour));
            }
            /* If they have no joy activity assigned, or they've been doing it for 1-3 hours, give them a new one. */
            if (toil.hangOut == null || toil.ticksToNextJoy < Find.TickManager.TicksGame)
            {
                toil.hangOut        = base.TryGiveJob(pawn);
                toil.ticksToNextJoy = Find.TickManager.TicksGame + Rand.RangeInclusive(GenDate.TicksPerHour, GenDate.TicksPerHour * 3);
            }
            /* If they need joy, go do the joy activity.*/
            if (toil.hangOut != null && friend.needs.food.CurLevel > 0.33f && pawn.needs.joy.CurLevel < 0.8f)
            {
                /* Sometimes the joy activity can't be reserved because it's for one person only. */
                Job job = new Job(toil.hangOut.def);
                job.targetA           = toil.hangOut.targetA;
                job.targetB           = toil.hangOut.targetB;
                job.targetC           = toil.hangOut.targetC;
                job.targetQueueA      = toil.hangOut.targetQueueA;
                job.targetQueueB      = toil.hangOut.targetQueueB;
                job.count             = toil.hangOut.count;
                job.countQueue        = toil.hangOut.countQueue;
                job.expiryInterval    = toil.hangOut.expiryInterval;
                job.locomotionUrgency = toil.hangOut.locomotionUrgency;
                if (job.TryMakePreToilReservations(pawn, false))
                {
                    return(job);
                }
                else
                {
                    pawn.ClearAllReservations(false);
                }
            }
            if (((pawn.Position - friend.Position).LengthHorizontalSquared >= 54 || !GenSight.LineOfSight(pawn.Position, friend.Position, pawn.Map, true)))
            { /* Make sure they are close to each other if they're not actively doing a joy activity. */
              /* If the other pawn is already walking over, just hang around until they get there. */
                if (friend.CurJob.def != JobDefOf.Goto)
                {
                    return(new Job(JobDefOf.Goto, friend));
                }
                else
                {
                    pawn.rotationTracker.FaceCell(friend.Position);
                    return(null);
                }
            }
            else
            {
                /* If they are already standing close enough, but can't do the joy activity together, then wander around. */
                IntVec3 result;
                /* Make sure they only wander within conversational distance. */
                Predicate <IntVec3> validator = (IntVec3 x) => x.Standable(pawn.Map) && x.InAllowedArea(pawn) && !x.IsForbidden(pawn) && pawn.CanReserveAndReach(x, PathEndMode.OnCell, Danger.None, 1, -1, null, false) &&
                                                (x - friend.Position).LengthHorizontalSquared < 50 && GenSight.LineOfSight(x, friend.Position, pawn.Map, true) && x != friend.Position;
                if (CellFinder.TryFindRandomReachableCellNear(pawn.Position, pawn.Map, 12f, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), (IntVec3 x) => validator(x), null, out result))
                {
                    if ((pawn.Position - friend.Position).LengthHorizontalSquared >= 5 || (LovePartnerRelationUtility.LovePartnerRelationExists(pawn, friend) && pawn.Position != friend.Position))
                    {
                        /* Sending them to goto a friend ends with them standing right next to/on top of them. So make them respect personal space a little more. */
                        pawn.mindState.nextMoveOrderIsWait = !pawn.mindState.nextMoveOrderIsWait;
                        if (!result.IsValid || pawn.mindState.nextMoveOrderIsWait)
                        {
                            /* Alternate between relaxing socially and wandering. */
                            pawn.rotationTracker.FaceCell(friend.Position);
                            return(null);
                        }
                    }
                    Job wander = new Job(JobDefOf.GotoWander, result);
                    pawn.Map.pawnDestinationReservationManager.Reserve(pawn, wander, result);
                    return(wander);
                }
                /* If we can't find a valid spot, just relax socially. */
                pawn.rotationTracker.FaceCell(friend.Position);
                return(null);
            }
        }
Exemple #27
0
        public override bool MoreChecks(Pawn pawn, Thing t, bool forced = false)
        {
            if (!RJWSettings.rape_enabled)
            {
                return(false);
            }

            Pawn target = t as Pawn;

            if (!RJWSettings.WildMode)
            {
                if (xxx.is_kind(pawn))
                {
                    JobFailReason.Is("refuses to rape");
                    return(false);
                }
                //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))))
                {
                    JobFailReason.Is("not horny enough");
                    return(false);
                }
                if (!target.IsDesignatedComfort())
                {
                    //JobFailReason.Is("not designated as CP", null);
                    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")))
                {
                    //--Log.Message("[RJW]WorkGiver_RapeCP::HasJobOnThing called0 - target isn't healthy enough or is in a forbidden position.");
                    JobFailReason.Is("target not healthy enough");
                    return(false);
                }
                if (pawn.relations.OpinionOf(target) > 50 && !xxx.is_rapist(pawn) && !xxx.is_psychopath(pawn) && !xxx.is_masochist(target))
                {
                    JobFailReason.Is("refuses to rape a friend");
                    return(false);
                }
                if (!xxx.can_rape(pawn))
                {
                    //--Log.Message("[RJW]WorkGiver_RapeCP::HasJobOnThing called1 - pawn don't need sex or is not healthy, or cannot rape");
                    JobFailReason.Is("cannot rape target (vulnerability too low, or age mismatch)");
                    return(false);
                }
                if (!xxx.isSingleOrPartnerNotHere(pawn) && !xxx.is_lecher(pawn) && !xxx.is_psychopath(pawn) && !xxx.is_nympho(pawn))
                {
                    if (!LovePartnerRelationUtility.LovePartnerRelationExists(pawn, target))
                    {
                        //--Log.Message("[RJW]WorkGiver_RapeCP::HasJobOnThing called2 - pawn is not single or has partner around");
                        JobFailReason.Is("cannot rape while in stable relationship");
                        return(false);
                    }
                }
            }

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

            //Log.Message("[RJW]" + this.GetType().ToString() + " extended checks: can start sex");
            return(true);
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            //Log.Message("Try give job GotoForLovinAvali");

            if (pawn.def != ThingDefOf.Avali)
            {
                //Log.Message("race = " + pawn.def.defName);
                return(null);
            }


            if (Find.TickManager.TicksGame < pawn.mindState.canLovinTick)
            {
                /*
                 * string inventory = pawn.inventory.ToString();
                 * if (inventory.Contains("EggAvali"))
                 * {
                 *
                 * }
                 */

                //Log.Message("TickManager.TicksGame < pawn.mindState.canLovinTick");
                return(null);
            }


            Predicate <Thing> validator = delegate(Thing t)
            {
                Pawn pawn3 = t as Pawn;

                return(!pawn3.Downed &&
                       !pawn3.IsForbidden(pawn) &&
                       !pawn3.health.HasHediffsNeedingTend() &&
                       pawn3.InBed() &&
                       //pawn3.CanCasuallyInteractNow(false) &&
                       !pawn.health.HasHediffsNeedingTend() &&
                       !pawn.Drafted &&
                       //!pawn.InBed() &&
                       LovePartnerRelationUtility.LovePartnerRelationExists(pawn, pawn3) &&
                       Find.TickManager.TicksGame >= pawn3.mindState.canLovinTick &&
                       //pawn.relations.OpinionOf(pawn3) >= 25 &&
                       //pawn3.relations.OpinionOf(pawn) >= 25 &&
                       pawn3.RaceProps.Humanlike == pawn.RaceProps.Humanlike);
            };
            Pawn pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(pawn.def), PathEndMode.Touch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 30f, validator, null, 0, -1, false, RegionType.Set_Passable, false);

            if (pawn2 == null)
            {
                //Log.Message("pawn2 = null");
                return(null);
            }

            Building_Bed bed = RestUtility.FindBedFor(pawn2);

            //Log.Message(pawn + " bed = " + bed);
            if (bed != null)
            {
                //Log.Message(pawn + " current bed = " + pawn2.CurrentBed());
                if (pawn2.CurrentBed() != bed)
                {
                    return(null);
                }

                //Log.Message(pawn + " bed medical = " + bed.Medical);
                if (!bed.Medical)
                {
                    //Log.Message("pawn2 = " + pawn2);
                    return(new Job(JobDefOf.GotoForLovinAvali, pawn2, bed));                    // give job
                }
            }

            return(null);
        }
 public static bool SingleInvBedIsSpare(Pawn p, Pawn sleepyPawn)
 {
     return(p.RaceProps.Animal || p.ownership.OwnedBed != null || LovePartnerRelationUtility.LovePartnerRelationExists(sleepyPawn, p));
 }
Exemple #30
0
        internal static float _ChanceOfBecomingChildOf(Pawn child, Pawn father, Pawn mother, PawnGenerationRequest?childGenerationRequest, PawnGenerationRequest?fatherGenerationRequest, PawnGenerationRequest?motherGenerationRequest)
        {
            var GetMelanin         = typeof(ChildRelationUtility).GetMethod("GetMelanin", BindingFlags.Static | BindingFlags.NonPublic);
            var GetSkinColorFactor = typeof(ChildRelationUtility).GetMethod("GetSkinColorFactor", BindingFlags.Static | BindingFlags.NonPublic);
            var GetParentAgeFactor = typeof(ChildRelationUtility).GetMethod("GetParentAgeFactor", BindingFlags.Static | BindingFlags.NonPublic);
            var NumberOfChildrenFemaleWantsEver = typeof(ChildRelationUtility).GetMethod("NumberOfChildrenFemaleWantsEver", BindingFlags.Static | BindingFlags.NonPublic);

            if (GetMelanin == null)
            {
                Log.Error("Could not reflect ChildRelationUtility.GetMelanin!");
                return(0f);
            }
            if (GetSkinColorFactor == null)
            {
                Log.Error("Could not reflect ChildRelationUtility.GetSkinColorFactor!");
                return(0f);
            }
            if (GetParentAgeFactor == null)
            {
                Log.Error("Could not reflect ChildRelationUtility.GetParentAgeFactor!");
                return(0f);
            }
            if (NumberOfChildrenFemaleWantsEver == null)
            {
                Log.Error("Could not reflect ChildRelationUtility.NumberOfChildrenFemaleWantsEver!");
                return(0f);
            }
            if (father != null && father.gender != Gender.Male)
            {
                Log.Warning("Tried to calculate chance for father with gender \"" + father.gender + "\".");
                return(0f);
            }
            if (mother != null && mother.gender != Gender.Female)
            {
                Log.Warning("Tried to calculate chance for mother with gender \"" + mother.gender + "\".");
                return(0f);
            }
            if (father != null && child.GetFather() != null && child.GetFather() != father)
            {
                return(0f);
            }
            if (mother != null && child.GetMother() != null && child.GetMother() != mother)
            {
                return(0f);
            }
            if (mother != null && father != null && !LovePartnerRelationUtility.LovePartnerRelationExists(mother, father) && !LovePartnerRelationUtility.ExLovePartnerRelationExists(mother, father))
            {
                return(0f);
            }
            float?melanin         = (float?)GetMelanin.Invoke(typeof(ChildRelationUtility), new object[] { child, childGenerationRequest });
            float?melanin2        = (float?)GetMelanin.Invoke(typeof(ChildRelationUtility), new object[] { father, fatherGenerationRequest });
            float?melanin3        = (float?)GetMelanin.Invoke(typeof(ChildRelationUtility), new object[] { mother, motherGenerationRequest });
            bool  fatherIsNew     = father != null && child.GetFather() != father;
            bool  motherIsNew     = mother != null && child.GetMother() != mother;
            float skinColorFactor = (float)GetSkinColorFactor.Invoke(typeof(ChildRelationUtility), new object[] { melanin, melanin2, melanin3, fatherIsNew, motherIsNew });

            if (skinColorFactor <= 0f)
            {
                return(0f);
            }
            float num  = 1f;
            float num2 = 1f;
            float num3 = 1f;
            float num4 = 1f;

            if (father != null && child.GetFather() == null)
            {
                PsychologyPawn realFather = father as PsychologyPawn;
                num = (float)GetParentAgeFactor.Invoke(typeof(ChildRelationUtility), new object[] { father, child, 14f, 30f, 50f });
                if (num == 0f)
                {
                    return(0f);
                }
                if (PsychologyBase.ActivateKinsey() && realFather != null)
                {
                    num4 = Mathf.InverseLerp(6f, 0f, realFather.sexuality.kinseyRating);
                }
                else if (father.story.traits.HasTrait(TraitDefOf.Gay))
                {
                    num4 = 0.1f;
                }
            }
            if (mother != null && child.GetMother() == null)
            {
                PsychologyPawn realMother = mother as PsychologyPawn;
                num2 = (float)GetParentAgeFactor.Invoke(typeof(ChildRelationUtility), new object[] { mother, child, 16f, 27f, 45f });
                if (num2 == 0f)
                {
                    return(0f);
                }
                int num5 = (int)NumberOfChildrenFemaleWantsEver.Invoke(typeof(ChildRelationUtility), new object[] { mother });
                if (mother.relations.ChildrenCount >= num5)
                {
                    return(0f);
                }
                num3 = 1f - (float)mother.relations.ChildrenCount / (float)num5;
                if (PsychologyBase.ActivateKinsey() && realMother != null)
                {
                    num4 = Mathf.InverseLerp(6f, 0f, realMother.sexuality.kinseyRating);
                }
                else if (mother.story.traits.HasTrait(TraitDefOf.Gay))
                {
                    num4 = 0.1f;
                }
            }
            float num6 = 1f;

            if (mother != null)
            {
                Pawn firstDirectRelationPawn = mother.relations.GetFirstDirectRelationPawn(PawnRelationDefOf.Spouse, null);
                if (firstDirectRelationPawn != null && firstDirectRelationPawn != father)
                {
                    num6 *= 0.15f;
                }
            }
            if (father != null)
            {
                Pawn firstDirectRelationPawn2 = father.relations.GetFirstDirectRelationPawn(PawnRelationDefOf.Spouse, null);
                if (firstDirectRelationPawn2 != null && firstDirectRelationPawn2 != mother)
                {
                    num6 *= 0.15f;
                }
            }
            return(skinColorFactor * num * num2 * num3 * num6 * num4);
        }