예제 #1
0
        public static float CalculateAttractionCategory(AttractionFactorCategoryDef category, Pawn observer, Pawn assessed)
        {
            List <AttractionFactorDef> veryHighFactors = new List <AttractionFactorDef>()
            {
            };
            List <AttractionFactorDef> highFactors = new List <AttractionFactorDef>()
            {
            };
            List <AttractionFactorDef> lowFactors = new List <AttractionFactorDef>()
            {
            };
            List <AttractionFactorDef> veryLowFactors = new List <AttractionFactorDef>()
            {
            };
            AttractionFactorDef reasonForInstantFailure = null;

            return(CalculateAttractionCategory(category, observer, assessed, out veryLowFactors, out lowFactors, out highFactors, out veryHighFactors, out reasonForInstantFailure));
        }
예제 #2
0
        public static float CalculateAttraction(Pawn observer, Pawn assessed, bool attractionOnly, bool formalRelationship, out List <AttractionFactorDef> veryLowFactors, out List <AttractionFactorDef> lowFactors, out List <AttractionFactorDef> highFactors, out List <AttractionFactorDef> veryHighFactors, out AttractionFactorDef reasonForInstantFailure)
        {
            veryLowFactors = new List <AttractionFactorDef>()
            {
            };
            lowFactors = new List <AttractionFactorDef>()
            {
            };
            highFactors = new List <AttractionFactorDef>()
            {
            };
            veryHighFactors = new List <AttractionFactorDef>()
            {
            };
            reasonForInstantFailure = null;
            float result = observer.GetComp <GRPawnComp>().RetrieveAttractionAndFactors(assessed, out veryLowFactors, out lowFactors, out highFactors, out veryHighFactors, formalRelationship, !attractionOnly);

            List <AttractionFactorCategoryDef> allCategories = DefDatabase <AttractionFactorCategoryDef> .AllDefsListForReading;

            foreach (AttractionFactorCategoryDef category in allCategories)
            {
                /*
                 * if (!formalRelationship && category.onlyForRomance)
                 * {
                 *  continue;
                 * }
                 * if (attractionOnly && category.chanceOnly)
                 * {
                 *  continue;
                 * }
                 */
                if (!category.alwaysRecalculate)
                {
                    continue;
                }
                result *= AttractionUtility.CalculateAttractionCategory(category, observer, assessed, out List <AttractionFactorDef> newVeryLowFactors, out List <AttractionFactorDef> newLowFactors, out List <AttractionFactorDef> newHighFactors, out List <AttractionFactorDef> newVeryHighFactors, out AttractionFactorDef newReasonForInstantFailure);

                veryHighFactors.AddRange(newVeryHighFactors);
                highFactors.AddRange(newHighFactors);
                lowFactors.AddRange(newLowFactors);
                veryLowFactors.AddRange(newVeryLowFactors);
                if (reasonForInstantFailure == null && newReasonForInstantFailure != null)
                {
                    reasonForInstantFailure = newReasonForInstantFailure;
                }
            }
            if (!formalRelationship)
            {
                veryHighFactors.RemoveAll(x => x.category.onlyForRomance);
                highFactors.RemoveAll(x => x.category.onlyForRomance);
                lowFactors.RemoveAll(x => x.category.onlyForRomance);
                veryLowFactors.RemoveAll(x => x.category.onlyForRomance);
            }
            if (!attractionOnly)
            {
                veryHighFactors.RemoveAll(x => x.category.chanceOnly);
                highFactors.RemoveAll(x => x.category.chanceOnly);
                lowFactors.RemoveAll(x => x.category.chanceOnly);
                veryLowFactors.RemoveAll(x => x.category.chanceOnly);
            }
            return(result);
        }
