From 4e8368ef3581b80c7e94f50e3002c903312f1217 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Sun, 21 Jul 2019 17:02:05 -0700 Subject: [PATCH 01/15] Make humpshroom grow in a reasonable amount of time, growable outside of hydroponics beds, and spawn naturally. --- Defs/ThingDefs/Drugs.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Defs/ThingDefs/Drugs.xml b/Defs/ThingDefs/Drugs.xml index 1ca2747c7..2452f0099 100644 --- a/Defs/ThingDefs/Drugs.xml +++ b/Defs/ThingDefs/Drugs.xml @@ -19,12 +19,13 @@ <plant> <fertilityMin>0.01</fertilityMin> <fertilitySensitivity>0.25</fertilitySensitivity> - <growDays>40.00</growDays> + <growDays>10.00</growDays> <harvestTag>Standard</harvestTag> <harvestedThingDef>HumpShroom</harvestedThingDef> <harvestYield>2</harvestYield> <sowMinSkill>4</sowMinSkill> <sowTags> + <li>Ground</li> <li>Hydroponic</li> </sowTags> <topWindExposure>0.1</topWindExposure> @@ -32,6 +33,8 @@ <min>0.3</min> <max>1.0</max> </visualSizeRange> + <wildClusterRadius>3</wildClusterRadius> + <wildClusterWeight>5</wildClusterWeight> </plant> <comps> <li Class="CompProperties_Glower"> -- GitLab From 5bcde8bd2d45e07f6d162de1fceff17f116f2773 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Sun, 21 Jul 2019 17:04:11 -0700 Subject: [PATCH 02/15] Give humpshroom addicts going through withdrawl a tiny amount of satisfaction so they aren't completely disabled. --- Source/Common/SexUtility.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Common/SexUtility.cs b/Source/Common/SexUtility.cs index 2b0b77911..dcb663df3 100644 --- a/Source/Common/SexUtility.cs +++ b/Source/Common/SexUtility.cs @@ -572,7 +572,7 @@ namespace rjw if (pawn.health.hediffSet.HasHediff(HediffDef.Named("HumpShroomAddiction")) && !pawn.health.hediffSet.HasHediff(HediffDef.Named("HumpShroomEffect"))) { //Log.Message("[RJW]xxx::satisfy 0 pawn is " + xxx.get_pawnname(pawn)); - satisfaction = 0; + satisfaction = 0.1f; } //--Log.Message("xxx::satisfy( " + pawn_name + ", " + partner_name + ", " + violent + "," + isCoreLovin + " ) - setting pawn joy"); -- GitLab From eb66b84733aed255f7ee901715df6f18402fb3f3 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Sun, 21 Jul 2019 17:11:47 -0700 Subject: [PATCH 03/15] Add some limited casual sex mechanics and better hookups with partners! Added: + Pawns who don't have partners might hook up with other pawns who don't have partners. At least partners who are around right now... Changed: + Nymphos no longer cheat on partners or homewreck. + Pawns will consider AllPawns, not just FreeColonists, so that they can bang guests too. Haven't tested with prisoners but come on it's only like 98% likely to have a bug. + Significantly increased the distance pawns will travel to find a hookup + Added vanilla Got Some Lovin' thought to partners after casual sex + Bug fix for xxx.HasNonPolyPartner() when neither RomanceDiversified or Psychology are active; it should have returned true when the pawn had any partner instead of false. + Refactored think about diseases into its own method. --- Source/Common/xxx.cs | 38 ++++++++++++++-- Source/JobDrivers/JobDriver_JoinInBed.cs | 2 +- Source/JobGivers/JobGiver_JoinInBed.cs | 55 ++++++++++++++++++------ 3 files changed, 77 insertions(+), 18 deletions(-) diff --git a/Source/Common/xxx.cs b/Source/Common/xxx.cs index 68dc0f6c7..c752d3434 100644 --- a/Source/Common/xxx.cs +++ b/Source/Common/xxx.cs @@ -129,6 +129,7 @@ namespace rjw public static readonly ThoughtDef violated_corpse = DefDatabase<ThoughtDef>.GetNamed("ViolatedCorpse"); public static readonly ThoughtDef gave_virginity = DefDatabase<ThoughtDef>.GetNamed("FortunateGaveVirginity"); public static readonly ThoughtDef lost_virginity = DefDatabase<ThoughtDef>.GetNamed("UnfortunateLostVirginity"); + public static readonly ThoughtDef VanillaGotSomeLovin = DefDatabase<ThoughtDef>.GetNamed("GotSomeLovin"); public static readonly ThoughtDef took_virginity = DefDatabase<ThoughtDef>.GetNamed("TookVirginity"); public static readonly JobDef fappin = DefDatabase<JobDef>.GetNamed("Fappin"); @@ -549,17 +550,36 @@ namespace rjw return need_sex.CurLevel < need_sex.thresh_frustrated(); } + public static bool is_horny(Pawn pawn) + { + Need_Sex need_sex = pawn.needs.TryGetNeed<Need_Sex>(); + if (need_sex == null) return false; + return need_sex.CurLevel < need_sex.thresh_horny(); + } + public static bool HasNonPolyPartner(Pawn pawn) { - if (!RomanceDiversifiedIsActive && !PsychologyIsActive) + if (!LovePartnerRelationUtility.HasAnyLovePartner(pawn)) return false; + if (!RomanceDiversifiedIsActive && !PsychologyIsActive) + return true; + foreach (DirectPawnRelation relation in pawn.relations.DirectRelations) { - if (relation.def != PawnRelationDefOf.Lover && relation.def != PawnRelationDefOf.Fiance && - relation.def != PawnRelationDefOf.Spouse) continue; + if (relation.def != PawnRelationDefOf.Lover && + relation.def != PawnRelationDefOf.Fiance && + relation.def != PawnRelationDefOf.Spouse) + { + continue; + } + if ((RomanceDiversifiedIsActive && relation.otherPawn.story.traits.HasTrait(polyamorous)) || - (PsychologyIsActive && relation.otherPawn.story.traits.HasTrait(polygamous))) continue; + (PsychologyIsActive && relation.otherPawn.story.traits.HasTrait(polygamous))) + { + continue; + } + return true; } return false; @@ -1529,9 +1549,19 @@ namespace rjw } } } + else if (is_human(partner)) + { + // human partner and not part of rape or necrophilia. add the vanilla GotSomeLovin thought + pawn.needs.mood.thoughts.memories.TryGainMemory(VanillaGotSomeLovin, partner); + } //--Log.Message("xxx::think_about_sex( " + xxx.get_pawnname(pawn) + ", " + xxx.get_pawnname(partner) + ", " + violent + " ) - setting disease thoughts"); + ThinkAboutDiseases(pawn, partner); + } + + private static void ThinkAboutDiseases(Pawn pawn, Pawn partner) + { // Dead and non-humans have no diseases (yet). if (partner.Dead || !is_human(partner)) return; diff --git a/Source/JobDrivers/JobDriver_JoinInBed.cs b/Source/JobDrivers/JobDriver_JoinInBed.cs index 2bde24449..11e513d23 100644 --- a/Source/JobDrivers/JobDriver_JoinInBed.cs +++ b/Source/JobDrivers/JobDriver_JoinInBed.cs @@ -68,7 +68,7 @@ namespace rjw initAction = delegate { // Trying to add some interactions and social logs - SexUtility.ProcessSex(Top, Partner, false, true); + SexUtility.ProcessSex(Top, Partner, false /*rape*/, true/*isCoreLovin*/, false /*whoring*/); }, defaultCompleteMode = ToilCompleteMode.Instant }; diff --git a/Source/JobGivers/JobGiver_JoinInBed.cs b/Source/JobGivers/JobGiver_JoinInBed.cs index b5a022069..2b8f89293 100644 --- a/Source/JobGivers/JobGiver_JoinInBed.cs +++ b/Source/JobGivers/JobGiver_JoinInBed.cs @@ -9,6 +9,9 @@ namespace rjw { public class JobGiver_JoinInBed : ThinkNode_JobGiver { + private const float NonNymphoHookupChance = 0.3f; + private const int MaxDistanceSquaredToFuck = 10000; + private static bool is_healthy(Pawn target) { return xxx.is_healthy(target) && (xxx.can_fuck(target) || xxx.can_be_fucked(target)); @@ -31,10 +34,12 @@ namespace rjw { Pawn best_fuckee = null; float best_distance = 1.0e6f; + bool pawnIsNympho = xxx.is_nympho(pawn); //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); - List<Pawn> targets = map.mapPawns.FreeColonists.Where(x + // Check AllPawns, not just colonists, to include guests. + List<Pawn> targets = map.mapPawns.AllPawns.Where(x => x.InBed() && x != pawn && !x.Position.IsForbidden(pawn) @@ -42,6 +47,7 @@ namespace rjw && !x.Downed && is_healthy(x) && x.Map == pawn.Map + && !x.HostileTo(pawn) && (xxx.is_laying_down_alone(x) || xxx.in_same_bed(x, pawn)) ).ToList(); @@ -58,32 +64,52 @@ namespace rjw foreach (Pawn target in partners) { //Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(target) + " ) partner found"); - if (pawn.Position.DistanceToSquared(target.Position) < 100 + if (pawn.Position.DistanceToSquared(target.Position) < MaxDistanceSquaredToFuck && pawn.CanReserveAndReach(target, PathEndMode.OnCell, Danger.Some, 1, 0) && target.CanReserve(pawn, 1, 0)) + { + Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(pawn) + " ) found lover (" + xxx.get_pawnname(target) + ")"); return target; + } //Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(target) + " ) partner cant be fucked right now"); } } - // No random lovin' for non-nymphos. - if (!xxx.is_nympho(pawn)) + // No lovers around... see if the pawn fancies a hookup. Nymphos and frustrated pawns always do! + bool canHookup = pawnIsNympho || xxx.is_frustrated(pawn) || (xxx.is_horny(pawn) && Rand.Value > NonNymphoHookupChance); + if (!canHookup) return null; - foreach (Pawn q in targets) + // No cheating from casual hookups... would probably make colony relationship management too annoying + Pawn pawnBestLover = LovePartnerRelationUtility.ExistingMostLikedLovePartner(pawn, false /*allowDead*/); + bool canHookupWithoutCheating = !xxx.HasNonPolyPartner(pawn) || pawnBestLover == null || pawnBestLover.Map != pawn.Map; + if (!canHookupWithoutCheating) + return null; + + foreach (Pawn targetPawn in targets) { - if (pawn.CanReserveAndReach(q, PathEndMode.OnCell, Danger.Some, 1, 0) && - q.CanReserve(pawn, 1, 0) && - roll_to_skip(pawn, q)) + // No homewrecking either! + if (xxx.HasNonPolyPartner(targetPawn) && + LovePartnerRelationUtility.ExistingMostLikedLovePartner(targetPawn, false /*allowDead*/).Map == pawn.Map) + continue; + + if (pawn.CanReserveAndReach(targetPawn, PathEndMode.OnCell, Danger.Some, 1, 0) && + targetPawn.CanReserve(pawn, 1, 0) && + roll_to_skip(pawn, targetPawn)) { - int dis = pawn.Position.DistanceToSquared(q.Position); - if (dis < best_distance) + int dis = pawn.Position.DistanceToSquared(targetPawn.Position); + if (dis < best_distance && dis < MaxDistanceSquaredToFuck) { - best_fuckee = q; + best_fuckee = targetPawn; best_distance = dis; } } } + + if (best_fuckee != null) + { + Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(pawn) + " ) found rando (" + xxx.get_pawnname(best_fuckee) + ")"); + } return best_fuckee; } @@ -91,8 +117,11 @@ namespace rjw { //--Log.Message("[RJW] JobGiver_JoinInBed( " + xxx.get_pawnname(pawn) + " ) called"); - if (pawn.Drafted) return null; - if (!SexUtility.ReadyForLovin(pawn) && !xxx.is_frustrated(pawn)) return null; + if (pawn.Drafted) + return null; + + if (!SexUtility.ReadyForLovin(pawn) && !xxx.is_frustrated(pawn)) + return null; if (pawn.CurJob == null || pawn.CurJob.def == JobDefOf.LayDown) { -- GitLab From 215d0eac8362b0d651c39c8457a49498badabe88 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Sun, 21 Jul 2019 20:41:57 -0700 Subject: [PATCH 04/15] - Fix double stacks of "got some lovin!" by making JobDriver_JoinInBed pass false for isCoreLovin to ProcessSex(). Found an interesting quirk about the vanilla thought, though: it stacks once per pawn, so someone who sleeps around a lot will get many different identical thoughts. - find_pawn_to_fuck now ignores animals unless the pawn is a zoophile. - Attempts to exclude pawns whose Duty is TravelOrLeave so that pawns trying to leave the map don't turn around to bang. --- Source/Common/SexUtility.cs | 8 ++++---- Source/Common/xxx.cs | 9 ++++++--- Source/JobDrivers/JobDriver_JoinInBed.cs | 2 +- Source/JobGivers/JobGiver_JoinInBed.cs | 10 ++++++++++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Source/Common/SexUtility.cs b/Source/Common/SexUtility.cs index dcb663df3..3e9382718 100644 --- a/Source/Common/SexUtility.cs +++ b/Source/Common/SexUtility.cs @@ -360,7 +360,7 @@ namespace rjw } xxx.UpdateRecords(pawn, partner, sextype, rape, isCoreLovin); - Satisfy(pawn, partner, sextype, rape, isCoreLovin); + Satisfy(pawn, partner, sextype, rape); CheckTraitGain(pawn); CheckTraitGain(partner); @@ -389,7 +389,7 @@ namespace rjw //check_trait_gain(pawn); } - private static void Satisfy(Pawn pawn, Pawn partner, xxx.rjwSextype sextype, bool rape = false, bool isCoreLovin = false) + private static void Satisfy(Pawn pawn, Pawn partner, xxx.rjwSextype sextype, bool rape = false) { //--Log.Message("xxx::satisfy( " + pawn_name + ", " + partner_name + ", " + violent + "," + isCoreLovin + " ) called"); @@ -698,8 +698,8 @@ namespace rjw Aftersex(pawn, partner, rape, isCoreLovin, sextype); //--Log.Message("SexUtility::processsex( " + pawn_name + ", " + partner_name + " ) - checking thoughts"); - xxx.think_about_sex(pawn, partner, receiving == pawn, rape, sextype); - xxx.think_about_sex(partner, pawn, receiving == partner, rape, sextype); + xxx.think_about_sex(pawn, partner, receiving == pawn, rape, sextype, isCoreLovin); + xxx.think_about_sex(partner, pawn, receiving == partner, rape, sextype, isCoreLovin); pawn.Drawer.Notify_MeleeAttackOn(partner); } diff --git a/Source/Common/xxx.cs b/Source/Common/xxx.cs index c752d3434..152205778 100644 --- a/Source/Common/xxx.cs +++ b/Source/Common/xxx.cs @@ -1449,7 +1449,7 @@ namespace rjw //violent - mark true when pawn rape partner //Note: violent is not reliable, since either pawn could be the rapist. Check jobdrivers instead, they're still active since this is called before ending the job. - public static void think_about_sex(Pawn pawn, Pawn partner, bool isReceiving, bool violent = false, rjwSextype sextype = rjwSextype.None) + public static void think_about_sex(Pawn pawn, Pawn partner, bool isReceiving, bool violent = false, rjwSextype sextype = rjwSextype.None, bool isCoreLovin = false) { // Partner should never be null, but just in case something gets changed elsewhere.. if (partner == null) @@ -1551,8 +1551,11 @@ namespace rjw } else if (is_human(partner)) { - // human partner and not part of rape or necrophilia. add the vanilla GotSomeLovin thought - pawn.needs.mood.thoughts.memories.TryGainMemory(VanillaGotSomeLovin, partner); + if (!isCoreLovin) + { + // human partner and not part of rape or necrophilia. add the vanilla GotSomeLovin thought + pawn.needs.mood.thoughts.memories.TryGainMemory(VanillaGotSomeLovin, partner); + } } //--Log.Message("xxx::think_about_sex( " + xxx.get_pawnname(pawn) + ", " + xxx.get_pawnname(partner) + ", " + violent + " ) - setting disease thoughts"); diff --git a/Source/JobDrivers/JobDriver_JoinInBed.cs b/Source/JobDrivers/JobDriver_JoinInBed.cs index 11e513d23..c8a4134bf 100644 --- a/Source/JobDrivers/JobDriver_JoinInBed.cs +++ b/Source/JobDrivers/JobDriver_JoinInBed.cs @@ -68,7 +68,7 @@ namespace rjw initAction = delegate { // Trying to add some interactions and social logs - SexUtility.ProcessSex(Top, Partner, false /*rape*/, true/*isCoreLovin*/, false /*whoring*/); + SexUtility.ProcessSex(Top, Partner, false /*rape*/, false/*isCoreLovin*/, false /*whoring*/); }, defaultCompleteMode = ToilCompleteMode.Instant }; diff --git a/Source/JobGivers/JobGiver_JoinInBed.cs b/Source/JobGivers/JobGiver_JoinInBed.cs index 2b8f89293..7bdbcf482 100644 --- a/Source/JobGivers/JobGiver_JoinInBed.cs +++ b/Source/JobGivers/JobGiver_JoinInBed.cs @@ -35,6 +35,8 @@ namespace rjw Pawn best_fuckee = null; float best_distance = 1.0e6f; bool pawnIsNympho = xxx.is_nympho(pawn); + bool pawnIsZoo = xxx.is_zoophile(pawn); + //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); @@ -48,6 +50,7 @@ namespace rjw && is_healthy(x) && x.Map == pawn.Map && !x.HostileTo(pawn) + && (pawnIsZoo || !xxx.is_animal(x)) && (xxx.is_laying_down_alone(x) || xxx.in_same_bed(x, pawn)) ).ToList(); @@ -123,6 +126,13 @@ namespace rjw if (!SexUtility.ReadyForLovin(pawn) && !xxx.is_frustrated(pawn)) return null; + // This check attempts to keep groups leaving the map, like guests or traders, from turning around to hook up + if (pawn.mindState?.duty?.def == DutyDefOf.TravelOrLeave) + { + Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(pawn) + " ) has TravelOrLeave, no time for lovin!"); + return null; + } + if (pawn.CurJob == null || pawn.CurJob.def == JobDefOf.LayDown) { //--Log.Message(" checking pawn and abilities"); -- GitLab From 9013c361274e94089fcbc090a6d13c224191a043 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Sun, 21 Jul 2019 23:51:33 -0700 Subject: [PATCH 05/15] - Don't add Got Some Lovin to whores while whoring. --- Source/Common/SexUtility.cs | 4 ++-- Source/Common/xxx.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Common/SexUtility.cs b/Source/Common/SexUtility.cs index 3e9382718..f1a653ed9 100644 --- a/Source/Common/SexUtility.cs +++ b/Source/Common/SexUtility.cs @@ -698,8 +698,8 @@ namespace rjw Aftersex(pawn, partner, rape, isCoreLovin, sextype); //--Log.Message("SexUtility::processsex( " + pawn_name + ", " + partner_name + " ) - checking thoughts"); - xxx.think_about_sex(pawn, partner, receiving == pawn, rape, sextype, isCoreLovin); - xxx.think_about_sex(partner, pawn, receiving == partner, rape, sextype, isCoreLovin); + xxx.think_about_sex(pawn, partner, receiving == pawn, rape, sextype, isCoreLovin, whoring); + xxx.think_about_sex(partner, pawn, receiving == partner, rape, sextype, isCoreLovin, false); pawn.Drawer.Notify_MeleeAttackOn(partner); } diff --git a/Source/Common/xxx.cs b/Source/Common/xxx.cs index 152205778..59ebecb36 100644 --- a/Source/Common/xxx.cs +++ b/Source/Common/xxx.cs @@ -1449,7 +1449,7 @@ namespace rjw //violent - mark true when pawn rape partner //Note: violent is not reliable, since either pawn could be the rapist. Check jobdrivers instead, they're still active since this is called before ending the job. - public static void think_about_sex(Pawn pawn, Pawn partner, bool isReceiving, bool violent = false, rjwSextype sextype = rjwSextype.None, bool isCoreLovin = false) + public static void think_about_sex(Pawn pawn, Pawn partner, bool isReceiving, bool violent = false, rjwSextype sextype = rjwSextype.None, bool isCoreLovin = false, bool whoring = false) { // Partner should never be null, but just in case something gets changed elsewhere.. if (partner == null) @@ -1551,7 +1551,7 @@ namespace rjw } else if (is_human(partner)) { - if (!isCoreLovin) + if (!isCoreLovin && !whoring) { // human partner and not part of rape or necrophilia. add the vanilla GotSomeLovin thought pawn.needs.mood.thoughts.memories.TryGainMemory(VanillaGotSomeLovin, partner); -- GitLab From 2ade5b8678d95e69b978772438faaf9d90524cbb Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Mon, 22 Jul 2019 08:53:30 -0700 Subject: [PATCH 06/15] Increase default vulnerability to 120% so that melee skill < 5 represents a penalty and melee skill 20 doesn't mean invulnerable. --- Defs/StatDefs/Stats.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Defs/StatDefs/Stats.xml b/Defs/StatDefs/Stats.xml index 7e9ef21a4..21b13514f 100644 --- a/Defs/StatDefs/Stats.xml +++ b/Defs/StatDefs/Stats.xml @@ -55,7 +55,7 @@ <skillNeedFactors> <li Class="rjw_CORE_EXPOSED.SkillNeed_BaseBonus"> <skill>Melee</skill> - <baseValue>1.00</baseValue> + <baseValue>1.25/baseValue> <bonusPerLevel>-0.05</bonusPerLevel> </li> </skillNeedFactors> -- GitLab From 5fdba84e1af228cff14d8347ef0f4a82e61d1aa8 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Mon, 22 Jul 2019 23:46:43 -0700 Subject: [PATCH 07/15] Fix typo --- Defs/StatDefs/Stats.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Defs/StatDefs/Stats.xml b/Defs/StatDefs/Stats.xml index 21b13514f..3c569d81f 100644 --- a/Defs/StatDefs/Stats.xml +++ b/Defs/StatDefs/Stats.xml @@ -55,7 +55,7 @@ <skillNeedFactors> <li Class="rjw_CORE_EXPOSED.SkillNeed_BaseBonus"> <skill>Melee</skill> - <baseValue>1.25/baseValue> + <baseValue>1.25</baseValue> <bonusPerLevel>-0.05</bonusPerLevel> </li> </skillNeedFactors> -- GitLab From 983fe2aeee506f76f6057fa830116ea8b77e3442 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Tue, 23 Jul 2019 08:58:07 -0700 Subject: [PATCH 08/15] Revert nonfunctional vulnerability fix and change it to 3.5% per melee level instead of 5%. --- Defs/StatDefs/Stats.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Defs/StatDefs/Stats.xml b/Defs/StatDefs/Stats.xml index 3c569d81f..ffbfeefbd 100644 --- a/Defs/StatDefs/Stats.xml +++ b/Defs/StatDefs/Stats.xml @@ -55,8 +55,8 @@ <skillNeedFactors> <li Class="rjw_CORE_EXPOSED.SkillNeed_BaseBonus"> <skill>Melee</skill> - <baseValue>1.25</baseValue> - <bonusPerLevel>-0.05</bonusPerLevel> + <baseValue>1.00</baseValue> + <bonusPerLevel>-0.035</bonusPerLevel> </li> </skillNeedFactors> <capacityFactors> -- GitLab From 97769a5f830338cd651013b45b0a99a5ec748e77 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Tue, 23 Jul 2019 08:59:23 -0700 Subject: [PATCH 09/15] -Give find_pawn_to_fuck hookups a chance to turn down offers using their own would_fuck() check. - Remove debug logs --- Source/JobGivers/JobGiver_JoinInBed.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Source/JobGivers/JobGiver_JoinInBed.cs b/Source/JobGivers/JobGiver_JoinInBed.cs index 7bdbcf482..5862dde83 100644 --- a/Source/JobGivers/JobGiver_JoinInBed.cs +++ b/Source/JobGivers/JobGiver_JoinInBed.cs @@ -23,6 +23,10 @@ namespace rjw float fuckability = xxx.would_fuck(pawn, target); // 0.0 to 1.0 if (fuckability < 0.1f) return false; + float reciprocity = xxx.would_fuck(target, pawn); + //Log.Message($"[RJW] roll_to_skip({xxx.get_pawnname(pawn)},{xxx.get_pawnname(target)}) fuckability ({fuckability},{reciprocity})"); + if (reciprocity < 0.1f) return false; + float chance_to_skip = 0.9f - 0.7f * fuckability; //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); @@ -71,7 +75,7 @@ namespace rjw && pawn.CanReserveAndReach(target, PathEndMode.OnCell, Danger.Some, 1, 0) && target.CanReserve(pawn, 1, 0)) { - Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(pawn) + " ) found lover (" + xxx.get_pawnname(target) + ")"); + //Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(pawn) + " ) found lover (" + xxx.get_pawnname(target) + ")"); return target; } //Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(target) + " ) partner cant be fucked right now"); @@ -111,7 +115,7 @@ namespace rjw if (best_fuckee != null) { - Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(pawn) + " ) found rando (" + xxx.get_pawnname(best_fuckee) + ")"); + //Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(pawn) + " ) found rando (" + xxx.get_pawnname(best_fuckee) + ")"); } return best_fuckee; } @@ -129,7 +133,7 @@ namespace rjw // This check attempts to keep groups leaving the map, like guests or traders, from turning around to hook up if (pawn.mindState?.duty?.def == DutyDefOf.TravelOrLeave) { - Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(pawn) + " ) has TravelOrLeave, no time for lovin!"); + //Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(pawn) + " ) has TravelOrLeave, no time for lovin!"); return null; } -- GitLab From c3fdaf23831b9b116f11cbb99706089b2f85fa2f Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Wed, 24 Jul 2019 09:07:54 -0700 Subject: [PATCH 10/15] Change ArtificialPrivatePartBase to use HediffClass Hediff_AddedPart instead of Hediff_Implant. This causes the Transhumanist and Body Purist traits to activate and love/hate their shiny new toys. Tested adding/removing them via surgery and via dev tools. --- Defs/HediffDefs/Hediffs_PrivateParts/Hediffs_PrivateParts.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Defs/HediffDefs/Hediffs_PrivateParts/Hediffs_PrivateParts.xml b/Defs/HediffDefs/Hediffs_PrivateParts/Hediffs_PrivateParts.xml index e423ac1c7..6c6953bdc 100644 --- a/Defs/HediffDefs/Hediffs_PrivateParts/Hediffs_PrivateParts.xml +++ b/Defs/HediffDefs/Hediffs_PrivateParts/Hediffs_PrivateParts.xml @@ -7,7 +7,7 @@ </HediffDef> <HediffDef Name="ArtificialPrivatePartBase" Abstract="True"> - <hediffClass>Hediff_Implant</hediffClass> + <hediffClass>Hediff_AddedPart</hediffClass> <defaultLabelColor>(0.5, 0.5, 0.9)</defaultLabelColor> <isBad>false</isBad> <addedPartProps> -- GitLab From 56f85d98e82f6402608b37faf149bfbde69352b6 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Sat, 27 Jul 2019 00:12:22 -0700 Subject: [PATCH 11/15] Bug fixes: - xxx.reduce_rest() would crash if a pawn didn't have a rest need if you passed in a negative value for rest amount. - xxx.HasNonPolyPartner() returned true even when the partner was dead which caused an NRE when someone considered them for hookup because their Map was null. I also made HasNonPolyPartner ignore Suspended pawns too. They're in stasis, they'll never know... - xxx.would_fuck() now skips the orientation check when initiated by an animal. - CompRJW.CheckPreference() now always returns true instead of false when evaluating the orientation preference of futas. - Hookup improvement: now ignores animal partner's opinion. - Hookup improvement: now never considered an animal hookup to be homewrecking, avoiding a bunch of irrelevant checks. - Hookup improvement: now cares more about fuckability than distance. the new formula is simply "fuckability/distance", with an automatic pass for a partner 2 squares away since they're likely in our current bed. --- Source/Common/xxx.cs | 18 +++++--- Source/Comps/CompRJW.cs | 6 +++ Source/JobGivers/JobGiver_JoinInBed.cs | 59 +++++++++++++++++++++----- 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/Source/Common/xxx.cs b/Source/Common/xxx.cs index 59ebecb36..d15cb82e0 100644 --- a/Source/Common/xxx.cs +++ b/Source/Common/xxx.cs @@ -524,10 +524,10 @@ namespace rjw if (has_quirk(pawn, "Vigorous")) x -= 1; Need_Rest need_rest = pawn.needs.TryGetNeed<Need_Rest>(); - if (need_rest != null || x <= 0) - { - need_rest.CurLevel -= need_rest.RestFallPerTick * x; - } + if (need_rest == null) + return; + + need_rest.CurLevel -= need_rest.RestFallPerTick * x; } public static float need_some_sex(Pawn pawn) @@ -574,6 +574,9 @@ namespace rjw continue; } + if (relation.otherPawn.Dead || relation.otherPawn.Suspended) + continue; + if ((RomanceDiversifiedIsActive && relation.otherPawn.story.traits.HasTrait(polyamorous)) || (PsychologyIsActive && relation.otherPawn.story.traits.HasTrait(polygamous))) { @@ -1037,8 +1040,8 @@ namespace rjw } } // Age not acceptable, automatic fail. + //Log.Message("would_fuck() - age_ok = " + age_ok.ToString()); if (!age_ok) return 0.0f; - //--Log.Message("would_fuck() - age_ok = " + age_ok.ToString()); float age_factor; @@ -1068,13 +1071,16 @@ namespace rjw { orientation_factor = 1.0f; - if (!ignore_gender) + if (!ignore_gender && !is_animal(fucker)) { if (is_asexual(fucker)) return 0.0f; if (!CompRJW.CheckPreference(fucker, fucked)) + { + //Log.Message("would_fuck() - preference fail"); return 0.0f; + } } } //Log.Message("would_fuck() - orientation_factor = " + orientation_factor.ToString()); diff --git a/Source/Comps/CompRJW.cs b/Source/Comps/CompRJW.cs index c8a3b444e..9e3bcaf19 100644 --- a/Source/Comps/CompRJW.cs +++ b/Source/Comps/CompRJW.cs @@ -347,6 +347,12 @@ namespace rjw bool isHomo = (Genital_Helper.has_vagina(pawn) && Genital_Helper.has_vagina(partner)) || ((Genital_Helper.has_penis(partner) || Genital_Helper.has_penis_infertile(partner)) && (Genital_Helper.has_penis(pawn) || Genital_Helper.has_penis_infertile(pawn))); + if (isHetero && isHomo) + { + // Oh you crazy futas. We could probably do a check against the pawn's gender, but eh. They've got so many parts available, they'll find something to do. + return true; + } + //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); switch (ori) diff --git a/Source/JobGivers/JobGiver_JoinInBed.cs b/Source/JobGivers/JobGiver_JoinInBed.cs index 5862dde83..f2a4500b9 100644 --- a/Source/JobGivers/JobGiver_JoinInBed.cs +++ b/Source/JobGivers/JobGiver_JoinInBed.cs @@ -18,14 +18,15 @@ namespace rjw } [SyncMethod] - private static bool roll_to_skip(Pawn pawn, Pawn target) + private static bool roll_to_skip(Pawn pawn, Pawn target, out float fuckability) { - float fuckability = xxx.would_fuck(pawn, target); // 0.0 to 1.0 + fuckability = xxx.would_fuck(pawn, target); // 0.0 to 1.0 if (fuckability < 0.1f) return false; - float reciprocity = xxx.would_fuck(target, pawn); + float reciprocity = xxx.is_animal(target) ? 1.0f : xxx.would_fuck(target, pawn); //Log.Message($"[RJW] roll_to_skip({xxx.get_pawnname(pawn)},{xxx.get_pawnname(target)}) fuckability ({fuckability},{reciprocity})"); - if (reciprocity < 0.1f) return false; + if (fuckability < 0.1f || reciprocity < 0.1f) + return false; float chance_to_skip = 0.9f - 0.7f * fuckability; //Rand.PopState(); @@ -36,8 +37,10 @@ namespace rjw [SyncMethod] public static Pawn find_pawn_to_fuck(Pawn pawn, Map map) { + //Log.Message($"[RJW] find_pawn_to_fuck: starting for pawn {xxx.get_pawnname(pawn)}"); + Pawn best_fuckee = null; - float best_distance = 1.0e6f; + float best_fuckability_score = 0; bool pawnIsNympho = xxx.is_nympho(pawn); bool pawnIsZoo = xxx.is_zoophile(pawn); @@ -58,6 +61,8 @@ namespace rjw && (xxx.is_laying_down_alone(x) || xxx.in_same_bed(x, pawn)) ).ToList(); + //Log.Message($"[RJW] find_pawn_to_fuck: considering {targets.Count} targets"); + // find lover/partner on same map List<Pawn> partners = targets.Where(x => pawn.relations.DirectRelationExists(PawnRelationDefOf.Lover, x) @@ -65,12 +70,15 @@ namespace rjw || pawn.relations.DirectRelationExists(PawnRelationDefOf.Spouse, x) ).ToList(); + //Log.Message($"[RJW] find_pawn_to_fuck: considering {partners.Count} partners"); + if (partners.Any()) { partners.Shuffle(); //Randomize order. foreach (Pawn target in partners) { - //Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(target) + " ) partner found"); + //Log.Message($"[RJW] find_pawn_to_fuck: checking partner {xxx.get_pawnname(target)}"); + if (pawn.Position.DistanceToSquared(target.Position) < MaxDistanceSquaredToFuck && pawn.CanReserveAndReach(target, PathEndMode.OnCell, Danger.Some, 1, 0) && target.CanReserve(pawn, 1, 0)) @@ -82,11 +90,13 @@ namespace rjw } } + //Log.Message($"[RJW] find_pawn_to_fuck: checking canHookup"); // No lovers around... see if the pawn fancies a hookup. Nymphos and frustrated pawns always do! bool canHookup = pawnIsNympho || xxx.is_frustrated(pawn) || (xxx.is_horny(pawn) && Rand.Value > NonNymphoHookupChance); if (!canHookup) return null; + //Log.Message($"[RJW] find_pawn_to_fuck: checking canHookupWithoutCheating"); // No cheating from casual hookups... would probably make colony relationship management too annoying Pawn pawnBestLover = LovePartnerRelationUtility.ExistingMostLikedLovePartner(pawn, false /*allowDead*/); bool canHookupWithoutCheating = !xxx.HasNonPolyPartner(pawn) || pawnBestLover == null || pawnBestLover.Map != pawn.Map; @@ -95,27 +105,54 @@ namespace rjw foreach (Pawn targetPawn in targets) { + //Log.Message($"[RJW] find_pawn_to_fuck: checking hookup {xxx.get_pawnname(targetPawn)}"); // No homewrecking either! - if (xxx.HasNonPolyPartner(targetPawn) && + if (!xxx.is_animal(targetPawn) && + xxx.HasNonPolyPartner(targetPawn) && LovePartnerRelationUtility.ExistingMostLikedLovePartner(targetPawn, false /*allowDead*/).Map == pawn.Map) + { continue; + } + //Log.Message($"[RJW] find_pawn_to_fuck: hookup {xxx.get_pawnname(targetPawn)} is sufficiently single"); + float fuckability = 0f; if (pawn.CanReserveAndReach(targetPawn, PathEndMode.OnCell, Danger.Some, 1, 0) && targetPawn.CanReserve(pawn, 1, 0) && - roll_to_skip(pawn, targetPawn)) + roll_to_skip(pawn, targetPawn, out fuckability)) { int dis = pawn.Position.DistanceToSquared(targetPawn.Position); - if (dis < best_distance && dis < MaxDistanceSquaredToFuck) + + if (dis <= 4) { + // Right next to me (in my bed)? You'll do. + //Log.Message($"[RJW] find_pawn_to_fuck: hookup {xxx.get_pawnname(targetPawn)} is right next to me. we'll bang, ok?"); + best_fuckability_score = 1.0e6f; best_fuckee = targetPawn; - best_distance = dis; + } + else if (dis > MaxDistanceSquaredToFuck) + { + // too far + //Log.Message($"[RJW] find_pawn_to_fuck: hookup {xxx.get_pawnname(targetPawn)} is too far... distance:{dis} max:{MaxDistanceSquaredToFuck}"); + continue; + } + else + { + // scaling fuckability by distance may give us more varied results and give the less attractive folks a chance + float fuckability_score = fuckability / GenMath.Sqrt(dis); + //Log.Message($"[RJW] find_pawn_to_fuck: hookup {xxx.get_pawnname(targetPawn)} is totally bangable. score:{fuckability_score}"); + + if (fuckability_score > best_fuckability_score) + { + best_fuckee = targetPawn; + best_fuckability_score = fuckability_score; + } } } } if (best_fuckee != null) { - //Log.Message("[RJW] find_pawn_to_fuck( " + xxx.get_pawnname(pawn) + " ) found rando (" + xxx.get_pawnname(best_fuckee) + ")"); + //Log.Message($"[RJW] find_pawn_to_fuck({xxx.get_pawnname(pawn)}) found rando {xxx.get_pawnname(best_fuckee)} with score {best_fuckability_score}"); } return best_fuckee; } -- GitLab From 9f87eceee7da038a5dbd917ba3de9b6ee3337a05 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Sat, 27 Jul 2019 09:57:27 -0700 Subject: [PATCH 12/15] Humpshroom value 80->10, drug 500->50, growdays up to 15, removed untested wildClusterRadius, set back to hydroponic only --- Defs/ThingDefs/Drugs.xml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Defs/ThingDefs/Drugs.xml b/Defs/ThingDefs/Drugs.xml index 2452f0099..cc788802b 100644 --- a/Defs/ThingDefs/Drugs.xml +++ b/Defs/ThingDefs/Drugs.xml @@ -19,13 +19,12 @@ <plant> <fertilityMin>0.01</fertilityMin> <fertilitySensitivity>0.25</fertilitySensitivity> - <growDays>10.00</growDays> + <growDays>15.00</growDays> <harvestTag>Standard</harvestTag> <harvestedThingDef>HumpShroom</harvestedThingDef> <harvestYield>2</harvestYield> <sowMinSkill>4</sowMinSkill> <sowTags> - <li>Ground</li> <li>Hydroponic</li> </sowTags> <topWindExposure>0.1</topWindExposure> @@ -33,8 +32,6 @@ <min>0.3</min> <max>1.0</max> </visualSizeRange> - <wildClusterRadius>3</wildClusterRadius> - <wildClusterWeight>5</wildClusterWeight> </plant> <comps> <li Class="CompProperties_Glower"> @@ -56,7 +53,7 @@ <graphicClass>Graphic_Single</graphicClass> </graphicData> <statBases> - <MarketValue>80</MarketValue> + <MarketValue>10</MarketValue> <Mass>0.1</Mass> <DeteriorationRate>4</DeteriorationRate> <Nutrition>0.40</Nutrition> @@ -289,7 +286,7 @@ <rotatable>false</rotatable> <statBases> <WorkToMake>450</WorkToMake> - <MarketValue>500</MarketValue> + <MarketValue>50</MarketValue> <Mass>0.05</Mass> <DeteriorationRate>6</DeteriorationRate> <Flammability>1.3</Flammability> -- GitLab From b0f513036b143f63544085a4bb03208919ad9621 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Sun, 28 Jul 2019 17:56:34 -0700 Subject: [PATCH 13/15] Whores were trying to serve downed pawns, though they aborted when they got all the way there and saw they were down. I fixed it by consolidating a couple of IsDowned and IsSuspended checks into xxx.is_healthy() and is_healthy_enough(). --- Source/Common/xxx.cs | 8 +++++++- Source/JobGivers/JobGiver_JoinInBed.cs | 9 ++++----- .../JobDrivers/JobDriver_WhoreInvitingVisitors.cs | 2 +- .../Whoring/JobGivers/JobGiver_WhoreInvitingVisitors.cs | 3 +-- Source/Modules/Whoring/Whoring_Helper.cs | 5 ----- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Source/Common/xxx.cs b/Source/Common/xxx.cs index d15cb82e0..42925eb6a 100644 --- a/Source/Common/xxx.cs +++ b/Source/Common/xxx.cs @@ -427,6 +427,8 @@ namespace rjw public static bool is_healthy(Pawn pawn) { return !pawn.Dead && + !pawn.Suspended && + !pawn.Downed && pawn.health.capacities.CanBeAwake && pawn.health.hediffSet.BleedRateTotal <= 0.0f && pawn.health.hediffSet.PainTotal < config.significant_pain_threshold; @@ -434,7 +436,11 @@ namespace rjw public static bool is_healthy_enough(Pawn pawn) { - return !pawn.Dead && pawn.health.capacities.CanBeAwake && pawn.health.hediffSet.BleedRateTotal <= 0.1f; + return !pawn.Dead && + !pawn.Suspended && + !pawn.Downed && + pawn.health.capacities.CanBeAwake && + pawn.health.hediffSet.BleedRateTotal <= 0.1f; } public static bool is_not_dying(Pawn pawn) diff --git a/Source/JobGivers/JobGiver_JoinInBed.cs b/Source/JobGivers/JobGiver_JoinInBed.cs index f2a4500b9..cf03aa796 100644 --- a/Source/JobGivers/JobGiver_JoinInBed.cs +++ b/Source/JobGivers/JobGiver_JoinInBed.cs @@ -12,9 +12,9 @@ namespace rjw private const float NonNymphoHookupChance = 0.3f; private const int MaxDistanceSquaredToFuck = 10000; - private static bool is_healthy(Pawn target) + private static bool CanFuck(Pawn target) { - return xxx.is_healthy(target) && (xxx.can_fuck(target) || xxx.can_be_fucked(target)); + return xxx.can_fuck(target) || xxx.can_be_fucked(target); } [SyncMethod] @@ -52,9 +52,8 @@ namespace rjw => x.InBed() && x != pawn && !x.Position.IsForbidden(pawn) - && !x.Suspended - && !x.Downed - && is_healthy(x) + && xxx.is_healthy(x) + && CanFuck(x) && x.Map == pawn.Map && !x.HostileTo(pawn) && (pawnIsZoo || !xxx.is_animal(x)) diff --git a/Source/Modules/Whoring/JobDrivers/JobDriver_WhoreInvitingVisitors.cs b/Source/Modules/Whoring/JobDrivers/JobDriver_WhoreInvitingVisitors.cs index 375238dca..b75ccbb61 100644 --- a/Source/Modules/Whoring/JobDrivers/JobDriver_WhoreInvitingVisitors.cs +++ b/Source/Modules/Whoring/JobDrivers/JobDriver_WhoreInvitingVisitors.cs @@ -61,7 +61,7 @@ namespace rjw yield return Toils_Goto.GotoThing(TargetPawnIndex, PathEndMode.Touch); Toil TryItOn = new Toil(); - TryItOn.AddFailCondition(() => !WhoringHelper.IsTargetPawnOkay(TargetPawn)); + TryItOn.AddFailCondition(() => !xxx.is_healthy(TargetPawn)); TryItOn.defaultCompleteMode = ToilCompleteMode.Delay; TryItOn.initAction = delegate { diff --git a/Source/Modules/Whoring/JobGivers/JobGiver_WhoreInvitingVisitors.cs b/Source/Modules/Whoring/JobGivers/JobGiver_WhoreInvitingVisitors.cs index 03e549a81..90540c35c 100644 --- a/Source/Modules/Whoring/JobGivers/JobGiver_WhoreInvitingVisitors.cs +++ b/Source/Modules/Whoring/JobGivers/JobGiver_WhoreInvitingVisitors.cs @@ -122,12 +122,11 @@ namespace rjw potentialClients = potentialClients.Where(x => x != whore && !x.IsForbidden(whore) - && !x.Suspended && !x.HostileTo(whore) && !x.IsPrisoner && x.Position.DistanceToSquared(pos) < max_distance_whore && whore.CanReserveAndReach(x, PathEndMode.ClosestTouch, Danger.Some, 1) - && xxx.is_healthy_enough(x)); + && xxx.is_healthy(x)); potentialClients = potentialClients.Except(potentialClients.Where(client.TraitCheckFail)); diff --git a/Source/Modules/Whoring/Whoring_Helper.cs b/Source/Modules/Whoring/Whoring_Helper.cs index 1e294e567..d3699998d 100644 --- a/Source/Modules/Whoring/Whoring_Helper.cs +++ b/Source/Modules/Whoring/Whoring_Helper.cs @@ -267,11 +267,6 @@ namespace rjw return AmountLeft; } - public static bool IsTargetPawnOkay(Pawn pawn) - { - return xxx.is_healthy(pawn) && !pawn.Downed && !pawn.Suspended; - } - [SyncMethod] public static bool IsHookupAppealing(Pawn target, Pawn whore) { -- GitLab From 4d3e8202321bc1268c38f354377258ac4f008ab9 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Sun, 28 Jul 2019 18:11:15 -0700 Subject: [PATCH 14/15] Casual sex: Don't consider targets who've recently banged and who aren't horny. --- Source/JobGivers/JobGiver_JoinInBed.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/JobGivers/JobGiver_JoinInBed.cs b/Source/JobGivers/JobGiver_JoinInBed.cs index cf03aa796..c93c291d1 100644 --- a/Source/JobGivers/JobGiver_JoinInBed.cs +++ b/Source/JobGivers/JobGiver_JoinInBed.cs @@ -110,6 +110,13 @@ namespace rjw xxx.HasNonPolyPartner(targetPawn) && LovePartnerRelationUtility.ExistingMostLikedLovePartner(targetPawn, false /*allowDead*/).Map == pawn.Map) { + //Log.Message($"[RJW] find_pawn_to_fuck: not hooking up with {xxx.get_pawnname(targetPawn)} to avoid homewrecking"); + continue; + } + + if (!SexUtility.ReadyForLovin(targetPawn) && !xxx.is_horny(targetPawn)) + { + //Log.Message($"[RJW] find_pawn_to_fuck: hookup {xxx.get_pawnname(targetPawn)} isn't ready for lovin'"); continue; } -- GitLab From 45d99d144a3f4a915806b0cfdad7eff8eabcc805 Mon Sep 17 00:00:00 2001 From: randomtyping <abuse@localhost.com> Date: Mon, 29 Jul 2019 17:40:23 -0700 Subject: [PATCH 15/15] Add comments better explaining the logic of xxx.HasNonPolyPartner(). --- Source/Common/xxx.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Source/Common/xxx.cs b/Source/Common/xxx.cs index 42925eb6a..1eaf83f50 100644 --- a/Source/Common/xxx.cs +++ b/Source/Common/xxx.cs @@ -563,14 +563,19 @@ namespace rjw return need_sex.CurLevel < need_sex.thresh_horny(); } + /// <summary> Checks to see if the pawn has any partners who don't have a Polyamorous/Polygamous trait; aka someone who'd get mad about sleeping around. </summary> + /// <returns> True if the pawn has at least one romantic partner who does not have a poly trait. False if no partners or all partners are poly. </returns> public static bool HasNonPolyPartner(Pawn pawn) { + // If they don't have a partner at all we can bail right away. if (!LovePartnerRelationUtility.HasAnyLovePartner(pawn)) return false; + // They have a partner, and if they don't have one of the mods that adds a poly trait then their partner must be non-poly. if (!RomanceDiversifiedIsActive && !PsychologyIsActive) return true; + // They have a partner and a mod that adds a poly trait, so check each partner to see if they're poly. foreach (DirectPawnRelation relation in pawn.relations.DirectRelations) { if (relation.def != PawnRelationDefOf.Lover && @@ -580,17 +585,22 @@ namespace rjw continue; } + // Dead partners don't count. And stasis'd partners will never find out! if (relation.otherPawn.Dead || relation.otherPawn.Suspended) continue; if ((RomanceDiversifiedIsActive && relation.otherPawn.story.traits.HasTrait(polyamorous)) || (PsychologyIsActive && relation.otherPawn.story.traits.HasTrait(polygamous))) { + // We have a partner who has the poly trait! But they could have multiple partners so keep checking. continue; } + // We found a partner who doesn't have a poly trait. return true; } + + // If we got here then we checked every partner and all of them had a poly trait, so they don't have a non-poly partner. return false; } -- GitLab