Compare commits

..

7 commits

13 changed files with 310 additions and 36 deletions

View file

@ -66,11 +66,52 @@ Any gene can give immunity against any genetic disease using an extension:
These extensions can be slapped on any gene,
but they are meant mostly to have infectors immune against their own diseases.
**Twinkification / Feminization**:
Both approaches follow the same general logic.
- Pawn `A` has Twinkifier Gene and fucks Pawn `B`
- `B` receives a `twinkification progress` hediff with some effects
- Upon having ANY sex, `B` can gain genes from a relevant genepool.
- Genes can be minor or major, depending on the progress of twinkification.
Pawn `B` might be immune against twinkifier as normal immunity logic against diseases.
But once the hediff is there, the twinkification can happen unless you wait for it to cool down.
Gene additions are subject to an application chance (25% for minor, 10% for major)
and might try to add a gene that already exists - then nothing happens.
*Twink Genepool*:
- (Minor) Body_Thin
- (Minor) Homosexual
- (Minor) Beard_NoBeardOnly
- (Minor) Small male genitalia
- (Major) Minor Vulnerability
- (Major) Infectious Homosexuality
- (Major) Delicate
- (Major) Beauty Pretty
- (Major) Fertile Anus
*Feminization Genepool*:
- (Minor) Long Hair
- (Minor) No-Beard
- (Minor) Small Male Genitals
- (Minor) No Cum
- (Minor) Big Breasts (will only show later)
- (Major) Female Only
- (Major) No Penis
- (Major) Minor Vulnerability
These are currently hardcoded but I can change them on popular demand.
In general minor changes are only cosmetic and wont change metabolism.
*Why are these changes Genetic?*
Because this is the genes mod, and I find things here quite robust.
## Changelog
**Additions:**
- Passive Gene: Genetic Disease Immunity. cannot get infected by any genetic diseases, and won't be affected by some other genes (see relevant genes)
- Gene: Genetic Disease Immunity. cannot get infected by any genetic diseases, and won't be affected by some other genes (see relevant genes)
- Disease Gene: Vulnerability. Pawn is likelier to be raped
- Disease Gene: Infectious Hypersexuality
- Disease Gene: Infectious Homosexuality & Bisexuality
@ -83,6 +124,10 @@ but they are meant mostly to have infectors immune against their own diseases.
- Gene: Sexual Genetic Swap. Pawns have a chance to switch a random gene with their sexpartner.
- (Archite) Gene: Sexual Genetic Thief. Pawns have a chance to steal a gene from their sexpartner. Genetic Disease Immunity shields against this.
- Gene: Sperm Displacement. Pawns might overwrite an existing pregnancy, becoming the new father. The pregnancy will stay in its gestation progress.
- Gene: Twinkification: Pawns turn their (male) sexual partners into breedable twinks.
- Gene: Feminization: Pawns turn their (male) sexual partners into women.
- Gene: Blocked Masturbation: Pawns cannot masturbate.
- Disease Gene: Infectious Blocked Masturbation
- Pawns will have negative thoughts about pawns with more genetic diseases than themselves.
- Faction Penalties for spreading diseases, stealing genes and aging pawns with age transfer
- Patch for [Imphilee Xeno](https://steamcommunity.com/sharedfiles/filedetails/?id=2990674516) by @Bunuffin
@ -118,6 +163,11 @@ Verse.Log:Error (string)
This is not dangerous.
*Blocked Masturbation*
Might not be fully working - for testing, I run things in DevMode, and I can just order people to masturbate.
Please playtest this a bit for me, as I want to make it work nicely.
*Supporting*
You can now support me with [buying me a coffee](https://buymeacoffee.com/vegapnk).

Binary file not shown.

View file

@ -15,7 +15,6 @@
</modExtensions>
</GeneDef>
<GeneDef ParentName="BreedingBase">
<defName>rjw_genes_mechbreeder</defName>
<label>mechbreeder</label>
@ -81,7 +80,6 @@
<biostatMet>-1</biostatMet>
</GeneDef>
<GeneDef ParentName="BreedingBase">
<defName>rjw_genes_mating_call</defName>
<label>Mating Call</label>
@ -98,7 +96,6 @@
<biostatMet>-1</biostatMet>
</GeneDef>
<GeneDef ParentName="BreedingBase">
<defName>rjw_genes_pheromone_spit</defName>
<label>Pheromone Spit</label>

View file

@ -7,8 +7,8 @@
<modExtensions>
<li MayRequire="OskarPotocki.VanillaFactionsExpanded.Core"
Class="VanillaGenesExpanded.GeneExtension">
<backgroundPathEndogenes>Genes/Icons/RJW_Genes_Endogene_Background</backgroundPathEndogenes>
<backgroundPathXenogenes>Genes/Icons/RJW_Genes_Xenogene_Background</backgroundPathXenogenes>
<backgroundPathEndogenes>Genes/Icons/RJW_Genes_Endogene_Disease_Background</backgroundPathEndogenes>
<backgroundPathXenogenes>Genes/Icons/RJW_Genes_Endogene_Disease_Background</backgroundPathXenogenes>
</li>
</modExtensions>
</GeneDef>
@ -85,6 +85,22 @@
</modExtensions>
</GeneDef>
<GeneDef ParentName="RJWGeneDisease">
<defName>rjw_genes_infectious_blocked_masturbation</defName>
<label>infectious masturbation block</label>
<description>Carriers of this gene are unable to masturbate - they need a partner or equipment.</description>
<iconPath>Genes/Icons/Hypersexual</iconPath>
<displayOrderInCategory>55</displayOrderInCategory>
<biostatCpx>1</biostatCpx>
<biostatMet>2</biostatMet>
<modExtensions>
<li Class="RJW_Genes.GeneticDiseaseExtension">
<infectionChance>0.05</infectionChance>
</li>
</modExtensions>
</GeneDef>
<GeneDef ParentName="RJWGeneDisease">
<defName>rjw_genes_infectious_low_fertility</defName>
<label>infectious low fertility vulnerability</label>
@ -178,7 +194,7 @@
<defName>rjw_genes_infectious_bisexuality</defName>
<label>infectious bisexuality</label>
<description>This gene makes the pawn bisexual, and has a chance to spread on intercourse.</description>
<iconPath>UI\Ideoligions\Universal\RoundC</iconPath>
<iconPath>Genes/Icons/RoundC</iconPath>
<biostatCpx>1</biostatCpx>
<biostatMet>0</biostatMet>
<displayOrderInCategory>8</displayOrderInCategory>
@ -205,7 +221,7 @@
<defName>rjw_genes_infectious_homosexuality</defName>
<label>infectious homosexuality</label>
<description>This gene makes the pawn homosexual, and has a chance to spread on intercourse.</description>
<iconPath>UI\Ideoligions\Universal\RoundC</iconPath>
<iconPath>Genes/Icons/RoundC</iconPath>
<biostatCpx>1</biostatCpx>
<biostatMet>0</biostatMet>
<displayOrderInCategory>9</displayOrderInCategory>

View file

@ -205,4 +205,22 @@
</modExtensions>
</GeneDef>
<GeneDef>
<defName>rjw_genes_blocked_masturbation</defName>
<label>no masturbation</label>
<displayCategory>Reproduction</displayCategory>
<description>Carriers of this gene are unable to masturbate - they need a partner or equipment.</description>
<iconPath>Genes/Icons/Hypersexual</iconPath>
<displayOrderInCategory>60</displayOrderInCategory>
<biostatCpx>0</biostatCpx>
<biostatMet>1</biostatMet>
<modExtensions>
<li MayRequire="OskarPotocki.VanillaFactionsExpanded.Core"
Class="VanillaGenesExpanded.GeneExtension">
<backgroundPathEndogenes>Genes/Icons/RJW_Genes_Endogene_Background</backgroundPathEndogenes>
<backgroundPathXenogenes>Genes/Icons/RJW_Genes_Xenogene_Background</backgroundPathXenogenes>
</li>
</modExtensions>
</GeneDef>
</Defs>

View file

@ -186,7 +186,7 @@
<description>Carriers with this gene slowly turn male sexual partners into females.</description>
<iconPath>UI/Icons/Genes/Gene_PsychicBonding</iconPath>
<displayOrderInCategory>31</displayOrderInCategory>
<biostatCpx>5</biostatCpx>
<biostatCpx>4</biostatCpx>
<biostatMet>-1</biostatMet>
<modExtensions>
<li Class="RJW_Genes.ImmunityAgainstGenesExtension">
@ -214,7 +214,7 @@
<iconPath>UI/Icons/Genes/Gene_PsychicBonding</iconPath>
<displayOrderInCategory>50</displayOrderInCategory>
<biostatCpx>4</biostatCpx>
<biostatMet>0</biostatMet>
<biostatMet>-1</biostatMet>
<modExtensions>
<li Class="RJW_Genes.ImmunityAgainstGenesExtension">
<givesImmunityAgainst>
@ -224,7 +224,7 @@
<li Class="RJW_Genes.HediffIncreaseOnSexExtension">
<hediffDef>rjw_genes_twinkification_progress</hediffDef>
<canCreateHediff>true</canCreateHediff>
<severityIncrease>0.99</severityIncrease>
<severityIncrease>0.01</severityIncrease>
<applicationChance>1.00</applicationChance>
<applicableForWomen>false</applicableForWomen>
<applicableForMen>true</applicableForMen>

View file

@ -17,7 +17,7 @@
</li>
</comps>
<stages>
<!-- DevNote: The labels and their effects can be changed, but the logic triggers at >0.6 for minor and >0.8 for major ! -->
<li>
<label>neglectable</label>
<becomeVisible>false</becomeVisible>
@ -89,7 +89,7 @@
</li>
</comps>
<stages>
<!-- DevNote: The labels and their effects can be changed, but the logic triggers at >0.6 for minor and >0.8 for major ! -->
<li>
<label>neglectable</label>
<becomeVisible>false</becomeVisible>

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

View file

@ -74,8 +74,9 @@ namespace RJW_Genes
public static readonly GeneDef rjw_genes_insectbreeder;
public static readonly GeneDef rjw_genes_insectincubator;
public static readonly GeneDef rjw_genes_hardwired_progenity;
// Cum
public static readonly GeneDef rjw_genes_blocked_masturbation;
// Cum
public static readonly GeneDef rjw_genes_no_cum;
public static readonly GeneDef rjw_genes_much_cum;
public static readonly GeneDef rjw_genes_very_much_cum;
@ -139,6 +140,7 @@ namespace RJW_Genes
public static readonly GeneDef rjw_genes_infectious_homosexuality;
public static readonly GeneDef rjw_genes_infectious_hypersexuality;
public static readonly GeneDef rjw_genes_stretcher;
public static readonly GeneDef rjw_genes_infectious_blocked_masturbation;
//Other Defs
public static readonly XenotypeDef rjw_genes_succubus;

View file

@ -0,0 +1,26 @@
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(xxx), "can_masturbate")]
public class Patch_BlockedMasturbation
{
public void PostFix(Pawn pawn, ref bool __result)
{
if (pawn != null && !pawn.IsAnimal() && pawn.genes != null)
{
__result = __result
&& !pawn.genes.HasActiveGene(GeneDefOf.rjw_genes_blocked_masturbation)
&& !pawn.genes.HasActiveGene(GeneDefOf.rjw_genes_infectious_blocked_masturbation);
}
}
}
}