예제 #3
0
        public static float CalculateAttractionCategory(AttractionFactorCategoryDef category, Pawn observer, Pawn assessed, out List <AttractionFactorDef> veryLowFactors, out List <AttractionFactorDef> lowFactors, out List <AttractionFactorDef> highFactors, out List <AttractionFactorDef> veryHighFactors, out AttractionFactorDef reasonForInstantFailure)
        {
            //Log.Message("Method start.");
            //Log.Message("Making null values.");
            veryHighFactors = new List <AttractionFactorDef>()
            {
            };
            highFactors = new List <AttractionFactorDef>()
            {
            };
            lowFactors = new List <AttractionFactorDef>()
            {
            };
            veryLowFactors = new List <AttractionFactorDef>()
            {
            };
            reasonForInstantFailure = null;
            //Log.Message("Retrieving factor defs.");
            IEnumerable <AttractionFactorDef> allFactors = (from def in DefDatabase <AttractionFactorDef> .AllDefsListForReading
                                                            where def.category == category
                                                            select def);

            float attraction = 1f;

            //Log.Message("Starting factor calculations for " + allFactors.Count().ToString() + "factors");

            foreach (AttractionFactorDef factor in allFactors)
            {
                if (factor.calculator.Check(observer, assessed) == false)
                {
                    continue;
                }

                //Log.Message("Doing calculation for " + factor.defName);
                float result = CalculateFactor(observer, assessed, factor);
                if (result == 1f)
                {
                    continue;
                }
                if (result == 0f)
                {
                    if (GradualRomanceMod.detailedAttractionLogs)
                    {
                        Log.Message("Instantly failed at " + factor.defName);
                    }
                    veryLowFactors.Add(factor);
                    reasonForInstantFailure = factor;
                    return(0f);
                }
                if (factor.hidden)
                {
                    continue;
                }
                //Log.Message("Sort factor into results.");
                if (result >= veryHighReasonThreshold)
                {
                    veryHighFactors.Add(factor);
                }
                else if (result >= highReasonThreshold)
                {
                    highFactors.Add(factor);
                }
                else if (result <= veryLowReasonThreshold)
                {
                    veryLowFactors.Add(factor);
                }
                else if (result <= lowReasonThreshold)
                {
                    lowFactors.Add(factor);
                }
                //Log.Message("Integrating result.");
                if (GradualRomanceMod.detailedAttractionLogs)
                {
                    Log.Message(factor.defName + "(" + observer.Name.ToStringShort + "," + assessed.Name.ToStringShort + ")(" + category.defName + "): " + result.ToString() + "=>" + (attraction * result).ToString());
                }

                attraction *= result;
            }
            //Log.Message("Concluding method.");
            return(attraction);
        }
