Merge 1.0.6.3

This commit is contained in:
lutepickle 2022-05-29 20:33:47 -07:00
commit ca70b0b1d4
11 changed files with 85 additions and 47 deletions

Binary file not shown.

View File

@ -1,4 +1,5 @@
using Verse;
using RimWorld;
using Verse;
#pragma warning disable IDE0051 // Remove unused private members
namespace RJW_Menstruation
@ -9,24 +10,28 @@ namespace RJW_Menstruation
private static void SetFollicular(Pawn p)
{
p.GetMenstruationComp().curStage = HediffComp_Menstruation.Stage.Follicular;
Messages.Message($"{p} is now follicular", MessageTypeDefOf.NeutralEvent, false);
}
[DebugAction("RJW Menstruation", "Set pawn's state to ovulatory", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void SetOvulatory(Pawn p)
{
p.GetMenstruationComp().curStage = HediffComp_Menstruation.Stage.Ovulatory;
Messages.Message($"{p} is now ovulatory", MessageTypeDefOf.NeutralEvent, false);
}
[DebugAction("RJW Menstruation", "Set pawn's state to luteal", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void SetLuteal(Pawn p)
{
p.GetMenstruationComp().curStage = HediffComp_Menstruation.Stage.Luteal;
Messages.Message($"{p} is now luteal", MessageTypeDefOf.NeutralEvent, false);
}
[DebugAction("RJW Menstruation", "Set pawn's state to bleeding", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void SetBleeding(Pawn p)
{
p.GetMenstruationComp().curStage = HediffComp_Menstruation.Stage.Bleeding;
Messages.Message($"{p} is now bleeding", MessageTypeDefOf.NeutralEvent, false);
}
/*
[DebugAction("RJW Menstruation", "Set pawn's state to recovering", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
@ -45,17 +50,20 @@ namespace RJW_Menstruation
private static void RemoveCums(Pawn p)
{
p.GetMenstruationComp().RemoveAllCums();
Messages.Message($"All cum removed from {p}'s womb", MessageTypeDefOf.NeutralEvent, false);
}
[DebugAction("RJW Menstruation", "Add egg to pawn's next ovulation", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void AddEgg(Pawn p)
{
p.GetMenstruationComp().eggstack++;
Messages.Message($"1 egg added to {p}'s next ovulation ({p.GetMenstruationComp().eggstack})", MessageTypeDefOf.NeutralEvent, false);
}
[DebugAction("RJW Menstruation", "Recalculate pawn's ovary power", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void RecalculateOvaryPower(Pawn p)
{
p.GetMenstruationComp().ovarypower = p.GetMenstruationComp().GetOvaryPowerByAge(p);
Messages.Message($"{p}'s ovarypower recalculated ({p.GetMenstruationComp().ovarypower})", MessageTypeDefOf.NeutralEvent, false);
}
}
}

View File

@ -56,14 +56,18 @@ namespace RJW_Menstruation
{
if (parent.pawn.health.hediffSet.HasHediff(VariousDefOf.RJW_IUD)) return false;
if (curStage == Stage.Follicular || curStage == Stage.ClimactericFollicular) return true;
else if (curStage == Stage.Luteal || curStage == Stage.ClimactericLuteal)
switch (curStage)
{
if (!IsEggExist) return false;
else return curStageHrs < Props.eggLifespanDays * 24;
case Stage.Follicular:
case Stage.ClimactericFollicular:
case Stage.Ovulatory:
return true;
case Stage.Luteal:
case Stage.ClimactericLuteal:
return IsEggExist && curStageHrs < Props.eggLifespanDays * 24;
default:
return false;
}
else if (curStage == Stage.Ovulatory) return true;
return false;
}
}

View File

@ -213,9 +213,7 @@ namespace RJW_Menstruation
{
float factor = 1.0f;
if (parent.pawn.Has(Quirk.Breeder)) factor = 10.0f;
//if (xxx.is_animal(parent.pawn)) factor *= RJWPregnancySettings.animal_impregnation_chance / 100f;
//else factor *= RJWPregnancySettings.humanlike_impregnation_chance / 100f;
return parent.pawn.health.capacities.GetLevel(xxx.reproduction) * factor;
return parent.pawn.health.capacities.GetLevel(xxx.reproduction) * Props.baseImplantationChanceFactor * factor;
}
}
public IEnumerable<string> GetCumsInfo
@ -397,16 +395,19 @@ namespace RJW_Menstruation
{
if (parent.pawn.health.hediffSet.HasHediff(VariousDefOf.RJW_IUD)) return false;
if (curStage == Stage.Follicular || curStage == Stage.ClimactericFollicular)
switch (curStage)
{
if (curStageHrs > 0.7f * (follicularIntervalhours - bleedingIntervalhours)) return true;
case Stage.Follicular:
case Stage.ClimactericFollicular:
return curStageHrs > 0.7f * (follicularIntervalhours - bleedingIntervalhours);
case Stage.Ovulatory:
return true;
case Stage.Luteal:
case Stage.ClimactericLuteal:
return curStageHrs < Props.eggLifespanDays * 24;
default:
return false;
}
else if (curStage == Stage.Luteal || curStage == Stage.ClimactericLuteal)
{
if (curStageHrs < Props.eggLifespanDays * 24) return true;
}
else if (curStage == Stage.Ovulatory) return true;
return false;
}
}
public int GetNumofEggs
@ -890,6 +891,7 @@ namespace RJW_Menstruation
{
follicularIntervalhours = PeriodRandomizer(Props.folicularIntervalDays * 24, Props.deviationFactor);
if (parent.pawn.health.capacities.GetLevel(xxx.reproduction) <= 0) curStage = Stage.Young;
else if (!IsBreedingSeason()) curStage = Stage.Anestrus;
else curStage = RandomStage();
}
@ -1030,10 +1032,7 @@ namespace RJW_Menstruation
public void SetEstrus(int days)
{
HediffDef estrusdef;
if (Props.concealedEstrus) estrusdef = VariousDefOf.Hediff_Estrus_Concealed;
else estrusdef = VariousDefOf.Hediff_Estrus;
HediffDef estrusdef = Props.concealedEstrus ? VariousDefOf.Hediff_Estrus_Concealed : VariousDefOf.Hediff_Estrus;
HediffWithComps hediff = (HediffWithComps)parent.pawn.health.hediffSet.GetFirstHediffOfDef(estrusdef);
if (hediff != null)
{
@ -1098,7 +1097,7 @@ namespace RJW_Menstruation
foreach (Egg egg in eggs)
{
if (!egg.fertilized || egg.fertstage < 168) continue;
else if (Rand.Range(0.0f, 1.0f) <= Configurations.ImplantationChance * Props.baseImplantationChanceFactor * ImplantFactor * InterspeciesImplantFactor(egg.fertilizer))
else if (Rand.Range(0.0f, 1.0f) <= Configurations.ImplantationChance * ImplantFactor * InterspeciesImplantFactor(egg.fertilizer))
{
Hediff_BasePregnancy pregnancy = parent.pawn.GetRJWPregnancy();
if (pregnancy != null)

View File

@ -89,11 +89,21 @@ namespace RJW_Menstruation
public const float buttonWidth = 50f;
public const float buttonHeight = 20f;
private static HediffComp_Menstruation GetFirstMenstruation(IEnumerable<Hediff> diffs, float rectWidth)
{
foreach (Hediff diff in diffs)
{
HediffComp_Menstruation comp = diff.GetMenstruationComp();
if (comp != null) return comp;
}
return null;
}
public static void Prefix(Rect rect, Pawn pawn, IEnumerable<Hediff> diffs, ref float curY)
{
if (Configurations.EnableButtonInHT && pawn.ShowStatus())
{
HediffComp_Menstruation comp = diffs.First().GetMenstruationComp();
HediffComp_Menstruation comp = GetFirstMenstruation(diffs, rect.width * 0.625f);
if (comp != null)
{
Rect buttonrect = new Rect((rect.xMax) / 2 - 5f, curY + 2f, buttonWidth, buttonHeight);

View File

@ -195,16 +195,17 @@ namespace RJW_Menstruation
private static readonly FieldInfo MinimumFuckabilityToHookup = AccessTools.Field(typeof(RJWHookupSettings), nameof(RJWHookupSettings.MinimumFuckabilityToHookup));
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
// We only want the first fuckability check, i.e. the estrus-haver towards a partner
bool found_fuckability = false;
bool first_fuckability = true;
foreach(CodeInstruction instruction in instructions)
{
if(!found_fuckability && instruction.LoadsField(MinimumFuckabilityToHookup))
if(instruction.LoadsField(MinimumFuckabilityToHookup))
{
found_fuckability = true;
yield return new CodeInstruction(OpCodes.Ldarg_0);
yield return new CodeInstruction(OpCodes.Ldarg_1);
// The first load will be for the estrus-haver considering a partner, the second for a pawn considering the estrus-haver
yield return new CodeInstruction(first_fuckability ? OpCodes.Ldarg_0 : OpCodes.Ldarg_1);
yield return new CodeInstruction(first_fuckability ? OpCodes.Ldarg_1 : OpCodes.Ldarg_0);
yield return CodeInstruction.Call(typeof(Roll_To_Skip_Patch), nameof(FuckabilityThreshold));
first_fuckability = false;
}
else yield return instruction;
}
@ -229,31 +230,39 @@ namespace RJW_Menstruation
private static readonly FieldInfo MinimumRelationshipToHookup = AccessTools.Field(typeof(RJWHookupSettings), nameof(RJWHookupSettings.MinimumRelationshipToHookup));
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
object pawn_index = null;
// Like in the last one, we're only interested in the first of each
bool found_first_attractiveness = false;
bool found_first_relationship = false;
LocalBuilder pawn_index = null;
// Like in the last one, we switch the arguments around for the second load
bool first_attractiveness = true;
bool first_relationship = true;
foreach(CodeInstruction instruction in instructions)
{
// Get where the compiler decided to index the pawn at
if (pawn_index is null && instruction.opcode == OpCodes.Stloc_S) // the first stloc.s in the IL is the pawn being loaded out of the list
{ // a future RJW or compiler update might change this, or maybe another mod's patch
pawn_index = instruction.operand;
pawn_index = (LocalBuilder)instruction.operand;
yield return instruction;
}
else if (!found_first_attractiveness && instruction.LoadsField(MinimumAttractivenessToHookup))
else if (instruction.LoadsField(MinimumAttractivenessToHookup))
{
found_first_attractiveness = true;
yield return new CodeInstruction(OpCodes.Ldarg_0);
yield return new CodeInstruction(OpCodes.Ldloc_S, pawn_index);
if (pawn_index?.LocalType != typeof(Pawn))
throw new System.InvalidOperationException($"pawn_index is not a Pawn ({pawn_index?.LocalType})");
yield return first_attractiveness ? new CodeInstruction(OpCodes.Ldarg_0) : new CodeInstruction(OpCodes.Ldloc_S, pawn_index);
yield return first_attractiveness ? new CodeInstruction(OpCodes.Ldloc_S, pawn_index) : new CodeInstruction(OpCodes.Ldarg_0);
yield return CodeInstruction.Call(typeof(FindBestPartner_Patch), nameof(AttractivenessThreshold));
}
else if (!found_first_relationship && instruction.LoadsField(MinimumRelationshipToHookup))
first_attractiveness = false;
}
else if (instruction.LoadsField(MinimumRelationshipToHookup))
{
found_first_relationship = true;
yield return new CodeInstruction(OpCodes.Ldarg_0);
yield return new CodeInstruction(OpCodes.Ldloc_S, pawn_index);
if (pawn_index?.LocalType != typeof(Pawn))
throw new System.InvalidOperationException($"pawn_index is not a Pawn ({pawn_index?.LocalType})");
yield return first_relationship ? new CodeInstruction(OpCodes.Ldarg_0) : new CodeInstruction(OpCodes.Ldloc_S, pawn_index);
yield return first_relationship ? new CodeInstruction(OpCodes.Ldloc_S, pawn_index) : new CodeInstruction(OpCodes.Ldarg_0);
yield return CodeInstruction.Call(typeof(FindBestPartner_Patch), nameof(RelationshipThreshold));
first_relationship = false;
}
else yield return instruction;
}

View File

@ -426,7 +426,7 @@ namespace RJW_Menstruation
lineRect.y += height;
}
statvalue = Configurations.ImplantationChance * comp.Props.baseImplantationChanceFactor * comp.ImplantFactor;
statvalue = Configurations.ImplantationChance * comp.ImplantFactor;
float fertchance = comp.GetFertilityChance();
FillableBarLabeled(lineRect, " " + xxx.reproduction.LabelCap.CapitalizeFirst() + " " + statvalue.ToStringPercent(), statvalue, TextureCache.FertilityTexture, Texture2D.blackTexture, Translations.FertilityDesc(String.Format("{0:0.##}", fertchance*100)));
Rect overayRect = new Rect(lineRect.x, lineRect.y, lineRect.width * Math.Min(1.0f, fertchance), lineRect.height);

View File

@ -458,7 +458,7 @@ namespace RJW_Menstruation
public static bool ShouldShowWombGizmo(this Pawn pawn)
{
if (Configurations.EnableWombIcon && pawn.gender == Gender.Female)
if (Configurations.EnableWombIcon)
{
if (!pawn.IsAnimal())
{

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Manifest>
<identifier>RJW Menstruation</identifier>
<version>1.0.6.2</version>
<version>1.0.6.3</version>
<dependencies>
</dependencies>
<incompatibleWith />

View File

@ -1,3 +1,11 @@
Version 1.0.6.3
- Fix pawn generation for races with a single lifestage.
- Show womb gizmo for males with vaginas, too.
- Originally, the casual hookup override only applied to a pawn searching for a partner. It will now also apply to a partner deciding whether to accept a hookup.
- Message feedback added to debug actions.
- Show the status button in the health tab for pawns with more than one genital.
- Known issue: The status button will be next to the first genital instead of the vagina.
Version 1.0.6.2
- Fix error/crash when a pawn in estrus (with hookup override enabled) looks for partners.
- Teratophiles get the "I came inside" mood buff for ugly partners instead of pretty ones.