View file

@ -0,0 +1,120 @@
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
{
/// <summary>
/// This patch handles the changes produced by `rjw_genes_feminizer`.
/// It requires the hediff `rjw_genes_feminzation_in_progress` which is managed separately, in `Patch_HediffIncreaseOnSex`.
/// </summary>
[HarmonyPatch(typeof(SexUtility), "Aftersex")]
public static class Patch_Feminizer
{
const float MINOR_APPLICATION_CHANCE = 0.25f; // = 25% to have a minor transformation
const float MAJOR_APPLICATION_CHANCE = 0.10f; // = 10% to have a major transformation
public static void Postfix(SexProps props)
{
if (props == null || props.pawn == null || !props.hasPartner() || props.partner == null)
return;
if (props.pawn.IsAnimal() || props.partner.IsAnimal())
return;
ApplyFeminization(props.pawn);
ApplyFeminization(props.partner);
}
private static void ApplyFeminization(Pawn pawn)
{
if (pawn == null) return;
Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.rjw_genes_feminization_progress);
if (hediff == null) return;
var Random = new Random();
// DevNote: I first had a switch (hediff.SeverityLabel) but SeverityLabel was null.
// So now I have this approach which feels a bit more robust.
// I was thinking about looking for strings in the label, but I think that will break the logic in case of translations.
switch (hediff.Severity)
{
case float f when f > 0.8f:
{
if (Random.NextDouble() < MAJOR_APPLICATION_CHANCE)
MajorChange(pawn);
} break;
case float f when f > 0.6f:
{
if (Random.NextDouble() < MINOR_APPLICATION_CHANCE)
MinorChange(pawn);
} break;
default:
{
ModLog.Debug($"Tried to feminize {pawn} - severity of feminization was too low ({hediff.def} @ {hediff.Severity} - {hediff.Label})") ;
} break;
}
}
private static void MinorChange(Pawn pawn)
{
List<GeneDef> possibleGenes = new List<GeneDef>() {
GeneDefOf.rjw_genes_small_male_genitalia,
GeneDefOf.rjw_genes_big_breasts,
GeneDefOf.rjw_genes_no_cum,
DefDatabase<GeneDef>.GetNamed("Beard_NoBeardOnly"),
DefDatabase<GeneDef>.GetNamed("Hair_LongOnly")
};
GeneDef chosen = possibleGenes.RandomElement();
if (chosen == null)
{
ModLog.Warning($"Error in retrieving a minor-feminization gene for feminizing {pawn}");
return;
}
// DevNote: I could do "hasActiveGene" but that could lead to the gene being there but not active.
if (!pawn.genes.GenesListForReading.Any(p => p.def == chosen))
{
ModLog.Debug($"{pawn} experienced a minor feminization change; {pawn} got new gene {chosen}.");
pawn.genes.AddGene(chosen, !RJW_Genes_Settings.rjw_genes_genetic_disease_as_endogenes);
} else
{
ModLog.Debug($"Tryed a minor feminization for {pawn} - {pawn} already had {chosen}");
}
}
private static void MajorChange(Pawn pawn)
{
List<GeneDef> possibleGenes = new List<GeneDef>() {
GeneDefOf.rjw_genes_female_only,
GeneDefOf.rjw_genes_no_penis,
GeneDefOf.rjw_genes_minor_vulnerability,
};
GeneDef chosen = possibleGenes.RandomElement();
if (chosen == null)
{
ModLog.Warning($"Error in retrieving a minor-feminization gene for feminizing {pawn}");
return;
}
// DevNote: I could do "hasActiveGene" but that could lead to the gene being there but not active.
if (!pawn.genes.GenesListForReading.Any(p => p.def == chosen))
{
ModLog.Debug($"{pawn} experienced a major feminization change; {pawn} got new gene {chosen}.");
pawn.genes.AddGene(chosen, !RJW_Genes_Settings.rjw_genes_genetic_disease_as_endogenes);
}
else
{
ModLog.Debug($"Tryed a major feminization for {pawn} - {pawn} already had {chosen}");
ModLog.Debug($"Trying minor feminization for {pawn} instead ...");
MinorChange(pawn);
}
}
}
}

