public override float Calculate(Pawn observer, Pawn assessed) { float opinion = AttractionUtility.GetRelationshipUnmodifiedOpinion(observer, assessed); float romanceFactor = Mathf.InverseLerp(-100, 100, opinion) * 2f; return(Mathf.Pow(romanceFactor, UniversalOpinionImportance)); }
public float SuccessChance(Pawn initiator, Pawn recipient) { float successChance = 0.6f * GradualRomanceMod.RomanticSuccessRate; successChance *= AttractionUtility.CalculateAttraction(recipient, initiator, false, true, out veryLowRecipientReasons, out lowRecipientReasons, out highRecipientReasons, out veryHighRecipientReasons, out AttractionFactorDef reasonForInstantFailure); return(Mathf.Clamp01(successChance)); }
public static bool HasReasonForBreakup(Pawn pawn, Pawn other) { PawnRelationDef relation = RelationshipUtility.MostAdvancedRelationshipBetween(pawn, other); if (relation == null) { return(false); } if (AttractionUtility.GetRelationshipUnmodifiedOpinion(pawn, other) < unmodifiedRelationshipBreakupThreshold) { return(true); } if (pawn.needs.mood.thoughts.memories.Memories.Any <Thought_Memory>(x => x.def.defName == "CheatedOnMe" && x.otherPawn == other)) { return(true); } if (pawn.needs.mood.thoughts.memories.Memories.Any <Thought_Memory>(x => x.def.defName == "CaughtFlirting" && x.otherPawn == other)) { return(true); } if (ThoughtDetector.HasSocialSituationalThought(pawn, other, ThoughtDefOfGR.FeelingNeglected)) { return(true); } return(false); }
/// <summary> /// /// </summary> /// <param name="initiator"></param> /// <param name="recipient"></param> /// <returns></returns> public override float RandomSelectionWeight(Pawn initiator, Pawn recipient) { if (!AttractionUtility.QuickCheck(initiator, recipient)) { return(0f); } 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); //if (intiatorFailureReasons.Count() > 0) //{ // EmptyReasons(); // return 0f; //} float romanceChance = recipientPhysicalAttraction * recipientRomanticAttraction * recipientRomanticAttraction * initiatorCircumstances; float flirtFactor = 0.5f; List <Thought_Memory> memoryList = initiator.needs.mood.thoughts.memories.Memories; for (int i = 0; i < memoryList.Count; i++) { Thought_Memory curMemory = memoryList[i]; if (curMemory.def == ThoughtDefOfGR.RomanticDisinterest && curMemory.otherPawn == recipient) { flirtFactor = flirtFactor * BadFlirtPenalty; } } flirtFactor = Mathf.Max(flirtFactor, 0.05f); lastInitiator = initiator; lastRecipient = recipient; return(GradualRomanceMod.BaseFlirtChance * romanceChance * flirtFactor * BaseFlirtWeight); }
public override float RandomSelectionWeight(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) { return(0f); } //Pawns will only ask their girlfriend/boyfriend to move in if (!initiator.relations.DirectRelationExists(PawnRelationDefOfGR.Lovefriend, recipient)) { return(0f); } if (!AttractionUtility.WouldConsiderFormalRelationship(initiator, recipient)) { return(0f); } if (!AttractionUtility.QuickCheck(initiator, recipient)) { return(0f); } EmptyReasons(); float attractiveness = AttractionUtility.CalculateAttraction(initiator, recipient, false, true, out veryLowInitiatorReasons, out lowInitiatorReasons, out highInitiatorReasons, out veryHighInitiatorReasons, out AttractionFactorDef reasonForInstantFailure); if (attractiveness == 0f) { return(0f); } float romanceChance = GradualRomanceMod.BaseRomanceChance; 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 ask to move in. float personalityFactor = Mathf.Pow(12f, (1f - PsycheHelper.Comp(initiator).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Romantic))); romanceChance *= personalityFactor * 0.02f; } //If their potential partner wouldn't consider a relationship with them, they're less likely to try and hit on them. But it doesn't put them off that much. if (AttractionUtility.WouldConsiderFormalRelationship(recipient, initiator)) { romanceChance *= 0.2f; } lastInitiator = initiator; lastRecipient = recipient; return(romanceChance * attractiveness); }
/* * 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) { AttractionFactorDef whoCares; if (lastInitiator != initiator || lastRecipient != recipient) { EmptyReasons(); initiatorAttraction = AttractionUtility.CalculateAttraction(initiator, recipient, false, false, out veryLowInitiatorReasons, out lowInitiatorReasons, out highInitiatorReasons, out veryHighInitiatorReasons, out whoCares); } pressureCache = AttractionUtility.RelationshipStress(initiator, recipient); 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); * } * } * } * * * } */ }
public override float Calculate(Pawn observer, Pawn assessed) { if (AttractionUtility.IsWeaklyGynephilic(observer) || AttractionUtility.IsExclusivelyAndrophilic(observer)) { return(0f); } if (AttractionUtility.IsOccasionallyGynephilic(observer)) { return(0.5f); } return(1f); }
public override float Calculate(Pawn observer, Pawn assessed) { if (!AttractionUtility.IsGynephilic(observer)) { return(0f); } if (AttractionUtility.IsWeaklyGynephilic(observer)) { return(0.5f); } return(1f); }
public AttractionRecord(Pawn pawn, Pawn other) { //Log.Message("Start constructor for " + pawn.Name.ToStringShort + " : " + other.Name.ToStringShort); lastRefreshedGameTick = Find.TickManager.TicksGame; //Log.Message("Made dictionary."); categoryCalculations = new Dictionary <AttractionFactorCategoryDef, float>(); if (pawn == other) { return; } totalAttraction = 1f; //Log.Message("Going through categories."); List <AttractionFactorCategoryDef> allDefs = DefDatabase <AttractionFactorCategoryDef> .AllDefsListForReading; foreach (AttractionFactorCategoryDef category in allDefs) { //Log.Message("Processing " + category.defName); AttractionFactorDef whoCares; List <AttractionFactorDef> newVeryHighFactors = new List <AttractionFactorDef>() { }; List <AttractionFactorDef> newHighFactors = new List <AttractionFactorDef>() { }; List <AttractionFactorDef> newLowFactors = new List <AttractionFactorDef>() { }; List <AttractionFactorDef> newVeryLowFactors = new List <AttractionFactorDef>() { }; if (category.alwaysRecalculate) { //Log.Message("Passing " + category.defName); continue; } else { //Log.Message("Adding result " + category.defName); float result = AttractionUtility.CalculateAttractionCategory(category, pawn, other, out newVeryLowFactors, out newLowFactors, out newHighFactors, out newVeryHighFactors, out whoCares); categoryCalculations.Add(category, result); totalAttraction *= result; } //Log.Message("Adding factors."); veryHighFactors.AddRange(newVeryHighFactors); highFactors.AddRange(newHighFactors); lowFactors.AddRange(newLowFactors); veryLowFactors.AddRange(newVeryLowFactors); //Log.Message("Finished adding factors."); } }
public override float Calculate(Pawn observer, Pawn assessed) { float observerValue = AttractionUtility.GetObjectiveSkillAttractiveness(observer); float assessedValue = AttractionUtility.GetObjectiveSkillAttractiveness(assessed); float value = assessedValue / observerValue; if (value < 1) { value = Mathf.Pow(value, SkillAttractivenessDampenerUpper); } else { value = Mathf.Pow(value, SkillAttractivenessDampenerLower); } return(value); }
public static bool RelationshipCanEvolveTo(Pawn pawn, Pawn other, PawnRelationDef newRelation) { List <ThoughtCondition> conditions; try { conditions = newRelation.GetModExtension <RomanticRelationExtension>().conditions; } catch (NullReferenceException) { return(false); } if (conditions.NullOrEmpty()) { return(false); } if (!AttractionUtility.IsAgeAppropriate(pawn) || !AttractionUtility.IsAgeAppropriate(other)) { try { if (newRelation.GetModExtension <RomanticRelationExtension>().doesLovin) { return(false); } } catch (NullReferenceException) { return(false); } } for (int i = 0; i < conditions.Count(); i++) { Log.Message(conditions[i].thought.defName + ": " + pawn.needs.mood.thoughts.memories.NumMemoriesOfDef(conditions[i].thought).ToString() + " " + other.needs.mood.thoughts.memories.NumMemoriesOfDef(conditions[i].thought) + " needs " + conditions[i].numberRequired.ToString()); if (GRThoughtUtility.NumOfMemoriesOfDefWhereOtherPawnIs(pawn, other, conditions[i].thought) < conditions[i].numberRequired || GRThoughtUtility.NumOfMemoriesOfDefWhereOtherPawnIs(other, pawn, conditions[i].thought) < conditions[i].numberRequired) { return(false); } } return(true); }
private float CalculateAndSort(AttractionFactorCategoryDef category, Pawn observer, Pawn assessed, bool observerIsInitiator = true) { float result = AttractionUtility.CalculateAttractionCategory(category, observer, assessed, out List <AttractionFactorDef> veryLowFactors, out List <AttractionFactorDef> lowFactors, out List <AttractionFactorDef> hightFactors, out List <AttractionFactorDef> veryHighFactors, out AttractionFactorDef reasonForInstantFailure); if (observerIsInitiator) { veryHighInitiatorReasons.AddRange(veryHighFactors); highInitiatorReasons.AddRange(hightFactors); lowInitiatorReasons.AddRange(lowFactors); veryLowInitiatorReasons.AddRange(veryLowFactors); intiatorFailureReasons.Add(reasonForInstantFailure); } else { veryHighRecipientReasons.AddRange(veryHighFactors); highRecipientReasons.AddRange(hightFactors); lowRecipientReasons.AddRange(lowFactors); veryLowRecipientReasons.AddRange(veryLowFactors); recipientFailureReasons.Add(reasonForInstantFailure); } return(result); }
public void Update(Pawn pawn, Pawn other) { lastRefreshedGameTick = Find.TickManager.TicksGame; veryHighFactors.Clear(); highFactors.Clear(); lowFactors.Clear(); veryLowFactors.Clear(); if (pawn == other) { return; } float oldAttraction = totalAttraction; totalAttraction = 1f; foreach (AttractionFactorCategoryDef category in DefDatabase <AttractionFactorCategoryDef> .AllDefs) { AttractionFactorDef whoCares; List <AttractionFactorDef> newVeryHighFactors; List <AttractionFactorDef> newHighFactors; List <AttractionFactorDef> newLowFactors; List <AttractionFactorDef> newVeryLowFactors; if (category.alwaysRecalculate || category.chanceOnly) { continue; } else { float result = AttractionUtility.CalculateAttractionCategory(category, pawn, other, out newVeryLowFactors, out newLowFactors, out newHighFactors, out newVeryHighFactors, out whoCares); categoryCalculations[category] = result; totalAttraction *= result; } veryHighFactors.AddRange(newVeryHighFactors); highFactors.AddRange(newHighFactors); lowFactors.AddRange(newLowFactors); veryLowFactors.AddRange(newVeryLowFactors); } }
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) { AttractionUtility.CalculateAttraction(initiator, recipient, false, true, out veryLowInitiatorReasons, out lowInitiatorReasons, out highInitiatorReasons, out veryHighInitiatorReasons, out AttractionFactorDef reasonForInstantFailure); } if (Rand.Value < this.SuccessChance(initiator, recipient)) { GRPawnRelationUtility.AdvanceRelationship(initiator, recipient, PawnRelationDefOf.Lover); LovePartnerRelationUtility.TryToShareBed(initiator, recipient); //TODO Add Move In tale if (PawnUtility.ShouldSendNotificationAbout(initiator) || PawnUtility.ShouldSendNotificationAbout(recipient)) { letterText = "MoveInLetterText".Translate(initiator.Named("PAWN1"), recipient.Named("PAWN2")); letterText += AttractionUtility.WriteReasonsParagraph(initiator, recipient, veryHighInitiatorReasons, highInitiatorReasons, lowInitiatorReasons, veryLowInitiatorReasons); letterText += AttractionUtility.WriteReasonsParagraph(recipient, initiator, veryHighRecipientReasons, highRecipientReasons, lowRecipientReasons, veryLowRecipientReasons); letterLabel = "MoveInLetterTitle".Translate(); letterDef = LetterDefOf.PositiveEvent; } else { letterText = null; letterLabel = null; letterDef = null; } //extraSentencePacks.Add(RulePackDefOf.Sentence_RomanceAttemptAccepted); } else { //extraSentencePacks.Add(RulePackDefOf.Sentence_RomanceAttemptRejected); letterText = null; letterLabel = null; letterDef = null; } }
/// <summary> /// /// </summary> /// <param name="initiator"></param> /// <param name="recipient"></param> /// <returns></returns> public override float RandomSelectionWeight(Pawn initiator, Pawn recipient) { if (!AttractionUtility.QuickCheck(initiator, recipient)) { return(0f); } EmptyReasons(); AttractionFactorDef whoCares; float currentAttraction = AttractionUtility.CalculateAttraction(initiator, recipient, false, false, out veryLowInitiatorReasons, out lowInitiatorReasons, out highInitiatorReasons, out veryHighInitiatorReasons, out whoCares); recipientPhysicalAttraction = GRHelper.GRPawnComp(initiator).RetrieveAttractionForCategory(recipient, AttractionFactorCategoryDefOf.Physical); recipientRomanticAttraction = GRHelper.GRPawnComp(initiator).RetrieveAttractionForCategory(recipient, AttractionFactorCategoryDefOf.Romantic); recipientSocialAttraction = GRHelper.GRPawnComp(initiator).RetrieveAttractionForCategory(recipient, AttractionFactorCategoryDefOf.Social); //initiatorCircumstances = CalculateAndSort(AttractionFactorCategoryDefOf.Circumstance, initiator, recipient); //if (intiatorFailureReasons.Count() > 0) //{ // EmptyReasons(); // return 0f; //} float flirtFactor = 0.5f; List <Thought_Memory> memoryList = initiator.needs.mood.thoughts.memories.Memories; for (int i = 0; i < memoryList.Count; i++) { Thought_Memory curMemory = memoryList[i]; if (curMemory.def == ThoughtDefOfGR.RomanticDisinterest && curMemory.otherPawn == recipient) { flirtFactor = flirtFactor * BadFlirtPenalty; } } flirtFactor = Mathf.Max(flirtFactor, 0.05f); lastInitiator = initiator; lastRecipient = recipient; return(GradualRomanceMod.BaseFlirtChance * currentAttraction * flirtFactor * BaseFlirtWeight); }
public static bool ShouldImplicitlyEndInformalRelationship(Pawn pawn, Pawn other, PawnRelationDef relation) { if (CanDecay(pawn, other, relation)) { return(true); } if (RelationshipUtility.IsPolygamist(pawn)) { return(false); } float chance = Mathf.InverseLerp(80, -20, AttractionUtility.GetRelationshipUnmodifiedOpinion(pawn, other)); chance *= (relation.GetModExtension <RomanticRelationExtension>().relationshipLevel / (relation.GetModExtension <RomanticRelationExtension>().relationshipLevel + 1)); if (PsycheHelper.PsychologyEnabled(pawn)) { chance *= Mathf.Lerp(0f, 2f, PsycheHelper.Comp(pawn).Psyche.GetPersonalityRating(PersonalityNodeDefOfGR.Moralistic)); } if (Rand.Value < chance) { return(true); } return(false); }
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 override float RandomSelectionWeight(Pawn initiator, Pawn recipient) { PawnRelationDef pawnRelation = RelationshipUtility.MostAdvancedRelationshipBetween(initiator, recipient); if (!AttractionUtility.QuickCheck(initiator, recipient)) { return(0f); } if (GradualRomanceMod.SeductionMode == GradualRomanceMod.SeductionModeSetting.NoSeduction) { return(0f); } else if (GradualRomanceMod.SeductionMode == GradualRomanceMod.SeductionModeSetting.OnlyRelationship) { if (pawnRelation == null || !RelationshipUtility.IsSexualRelationship(pawnRelation)) { return(0f); } } else if (GradualRomanceMod.SeductionMode == GradualRomanceMod.SeductionModeSetting.RelationshipAndNonColonists) { if (pawnRelation == null && recipient.IsColonist) { return(0f); } if (pawnRelation != null && !RelationshipUtility.IsSexualRelationship(pawnRelation) && recipient.IsColonist) { return(0f); } } //shouldn't seduce if you can't move if (initiator.health.capacities.GetLevel(PawnCapacityDefOf.Consciousness) <= 0.5f || initiator.health.capacities.GetLevel(PawnCapacityDefOf.Moving) <= 0.25f) { return(0f); } if (recipient.health.capacities.GetLevel(PawnCapacityDefOf.Consciousness) <= 0.5f || recipient.health.capacities.GetLevel(PawnCapacityDefOf.Moving) <= 0.25f) { return(0f); } //shouldn't seduce while working TimeAssignmentDef initiatorAssignment = initiator.timetable.GetAssignment(GenLocalDate.HourOfDay(initiator.Map)); TimeAssignmentDef recipientAssignment = recipient.timetable.GetAssignment(GenLocalDate.HourOfDay(recipient.Map)); if (initiatorAssignment != TimeAssignmentDefOf.Joy || initiatorAssignment != TimeAssignmentDefOf.Anything) { return(0f); } if (recipientAssignment != TimeAssignmentDefOf.Joy || recipientAssignment != TimeAssignmentDefOf.Anything) { return(0f); } EmptyReasons(); AttractionFactorDef whoCares; initiatorAttraction = AttractionUtility.CalculateAttraction(initiator, recipient, false, false, out veryLowInitiatorReasons, out lowInitiatorReasons, out highInitiatorReasons, out veryHighInitiatorReasons, out whoCares); float tensionFactor = 1.33f * RelationshipUtility.LevelOfSexualTension(initiator, recipient); tensionFactor = Mathf.Max(1f, tensionFactor); lastInitiator = initiator; lastRecipient = recipient; return(GradualRomanceMod.BaseSeductionChance * initiatorAttraction * tensionFactor * AttractionUtility.PropensityToSeduce(initiator)); }
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) { AttractionUtility.CalculateAttraction(initiator, recipient, false, true, out veryLowInitiatorReasons, out lowInitiatorReasons, out highInitiatorReasons, out veryHighInitiatorReasons, out AttractionFactorDef reasonForInstantFailure); } if (Rand.Value < this.SuccessChance(initiator, recipient)) { List <Pawn> list; this.BreakLoverAndFianceRelations(initiator, out list); List <Pawn> list2; this.BreakLoverAndFianceRelations(recipient, out list2); for (int i = 0; i < list.Count; i++) { BreakupUtility.TryAddCheaterThought(list[i], initiator, recipient); } for (int j = 0; j < list2.Count; j++) { BreakupUtility.TryAddCheaterThought(list2[j], recipient, initiator); } initiator.relations.TryRemoveDirectRelation(PawnRelationDefOf.ExLover, recipient); initiator.relations.TryRemoveDirectRelation(PawnRelationDefOfGR.ExLovefriend, recipient); GRPawnRelationUtility.AdvanceRelationship(recipient, initiator, PawnRelationDefOfGR.Lovefriend); //TODO Change record tale TaleRecorder.RecordTale(TaleDefOf.BecameLover, new object[] { initiator, recipient }); initiator.needs.mood.thoughts.memories.RemoveMemoriesOfDefWhereOtherPawnIs(ThoughtDefOf.BrokeUpWithMe, recipient); recipient.needs.mood.thoughts.memories.RemoveMemoriesOfDefWhereOtherPawnIs(ThoughtDefOf.BrokeUpWithMe, initiator); initiator.needs.mood.thoughts.memories.RemoveMemoriesOfDefWhereOtherPawnIs(ThoughtDefOf.FailedRomanceAttemptOnMe, recipient); initiator.needs.mood.thoughts.memories.RemoveMemoriesOfDefWhereOtherPawnIs(ThoughtDefOf.FailedRomanceAttemptOnMeLowOpinionMood, recipient); recipient.needs.mood.thoughts.memories.RemoveMemoriesOfDefWhereOtherPawnIs(ThoughtDefOf.FailedRomanceAttemptOnMe, initiator); recipient.needs.mood.thoughts.memories.RemoveMemoriesOfDefWhereOtherPawnIs(ThoughtDefOf.FailedRomanceAttemptOnMeLowOpinionMood, initiator); if (PawnUtility.ShouldSendNotificationAbout(initiator) || PawnUtility.ShouldSendNotificationAbout(recipient)) { this.GetNewLoversLetter(initiator, recipient, list, list2, out letterText, out letterLabel, out letterDef); letterText += AttractionUtility.WriteReasonsParagraph(initiator, recipient, veryHighInitiatorReasons, highInitiatorReasons, lowInitiatorReasons, veryLowInitiatorReasons); letterText += AttractionUtility.WriteReasonsParagraph(recipient, initiator, veryHighRecipientReasons, highRecipientReasons, lowRecipientReasons, veryLowRecipientReasons); } else { letterText = null; letterLabel = null; letterDef = null; } extraSentencePacks.Add(RulePackDefOf.Sentence_RomanceAttemptAccepted); } else { initiator.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.RebuffedMyRomanceAttempt, recipient); recipient.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.FailedRomanceAttemptOnMe, initiator); if (recipient.relations.OpinionOf(initiator) <= 0) { recipient.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.FailedRomanceAttemptOnMeLowOpinionMood, initiator); } extraSentencePacks.Add(RulePackDefOf.Sentence_RomanceAttemptRejected); letterText = null; letterLabel = null; letterDef = null; } }
public override float RandomSelectionWeight(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) { return(0f); } //Pawns will only romance characters with which they have a mild relationship if (!GRPawnRelationUtility.HasInformalRelationship(initiator, recipient)) { return(0f); } //Pawns won't hit on their spouses. 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); } //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); } //People only hit on people if they would consider a formal relationship with them. if (!AttractionUtility.WouldConsiderFormalRelationship(initiator, recipient)) { return(0f); } if (!AttractionUtility.QuickCheck(initiator, recipient)) { return(0f); } EmptyReasons(); float attractiveness = AttractionUtility.CalculateAttraction(initiator, recipient, false, true, out veryLowInitiatorReasons, out lowInitiatorReasons, out highInitiatorReasons, out veryHighInitiatorReasons, out AttractionFactorDef reasonForInstantFailure); if (attractiveness == 0f) { return(0f); } int opinion = initiator.relations.OpinionOf(recipient); float romanceChance = GradualRomanceMod.BaseRomanceChance; 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; } //If their partner wouldn't consider a relationship with them, they're less likely to try and hit on them. But it doesn't put them off that much. if (AttractionUtility.WouldConsiderFormalRelationship(recipient, initiator)) { romanceChance *= 0.4f; } lastInitiator = initiator; lastRecipient = recipient; return(romanceChance * attractiveness); }
/* * 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")); * } * }*/ } } }
public override float Calculate(Pawn observer, Pawn assessed) { return(Mathf.InverseLerp(0f, AttractionUtility.GetObjectiveWealthAttractiveness(observer), AttractionUtility.GetObjectiveWealthAttractiveness(assessed))); }