예제 #4
0
        // ATTRACTION FACTOR TOOLS //

        public static float CalculateFactor(Pawn observer, Pawn assessed, AttractionFactorDef attractionFactor)
        {
            AttractionCalculator calculator = attractionFactor.calculator;

            if (attractionFactor.needsSight && observer.health.capacities.GetLevel(PawnCapacityDefOf.Sight) <= .1f)
            {
                return(1f);
            }
            if (attractionFactor.needsHearing && observer.health.capacities.GetLevel(PawnCapacityDefOf.Hearing) <= .1f)
            {
                return(1f);
            }
            if (attractionFactor.requiredTraits.Count() > 0)
            {
                bool hasRequiredTrait = false;
                foreach (TraitDef trait in attractionFactor.requiredTraits)
                {
                    if (observer.story.traits.HasTrait(trait))
                    {
                        hasRequiredTrait = true;
                        break;
                    }
                    if (hasRequiredTrait == false)
                    {
                        return(1f);
                    }
                }
            }
            if (attractionFactor.nullifyingTraits.Count() > 0)
            {
                bool hasNullifyingTraits = false;
                foreach (TraitDef trait in attractionFactor.nullifyingTraits)
                {
                    if (observer.story.traits.HasTrait(trait))
                    {
                        hasNullifyingTraits = true;
                        break;
                    }
                    if (hasNullifyingTraits == true)
                    {
                        return(1f);
                    }
                }
            }
            if (!calculator.Check(observer, assessed))
            {
                return(1f);
            }
            float value = calculator.Calculate(observer, assessed);

            if (value == 1f)
            {
                return(1f);
            }

            if (value == 0f)
            {
                return(0f);
            }

            if (attractionFactor.reversingTraits.Count() > 0)
            {
                bool hasReversingTraits = false;
                foreach (TraitDef trait in attractionFactor.reversingTraits)
                {
                    if (observer.story.traits.HasTrait(trait))
                    {
                        hasReversingTraits = true;
                        break;
                    }
                    if (hasReversingTraits == true)
                    {
                        if (value < 1)
                        {
                            value = Mathf.Max(Mathf.Lerp(2.5f, 1f, value), 0.05f);
                        }
                        else
                        {
                            value = Mathf.Pow(value, (value - (2 * value)));
                        }
                    }
                }
            }

            if (attractionFactor.traitImportanceModifiers.Count() > 0)
            {
                foreach (TraitModifier traitMod in attractionFactor.traitImportanceModifiers)
                {
                    if (observer.story.traits.HasTrait(traitMod.trait))
                    {
                        if (traitMod.modifier == 0)
                        {
                            return(0f);
                        }
                        else
                        {
                            value = Mathf.Pow(value, traitMod.modifier);
                        }
                    }
                }
            }

            if (attractionFactor.personalityImportanceModifiers.Count() > 0 && PsycheHelper.PsychologyEnabled(observer) && GradualRomanceMod.AttractionCalculation == GradualRomanceMod.AttractionCalculationSetting.Complex)
            {
                foreach (PersonalityNodeModifier perMod in attractionFactor.personalityImportanceModifiers)
                {
                    if (perMod.reverse == false)
                    {
                        value = Mathf.Pow(value, Mathf.Lerp(0.5f, 1.5f, PsycheHelper.Comp(observer).Psyche.GetPersonalityRating(perMod.personalityNode)) * perMod.modifier);
                    }
                    else
                    {
                        value = Mathf.Pow(value, Mathf.Lerp(0.5f, 1.5f, 1f - PsycheHelper.Comp(observer).Psyche.GetPersonalityRating(perMod.personalityNode)) * perMod.modifier);
                    }
                }
            }

            if (value < 1)
            {
                if (attractionFactor.lowAttractionTraitModifiers.Count() > 0)
                {
                    foreach (TraitModifier traitMod in attractionFactor.lowAttractionTraitModifiers)
                    {
                        if (observer.story.traits.HasTrait(traitMod.trait))
                        {
                            if (traitMod.modifier == 0)
                            {
                                return(0f);
                            }
                            else
                            {
                                value = Mathf.Pow(value, traitMod.modifier);
                            }
                        }
                    }
                }
                if (attractionFactor.lowAttractionPersonalityModifiers.Count() > 0 && PsycheHelper.PsychologyEnabled(observer) && GradualRomanceMod.AttractionCalculation == GradualRomanceMod.AttractionCalculationSetting.Complex)
                {
                    foreach (PersonalityNodeModifier perMod in attractionFactor.lowAttractionPersonalityModifiers)
                    {
                        if (perMod.reverse == false)
                        {
                            value = Mathf.Pow(value, Mathf.Lerp(0.5f, 1.5f, PsycheHelper.Comp(observer).Psyche.GetPersonalityRating(perMod.personalityNode)) * perMod.modifier);
                        }
                        else
                        {
                            value = Mathf.Pow(value, Mathf.Lerp(0.5f, 1.5f, 1f - PsycheHelper.Comp(observer).Psyche.GetPersonalityRating(perMod.personalityNode)) * perMod.modifier);
                        }
                    }
                }
            }
            else
            {
                if (attractionFactor.highAttractionTraitModifiers.Count() > 0)
                {
                    foreach (TraitModifier traitMod in attractionFactor.highAttractionTraitModifiers)
                    {
                        if (observer.story.traits.HasTrait(traitMod.trait))
                        {
                            if (traitMod.modifier == 0)
                            {
                                return(0f);
                            }
                            else
                            {
                                value = Mathf.Pow(value, traitMod.modifier);
                            }
                        }
                    }
                }
                if (attractionFactor.highAttractionPersonalityModifiers.Count() > 0 && PsycheHelper.PsychologyEnabled(observer) && GradualRomanceMod.AttractionCalculation == GradualRomanceMod.AttractionCalculationSetting.Complex)
                {
                    foreach (PersonalityNodeModifier perMod in attractionFactor.highAttractionPersonalityModifiers)
                    {
                        if (perMod.reverse == false)
                        {
                            value = Mathf.Pow(value, Mathf.Lerp(0.5f, 1.5f, PsycheHelper.Comp(observer).Psyche.GetPersonalityRating(perMod.personalityNode)) * perMod.modifier);
                        }
                        else
                        {
                            value = Mathf.Pow(value, Mathf.Lerp(0.5f, 1.5f, 1f - PsycheHelper.Comp(observer).Psyche.GetPersonalityRating(perMod.personalityNode)) * perMod.modifier);
                        }
                    }
                }
            }

            return(Mathf.Clamp(value, attractionFactor.minFactor, attractionFactor.maxFactor));
        }
