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)); }
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); }
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); }
// 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)); }
/* * 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")); * } * }*/ } } }