mirror of
https://github.com/vegapnk/RJW-Genes.git
synced 2024-08-15 00:23:31 +00:00
Added a new gene that increases penis size on oral sex
This commit is contained in:
parent
93a4699fba
commit
d5580ba92a
12 changed files with 136 additions and 6 deletions
79
Source/Genes/Special/Patches/Patch_AgeDrain.cs
Normal file
79
Source/Genes/Special/Patches/Patch_AgeDrain.cs
Normal file
|
@ -0,0 +1,79 @@
|
|||
using HarmonyLib;
|
||||
using rjw;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace RJW_Genes.Genes.Special
|
||||
{
|
||||
[HarmonyPatch(typeof(SexUtility), "Aftersex")]
|
||||
public static class Patch_AgeDrain
|
||||
{
|
||||
/**
|
||||
* Update Issue #26:
|
||||
* There are options that a 16 yo pawn and a 16 yo pawn have sex,
|
||||
* or there are races that have a different age-limits.
|
||||
* I am not sure how I feel about this, but as some people that I consider "normal" asked me about this I changed it as requested in #26 and #28
|
||||
*/
|
||||
|
||||
const long AGE_TRANSFERED_FALLBACK = 120000; // 120k == 2 days
|
||||
// 18 Years * 60 Days / Year * 60k Ticks/Day + 1 for safety
|
||||
const long MINIMUM_AGE_FALLBACK = 18 * 60 * 60000 + 1;
|
||||
|
||||
public static void Postfix(SexProps props)
|
||||
{
|
||||
if (props == null || props.pawn == null || props.partner == null || props.partner.IsAnimal() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Pawn pawn = props.pawn;
|
||||
Pawn partner = props.partner;
|
||||
|
||||
if (GeneUtility.IsAgeDrainer(pawn) && !GeneUtility.IsAgeDrainer(partner))
|
||||
{
|
||||
TransferAge(pawn, partner);
|
||||
}
|
||||
else if (GeneUtility.IsAgeDrainer(partner) && !GeneUtility.IsAgeDrainer(pawn))
|
||||
{
|
||||
TransferAge(partner,pawn);
|
||||
}
|
||||
else if (GeneUtility.IsAgeDrainer(partner) && GeneUtility.IsAgeDrainer(pawn) && RJW_Genes_Settings.rjw_genes_detailed_debug)
|
||||
{
|
||||
ModLog.Message($"[Sexual Age Drainer] both {pawn} and {partner} are sexual-age-drainers - nothing happens.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transfers age from the giver to the receiver.
|
||||
/// </summary>
|
||||
/// <param name="receiver">The pawn that will receive biological-Age-Ticks, and becomes younger if they are not already young. </param>
|
||||
/// <param name="giver">The pawn that will be giving biological-Age-Ticks. This pawn is always aged, even if the other pawn is too young.</param>
|
||||
private static void TransferAge(Pawn receiver, Pawn giver)
|
||||
{
|
||||
AgeTransferExtension transferExt = GeneDefOf.rjw_genes_sex_age_drain.GetModExtension<AgeTransferExtension>();
|
||||
long age_transfered = transferExt?.ageTickChange ?? AGE_TRANSFERED_FALLBACK;
|
||||
long minimum_age = transferExt?.minAgeInYears * 60 * 60000 + 1 ?? MINIMUM_AGE_FALLBACK;
|
||||
|
||||
var pawnAge = receiver.ageTracker.AgeBiologicalTicks;
|
||||
|
||||
if (RJW_Genes_Settings.rjw_genes_detailed_debug)
|
||||
ModLog.Message($"[Sexual Age Drainer] {receiver} is aging {giver} by {age_transfered} ({Math.Round(age_transfered / 60000.0, 2)} days)");
|
||||
|
||||
// Giver ALWAYS ages
|
||||
giver.ageTracker.AgeBiologicalTicks += age_transfered;
|
||||
|
||||
// Make Receiver younger if they are older than minimum age
|
||||
if (pawnAge - age_transfered > minimum_age)
|
||||
receiver.ageTracker.AgeBiologicalTicks = Math.Max(minimum_age, (pawnAge - age_transfered));
|
||||
else {
|
||||
if (RJW_Genes_Settings.rjw_genes_detailed_debug)
|
||||
ModLog.Message($"[Sexual Age Drainer] {receiver} was too young ({receiver.ageTracker.AgeBiologicalYears}), and remains unchanged.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
76
Source/Genes/Special/Patches/Patch_HormonalSaliva.cs
Normal file
76
Source/Genes/Special/Patches/Patch_HormonalSaliva.cs
Normal file
|
@ -0,0 +1,76 @@
|
|||
using HarmonyLib;
|
||||
using rjw;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Verse;
|
||||
|
||||
namespace RJW_Genes
|
||||
{
|
||||
[HarmonyPatch(typeof(SexUtility), "Aftersex")]
|
||||
public class Patch_HormonalSaliva
|
||||
{
|
||||
// TODO: Reduce to 0.02 after debug.
|
||||
const float SIZE_INCREMENT_FALLBACK = 0.02f;
|
||||
const float MAX_BODY_SIZE_FALLBACK = 2.5f;
|
||||
const float CUM_MULTIPLIER_FALLBACK = 1.05f;
|
||||
|
||||
public static void Postfix(SexProps props)
|
||||
{
|
||||
if (props == null || props.pawn == null || props.partner == null || props.partner.IsAnimal())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Pawn pawn = props.pawn;
|
||||
Pawn partner = props.partner;
|
||||
|
||||
|
||||
if (GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_hormonal_saliva) && (props.sexType == xxx.rjwSextype.Oral || props.sexType == xxx.rjwSextype.Sixtynine || props.sexType == xxx.rjwSextype.Fellatio))
|
||||
{
|
||||
GrowPenisses(partner);
|
||||
}
|
||||
|
||||
if (GeneUtility.HasGeneNullCheck(partner, GeneDefOf.rjw_genes_hormonal_saliva) && (props.sexType == xxx.rjwSextype.Oral || props.sexType == xxx.rjwSextype.Sixtynine || props.sexType == xxx.rjwSextype.Fellatio))
|
||||
{
|
||||
GrowPenisses(pawn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void GrowPenisses(Pawn pawn)
|
||||
{
|
||||
|
||||
HormonalSalivaExtension salivaExt = GeneDefOf.rjw_genes_hormonal_saliva.GetModExtension<HormonalSalivaExtension>();
|
||||
|
||||
float size_increment = salivaExt?.sizeIncrement ?? SIZE_INCREMENT_FALLBACK;
|
||||
float maximum_body_size = salivaExt?.maxBodySize ?? MAX_BODY_SIZE_FALLBACK;
|
||||
float cum_multiplier = salivaExt?.cumMultiplier ?? CUM_MULTIPLIER_FALLBACK;
|
||||
|
||||
|
||||
List<Hediff> AllPenisses = Genital_Helper.get_AllPartsHediffList(pawn).FindAll(x => Genital_Helper.is_penis(x));
|
||||
foreach (Hediff penis in AllPenisses)
|
||||
{
|
||||
CompHediffBodyPart CompHediff = penis.TryGetComp<rjw.CompHediffBodyPart>();
|
||||
if (penis.Severity < 1.00)
|
||||
{
|
||||
penis.Severity = Math.Min(1.01f, penis.Severity + size_increment);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CompHediff != null && CompHediff.SizeOwner <= maximum_body_size)
|
||||
{
|
||||
CompHediff.SizeOwner += size_increment;
|
||||
}
|
||||
}
|
||||
|
||||
// Increase Fluid
|
||||
if (CompHediff != null)
|
||||
CompHediff.FluidAmmount *= cum_multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
323
Source/Genes/Special/Patches/Patch_OrgasmMytosis.cs
Normal file
323
Source/Genes/Special/Patches/Patch_OrgasmMytosis.cs
Normal file
|
@ -0,0 +1,323 @@
|
|||
using HarmonyLib;
|
||||
using RimWorld;
|
||||
using RimWorld.QuestGen;
|
||||
using rjw;
|
||||
using rjw.Modules.Shared.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Verse;
|
||||
|
||||
namespace RJW_Genes
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// There was a big change with RJW 5.3.6 and I got a new Issue #52 documenting it.
|
||||
/// Basically, the reroll and orgasm logic was changed.
|
||||
/// </summary>
|
||||
|
||||
[HarmonyPatch(typeof(JobDriver_Sex), "SetupOrgasmTicks")]
|
||||
public static class Patch_OrgasmMytosis
|
||||
{
|
||||
|
||||
private const float SEVERITY_INCREASE_PER_ORGASM = 0.075f;
|
||||
|
||||
public static void Postfix(JobDriver_Sex __instance)
|
||||
{
|
||||
Pawn orgasmingPawn = __instance.pawn;
|
||||
if (orgasmingPawn != null && GeneUtility.HasGeneNullCheck(orgasmingPawn, GeneDefOf.rjw_genes_sexual_mytosis) && ! orgasmingPawn.health.hediffSet.HasHediff(HediffDefOf.rjw_genes_mytosis_shock_hediff))
|
||||
{
|
||||
var mytosisHediff = GetOrgasmMytosisHediff(orgasmingPawn);
|
||||
mytosisHediff.Severity += SEVERITY_INCREASE_PER_ORGASM;
|
||||
|
||||
if (mytosisHediff.Severity >= 1.0)
|
||||
{
|
||||
orgasmingPawn.health.RemoveHediff(mytosisHediff);
|
||||
|
||||
var copy = Multiply(orgasmingPawn);
|
||||
|
||||
ApplyMytosisShock(copy);
|
||||
ApplyMytosisShock(orgasmingPawn);
|
||||
|
||||
orgasmingPawn.Strip();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
float orgasm_time_reduction = Math.Max(1.0f - mytosisHediff.Severity, 0.1f);
|
||||
__instance.sex_ticks = (int) (__instance.sex_ticks * orgasm_time_reduction);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void ApplyMytosisShock(Pawn copy)
|
||||
{
|
||||
var stunA = HediffMaker.MakeHediff(HediffDefOf.rjw_genes_mytosis_shock_hediff, copy);
|
||||
stunA.Severity = 1;
|
||||
copy.health.AddHediff(stunA);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helps to get the Orgasm Mytosis Hediff of a Pawn. If it does not exist, one is added.
|
||||
/// </summary>
|
||||
/// <param name="orgasmed">The pawn that had the orgasm, for which a hediff is looked up or created.</param>
|
||||
/// <returns></returns>
|
||||
public static Hediff GetOrgasmMytosisHediff(Pawn orgasmed)
|
||||
{
|
||||
Hediff orgasmicMytosisHediff = orgasmed.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.rjw_genes_orgasmic_mytosis_hediff);
|
||||
if (orgasmicMytosisHediff == null)
|
||||
{
|
||||
orgasmicMytosisHediff = HediffMaker.MakeHediff(HediffDefOf.rjw_genes_orgasmic_mytosis_hediff, orgasmed);
|
||||
orgasmicMytosisHediff.Severity = 0;
|
||||
orgasmed.health.AddHediff(orgasmicMytosisHediff);
|
||||
}
|
||||
return orgasmicMytosisHediff;
|
||||
}
|
||||
|
||||
public static Pawn Multiply(Pawn toMultiply)
|
||||
{
|
||||
if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message("Hitting Multiply of Mytosis Pawn!");
|
||||
|
||||
PawnGenerationRequest request = new PawnGenerationRequest(
|
||||
kind: toMultiply.kindDef,
|
||||
faction: toMultiply.Faction,
|
||||
forceGenerateNewPawn: true,
|
||||
developmentalStages: DevelopmentalStage.Adult,
|
||||
allowDowned: true,
|
||||
canGeneratePawnRelations: false,
|
||||
colonistRelationChanceFactor: 0,
|
||||
allowFood: false,
|
||||
allowAddictions: false,
|
||||
relationWithExtraPawnChanceFactor: 0,
|
||||
forbidAnyTitle: true,
|
||||
forceNoBackstory: true,
|
||||
fixedGender: toMultiply.gender
|
||||
);
|
||||
|
||||
/*
|
||||
* Devnote: Adding these will lead to deadly issues!
|
||||
fixedBiologicalAge: toMultiply.ageTracker.AgeBiologicalTicks,
|
||||
fixedChronologicalAge: toMultiply.ageTracker.AgeChronologicalTicks,
|
||||
*/
|
||||
|
||||
Pawn copy = PawnGenerator.GeneratePawn(request);
|
||||
|
||||
|
||||
copy.gender = toMultiply.gender;
|
||||
copy.ageTracker = toMultiply.ageTracker;
|
||||
copy.Name = CreateCloneName(toMultiply,2);
|
||||
|
||||
copy.health = CopyRelevantHediffs(copy, toMultiply);
|
||||
copy.genes = CopyGeneTracker(copy,toMultiply.genes);
|
||||
|
||||
copy.ideo = toMultiply.ideo;
|
||||
copy.records = new Pawn_RecordsTracker(copy);
|
||||
copy.outfits = toMultiply.outfits;
|
||||
|
||||
copy.relations = toMultiply.relations;
|
||||
copy.skills = CopySkillTracker(copy,toMultiply.skills);
|
||||
|
||||
copy.equipment.DestroyAllEquipment();
|
||||
copy.apparel.DestroyAll();
|
||||
|
||||
//TODO: Make a letter on birth!
|
||||
|
||||
|
||||
PawnUtility.TrySpawnHatchedOrBornPawn(copy, toMultiply);
|
||||
// Move the copy in front of the origin, rather than on top
|
||||
if (toMultiply.Spawned)
|
||||
if (toMultiply.CurrentBed() != null)
|
||||
{
|
||||
copy.Position = copy.Position + new IntVec3(0, 0, 1).RotatedBy(toMultiply.CurrentBed().Rotation);
|
||||
}
|
||||
|
||||
|
||||
// Birthmother doesn't show as relation (See log below)
|
||||
// copy.relations.AddDirectRelation(PawnRelationDefOf.ParentBirth, toMultiply);
|
||||
|
||||
|
||||
copy.style = CopyStyleTracker(copy, toMultiply.style);
|
||||
copy.story = CopyStoryTracker(copy, toMultiply.story);
|
||||
|
||||
copy.Draw();
|
||||
return copy;
|
||||
}
|
||||
|
||||
private static Name CreateCloneName(Pawn toCopyFrom, int additions=1)
|
||||
{
|
||||
if (toCopyFrom.Name is NameTriple)
|
||||
{
|
||||
NameTriple casted = (NameTriple)toCopyFrom.Name;
|
||||
String Postfix = " " + RandomNamePostFix(additions);
|
||||
Name newName = new NameTriple(first:casted.First + Postfix, nick: casted.Nick + Postfix, last: casted.Last);
|
||||
if (newName.UsedThisGame)
|
||||
return CreateCloneName(toCopyFrom, additions);
|
||||
return newName;
|
||||
}
|
||||
return toCopyFrom.Name;
|
||||
}
|
||||
|
||||
private static Pawn_GeneTracker CopyGeneTracker(Pawn toCopyTo, Pawn_GeneTracker toCopyFrom)
|
||||
{
|
||||
var tracker = new Pawn_GeneTracker(toCopyTo);
|
||||
|
||||
// Due to Overwrite logics, we first add Endogenes and then a second pass on xenogenes
|
||||
|
||||
// Pass 1: Endogenes
|
||||
foreach (Gene gene in toCopyFrom.GenesListForReading) {
|
||||
GeneDef def = gene.def;
|
||||
if (!toCopyFrom.Xenogenes.Contains(gene))
|
||||
tracker.AddGene(def, false);
|
||||
}
|
||||
|
||||
// Pass 2: Xenogenes
|
||||
foreach (Gene gene in toCopyFrom.GenesListForReading)
|
||||
{
|
||||
GeneDef def = gene.def;
|
||||
if (toCopyFrom.Xenogenes.Contains(gene))
|
||||
tracker.AddGene(def, true);
|
||||
}
|
||||
|
||||
tracker.Reset();
|
||||
var skin = tracker.GetMelaninGene();
|
||||
var hair = tracker.GetHairColorGene();
|
||||
|
||||
//ModLog.Message($"{toCopyTo} had Skin {skin.defName} and {hair.defName} as colour-genes");
|
||||
|
||||
|
||||
return tracker;
|
||||
}
|
||||
|
||||
private static Pawn_StoryTracker CopyStoryTracker(Pawn toCopyTo, Pawn_StoryTracker toCopyFrom)
|
||||
{
|
||||
var tracker = new Pawn_StoryTracker(toCopyTo);
|
||||
|
||||
tracker.Childhood = toCopyFrom.Childhood;
|
||||
tracker.Adulthood = toCopyFrom.Adulthood;
|
||||
|
||||
tracker.headType = toCopyFrom.headType;
|
||||
tracker.bodyType = toCopyFrom.bodyType;
|
||||
tracker.hairDef = toCopyFrom.hairDef;
|
||||
tracker.furDef = toCopyFrom.furDef;
|
||||
|
||||
tracker.traits = toCopyFrom.traits;
|
||||
|
||||
tracker.skinColorOverride = toCopyFrom.skinColorOverride;
|
||||
tracker.HairColor = toCopyFrom.HairColor;
|
||||
|
||||
|
||||
return tracker;
|
||||
}
|
||||
|
||||
private static Pawn_SkillTracker CopySkillTracker(Pawn toCopyTo, Pawn_SkillTracker toCopyFrom)
|
||||
{
|
||||
var tracker = new Pawn_SkillTracker(toCopyTo);
|
||||
|
||||
tracker.skills = toCopyFrom.skills;
|
||||
|
||||
return tracker;
|
||||
}
|
||||
|
||||
private static Pawn_HealthTracker CopyRelevantHediffs(Pawn toCopyTo, Pawn copiedFrom)
|
||||
{
|
||||
var toCopyFrom = copiedFrom.health;
|
||||
var tracker = toCopyTo.health;
|
||||
// Step 0: Remove everything, Reset
|
||||
tracker.RemoveAllHediffs();
|
||||
tracker.Reset();
|
||||
// Step 1: Copy ALL Hediffs
|
||||
foreach (Hediff hed in toCopyFrom.hediffSet.hediffs)
|
||||
{
|
||||
// DevNote: There were a lot of issues around bodyparts:
|
||||
// Some Hediffs really need to know their bodypart, e.g. an implanted arm can either be left or right.
|
||||
// Ignoring this will lead to many errors, mostly around nullpointers.
|
||||
|
||||
BodyPartRecord originalBPR = hed.Part;
|
||||
if (originalBPR != null) {
|
||||
BodyPartRecord copyBPR = toCopyTo.RaceProps?.body.AllParts.Find(bpr => bpr.def == originalBPR.def);
|
||||
if (copyBPR != null && !copyBPR.IsMissingForPawn(toCopyTo)) {
|
||||
Hediff copiedHediff = HediffMaker.MakeHediff(hed.def, toCopyTo, copyBPR);
|
||||
tracker.AddHediff(copiedHediff);
|
||||
}
|
||||
} else
|
||||
{
|
||||
Hediff copiedHediff = HediffMaker.MakeHediff(hed.def, toCopyTo);
|
||||
tracker.AddHediff(copiedHediff);
|
||||
}
|
||||
}
|
||||
// Step 2: Remove all Artifical Parts
|
||||
List<Hediff> hediffsToRemove = new List<Hediff>();
|
||||
foreach (Hediff hed in tracker.hediffSet.hediffs)
|
||||
{
|
||||
if (hed is Hediff_AddedPart && ((Hediff_AddedPart)hed).def.countsAsAddedPartOrImplant)
|
||||
{
|
||||
hediffsToRemove.Add(hed);
|
||||
}
|
||||
}
|
||||
tracker.hediffSet.hediffs.RemoveAll(x => hediffsToRemove.Contains(x));
|
||||
|
||||
// Step 3: Tend issues from Removal
|
||||
foreach (Hediff copiedHediff in tracker.hediffSet.hediffs)
|
||||
{
|
||||
if (copiedHediff.Bleeding)
|
||||
copiedHediff.Tended(1.0f,1.0f);
|
||||
}
|
||||
|
||||
return tracker;
|
||||
}
|
||||
|
||||
private static Pawn_StyleTracker CopyStyleTracker(Pawn toCopyTo, Pawn_StyleTracker toCopyFrom)
|
||||
{
|
||||
var tracker = new Pawn_StyleTracker(toCopyTo);
|
||||
|
||||
tracker.beardDef = toCopyFrom.beardDef;
|
||||
tracker.BodyTattoo = toCopyFrom.BodyTattoo;
|
||||
tracker.FaceTattoo = toCopyFrom.FaceTattoo;
|
||||
|
||||
return tracker;
|
||||
}
|
||||
|
||||
private static String RandomNamePostFix(int numberOfParts)
|
||||
{
|
||||
List<String> additions = new List<String>()
|
||||
{
|
||||
"A","B","C","D","E","F","X","Y","Z",
|
||||
"Two",
|
||||
"Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega"
|
||||
};
|
||||
|
||||
additions.Shuffle();
|
||||
return String.Join(" ",additions.Take(numberOfParts));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*Warning:
|
||||
*Tried to add pawn relation ParentBirth with self, pawn=Henri
|
||||
UnityEngine.StackTraceUtility:ExtractStackTrace ()
|
||||
Verse.Log:Warning (string)
|
||||
RimWorld.Pawn_RelationsTracker:AddDirectRelation (RimWorld.PawnRelationDef,Verse.Pawn)
|
||||
RJW_Genes.Patch_OrgasmMytosis:Multiply (Verse.Pawn)
|
||||
RJW_Genes.Patch_OrgasmMytosis:Postfix (rjw.JobDriver_Sex,int&)
|
||||
(wrapper dynamic-method) rjw.JobDriver_Sex:rjw.JobDriver_Sex.Roll_Orgasm_Duration_Reset_Patch1 (rjw.JobDriver_Sex)
|
||||
(wrapper dynamic-method) rjw.JobDriver_Sex:rjw.JobDriver_Sex.Orgasm_Patch2 (rjw.JobDriver_Sex)
|
||||
(wrapper dynamic-method) rjw.JobDriver_Sex:rjw.JobDriver_Sex.SexTick_Patch1 (rjw.JobDriver_Sex,Verse.Pawn,Verse.Thing,bool,bool)
|
||||
rjw.JobDriver_Rape/<>c__DisplayClass1_0:<MakeNewToils>b__6 ()
|
||||
(wrapper dynamic-method) Verse.AI.JobDriver:Verse.AI.JobDriver.DriverTick_Patch0 (Verse.AI.JobDriver)
|
||||
Verse.AI.Pawn_JobTracker:JobTrackerTick ()
|
||||
Verse.Pawn:Tick ()
|
||||
Verse.TickList:Tick ()
|
||||
(wrapper dynamic-method) Verse.TickManager:Verse.TickManager.DoSingleTick_Patch2 (Verse.TickManager)
|
||||
Verse.TickManager:TickManagerUpdate ()
|
||||
Verse.Game:UpdatePlay ()
|
||||
Verse.Root_Play:Update ()
|
||||
|
||||
*/
|
65
Source/Genes/Special/Patches/Patch_OrgasmRush.cs
Normal file
65
Source/Genes/Special/Patches/Patch_OrgasmRush.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
using HarmonyLib;
|
||||
using rjw;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Verse;
|
||||
|
||||
namespace RJW_Genes
|
||||
{
|
||||
|
||||
[HarmonyPatch(typeof(SexUtility), nameof(SexUtility.SatisfyPersonal))]
|
||||
public static class Patch_OrgasmRush
|
||||
{
|
||||
|
||||
private const float REST_INCREASE = 0.05f;
|
||||
private const float ORGASMS_NEEDED_FOR_SUPERCHARGE = 3.0f;
|
||||
|
||||
public static void Postfix(SexProps props)
|
||||
{
|
||||
// ShortCuts: Exit Early if Pawn or Partner are null (can happen with Masturbation or other nieche-cases)
|
||||
if (props == null || props.pawn == null || !props.hasPartner())
|
||||
return;
|
||||
|
||||
// Exit for Animals - Animals can't get or trigger Orgasm Rushes. Fixes #15
|
||||
if (props.pawn.IsAnimal() || props.partner.IsAnimal())
|
||||
return;
|
||||
|
||||
if (props.pawn.genes != null && props.pawn.genes.HasGene(GeneDefOf.rjw_genes_orgasm_rush))
|
||||
{
|
||||
|
||||
// Pump up Wake-Ness
|
||||
if (props.pawn.needs.rest != null)
|
||||
props.pawn.needs.rest.CurLevel += REST_INCREASE;
|
||||
|
||||
// Add or Update Hediff for Orgasm Rush
|
||||
Hediff rush = GetOrgasmRushHediff(props.pawn);
|
||||
float added_severity = props.orgasms / ORGASMS_NEEDED_FOR_SUPERCHARGE;
|
||||
rush.Severity += added_severity;
|
||||
// Severity should be capped to 1 by the XML logic
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helps to get the Orgasm Rush Hediff of a Pawn. If it does not exist, one is added.
|
||||
/// </summary>
|
||||
/// <param name="orgasmed">The pawn that had the orgasm, for which a hediff is looked up or created.</param>
|
||||
/// <returns></returns>
|
||||
public static Hediff GetOrgasmRushHediff(Pawn orgasmed)
|
||||
{
|
||||
Hediff orgasmRushHediff = orgasmed.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.rjw_genes_orgasm_rush_hediff);
|
||||
if (orgasmRushHediff == null)
|
||||
{
|
||||
orgasmRushHediff = HediffMaker.MakeHediff(HediffDefOf.rjw_genes_orgasm_rush_hediff, orgasmed);
|
||||
orgasmRushHediff.Severity = 0;
|
||||
orgasmed.health.AddHediff(orgasmRushHediff);
|
||||
}
|
||||
return orgasmRushHediff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
64
Source/Genes/Special/Patches/Patch_Youth_Fountain.cs
Normal file
64
Source/Genes/Special/Patches/Patch_Youth_Fountain.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
using HarmonyLib;
|
||||
using rjw;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Verse;
|
||||
|
||||
namespace RJW_Genes.Genes.Special
|
||||
{
|
||||
[HarmonyPatch(typeof(SexUtility), "Aftersex")]
|
||||
public static class Patch_Youth_Fountain
|
||||
{
|
||||
/**
|
||||
* Update Issue #26:
|
||||
* There are options that a 16 yo pawn and a 16 yo pawn have sex,
|
||||
* or there are races that have a different age-limits.
|
||||
* I am not sure how I feel about this, but as some people that I consider "normal" asked me about this I changed it as requested in #26 and #28
|
||||
*/
|
||||
|
||||
const long AGE_REDUCTION_FALLBACK = 60000; // 60k == 1 day
|
||||
// 18 Years * 60 Days / Year * 60k Ticks/Day + 1 for safety
|
||||
const long MINIMUM_AGE_FALLBACK = 18 * 60 * 60000 + 1;
|
||||
|
||||
public static void Postfix(SexProps props)
|
||||
{
|
||||
if (props == null || props.pawn == null || props.partner == null || props.partner.IsAnimal())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (GeneUtility.IsYouthFountain(props.pawn))
|
||||
{
|
||||
ChangeAgeForPawn(props.partner, props.pawn);
|
||||
}
|
||||
if (GeneUtility.IsYouthFountain(props.partner))
|
||||
{
|
||||
ChangeAgeForPawn(props.pawn,props.partner);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void ChangeAgeForPawn(Pawn ToYouth, Pawn YouthingPawn)
|
||||
{
|
||||
AgeTransferExtension transferExt = GeneDefOf.rjw_genes_youth_fountain.GetModExtension<AgeTransferExtension>();
|
||||
long age_reduction = transferExt?.ageTickChange ?? AGE_REDUCTION_FALLBACK;
|
||||
long minimum_age = transferExt?.minAgeInYears * 60 * 60000 + 1 ?? MINIMUM_AGE_FALLBACK;
|
||||
|
||||
var partnerAge = ToYouth.ageTracker.AgeBiologicalTicks;
|
||||
|
||||
if (RJW_Genes_Settings.rjw_genes_detailed_debug)
|
||||
ModLog.Message($"Firing Youth Fountain - {YouthingPawn} is youthing {ToYouth} by {age_reduction} ({Math.Round(age_reduction / 60000.0, 2)} days)");
|
||||
|
||||
if (partnerAge - age_reduction > minimum_age) {
|
||||
ToYouth.ageTracker.AgeBiologicalTicks = Math.Max(minimum_age, partnerAge - age_reduction);
|
||||
}
|
||||
else if (RJW_Genes_Settings.rjw_genes_detailed_debug)
|
||||
ModLog.Message($"[Youth Fountain] {ToYouth} was too young ({ToYouth.ageTracker.AgeBiologicalYears}), and remains unchanged.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue