diff --git a/1.4/Defs/GeneDefs/GeneDefs_Menstruation.xml b/1.4/Defs/GeneDefs/GeneDefs_Menstruation.xml
index bc136a5..9733ab0 100644
--- a/1.4/Defs/GeneDefs/GeneDefs_Menstruation.xml
+++ b/1.4/Defs/GeneDefs/GeneDefs_Menstruation.xml
@@ -73,7 +73,7 @@
Menstruation_DoubleOvulation
- Carriers of this gene will ovulate twice as many eggs.
+ Wombs with this gene will ovulate twice as many eggs.
-1
30
@@ -81,7 +81,7 @@
Menstruation_QuadOvulation
- Carriers of this gene will ovulate four times as many eggs.
+ Wombs with this gene will ovulate four times as many eggs.
-1
35
@@ -90,7 +90,7 @@
Menstruation_NoBleeding
Menstruation
- Carriers of this gene will not bleed at the end of their cycle.
+ Wombs with this gene will not bleed at the end of their cycle.
1
40
diff --git a/1.4/Languages/ChineseTraditional/DefInjected/GeneDefs/GeneDefs_Menstruation.xml b/1.4/Languages/ChineseTraditional/DefInjected/GeneDefs/GeneDefs_Menstruation.xml
deleted file mode 100644
index 377a6b5..0000000
--- a/1.4/Languages/ChineseTraditional/DefInjected/GeneDefs/GeneDefs_Menstruation.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
- 月經週期
- 較短卵細胞壽命
- 未受精卵細胞存活時長僅有原先的3/4
- 雙倍卵細胞壽命
- 未受精卵細胞可存活至原先的2倍之久
- 四倍卵細胞壽命
- 未受精卵細胞可存活至原先的4倍之久
- 永不發情
- 基因攜帶者永遠不會進入發情期。
- 始終發情
- 基因攜帶者的每一個月經週期均具備發情期,無論陰道類型為何。
- 雙倍排卵
- 基因攜帶者的子宮可以在每個排卵週期產生雙倍的卵子。
- 四倍排卵
- 基因攜帶者的子宮可以在每個排卵週期產生四倍的卵子。
- 無經血
- 基因攜帶者的子宮內膜不會脫落出血。
-
diff --git a/1.4/Languages/ChineseTraditional/DefInjected/ThoughtDefs/Thoughts_sex.xml b/1.4/Languages/ChineseTraditional/DefInjected/ThoughtDefs/Thoughts_sex.xml
index b1eeb56..7cd43fc 100644
--- a/1.4/Languages/ChineseTraditional/DefInjected/ThoughtDefs/Thoughts_sex.xml
+++ b/1.4/Languages/ChineseTraditional/DefInjected/ThoughtDefs/Thoughts_sex.xml
@@ -8,7 +8,4 @@
總算把這事了結了。
吃了避孕藥
我想要小孩!
-
- 卵母細胞再生術
- 我可以繼續繁衍一小段時間了!
diff --git a/1.4/Languages/ChineseTraditional/Keyed/RJW_Menstruation.xml b/1.4/Languages/ChineseTraditional/Keyed/RJW_Menstruation.xml
index c436751..1f4b8e7 100644
--- a/1.4/Languages/ChineseTraditional/Keyed/RJW_Menstruation.xml
+++ b/1.4/Languages/ChineseTraditional/Keyed/RJW_Menstruation.xml
@@ -37,7 +37,7 @@
月經加速
加快月經週期
除錯
- 顯示除錯資訊
啟用時會令「胎兒信息級別」選項調至「全部細節」。
+ 顯示除錯資訊
子宮狀態
在狀態窗口中繪製子宮圖標
陰道狀態
@@ -62,6 +62,7 @@
最大雙胞胎數量
設置最大雙胞胎數量
清洗陰道
+
絕經
乏情期
@@ -97,7 +98,7 @@
本模組作用於:
這些小人的「RJW月經週期」工具欄對玩家可見。
使用進階雜交定義
- 覆寫RJW和RaceSupport插件的雜交定義。Overrides RJW and RaceSupport's hybrid definition.
+ 複寫RJW和RaceSupport插件的雜交定義。Overrides RJW and RaceSupport's hybrid definition.
主導混合擴展決定了首先使用誰的定義。不建議更改此設置。Dominant hybrid extension determines whose definition used first. Not recommended to change this.
主導混合擴展Dominant hybrid extension
母本
@@ -110,7 +111,7 @@
乳頭在孕期間的改變會在孕期結束後保留多少?
客製化雜交細節
開啟雜交編輯器
-該選項會覆寫XML文件中的雜交定義。
+該選項會複寫XML文件中的雜交定義。
允許圖標縮小
允許圖標在特殊場合縮小。
卵細胞生命期乘數
@@ -122,7 +123,7 @@
擴張力度
調節擴張力度。
啟用「擠出精液」按鈕
- 令「發情期」機制覆寫RJW的濫交選項
+ 令「發情期」機制複寫RJW的濫交選項
啟用時,處於顯式發情期的小人將會使用以下選項來選定床伴。RJW的原始設定會被忽略。
所有數值與RJW的對應選項相同。
發情期床伴:最低fuckability
@@ -138,13 +139,4 @@
{0}之雜交
當{0}與{1}產生後代,有{3}的概率生出{2}。
若兩個種族相互間皆存在雜交定義,則以父本的定義為準。
-
- 使用RJW的簡單懷孕系統
- 使用本模組的多重懷孕
- 使用「生機」(Biotech)追加的懷孕機制
- 於「徵召」狀態下仍顯示子宮狀態
- 角色處於被徵召狀態時,子宮圖標不予隱藏。
- 沒有卵細胞
- 必須擁有子宮
- {PAWN_labelShort}完成了{PAWN_possessive}卵母細胞再生術(cycle)
diff --git a/1.4/Patches/Pregenerated_Babies.xml b/1.4/Patches/Pregenerated_Babies.xml
deleted file mode 100644
index 07d05b3..0000000
--- a/1.4/Patches/Pregenerated_Babies.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
- Biotech
-
-
- /Defs/HediffDef[defName="PregnantHuman" or defName="PregnancyLabor" or defName="PregnancyLaborPushing"]/comps
-
-
- RJW_Menstruation.HediffComp_PregeneratedBabies
-
-
-
-
-
\ No newline at end of file
diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PregeneratedBabies.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PregeneratedBabies.cs
deleted file mode 100644
index ef0e8ad..0000000
--- a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PregeneratedBabies.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-using RimWorld;
-using RimWorld.BaseGen;
-using rjw;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using Verse;
-
-namespace RJW_Menstruation
-{
- public class HediffComp_PregeneratedBabies : HediffComp
- {
- public List babies;
- // Unused, but can't hurt to track
- protected Dictionary enzygoticSiblings;
-
- protected static readonly MethodInfo RandomLastName = typeof(PregnancyUtility).GetMethod("RandomLastName", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn), typeof(Pawn) }, null);
-
- public bool HasBaby
- {
- get => !babies.NullOrEmpty();
- }
-
- public Pawn PopBaby()
- {
- if (babies.NullOrEmpty()) return null;
-
- Pawn firstBaby = babies.First();
- babies.Remove(firstBaby);
- return firstBaby;
- }
-
- public override void CompPostPostRemoved()
- {
- // At this point in the hediff removal process, the new hediff is already on the pawn
- // But it is possible that there is no new hediff (be it a birth, miscarrage, or dev edit)
- base.CompPostPostRemoved();
-
- switch (parent)
- {
- case Hediff_Pregnant hediff_Pregnant:
- Hediff_Labor labor = (Hediff_Labor)Pawn.health.hediffSet.hediffs.Where(hediff => hediff is Hediff_Labor).MaxByWithFallback(hediff => hediff.loadID);
- HediffComp_PregeneratedBabies laborcomp = labor?.TryGetComp();
- if (laborcomp == null) return;
- laborcomp.babies = this.babies;
- laborcomp.enzygoticSiblings = this.enzygoticSiblings;
- break;
- case Hediff_Labor hediff_Labor:
- Hediff_LaborPushing pushing = (Hediff_LaborPushing)Pawn.health.hediffSet.hediffs.Where(hediff => hediff is Hediff_LaborPushing).MaxByWithFallback(hediff => hediff.loadID);
- HediffComp_PregeneratedBabies pushingcomp = pushing?.TryGetComp();
- if (pushingcomp == null) return;
- pushingcomp.babies = this.babies;
- pushingcomp.enzygoticSiblings = this.enzygoticSiblings;
- break;
- case Hediff_LaborPushing hediff_LaborPushing:
- // Nothing to do, the laborpushing transpiler will pick it up
- break;
- }
- }
-
- public override void CompExposeData()
- {
- base.CompExposeData();
- Scribe_Collections.Look(ref babies, "babies", LookMode.Deep);
- Scribe_Collections.Look(ref enzygoticSiblings, "enzygoticSiblings", keyLookMode: LookMode.Reference, valueLookMode: LookMode.Reference);
- }
-
-
- public void AddNewBaby(Pawn mother, Pawn father)
- {
- if (babies == null) babies = new List();
- PawnKindDef babyPawnKind = PregnancyCommon.BabyPawnKindDecider(mother, father);
- PawnGenerationRequest request = new PawnGenerationRequest
- (
- kind: babyPawnKind,
- faction: mother.Faction,
- allowDowned: true,
- fixedLastName: (string)RandomLastName.Invoke(null, new object[] { mother, mother, xxx.is_human(father) ? father : null }),
- forceNoIdeo: true,
- // Kill on bad positivity in the post-birth
- // forceDead: positivityIndex == -1
- forcedEndogenes: PregnancyUtility.GetInheritedGenes(father, mother),
- forcedXenotype: XenotypeDefOf.Baseliner,
- developmentalStages: DevelopmentalStage.Newborn
- );
- int division = 1;
- Pawn firstbaby = null;
- while (Rand.Chance(Configurations.EnzygoticTwinsChance) && division < Configurations.MaxEnzygoticTwins) division++;
- if (division > 1 && enzygoticSiblings == null) enzygoticSiblings = new Dictionary();
- for (int i = 0; i < division; i++)
- {
- Pawn baby = PawnGenerator.GeneratePawn(request);
- if (baby == null) break;
- PregnancyCommon.SetupBabyXenotype(mother, father, baby);
- if (division > 1)
- {
- if (i == 0)
- {
- if (baby.IsHAR())
- baby.Drawer.renderer.graphics.ResolveAllGraphics();
- firstbaby = baby;
- request.FixedGender = baby.gender;
- request.ForcedEndogenes = baby.genes?.Endogenes.Select(gene => gene.def).ToList();
- }
- else
- {
- enzygoticSiblings.Add(baby, firstbaby);
-
- if (baby.story != null)
- {
- baby.story.headType = firstbaby.story.headType;
- baby.story.hairDef = firstbaby.story.hairDef;
- baby.story.bodyType = firstbaby.story.bodyType;
- baby.story.furDef = firstbaby.story.furDef;
- }
-
- if (baby.genes != null && ModsConfig.BiotechActive)
- {
- baby.genes.SetXenotypeDirect(firstbaby.genes.Xenotype);
- baby.genes.xenotypeName = firstbaby.genes.xenotypeName;
- baby.genes.iconDef = firstbaby.genes.iconDef;
- baby.genes.hybrid = firstbaby.genes.hybrid;
- }
-
- if (baby.IsHAR())
- HARCompatibility.CopyHARProperties(baby, firstbaby);
-
- // MultiplePregnancy calls this post-birth because RJW resets private parts
- // So xenotype things shouldn't be shared
- PregnancyCommon.ProcessIdenticalSibling(baby, firstbaby);
- }
- }
- babies.Add(baby);
- }
- }
- }
-}
diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs
index 67b4820..c1d995a 100644
--- a/1.4/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs
+++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs
@@ -13,6 +13,9 @@ namespace RJW_Menstruation
{
protected Dictionary enzygoticSiblings = new Dictionary(); // Each pawn and who they split from
+ protected readonly MethodInfo TryGetInheritedXenotype = typeof(PregnancyUtility).GetMethod("TryGetInheritedXenotype", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn), typeof(XenotypeDef).MakeByRefType() }, null );
+ protected readonly MethodInfo ShouldByHybrid = typeof(PregnancyUtility).GetMethod("ShouldByHybrid", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn) }, null);
+
public override void DiscoverPregnancy()
{
PregnancyThought();
@@ -79,6 +82,48 @@ namespace RJW_Menstruation
breastcomp?.GaveBirth();
}
+ public string GetBabyInfo()
+ {
+ if (babies.NullOrEmpty())
+ return "Null";
+
+ StringBuilder res = new StringBuilder();
+
+ IEnumerable babiesdistinct = babies.Distinct(new RaceComparer());
+ int iteration = 0;
+ foreach (Pawn baby in babiesdistinct)
+ {
+ int num = babies.Where(x => x.def.Equals(baby.def)).Count();
+ if (iteration > 0) res.Append(", ");
+ res.AppendFormat("{0} {1}", num, baby.def.label);
+ iteration++;
+ }
+ res.AppendFormat(" {0}", Translations.Dialog_WombInfo02);
+ return res.ToString();
+ }
+
+ public string GetFatherInfo()
+ {
+ if (babies.NullOrEmpty())
+ return "Null";
+
+ StringBuilder res = new StringBuilder();
+ res.AppendFormat("{0}: ", Translations.Dialog_WombInfo03);
+
+ if (!is_parent_known && Configurations.InfoDetail != Configurations.DetailLevel.All)
+ return res.Append(Translations.Dialog_FatherUnknown).ToString();
+
+ IEnumerable babiesdistinct = babies.Distinct(new FatherComparer(pawn));
+ int iteration = 0;
+ foreach (Pawn baby in babiesdistinct)
+ {
+ if (iteration > 0) res.Append(", ");
+ res.Append(Utility.GetFather(baby, pawn)?.LabelShort ?? Translations.Dialog_FatherUnknown);
+ iteration++;
+ }
+ return res.ToString();
+ }
+
private void HumanlikeBirth(Pawn baby)
{
Pawn mother = pawn; Pawn father = Utility.GetFather(baby, pawn);
@@ -122,7 +167,7 @@ namespace RJW_Menstruation
if (ModsConfig.BiotechActive)
{
// Ugly, but it'll have to do
- OutcomeChance bestOutcome = RitualOutcomeEffectDefOf.ChildBirth.BestOutcome;
+ OutcomeChance bestOutcome = RitualOutcomeEffectDefOf.ChildBirth.outcomeChances.Find(chance => chance.positivityIndex == 1);
string label = bestOutcome.label;
string description = bestOutcome.description.Formatted(mother.Named("MOTHER"));
@@ -167,12 +212,65 @@ namespace RJW_Menstruation
//baby.story.birthLastName = last_name;
}
+ protected void CopyBodyPartProperties(Hediff part, Hediff originalPart)
+ {
+ CompHediffBodyPart comp = part.TryGetComp();
+ CompHediffBodyPart originalComp = originalPart.TryGetComp();
+
+ if (comp != null && originalComp != null)
+ {
+ // the string properties should be the same between both pawns anyways, besides the name of the owner
+ part.Severity = originalPart.Severity;
+ comp.SizeBase = originalComp.SizeBase;
+ comp.SizeOwner = originalComp.SizeOwner;
+ comp.EffSize = originalComp.EffSize;
+ comp.FluidAmmount = originalComp.FluidAmmount;
+ comp.FluidModifier = originalComp.FluidModifier;
+ }
+
+ HediffComp_Menstruation originalMenstruationComp = originalPart.GetMenstruationCompFromVagina();
+ if (originalMenstruationComp != null)
+ {
+ part.GetMenstruationCompFromVagina()?.CopyCycleProperties(originalMenstruationComp);
+ }
+ HediffComp_Breast originalBreastComp = originalPart.GetBreastComp();
+ if (originalBreastComp != null)
+ {
+ part.GetBreastComp()?.CopyBreastProperties(originalBreastComp);
+ }
+ }
+
+ protected void CopyBodyPartRecord(Pawn baby, Pawn original, BodyPartRecord babyBPR, BodyPartRecord originalBPR)
+ {
+ if (babyBPR == null || originalBPR == null) return;
+
+ RemoveBabyParts(baby, Genital_Helper.get_PartsHediffList(baby, babyBPR));
+ foreach (Hediff originalPart in Genital_Helper.get_PartsHediffList(original, originalBPR))
+ {
+ Hediff part = SexPartAdder.MakePart(originalPart.def, baby, babyBPR);
+ CopyBodyPartProperties(part, originalPart);
+ baby.health.AddHediff(part, babyBPR);
+ }
+ }
+
+ // Baby is the sibling to be changed, original is the first of the set and the one to copy to the rest.
+ public virtual void ProcessIdenticalSibling(Pawn baby, Pawn original)
+ {
+ // They'll be the same pawnkind, which lets us make a lot of useful assumptions
+ // However, some RNG might still be involved in genital generation (e.g. futas), so the easiest method is to clear out and re-generate
+ // A bit wasteful since Hediff_BasePregnancy.PostBirth already redid the genitals
+ CopyBodyPartRecord(baby, original, Genital_Helper.get_genitalsBPR(baby), Genital_Helper.get_genitalsBPR(original));
+ CopyBodyPartRecord(baby, original, Genital_Helper.get_breastsBPR(baby), Genital_Helper.get_breastsBPR(original));
+ CopyBodyPartRecord(baby, original, Genital_Helper.get_uddersBPR(baby), Genital_Helper.get_uddersBPR(original));
+ CopyBodyPartRecord(baby, original, Genital_Helper.get_anusBPR(baby), Genital_Helper.get_anusBPR(original));
+ }
+
public override void PostBirth(Pawn mother, Pawn father, Pawn baby)
{
base.PostBirth(mother, father, baby);
// Has to happen on birth since RJW redoes the genitals at birth
if (!enzygoticSiblings.NullOrEmpty() && enzygoticSiblings.TryGetValue(baby, out Pawn original) && baby != original)
- PregnancyCommon.ProcessIdenticalSibling(baby, original);
+ ProcessIdenticalSibling(baby, original);
}
// From RJW's trait code
@@ -313,7 +411,7 @@ namespace RJW_Menstruation
allowAddictions: false,
relationWithExtraPawnChanceFactor: 0,
fixedLastName: lastname,
- kind: PregnancyCommon.BabyPawnKindDecider(mother, father),
+ kind: BabyPawnKindDecider(mother, father),
//fixedIdeo: mother.Ideo,
forbidAnyTitle: true,
forceNoBackstory: true,
@@ -330,7 +428,25 @@ namespace RJW_Menstruation
{
Pawn baby = GenerateBaby(request, mother, father, parentTraits, traitSeed);
if (baby == null) break;
- PregnancyCommon.SetupBabyXenotype(mother, father, baby);
+ if (baby.genes != null && ModsConfig.BiotechActive)
+ {
+ if (GeneUtility.SameHeritableXenotype(mother, father) && mother.genes.UniqueXenotype)
+ {
+ baby.genes.xenotypeName = mother.genes.xenotypeName;
+ baby.genes.iconDef = mother.genes.iconDef;
+ }
+
+ object[] args = new object[] { mother, father, null };
+ if ((bool)TryGetInheritedXenotype.Invoke(null, args))
+ {
+ baby.genes.SetXenotypeDirect((XenotypeDef)args[2]);
+ }
+ else if((bool)ShouldByHybrid.Invoke(null, new object[] { mother, father }))
+ {
+ baby.genes.hybrid = true;
+ baby.genes.xenotypeName = "Hybrid".Translate();
+ }
+ }
if (division > 1)
{
if (i == 0)
@@ -350,7 +466,6 @@ namespace RJW_Menstruation
baby.story.headType = firstbaby.story.headType;
baby.story.hairDef = firstbaby.story.hairDef;
baby.story.bodyType = firstbaby.story.bodyType;
- baby.story.furDef = firstbaby.story.furDef;
}
if (baby.genes != null && ModsConfig.BiotechActive)
@@ -404,6 +519,174 @@ namespace RJW_Menstruation
return baby;
}
+ ///
+ /// Decide pawnkind from mother and father
+ /// Come from RJW
+ ///
+ ///
+ ///
+ ///
+ public PawnKindDef BabyPawnKindDecider(Pawn mother, Pawn father)
+ {
+ PawnKindDef motherKindDef = Utility.GetRacesPawnKind(mother);
+ PawnKindDef fatherKindDef = Utility.GetRacesPawnKind(father);
+
+ PawnKindDef spawn_kind_def = motherKindDef;
+
+ int flag = 0;
+ if (xxx.is_human(mother)) flag += 2;
+ if (xxx.is_human(father)) flag += 1;
+ //Mother - Father = Flag
+ //Human - Human = 3
+ //Human - Animal = 2
+ //Animal - Human = 1
+ //Animal - Animal = 0
+
+ switch (flag)
+ {
+ case 3:
+ if (!Rand.Chance(RJWPregnancySettings.humanlike_DNA_from_mother)) spawn_kind_def = fatherKindDef;
+ break;
+ case 2:
+ if (RJWPregnancySettings.bestiality_DNA_inheritance == 0f) spawn_kind_def = fatherKindDef;
+ else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
+ break;
+ case 1:
+ if (RJWPregnancySettings.bestiality_DNA_inheritance == 1f) spawn_kind_def = fatherKindDef;
+ else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
+ break;
+ case 0:
+ if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
+ break;
+ }
+
+ bool IsAndroidmother = AndroidsCompatibility.IsAndroid(mother);
+ bool IsAndroidfather = AndroidsCompatibility.IsAndroid(father);
+ if (IsAndroidmother && !IsAndroidfather)
+ {
+ spawn_kind_def = fatherKindDef;
+ }
+ else if (!IsAndroidmother && IsAndroidfather)
+ {
+ spawn_kind_def = motherKindDef;
+ }
+
+ string MotherRaceName = "";
+ string FatherRaceName = "";
+ MotherRaceName = motherKindDef?.race?.defName;
+ PawnKindDef non_hybrid_kind_def = spawn_kind_def;
+ if (father != null)
+ FatherRaceName = fatherKindDef?.race?.defName;
+
+
+ if (FatherRaceName != "" && Configurations.UseHybridExtention)
+ {
+ spawn_kind_def = GetHybrid(father, mother);
+ //Log.Message("pawnkind: " + spawn_kind_def?.defName);
+ }
+
+ if (MotherRaceName != FatherRaceName && FatherRaceName != "")
+ {
+ if (!Configurations.UseHybridExtention || spawn_kind_def == null)
+ {
+ spawn_kind_def = non_hybrid_kind_def;
+ IEnumerable groups = DefDatabase.AllDefs.Where(x => !(x.hybridRaceParents.NullOrEmpty() || x.hybridChildKindDef.NullOrEmpty()));
+
+
+ //ModLog.Message(" found custom RaceGroupDefs " + groups.Count());
+ foreach (RaceGroupDef t in groups)
+ {
+ if ((t.hybridRaceParents.Contains(MotherRaceName) && t.hybridRaceParents.Contains(FatherRaceName))
+ || (t.hybridRaceParents.Contains("Any") && (t.hybridRaceParents.Contains(MotherRaceName) || t.hybridRaceParents.Contains(FatherRaceName))))
+ {
+ //ModLog.Message(" has hybridRaceParents");
+ if (t.hybridChildKindDef.Contains("MotherKindDef"))
+ spawn_kind_def = motherKindDef;
+ else if (t.hybridChildKindDef.Contains("FatherKindDef") && father != null)
+ spawn_kind_def = fatherKindDef;
+ else
+ {
+ //ModLog.Message(" trying hybridChildKindDef " + t.defName);
+ List child_kind_def_list = new List();
+ child_kind_def_list.AddRange(DefDatabase.AllDefs.Where(x => t.hybridChildKindDef.Contains(x.defName)));
+
+ //ModLog.Message(" found custom hybridChildKindDefs " + t.hybridChildKindDef.Count);
+ if (!child_kind_def_list.NullOrEmpty())
+ spawn_kind_def = child_kind_def_list.RandomElement();
+ }
+ }
+ }
+ }
+
+ }
+ else if (!Configurations.UseHybridExtention || spawn_kind_def == null)
+ {
+ spawn_kind_def = mother.RaceProps?.AnyPawnKind ?? motherKindDef;
+ }
+
+ if (spawn_kind_def.defName.Contains("Nymph"))
+ {
+ //child is nymph, try to find other PawnKindDef
+ List spawn_kind_def_list = new List();
+ spawn_kind_def_list.AddRange(DefDatabase.AllDefs.Where(x => x.race == spawn_kind_def.race && !x.defName.Contains("Nymph")));
+ //no other PawnKindDef found try mother
+ if (spawn_kind_def_list.NullOrEmpty())
+ spawn_kind_def_list.AddRange(DefDatabase.AllDefs.Where(x => x.race == motherKindDef.race && !x.defName.Contains("Nymph")));
+ //no other PawnKindDef found try father
+ if (spawn_kind_def_list.NullOrEmpty() && father != null)
+ spawn_kind_def_list.AddRange(DefDatabase.AllDefs.Where(x => x.race == fatherKindDef.race && !x.defName.Contains("Nymph")));
+ //no other PawnKindDef found fallback to generic colonist
+ if (spawn_kind_def_list.NullOrEmpty())
+ spawn_kind_def = PawnKindDefOf.Colonist;
+
+ if (!spawn_kind_def_list.NullOrEmpty()) spawn_kind_def = spawn_kind_def_list.RandomElement();
+ }
+
+ return spawn_kind_def;
+
+ }
+
+ public PawnKindDef GetHybrid(Pawn first, Pawn second)
+ {
+ PawnKindDef res = null;
+ Pawn opposite = second;
+ HybridInformations info = null;
+
+
+ if (!Configurations.HybridOverride.NullOrEmpty())
+ {
+ info = Configurations.HybridOverride.FirstOrDefault(x => x.DefName == first.def?.defName && (x.hybridExtension?.Exists(y => y.DefName == second.def?.defName) ?? false));
+ if (info == null)
+ {
+ info = Configurations.HybridOverride.FirstOrDefault(x => x.DefName == second.def?.defName && (x.hybridExtension?.Exists(y => y.DefName == first.def?.defName) ?? false));
+ opposite = first;
+ }
+ }
+
+ if (info != null)
+ {
+ res = info.GetHybridWith(opposite.def.defName) ?? null;
+ }
+ if (res != null) return res;
+
+
+ PawnDNAModExtension dna;
+ dna = first.def.GetModExtension();
+ if (dna != null)
+ {
+ res = dna.GetHybridWith(second.def.defName) ?? null;
+ }
+ else
+ {
+ dna = second.def.GetModExtension();
+ if (dna != null)
+ {
+ res = dna.GetHybridWith(first.def.defName) ?? null;
+ }
+ }
+ return res;
+ }
+
///
/// Copy from RJW
///
diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/PregnancyCommon.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/PregnancyCommon.cs
deleted file mode 100644
index b642947..0000000
--- a/1.4/source/RJW_Menstruation/RJW_Menstruation/PregnancyCommon.cs
+++ /dev/null
@@ -1,300 +0,0 @@
-using RimWorld;
-using rjw;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using Verse;
-
-namespace RJW_Menstruation
-{
- public static class PregnancyCommon
- {
- private static readonly MethodInfo TryGetInheritedXenotype = typeof(PregnancyUtility).GetMethod("TryGetInheritedXenotype", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn), typeof(XenotypeDef).MakeByRefType() }, null);
- private static readonly MethodInfo ShouldByHybrid = typeof(PregnancyUtility).GetMethod("ShouldByHybrid", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn) }, null);
-
- public static string GetBabyInfo(IEnumerable babies)
- {
- if (babies == null || !babies.Any()) return "Null";
-
- StringBuilder res = new StringBuilder();
-
- IEnumerable babiesdistinct = babies.Distinct(new RaceComparer());
- int iteration = 0;
- foreach (Pawn baby in babiesdistinct)
- {
- int num = babies.Where(x => x.def.Equals(baby.def)).Count();
- if (iteration > 0) res.Append(", ");
- res.AppendFormat("{0} {1}", num, baby.def.label);
- iteration++;
- }
- res.AppendFormat(" {0}", Translations.Dialog_WombInfo02);
- return res.ToString();
- }
-
- public static string GetFatherInfo(IEnumerable babies, Pawn mother, bool is_parent_known)
- {
- if (babies == null || !babies.Any()) return "Null";
-
- StringBuilder res = new StringBuilder();
- res.AppendFormat("{0}: ", Translations.Dialog_WombInfo03);
-
- if (!is_parent_known && Configurations.InfoDetail != Configurations.DetailLevel.All)
- return res.Append(Translations.Dialog_FatherUnknown).ToString();
-
- IEnumerable babiesdistinct = babies.Distinct(new FatherComparer(mother));
- int iteration = 0;
- foreach (Pawn baby in babiesdistinct)
- {
- if (iteration > 0) res.Append(", ");
- res.Append(Utility.GetFather(baby, mother)?.LabelShort ?? Translations.Dialog_FatherUnknown);
- iteration++;
- }
- return res.ToString();
- }
-
- ///
- /// Decide pawnkind from mother and father
- /// Come from RJW
- ///
- ///
- ///
- ///
-
- public static PawnKindDef BabyPawnKindDecider(Pawn mother, Pawn father)
- {
- PawnKindDef motherKindDef = Utility.GetRacesPawnKind(mother);
- PawnKindDef fatherKindDef = Utility.GetRacesPawnKind(father);
-
- PawnKindDef spawn_kind_def = motherKindDef;
-
- int flag = 0;
- if (xxx.is_human(mother)) flag += 2;
- if (xxx.is_human(father)) flag += 1;
- //Mother - Father = Flag
- //Human - Human = 3
- //Human - Animal = 2
- //Animal - Human = 1
- //Animal - Animal = 0
-
- switch (flag)
- {
- case 3:
- if (!Rand.Chance(RJWPregnancySettings.humanlike_DNA_from_mother)) spawn_kind_def = fatherKindDef;
- break;
- case 2:
- if (RJWPregnancySettings.bestiality_DNA_inheritance == 0f) spawn_kind_def = fatherKindDef;
- else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
- break;
- case 1:
- if (RJWPregnancySettings.bestiality_DNA_inheritance == 1f) spawn_kind_def = fatherKindDef;
- else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
- break;
- case 0:
- if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
- break;
- }
-
- bool IsAndroidmother = AndroidsCompatibility.IsAndroid(mother);
- bool IsAndroidfather = AndroidsCompatibility.IsAndroid(father);
- if (IsAndroidmother && !IsAndroidfather)
- {
- spawn_kind_def = fatherKindDef;
- }
- else if (!IsAndroidmother && IsAndroidfather)
- {
- spawn_kind_def = motherKindDef;
- }
-
- string MotherRaceName = "";
- string FatherRaceName = "";
- MotherRaceName = motherKindDef?.race?.defName;
- PawnKindDef non_hybrid_kind_def = spawn_kind_def;
- if (father != null)
- FatherRaceName = fatherKindDef?.race?.defName;
-
-
- if (FatherRaceName != "" && Configurations.UseHybridExtention)
- {
- spawn_kind_def = GetHybrid(father, mother);
- //Log.Message("pawnkind: " + spawn_kind_def?.defName);
- }
-
- if (MotherRaceName != FatherRaceName && FatherRaceName != "")
- {
- if (!Configurations.UseHybridExtention || spawn_kind_def == null)
- {
- spawn_kind_def = non_hybrid_kind_def;
- IEnumerable groups = DefDatabase.AllDefs.Where(x => !(x.hybridRaceParents.NullOrEmpty() || x.hybridChildKindDef.NullOrEmpty()));
-
-
- //ModLog.Message(" found custom RaceGroupDefs " + groups.Count());
- foreach (RaceGroupDef t in groups)
- {
- if ((t.hybridRaceParents.Contains(MotherRaceName) && t.hybridRaceParents.Contains(FatherRaceName))
- || (t.hybridRaceParents.Contains("Any") && (t.hybridRaceParents.Contains(MotherRaceName) || t.hybridRaceParents.Contains(FatherRaceName))))
- {
- //ModLog.Message(" has hybridRaceParents");
- if (t.hybridChildKindDef.Contains("MotherKindDef"))
- spawn_kind_def = motherKindDef;
- else if (t.hybridChildKindDef.Contains("FatherKindDef") && father != null)
- spawn_kind_def = fatherKindDef;
- else
- {
- //ModLog.Message(" trying hybridChildKindDef " + t.defName);
- List child_kind_def_list = new List();
- child_kind_def_list.AddRange(DefDatabase.AllDefs.Where(x => t.hybridChildKindDef.Contains(x.defName)));
-
- //ModLog.Message(" found custom hybridChildKindDefs " + t.hybridChildKindDef.Count);
- if (!child_kind_def_list.NullOrEmpty())
- spawn_kind_def = child_kind_def_list.RandomElement();
- }
- }
- }
- }
-
- }
- else if (!Configurations.UseHybridExtention || spawn_kind_def == null)
- {
- spawn_kind_def = mother.RaceProps?.AnyPawnKind ?? motherKindDef;
- }
-
- if (spawn_kind_def.defName.Contains("Nymph"))
- {
- //child is nymph, try to find other PawnKindDef
- List spawn_kind_def_list = new List();
- spawn_kind_def_list.AddRange(DefDatabase.AllDefs.Where(x => x.race == spawn_kind_def.race && !x.defName.Contains("Nymph")));
- //no other PawnKindDef found try mother
- if (spawn_kind_def_list.NullOrEmpty())
- spawn_kind_def_list.AddRange(DefDatabase.AllDefs.Where(x => x.race == motherKindDef.race && !x.defName.Contains("Nymph")));
- //no other PawnKindDef found try father
- if (spawn_kind_def_list.NullOrEmpty() && father != null)
- spawn_kind_def_list.AddRange(DefDatabase.AllDefs.Where(x => x.race == fatherKindDef.race && !x.defName.Contains("Nymph")));
- //no other PawnKindDef found fallback to generic colonist
- if (spawn_kind_def_list.NullOrEmpty())
- spawn_kind_def = PawnKindDefOf.Colonist;
-
- if (!spawn_kind_def_list.NullOrEmpty()) spawn_kind_def = spawn_kind_def_list.RandomElement();
- }
-
- return spawn_kind_def;
-
- }
-
- public static void SetupBabyXenotype(Pawn mother, Pawn father, Pawn baby)
- {
- if (baby.genes == null || !ModsConfig.BiotechActive) return;
-
- if (GeneUtility.SameHeritableXenotype(mother, father) && mother.genes.UniqueXenotype)
- {
- baby.genes.xenotypeName = mother.genes.xenotypeName;
- baby.genes.iconDef = mother.genes.iconDef;
- }
-
- object[] args = new object[] { mother, father, null };
- if ((bool)TryGetInheritedXenotype.Invoke(null, args))
- {
- baby.genes.SetXenotypeDirect((XenotypeDef)args[2]);
- }
- else if ((bool)ShouldByHybrid.Invoke(null, new object[] { mother, father }))
- {
- baby.genes.hybrid = true;
- baby.genes.xenotypeName = "Hybrid".Translate();
- }
- }
-
- public static PawnKindDef GetHybrid(Pawn first, Pawn second)
- {
- PawnKindDef res = null;
- Pawn opposite = second;
- HybridInformations info = null;
-
-
- if (!Configurations.HybridOverride.NullOrEmpty())
- {
- info = Configurations.HybridOverride.FirstOrDefault(x => x.DefName == first.def?.defName && (x.hybridExtension?.Exists(y => y.DefName == second.def?.defName) ?? false));
- if (info == null)
- {
- info = Configurations.HybridOverride.FirstOrDefault(x => x.DefName == second.def?.defName && (x.hybridExtension?.Exists(y => y.DefName == first.def?.defName) ?? false));
- opposite = first;
- }
- }
-
- if (info != null)
- {
- res = info.GetHybridWith(opposite.def.defName) ?? null;
- }
- if (res != null) return res;
-
-
- PawnDNAModExtension dna;
- dna = first.def.GetModExtension();
- if (dna != null)
- {
- res = dna.GetHybridWith(second.def.defName) ?? null;
- }
- else
- {
- dna = second.def.GetModExtension();
- if (dna != null)
- {
- res = dna.GetHybridWith(first.def.defName) ?? null;
- }
- }
- return res;
- }
-
- private static void CopyBodyPartProperties(Hediff part, Hediff originalPart)
- {
- CompHediffBodyPart comp = part.TryGetComp();
- CompHediffBodyPart originalComp = originalPart.TryGetComp();
-
- if (comp != null && originalComp != null)
- {
- // the string properties should be the same between both pawns anyways, besides the name of the owner
- part.Severity = originalPart.Severity;
- comp.SizeBase = originalComp.SizeBase;
- comp.SizeOwner = originalComp.SizeOwner;
- comp.EffSize = originalComp.EffSize;
- comp.FluidAmmount = originalComp.FluidAmmount;
- comp.FluidModifier = originalComp.FluidModifier;
- }
-
- HediffComp_Menstruation originalMenstruationComp = originalPart.GetMenstruationCompFromVagina();
- if (originalMenstruationComp != null)
- {
- part.GetMenstruationCompFromVagina()?.CopyCycleProperties(originalMenstruationComp);
- }
- HediffComp_Breast originalBreastComp = originalPart.GetBreastComp();
- if (originalBreastComp != null)
- {
- part.GetBreastComp()?.CopyBreastProperties(originalBreastComp);
- }
- }
-
- private static void CopyBodyPartRecord(Pawn baby, Pawn original, BodyPartRecord babyBPR, BodyPartRecord originalBPR)
- {
- if (babyBPR == null || originalBPR == null) return;
-
- Hediff_BasePregnancy.RemoveBabyParts(baby, Genital_Helper.get_PartsHediffList(baby, babyBPR));
- foreach (Hediff originalPart in Genital_Helper.get_PartsHediffList(original, originalBPR))
- {
- Hediff part = SexPartAdder.MakePart(originalPart.def, baby, babyBPR);
- CopyBodyPartProperties(part, originalPart);
- baby.health.AddHediff(part, babyBPR);
- }
- }
-
- // Baby is the sibling to be changed, original is the first of the set and the one to copy to the rest.
- public static void ProcessIdenticalSibling(Pawn baby, Pawn original)
- {
- // They'll be the same pawnkind, which lets us make a lot of useful assumptions
- // However, some RNG might still be involved in genital generation (e.g. futas), so the easiest method is to clear out and re-generate
- // A bit wasteful since Hediff_BasePregnancy.PostBirth already redid the genitals
- CopyBodyPartRecord(baby, original, Genital_Helper.get_genitalsBPR(baby), Genital_Helper.get_genitalsBPR(original));
- CopyBodyPartRecord(baby, original, Genital_Helper.get_breastsBPR(baby), Genital_Helper.get_breastsBPR(original));
- CopyBodyPartRecord(baby, original, Genital_Helper.get_uddersBPR(baby), Genital_Helper.get_uddersBPR(original));
- CopyBodyPartRecord(baby, original, Genital_Helper.get_anusBPR(baby), Genital_Helper.get_anusBPR(original));
- }
- }
-}
diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/RJW_Menstruation.csproj b/1.4/source/RJW_Menstruation/RJW_Menstruation/RJW_Menstruation.csproj
index 0266ab8..1a35c67 100644
--- a/1.4/source/RJW_Menstruation/RJW_Menstruation/RJW_Menstruation.csproj
+++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/RJW_Menstruation.csproj
@@ -69,14 +69,12 @@
-
-
diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs
index 36e026b..8a8e380 100644
--- a/1.4/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs
+++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs
@@ -172,8 +172,8 @@ namespace RJW_Menstruation
Pawn fetus = comp.GetFetus();
if (fetus != null && Utility.ShowFetusInfo())
{
- string feinfo = PregnancyCommon.GetBabyInfo(m.babies);
- string fainfo = PregnancyCommon.GetFatherInfo(m.babies, m.pawn, m.is_parent_known) + " ";
+ string feinfo = m.GetBabyInfo();
+ string fainfo = m.GetFatherInfo() + " ";
if (feinfo.Length + fainfo.Length > 45)
{
preginfoheight = fontheight + 2;
diff --git a/About/Manifest.xml b/About/Manifest.xml
index 015d8cc..13e6eed 100644
--- a/About/Manifest.xml
+++ b/About/Manifest.xml
@@ -1,7 +1,7 @@
RJW Menstruation
- 1.0.8.6
+ 1.0.8.5
diff --git a/changelogs.txt b/changelogs.txt
index 2beba13..a798296 100644
--- a/changelogs.txt
+++ b/changelogs.txt
@@ -1,7 +1,3 @@
-Version 1.0.8.6
- - Updated Traditional Chinese translation by Hydrogen.
- - Added several menstruation-related genes.
-
Version 1.0.8.5
- Added biosculpter recipe to restore 1 year's worth of eggs, with icon by DestinyPlayer.
- Vaginal sex with the "avoid pregnancy" relation will (usually) pull out prevent cum from entering the womb if there's a risk of pregnancy.