2022-11-04 02:01:50 +00:00
using HarmonyLib ;
2022-11-04 14:08:59 +00:00
using System.Linq ;
2022-11-04 02:01:50 +00:00
using RimWorld ;
using Verse ;
2022-11-11 05:25:07 +00:00
using System.Collections.Generic ;
2022-11-22 06:21:38 +00:00
using System.Reflection ;
2023-01-11 15:32:50 +00:00
using System ;
using System.Reflection.Emit ;
2022-11-04 02:01:50 +00:00
namespace RJW_Menstruation
{
[HarmonyPatch(typeof(Hediff_Pregnant), "Miscarry")]
public class Miscarry_Patch
{
public static void Postfix ( Hediff_Pregnant __instance )
{
HediffComp_Menstruation comp = __instance . GetMenstruationCompFromPregnancy ( ) ;
if ( comp = = null ) return ;
comp . Pregnancy = null ;
}
}
[HarmonyPatch(typeof(Hediff_Pregnant), nameof(Hediff_Pregnant.StartLabor))]
public class StartLabor_Patch
{
public static void Postfix ( Hediff_Pregnant __instance )
{
HediffComp_Menstruation comp = __instance . GetMenstruationCompFromPregnancy ( ) ;
if ( comp = = null ) return ;
comp . Pregnancy = __instance . pawn . health . hediffSet . GetFirstHediffOfDef ( HediffDefOf . PregnancyLabor ) ;
}
}
[HarmonyPatch(typeof(Hediff_Labor), nameof(Hediff_Labor.PreRemoved))]
public class Labor_PreRemoved_Patch
{
2023-03-13 00:27:04 +00:00
public static void Postfix ( Hediff_Labor __instance )
2022-11-04 02:01:50 +00:00
{
HediffComp_Menstruation comp = __instance . GetMenstruationCompFromPregnancy ( ) ;
if ( comp = = null ) return ;
comp . Pregnancy = __instance . pawn . health . hediffSet . GetFirstHediffOfDef ( HediffDefOf . PregnancyLaborPushing ) ;
}
}
[HarmonyPatch(typeof(Hediff_LaborPushing), nameof(Hediff_LaborPushing.PreRemoved))]
public class LaborPushing_PreRemoved_Patch
{
2023-03-13 00:27:04 +00:00
public static void Postfix ( Hediff_LaborPushing __instance )
2022-11-04 02:01:50 +00:00
{
HediffComp_Menstruation comp = __instance . GetMenstruationCompFromPregnancy ( ) ;
if ( comp = = null ) return ;
comp . Pregnancy = null ;
}
}
2022-11-04 14:08:59 +00:00
// Prevents a pregnancy from going into labor if another pregnancy already is
[HarmonyPatch(typeof(Hediff_Pregnant), nameof(Hediff_Pregnant.GestationProgress), MethodType.Getter)]
public class Hediff_Pregnant_GestationProgess_Patch
{
2023-03-13 00:27:04 +00:00
public static void Postfix ( Hediff_Pregnant __instance , ref float __result )
2022-11-04 14:08:59 +00:00
{
if ( __result < 1f ) return ;
Pawn pawn = __instance . pawn ;
if ( pawn . health . hediffSet . hediffs . Any ( hediff = > hediff . def = = HediffDefOf . PregnancyLabor | | hediff . def = = HediffDefOf . PregnancyLaborPushing ) )
__result = 0.999f ;
}
}
2022-11-11 05:25:07 +00:00
[HarmonyPatch(typeof(Recipe_ExtractOvum), nameof(Recipe_ExtractOvum.AvailableReport))]
public class ExtractOvum_AvailableReport_Patch
{
2023-03-13 00:27:04 +00:00
public static void Postfix ( Thing thing , ref AcceptanceReport __result )
2022-11-11 05:25:07 +00:00
{
if ( ! __result . Accepted ) return ;
Pawn pawn = ( Pawn ) thing ;
if ( pawn . IsRJWPregnant ( ) )
{
__result = "CannotPregnant" . Translate ( ) ;
return ;
}
List < HediffComp_Menstruation > comps = pawn . GetMenstruationComps ( ) . ToList ( ) ;
if ( ! comps . Any ( ) ) return ;
if ( comps . All ( comp = > comp . ovarypower < = 0 ) )
{
__result = Translations . CannotNoEggs ;
return ;
}
return ;
}
}
2022-11-11 05:46:42 +00:00
[HarmonyPatch(typeof(Recipe_ExtractOvum), "OnSurgerySuccess")]
public class ExtractOvum_OnSurgerySuccess_Patch
{
2023-03-13 00:27:04 +00:00
public static void Postfix ( Pawn pawn )
2022-11-11 05:46:42 +00:00
{
List < HediffComp_Menstruation > comps = pawn . GetMenstruationComps ( ) . ToList ( ) ;
if ( ! comps . Any ( ) ) return ;
HediffComp_Menstruation mostEggs = comps . MaxBy ( comp = > comp . ovarypower ) ;
if ( mostEggs . ovarypower < = 0 ) return ; // Shouldn't happen
mostEggs . ovarypower - - ;
}
}
2022-11-11 05:50:31 +00:00
[HarmonyPatch(typeof(Recipe_ImplantEmbryo), nameof(Recipe_ImplantEmbryo.ApplyOnPawn))]
public class ImplantEmbryo_ApplyOnPawn_Patch
{
2023-03-13 00:27:04 +00:00
public static void Postfix ( Pawn pawn )
2022-11-11 05:50:31 +00:00
{
foreach ( HediffComp_Menstruation comp in pawn . GetMenstruationComps ( ) )
comp . TakeLoosePregnancy ( ) ;
}
}
2022-11-22 06:21:38 +00:00
2022-11-24 15:12:30 +00:00
[HarmonyPatch(typeof(PregnancyUtility), nameof(PregnancyUtility.ApplyBirthOutcome))]
2023-01-08 18:11:58 +00:00
public class ApplyBirthOutcome_Breast_Patch
2022-11-24 15:12:30 +00:00
{
2023-03-13 00:27:04 +00:00
public static void Postfix ( Thing birtherThing )
2022-11-24 15:12:30 +00:00
{
2023-04-18 14:20:35 +00:00
if ( birtherThing is Pawn pawn & & ! pawn . Dead )
2022-11-24 15:12:30 +00:00
pawn . GetBreastComp ( ) ? . GaveBirth ( ) ;
}
}
2023-01-11 15:32:50 +00:00
[HarmonyPatch]
public class TerminatePregnancy_Patch
2022-11-22 06:21:38 +00:00
{
2023-01-11 15:32:50 +00:00
public static IEnumerable < MethodBase > TargetMethods ( )
{
yield return AccessTools . Method ( typeof ( PregnancyUtility ) , nameof ( PregnancyUtility . TryTerminatePregnancy ) ) ;
yield return AccessTools . Method ( typeof ( Recipe_TerminatePregnancy ) , nameof ( Recipe_TerminatePregnancy . ApplyOnPawn ) ) ;
}
private static PregnancyAttitude ? GetAttitude ( Hediff pregnancy )
{
if ( pregnancy is Hediff_Pregnant preg ) return preg . Attitude ;
else return null ;
}
2022-11-22 06:21:38 +00:00
private static Hediff GetEarliestPregnancy ( Pawn pawn )
{
Hediff Earliest_Pregnancy = PregnancyUtility . GetPregnancyHediff ( pawn ) ;
foreach ( HediffComp_Menstruation comp in pawn . GetMenstruationComps ( ) )
{
Hediff pregnancy = comp . Pregnancy ;
if ( pregnancy = = null ) continue ;
if ( Earliest_Pregnancy = = null | | Earliest_Pregnancy . Severity > pregnancy . Severity ) Earliest_Pregnancy = pregnancy ;
}
2022-12-25 03:44:07 +00:00
2022-11-22 06:21:38 +00:00
return Earliest_Pregnancy ;
}
2023-01-11 15:32:50 +00:00
private static readonly MethodInfo GetPregnancyHediff = AccessTools . Method ( typeof ( PregnancyUtility ) , nameof ( PregnancyUtility . GetPregnancyHediff ) , new Type [ ] { typeof ( Pawn ) } ) ;
private static readonly MethodInfo Get_Attitude = AccessTools . DeclaredPropertyGetter ( typeof ( Hediff_Pregnant ) , nameof ( Hediff_Pregnant . Attitude ) ) ;
2022-11-22 06:21:38 +00:00
public static IEnumerable < CodeInstruction > Transpiler ( IEnumerable < CodeInstruction > instructions )
{
2023-01-11 15:32:50 +00:00
if ( GetPregnancyHediff = = null | | GetPregnancyHediff . ReturnType ! = typeof ( Hediff ) ) throw new InvalidOperationException ( "GetPregnancyHediff not found" ) ;
if ( Get_Attitude = = null | | Nullable . GetUnderlyingType ( Get_Attitude . ReturnType ) ! = typeof ( PregnancyAttitude ) ) throw new InvalidOperationException ( "get_Attitude not found" ) ;
2022-11-22 06:21:38 +00:00
foreach ( CodeInstruction instruction in instructions )
{
if ( instruction . Calls ( GetPregnancyHediff ) )
2023-01-11 15:32:50 +00:00
yield return CodeInstruction . Call ( typeof ( TerminatePregnancy_Patch ) , nameof ( TerminatePregnancy_Patch . GetEarliestPregnancy ) ) ;
// Menstruation pregnancies don't have an attitude, so skip the cast to Hediff_Pregnant and call a version that handles it
else if ( instruction . opcode = = OpCodes . Castclass & & ( Type ) instruction . operand = = typeof ( Hediff_Pregnant ) )
yield return new CodeInstruction ( OpCodes . Nop ) ;
else if ( instruction . Calls ( Get_Attitude ) )
yield return CodeInstruction . Call ( typeof ( TerminatePregnancy_Patch ) , nameof ( TerminatePregnancy_Patch . GetAttitude ) ) ;
2022-11-22 06:21:38 +00:00
else yield return instruction ;
}
}
2023-01-11 15:32:50 +00:00
}
2022-11-22 06:21:38 +00:00
2023-01-11 15:32:50 +00:00
[HarmonyPatch(typeof(PregnancyUtility), nameof(PregnancyUtility.TryTerminatePregnancy))]
public class PregnancyUtility_TryTerminatePregnancy_Patch
{
2022-11-22 06:21:38 +00:00
public static void Postfix ( bool __result , Pawn pawn )
{
if ( __result )
foreach ( HediffComp_Menstruation comp in pawn . GetMenstruationComps ( ) )
_ = comp . Pregnancy ; // get_Pregnancy will remove the hediff attached to the comp that doesn't have it anymore
}
}
[HarmonyPatch(typeof(Recipe_TerminatePregnancy), nameof(Recipe_TerminatePregnancy.AvailableOnNow))]
public class TerminatePregnancy_AvailableOnNow_Patch
{
public static void Postfix ( ref bool __result , Thing thing )
{
if ( ! ModsConfig . BiotechActive | | ! ( thing is Pawn pawn ) ) return ;
__result | = pawn . GetMenstruationComps ( ) . Any ( comp = > comp . Pregnancy ! = null ) ;
}
}
2023-04-09 15:48:51 +00:00
[HarmonyPatch(typeof(Pawn_GeneTracker), "AddGene", new Type[] { typeof ( Gene ) , typeof ( bool ) } ) ]
2023-01-22 17:44:28 +00:00
public class AddGene_Patch
{
public static bool Prefix ( ref Gene __result , Gene gene , Pawn ___pawn )
{
2023-04-09 15:48:51 +00:00
if ( ! VariousDefOf . WombGenes . Contains ( gene . def ) ) return true ;
bool keepGene ;
if ( PawnGenerator . IsBeingGenerated ( ___pawn ) )
2023-04-10 22:32:51 +00:00
// During pawn generation, the vagina hediff doesn't exist yet, so use gender to decide instead
2023-04-09 15:48:51 +00:00
// Not the most accurate, but close enough
keepGene = ___pawn . gender = = Gender . Female ;
else keepGene = ___pawn . GetMenstruationComps ( ) . Any ( ) ;
if ( ! keepGene ) __result = null ;
return keepGene ;
2023-01-22 17:44:28 +00:00
}
}
2023-04-10 22:32:51 +00:00
[HarmonyPatch(typeof(Pawn_GeneTracker), "Notify_GenesChanged")]
2023-01-04 06:48:06 +00:00
public class Notify_GenesChanged_Patch
{
public static void Postfix ( Pawn_GeneTracker __instance )
{
foreach ( HediffComp_Menstruation comp in __instance . pawn . GetMenstruationComps ( ) )
comp . Notify_UpdatedGenes ( ) ;
}
}
2023-03-02 01:00:58 +00:00
//[HarmonyPatch(typeof(ChildcareUtility), nameof(ChildcareUtility.SuckleFromLactatingPawn))]
//public class GreedyConsume_Patch
//{
// private static float ConsumeAndAdjustNipples(HediffComp_Chargeable instance, float desiredCharge)
// {
// // Pulling breast comp every tick might be too much for performance.
// const float averageNippleChangePerTick = 0.0025f / 50000f;
// instance.Pawn.GetBreastComp()?.AdjustNippleProgress(Rand.Range(0.0f, averageNippleChangePerTick * 2) * Configurations.MaxBreastIncrementFactor);
// return instance.GreedyConsume(desiredCharge);
// }
// private static readonly MethodInfo GreedyConsume = AccessTools.Method(typeof(HediffComp_Chargeable), nameof(HediffComp_Chargeable.GreedyConsume), new Type[] { typeof(HediffComp_Chargeable), typeof(float) });
// public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
// {
// if(GreedyConsume == null) throw new InvalidOperationException("GreedyConsume not found");
// foreach (var instruction in instructions)
// {
// if (instruction.Calls(GreedyConsume))
// yield return CodeInstruction.Call(typeof(GreedyConsume_Patch), nameof(GreedyConsume_Patch.ConsumeAndAdjustNipples));
// yield return instruction;
// }
// }
//}
2022-11-04 02:01:50 +00:00
}