View file

@ -35,44 +35,87 @@ namespace RJW_Genes
if (pawn == null) return;
Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.rjw_genes_twinkification_progress);
if (hediff == null) return;
var Random = new Random();
switch (hediff.SeverityLabel)
// DevNote: I first had a switch (hediff.SeverityLabel) but SeverityLabel was null.
// So now I have this approach which feels a bit more robust.
// I was thinking about looking for strings in the label, but I think that will break the logic in case of translations.
switch (hediff.Severity)
{
case "severe":
case "critical":
case float f when f > 0.8f:
{
if (Random.NextDouble() < MAJOR_APPLICATION_CHANCE)
majorChange(pawn);
MajorChange(pawn);
} break;
case "minor":
case float f when f > 0.6f:
{
if (Random.NextDouble() < MINOR_APPLICATION_CHANCE)
minorChange(pawn);
MinorChange(pawn);
} break;
default:
{
ModLog.Debug($"Tried to twinkify {pawn} - severity of twinkification was too low ({hediff.def} @ {hediff.Severity} - {hediff.Label})") ;
} break;
}
}
private static void minorChange(Pawn pawn)
private static void MinorChange(Pawn pawn)
{
// Minor Infectious Vulnerability
// Smaller Genitalia
// Remove Beard
// Thin Body Type
List<GeneDef> possibleGenes = new List<GeneDef>() {
GeneDefOf.rjw_genes_small_male_genitalia,
DefDatabase<GeneDef>.GetNamed("Beard_NoBeardOnly"),
DefDatabase<GeneDef>.GetNamed("Body_Thin"),
GeneDefOf.rjw_genes_homosexual
};
GeneDef chosen = possibleGenes.RandomElement();
if (chosen == null)
{
ModLog.Warning($"Error in retrieving a minor-twinkification gene for twinkifying {pawn}");
return;
}
// DevNote: I could do "hasActiveGene" but that could lead to the gene being there but not active.
if (!pawn.genes.GenesListForReading.Any(p => p.def == chosen))
{
ModLog.Debug($"{pawn} experienced a minor twinkification change; {pawn} got new gene {chosen}.");
pawn.genes.AddGene(chosen, !RJW_Genes_Settings.rjw_genes_genetic_disease_as_endogenes);
} else
{
ModLog.Debug($"Tryed a minor twinkification for {pawn} - {pawn} already had {chosen}");
}
}
private static void majorChange(Pawn pawn)
private static void MajorChange(Pawn pawn)
{
// Final Gene-Pool should have:
// - Fragile (?)
// - Infectious Vulnerability
// - Infectious Homosexuality
// - Beauty
// - Fertile Anus
List<GeneDef> possibleGenes = new List<GeneDef>() {
GeneDefOf.rjw_genes_fertile_anus,
DefDatabase<GeneDef>.GetNamed("Beauty_Pretty"),
DefDatabase<GeneDef>.GetNamed("Delicate"),
GeneDefOf.rjw_genes_minor_vulnerability,
GeneDefOf.rjw_genes_infectious_homosexuality
};
pawn.genes.AddGene(GeneDefOf.rjw_genes_fertile_anus, !RJW_Genes_Settings.rjw_genes_genetic_disease_as_endogenes);
pawn.genes.AddGene(GeneDefOf.rjw_genes_infectious_homosexuality, !RJW_Genes_Settings.rjw_genes_genetic_disease_as_endogenes);
GeneDef chosen = possibleGenes.RandomElement();
if (chosen == null)
{
ModLog.Warning($"Error in retrieving a minor-twinkification gene for twinkifying {pawn}");
return;
}
// DevNote: I could do "hasActiveGene" but that could lead to the gene being there but not active.
if (!pawn.genes.GenesListForReading.Any(p => p.def == chosen))
{
ModLog.Debug($"{pawn} experienced a major twinkification change; {pawn} got new gene {chosen}.");
pawn.genes.AddGene(chosen, !RJW_Genes_Settings.rjw_genes_genetic_disease_as_endogenes);
}
else
{
ModLog.Debug($"Tryed a major twinkification for {pawn} - {pawn} already had {chosen}");
ModLog.Debug($"Trying minor twinkification for {pawn} instead ...");
MinorChange(pawn);
}
}
}
}

