From f21812a3ebdd9ddb56b8476cd15a0705ebc03ceb Mon Sep 17 00:00:00 2001 From: c0ffee12 Date: Thu, 29 Jul 2021 18:33:08 -0700 Subject: [PATCH] Induce lactation --- .../1.3/Assemblies/CRIALactation.dll | Bin 11776 -> 20992 bytes CRIALactation/CRIALactation.csproj | 8 ++ .../Defs/JobDefs/Jobs_CRIALactation.xml | 9 ++ .../WorkGiver_MassageBreasts.xml | 15 ++ .../Patches/Patch_LactationInduction.xml | 28 ++++ .../CompProperties_InduceLactation.cs | 23 +++ .../Source/Comps/CompInduceLactation.cs | 131 ++++++++++++++++++ .../Source/JobDefOf/JobDefOf_CRIALactation.cs | 21 +++ .../JobDrivers/JobDriver_MassageBreasts.cs | 79 +++++++++++ CRIALactation/Source/LactationUtility.cs | 12 ++ .../WorkGivers/WorkGiver_MassageBreasts.cs | 56 ++++++++ 11 files changed, 382 insertions(+) create mode 100644 CRIALactation/Defs/JobDefs/Jobs_CRIALactation.xml create mode 100644 CRIALactation/Defs/WorkGiverDefs/WorkGiver_MassageBreasts.xml create mode 100644 CRIALactation/Patches/Patch_LactationInduction.xml create mode 100644 CRIALactation/Source/CompProperties/CompProperties_InduceLactation.cs create mode 100644 CRIALactation/Source/Comps/CompInduceLactation.cs create mode 100644 CRIALactation/Source/JobDefOf/JobDefOf_CRIALactation.cs create mode 100644 CRIALactation/Source/JobDrivers/JobDriver_MassageBreasts.cs create mode 100644 CRIALactation/Source/WorkGivers/WorkGiver_MassageBreasts.cs diff --git a/CRIALactation/1.3/Assemblies/CRIALactation.dll b/CRIALactation/1.3/Assemblies/CRIALactation.dll index 603de228578489fb1e7966c7c01033c4dc15042b..15d9f7e835d7cbf7472708cf49d7af0dfb52a55b 100644 GIT binary patch literal 20992 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 L`v2?yo(KLLjRir0 diff --git a/CRIALactation/CRIALactation.csproj b/CRIALactation/CRIALactation.csproj index 05c1d6c..f1c7208 100644 --- a/CRIALactation/CRIALactation.csproj +++ b/CRIALactation/CRIALactation.csproj @@ -70,10 +70,14 @@ + + + + @@ -81,12 +85,16 @@ + + + + \ No newline at end of file diff --git a/CRIALactation/Defs/JobDefs/Jobs_CRIALactation.xml b/CRIALactation/Defs/JobDefs/Jobs_CRIALactation.xml new file mode 100644 index 0000000..970f70b --- /dev/null +++ b/CRIALactation/Defs/JobDefs/Jobs_CRIALactation.xml @@ -0,0 +1,9 @@ + + + + MassageBreasts + CRIALactation.JobDriver_MassageBreasts + stimulating TargetA's breasts. + true + + diff --git a/CRIALactation/Defs/WorkGiverDefs/WorkGiver_MassageBreasts.xml b/CRIALactation/Defs/WorkGiverDefs/WorkGiver_MassageBreasts.xml new file mode 100644 index 0000000..b1dee55 --- /dev/null +++ b/CRIALactation/Defs/WorkGiverDefs/WorkGiver_MassageBreasts.xml @@ -0,0 +1,15 @@ + + + + MassageBreasts + + CRIALactation.WorkGiver_MassageBreasts + Handling + massage + stimulating the breasts of + 91 + +
  • Manipulation
  • +
    +
    +
    diff --git a/CRIALactation/Patches/Patch_LactationInduction.xml b/CRIALactation/Patches/Patch_LactationInduction.xml new file mode 100644 index 0000000..fb63d15 --- /dev/null +++ b/CRIALactation/Patches/Patch_LactationInduction.xml @@ -0,0 +1,28 @@ + + + + Always + +
  • + /Defs/ThingDef/comps + Always + + /Defs/ThingDef + + + + +
  • + +
  • + /Defs/ThingDef[@Name="BasePawn"]/comps + +
  • + 15 + 2.5 +
  • + + +
    +
    +
    diff --git a/CRIALactation/Source/CompProperties/CompProperties_InduceLactation.cs b/CRIALactation/Source/CompProperties/CompProperties_InduceLactation.cs new file mode 100644 index 0000000..9c119b2 --- /dev/null +++ b/CRIALactation/Source/CompProperties/CompProperties_InduceLactation.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; +using rjw; +using Milk; +using UnityEngine; + +namespace CRIALactation +{ + public class CompProperties_InduceLactation : CompProperties + { + public CompProperties_InduceLactation() + { + this.compClass = typeof(CompInduceLactation); + } + + public float DaysToLactating = 15; + public float TimesMassagedADay = 2.5f; + } +} diff --git a/CRIALactation/Source/Comps/CompInduceLactation.cs b/CRIALactation/Source/Comps/CompInduceLactation.cs new file mode 100644 index 0000000..2695ffc --- /dev/null +++ b/CRIALactation/Source/Comps/CompInduceLactation.cs @@ -0,0 +1,131 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; +using rjw; +using Milk; +using UnityEngine; + +namespace CRIALactation +{ + public class CompInduceLactation : ThingComp + { + private readonly int OneDayInTicks = 60000; + private int TicksSinceLastMassage = -60000; + + private float InductionCompletionPercent = 0f; + public bool isActive = false; + public bool CanMassage = true; + + public override void CompTick() + { + base.CompTick(); + Pawn p = this.parent as Pawn; + + if (!isActive) + { + return; + } + if (!p.IsHashIntervalTick(100)) + { + return; + } + + if (LactationUtility.IsLactating(p)) + { + isActive = false; + return; + } + + if(TicksSinceLastMassage + OneDayInTicks / Props.TimesMassagedADay < GenTicks.TicksGame) + { + CanMassage = true; + } + + if(InductionCompletionPercent >= 1) + { + string main = p.Name.ToStringShort + "'s breasts have been stimulated enough to induce lactation! They can now begin producing milk for their colony's consumption."; + + var letter = LetterMaker.MakeLetter(p.Name.ToStringShort + " induced lactation", main, LetterDefOf.PositiveEvent); + Find.LetterStack.ReceiveLetter(letter); + + LactationUtility.StartLactating(p, true); + isActive = false; + InductionCompletionPercent = 0.6f; //start at 60% in case they ever lose lactating again + } + } + + public void MassageBreasts() + { + InductionCompletionPercent += (float)1 / (Props.DaysToLactating * (Props.TimesMassagedADay + Rand.Value)); + TicksSinceLastMassage = GenTicks.TicksGame; + CanMassage = false; + } + + public CompProperties_InduceLactation Props + { + get + { + return (CompProperties_InduceLactation)props; + } + } + + public override IEnumerable CompFloatMenuOptions(Pawn pawn) + { + if (pawn != this.parent as Pawn) yield break; + if (LactationUtility.IsLactating(pawn)) yield break; + if(LactationUtility.HasMilkableBreasts(this.parent as Pawn)) + { + if(isActive) + { + //stop trying to induce lactation + yield return new FloatMenuOption("Undesignate induce lactation", () => + { + isActive = false; + }); + } + else + { + //induce lactation + yield return new FloatMenuOption("Designate induce lactation", () => + { + isActive = true; + }); + } + } + else + { + yield return new FloatMenuOption("Designate induce lactation (no milkable breasts)", null); + } + + yield break; + } + + public override void PostExposeData() + { + base.PostExposeData(); + Scribe_Values.Look(ref this.InductionCompletionPercent, "InductionCompletionPercent", 0f); + Scribe_Values.Look(ref this.TicksSinceLastMassage, "TicksSinceLastMassage", -60000); + + Scribe_Values.Look(ref this.isActive, "IsActive", false); + Scribe_Values.Look(ref this.CanMassage, "CanMassage", false); + + } + + public override string CompInspectStringExtra() + { + if (!isActive) return null; + + string result = "Induce lactation completion: " + InductionCompletionPercent.ToStringPercent(); + + if(CanMassage) + { + result += "\nReady to massage."; + } + + return result; + } + } +} diff --git a/CRIALactation/Source/JobDefOf/JobDefOf_CRIALactation.cs b/CRIALactation/Source/JobDefOf/JobDefOf_CRIALactation.cs new file mode 100644 index 0000000..7aa204d --- /dev/null +++ b/CRIALactation/Source/JobDefOf/JobDefOf_CRIALactation.cs @@ -0,0 +1,21 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; + +namespace CRIALactation +{ + [DefOf] + public static class JobDefOf_CRIALactation + { + static JobDefOf_CRIALactation() + { + DefOfHelper.EnsureInitializedInCtor(typeof(HediffDefOf_Milk)); + } + + public static JobDef MassageBreasts; + } +} diff --git a/CRIALactation/Source/JobDrivers/JobDriver_MassageBreasts.cs b/CRIALactation/Source/JobDrivers/JobDriver_MassageBreasts.cs new file mode 100644 index 0000000..4092ef0 --- /dev/null +++ b/CRIALactation/Source/JobDrivers/JobDriver_MassageBreasts.cs @@ -0,0 +1,79 @@ +using Milk; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; +using Verse.AI; + +namespace CRIALactation +{ + public class JobDriver_MassageBreasts : JobDriver + { + private readonly float WorkTotal = 300f; + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + LocalTargetInfo Target = job.GetTarget(TargetIndex.A); + return pawn.Reserve(Target, job, 1, -1, null, errorOnFailed); + } + + protected override IEnumerable MakeNewToils() + { + this.FailOnDespawnedNullOrForbidden(TargetIndex.A); + yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch); + Toil massage = new Toil(); + massage.FailOnDespawnedOrNull(TargetIndex.A); + massage.FailOnAggroMentalStateAndHostile(TargetIndex.A); + massage.initAction = delegate + { + Pawn p = job.GetTarget(TargetIndex.A).Thing as Pawn; + pawn.pather.StopDead(); + PawnUtility.ForceWait(p, 15000, null, true); + }; + massage.tickAction = delegate () + { + pawn.skills.Learn(SkillDefOf.Animals, 0.13f, false); + massageProgress += pawn.GetStatValue(StatDefOf.AnimalGatherSpeed, true); + + }; + massage.AddEndCondition(delegate + { + Pawn p = job.GetTarget(TargetIndex.A).Thing as Pawn; + if (massageProgress >= WorkTotal) + { + p.TryGetComp().MassageBreasts(); + return JobCondition.Succeeded; + } + + if (!(p.TryGetComp().isActive && p.TryGetComp().CanMassage)) + { + return JobCondition.Incompletable; + } + + return JobCondition.Ongoing; + + }); + + massage.AddFinishAction(delegate { + Pawn pawn = this.job.GetTarget(TargetIndex.A).Thing as Pawn; + if (pawn != null && pawn.CurJobDef == JobDefOf.Wait_MaintainPosture) + { + pawn.jobs.EndCurrentJob(JobCondition.InterruptForced, true, true); + } + }); + massage.defaultCompleteMode = ToilCompleteMode.Never; + + massage.WithProgressBar(TargetIndex.A, () => massageProgress / WorkTotal); + massage.activeSkill = (() => SkillDefOf.Animals); + yield return massage; + yield break; + + } + + float massageProgress = 0f; + } +} diff --git a/CRIALactation/Source/LactationUtility.cs b/CRIALactation/Source/LactationUtility.cs index 00e0246..12ee7d0 100644 --- a/CRIALactation/Source/LactationUtility.cs +++ b/CRIALactation/Source/LactationUtility.cs @@ -38,5 +38,17 @@ namespace CRIALactation lactating.Severity = Rand.Value; p.health.AddHediff(lactating, Genital_Helper.get_breastsBPR(p)); } + + public static bool isMassageable(Pawn p) + { + CompInduceLactation c = p.TryGetComp(); + if (c != null && c.isActive && c.CanMassage) + { + return true; + } + + return false; + + } } } diff --git a/CRIALactation/Source/WorkGivers/WorkGiver_MassageBreasts.cs b/CRIALactation/Source/WorkGivers/WorkGiver_MassageBreasts.cs new file mode 100644 index 0000000..db54550 --- /dev/null +++ b/CRIALactation/Source/WorkGivers/WorkGiver_MassageBreasts.cs @@ -0,0 +1,56 @@ +using Milk; +using RimWorld; +using RimWorld.Planet; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; + +namespace CRIALactation +{ + public class WorkGiver_MassageBreasts : WorkGiver_Scanner + { + public override IEnumerable PotentialWorkThingsGlobal(Pawn pawn) + { + return pawn.Map.mapPawns.SpawnedPawnsInFaction(pawn.Faction); + } + + public override bool ShouldSkip(Pawn pawn, bool forced = false) + { + List list = pawn.Map.mapPawns.SpawnedPawnsInFaction(pawn.Faction); + for(int i = 0; i < list.Count; i++) + { + if(LactationUtility.isMassageable(list[i])) + { + return false; + } + } + + return true; + } + + public override bool HasJobOnThing(Pawn p, Thing t, bool forced = false) + { + Pawn pawn2 = t as Pawn; + if(pawn2?.TryGetComp() == null) + { + return false; + } + CompInduceLactation c = pawn2.TryGetComp(); + + return p != pawn2 && c.isActive && c.CanMassage && !pawn2.Downed && !pawn2.Drafted && !pawn2.InAggroMentalState && !pawn2.IsFormingCaravan() && pawn2.CanCasuallyInteractNow(false, true, false) && p.CanReserve(pawn2, 1, -1, null, forced); + + } + + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + return JobMaker.MakeJob(JobDefOf_CRIALactation.MassageBreasts, t); + } + + + } +}