예제 #5
0
        /*
         * public float SuccessChance(Pawn initiator, Pawn recipient)
         * {
         *  float recipientAttraction = recipient.relations.SecondaryRomanceChanceFactor(initiator);
         *  return 1f;
         * }
         */
        //
        //allDefsListForReading.TryRandomElementByWeight((InteractionDef x) => x.Worker.RandomSelectionWeight(this.pawn, p), out intDef)

        public override void Interacted(Pawn initiator, Pawn recipient, List <RulePackDef> extraSentencePacks, out string letterText, out string letterLabel, out LetterDef letterDef)
        {
            if (lastInitiator != initiator || lastRecipient != recipient)
            {
                EmptyReasons();
                recipientPhysicalAttraction = CalculateAndSort(AttractionFactorCategoryDefOf.Physical, initiator, recipient);
                recipientRomanticAttraction = CalculateAndSort(AttractionFactorCategoryDefOf.Romantic, initiator, recipient);
                recipientSocialAttraction   = CalculateAndSort(AttractionFactorCategoryDefOf.Social, initiator, recipient);
                initiatorCircumstances      = CalculateAndSort(AttractionFactorCategoryDefOf.Circumstance, initiator, recipient);
            }
            AttractionFactorDef whoCares;

            /*
             * initiatorPhysicalAttraction = CalculateAndSort(AttractionFactorCategoryDefOf.Physical, recipient, initiator, false);
             * initiatorRomanticAttraction = CalculateAndSort(AttractionFactorCategoryDefOf.Romantic, recipient, initiator, false);
             * initiatorSocialAttraction = CalculateAndSort(AttractionFactorCategoryDefOf.Social, recipient, initiator, false);
             * recipientCircumstances = CalculateAndSort(AttractionFactorCategoryDefOf.Circumstance, recipient, initiator, false);
             */
            recipientCircumstances = AttractionUtility.CalculateAttractionCategory(AttractionFactorCategoryDefOf.Circumstance, recipient, initiator);
            float totalAttraction = AttractionUtility.CalculateAttraction(recipient, initiator, false, false, out veryLowRecipientReasons, out lowRecipientReasons, out highRecipientReasons, out veryHighRecipientReasons, out whoCares);

            initiatorPhysicalAttraction = GRHelper.GRPawnComp(recipient).RetrieveAttractionForCategory(initiator, AttractionFactorCategoryDefOf.Physical);
            initiatorRomanticAttraction = GRHelper.GRPawnComp(recipient).RetrieveAttractionForCategory(initiator, AttractionFactorCategoryDefOf.Romantic);
            initiatorSocialAttraction   = GRHelper.GRPawnComp(recipient).RetrieveAttractionForCategory(initiator, AttractionFactorCategoryDefOf.Social);
            LogFlirt(initiator.Name.ToStringShort + "=>" + recipient.Name.ToStringShort + " attraction: physical " + recipientPhysicalAttraction.ToString() + ", romantic " + recipientRomanticAttraction.ToString() + ", social " + recipientSocialAttraction.ToString() + ".");
            List <FlirtStyleDef> allDefsListForReading = DefDatabase <FlirtStyleDef> .AllDefsListForReading;
            FlirtStyleDef        flirtStyle;

            pressureCache = AttractionUtility.RelationshipStress(initiator, recipient);
            allDefsListForReading.TryRandomElementByWeight((FlirtStyleDef x) => CalculateFlirtStyleWeight(x, initiator, recipient), out flirtStyle);
            if (flirtStyle == null)
            {
                Log.Error("FailedToFindFlirt_error".Translate());
                letterText  = null;
                letterLabel = null;
                letterDef   = null;
                return;
            }
            if (veryHighInitiatorReasons.Count() > 0)
            {
                AttractionFactorDef reason = veryHighInitiatorReasons.RandomElement <AttractionFactorDef>();
                extraSentencePacks.Add(reason.intriguedByText);
            }
            else if (highInitiatorReasons.Count() > 0)
            {
                AttractionFactorDef reason = highInitiatorReasons.RandomElement <AttractionFactorDef>();
                extraSentencePacks.Add(reason.intriguedByText);
            }
            if (recipient.gender == Gender.Male)
            {
                extraSentencePacks.Add(flirtStyle.rulePackMale);
            }
            if (recipient.gender == Gender.Female)
            {
                extraSentencePacks.Add(flirtStyle.rulePackFemale);
            }
            LogFlirt("Flirt chosen: " + flirtStyle.defName + ".");
            LogFlirt(recipient.Name.ToStringShort + "=>" + initiator.Name.ToStringShort + " attraction: physical " + initiatorPhysicalAttraction.ToString() + ", romantic " + initiatorRomanticAttraction.ToString() + ", social " + initiatorSocialAttraction.ToString() + ".");

            if (initiatorPhysicalAttraction == 0f || initiatorRomanticAttraction == 0f || initiatorSocialAttraction == 0f)
            {
                successImpossible = true;
            }
            else
            {
                successImpossible = false;
            }
            FlirtReactionDef flirtReaction = null;
            IEnumerable <FlirtReactionDef> successfulFlirtReactions = (from reaction in DefDatabase <FlirtReactionDef> .AllDefsListForReading
                                                                       where reaction.successful
                                                                       select reaction);
            IEnumerable <FlirtReactionDef> unsuccessfulFlirtReactions = (from reaction in DefDatabase <FlirtReactionDef> .AllDefsListForReading
                                                                         where !reaction.successful
                                                                         select reaction);
            List <FlirtReactionDef> allFlirtReactions = DefDatabase <FlirtReactionDef> .AllDefsListForReading;
            FlirtReactionDef        successfulFlirt;
            FlirtReactionDef        unsuccessfulFlirt;

            successfulFlirtReactions.TryRandomElementByWeight((FlirtReactionDef x) => CalculateFlirtReactionWeight(flirtStyle, x, initiator, recipient), out successfulFlirt);
            unsuccessfulFlirtReactions.TryRandomElementByWeight((FlirtReactionDef x) => CalculateFlirtReactionWeight(flirtStyle, x, initiator, recipient), out unsuccessfulFlirt);
            if (successImpossible)
            {
                flirtReaction = unsuccessfulFlirt;
            }
            else
            {
                //revise to include flirt type
                float chance = Mathf.Clamp01(GradualRomanceMod.RomanticSuccessRate * Mathf.Pow(initiatorPhysicalAttraction, flirtStyle.baseSexiness) * Mathf.Pow(initiatorRomanticAttraction, flirtStyle.baseRomance) * Mathf.Pow(initiatorSocialAttraction, flirtStyle.baseLogic) * recipientCircumstances * 0.65f);
                Log.Message("Romance success chance: " + chance.ToString());
                if (Rand.Value < chance)
                {
                    flirtReaction = successfulFlirt;
                }
                else
                {
                    flirtReaction = unsuccessfulFlirt;
                }
                LogFlirt(recipient.Name.ToStringShort + " chose reaction " + flirtReaction.defName + " from Successful: " + successfulFlirt.defName + "; Unsuccessful: " + unsuccessfulFlirt.defName + ".");
            }


            if (flirtReaction == null)
            {
                Log.Error("FailedToFindReaction_error".Translate());
                letterText  = null;
                letterLabel = null;
                letterDef   = null;
                return;
            }

            if (initiator.gender == Gender.Male)
            {
                extraSentencePacks.Add(flirtReaction.maleRulePack);
            }
            if (initiator.gender == Gender.Female)
            {
                extraSentencePacks.Add(flirtReaction.femaleRulePack);
            }
            if (flirtReaction != FlirtReactionDefOf.Ignorant)
            {
                if (flirtReaction.successful)
                {
                    if (veryHighRecipientReasons.Count() > 0)
                    {
                        AttractionFactorDef reason = veryHighRecipientReasons.RandomElement <AttractionFactorDef>();
                        extraSentencePacks.Add(reason.reactionPositiveText);
                    }
                    else if (highRecipientReasons.Count() > 0)
                    {
                        AttractionFactorDef reason = highRecipientReasons.RandomElement <AttractionFactorDef>();
                        extraSentencePacks.Add(reason.reactionPositiveText);
                    }
                }
                else
                {
                    if (veryLowRecipientReasons.Count() > 0)
                    {
                        AttractionFactorDef reason = veryLowRecipientReasons.RandomElement <AttractionFactorDef>();
                        extraSentencePacks.Add(reason.reactionNegativeText);
                    }
                    else if (lowRecipientReasons.Count() > 0)
                    {
                        AttractionFactorDef reason = lowRecipientReasons.RandomElement <AttractionFactorDef>();
                        extraSentencePacks.Add(reason.reactionNegativeText);
                    }
                }
            }

            flirtReaction.worker.GiveThoughts(initiator, recipient, out List <RulePackDef> yetMoreSentencePacks);

            extraSentencePacks.AddRange(yetMoreSentencePacks);

            letterText  = null;
            letterLabel = null;
            letterDef   = null;

            List <Pawn> loversInSight  = RelationshipUtility.PotentiallyJealousPawnsInLineOfSight(initiator);
            List <Pawn> loversInSight2 = RelationshipUtility.PotentiallyJealousPawnsInLineOfSight(recipient);

            for (int i = 0; i < loversInSight.Count(); i++)
            {
                if (BreakupUtility.ShouldBeJealous(loversInSight[i], initiator, recipient))
                {
                    loversInSight[i].needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOfGR.CaughtFlirting, initiator);
                    if (flirtReaction.successful)
                    {
                        loversInSight[i].needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOfGR.CaughtFlirtingWithLover, recipient);
                    }
                }
            }

            if (flirtReaction.successful)
            {
                if (flirtReaction.provokesJealousy)
                {
                    for (int i = 0; i < loversInSight2.Count(); i++)
                    {
                        if (BreakupUtility.ShouldBeJealous(loversInSight2[i], initiator, recipient))
                        {
                            loversInSight2[i].needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOfGR.CaughtFlirting, recipient);
                            loversInSight2[i].needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOfGR.CaughtFlirtingWithLover, initiator);
                        }
                    }
                }


                RelationshipUtility.AdvanceInformalRelationship(initiator, recipient, out PawnRelationDef newRelation, (flirtStyle.baseSweetheartChance * flirtReaction.sweetheartModifier));

                if (newRelation != null && (PawnUtility.ShouldSendNotificationAbout(initiator) || PawnUtility.ShouldSendNotificationAbout(recipient)))
                {
                    string initiatorParagraph = AttractionUtility.WriteReasonsParagraph(initiator, recipient, veryHighInitiatorReasons, highInitiatorReasons, lowInitiatorReasons, veryLowInitiatorReasons);
                    string recipientParagraph = AttractionUtility.WriteReasonsParagraph(recipient, initiator, veryHighRecipientReasons, highRecipientReasons, lowRecipientReasons, veryLowRecipientReasons);
                    letterDef   = LetterDefOf.PositiveEvent;
                    letterLabel = newRelation.GetModExtension <RomanticRelationExtension>().newRelationshipTitleText.Translate();
                    letterText  = newRelation.GetModExtension <RomanticRelationExtension>().newRelationshipLetterText.Translate(initiator.Named("PAWN1"), recipient.Named("PAWN2"));


                    letterText += initiatorParagraph;
                    letterText += recipientParagraph;

                    /*    if (newRelation == PawnRelationDefOfGR.Sweetheart)
                     *  {
                     *      letterDef = LetterDefOf.PositiveEvent;
                     *      letterLabel = "NewSweetheartsLabel".Translate();
                     *      letterText = "NewSweetheartsText".Translate(initiator.Named("PAWN1"), recipient.Named("PAWN2"));
                     *  }
                     *  if (newRelation == PawnRelationDefOfGR.Lovebuddy)
                     *  {
                     *      letterDef = LetterDefOf.PositiveEvent;
                     *      letterLabel = "NewLovebuddiesLabel".Translate();
                     *      letterText = "NewLovebuddiesText".Translate(initiator.Named("PAWN1"), recipient.Named("PAWN2"));
                     *  }
                     *  if (newRelation == PawnRelationDefOfGR.Paramour)
                     *  {
                     *      if (RelationshipUtility.IsAnAffair(initiator, recipient, out Pawn initiatorSO, out Pawn recipientSO))
                     *      {
                     *          letterDef = LetterDefOf.NegativeEvent;
                     *          letterLabel = "ParamoursAffairLabel".Translate();
                     *          if (initiatorSO != null && recipientSO != null)
                     *          {
                     *              letterText = "ParamoursAffairTwoCuckoldsText".Translate(initiator.Named("PAWN1"), recipient.Named("PAWN2"), initiatorSO.Named("CUCKOLD1"), recipientSO.Named("CUCKOLD2"));
                     *          }
                     *          if (initiatorSO != null && recipientSO == null)
                     *          {
                     *              letterText = "ParamoursAffairInitiatorCuckoldText".Translate(initiator.Named("PAWN1"), recipient.Named("PAWN2"), initiatorSO.Named("CUCKOLD1"));
                     *          }
                     *          if (initiatorSO == null && recipientSO != null)
                     *          {
                     *              letterText = "ParamoursAffairRecipientCuckoldText".Translate(initiator.Named("PAWN1"), recipient.Named("PAWN2"), recipientSO.Named("CUCKOLD1"));
                     *          }
                     *      }
                     *      else
                     *      {
                     *          letterDef = LetterDefOf.PositiveEvent;
                     *          letterLabel = "NewParamoursLabel".Translate();
                     *          letterText = "NewParamoursText".Translate(initiator.Named("PAWN1"), recipient.Named("PAWN2"));
                     *      }
                     *  }*/
                }
            }
        }