View file

@ -81,6 +81,7 @@
<Compile Include="Genes\Breeding\ConditionalStatAffecters\ConditionalStatAffecter_VeryManyChildren.cs" />
<Compile Include="Genes\Breeding\Genes\Gene_FerventOvipositor.cs" />
<Compile Include="Genes\Breeding\Genes\Gene_InsectIncubator.cs" />
<Compile Include="Genes\Breeding\Patches\Patch_BlockedMasturbation.cs" />
<Compile Include="Genes\Cum\Patch_LikesCumflation.cs" />
<Compile Include="Genes\Damage\Gene_Elasticity.cs" />
<Compile Include="Genes\Diseases\Defs\GeneticDiseaseExtension.cs" />
@ -197,6 +198,7 @@
<Compile Include="Genes\Special\Patches\Patch_OrgasmMytosis.cs" />
<Compile Include="Genes\Special\Patches\Patch_PregnancyOverwrite.cs" />
<Compile Include="Genes\Special\Patches\Patch_SexualTamer.cs" />
<Compile Include="Genes\Special\Patches\Patch_Feminizer.cs" />
<Compile Include="Genes\Special\Patches\Patch_Twinkifier.cs" />
<Compile Include="Genes\Special\Thoughts\ThoughtWorker_Aphrodisiac_Pheromones_Social.cs" />
<Compile Include="LetterDefOf.cs" />