diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b63394..b087e0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,7 @@ 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. - 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 **Fixes:** diff --git a/Common/Defs/GeneDefs/GeneDefs_Breeding.xml b/Common/Defs/GeneDefs/GeneDefs_Breeding.xml index b3a9844..832621a 100644 --- a/Common/Defs/GeneDefs/GeneDefs_Breeding.xml +++ b/Common/Defs/GeneDefs/GeneDefs_Breeding.xml @@ -152,4 +152,16 @@ 1 0 + + + rjw_genes_pregnancy_overwrite + + Carriers of this gene can 'overwrite' an existing pregnancy, keeping the progress but effectively replacing the father. + Genes/Icons/RJW_Genes_PheromoneSpit + 75 + + 4 + -2 + + \ No newline at end of file diff --git a/Common/Defs/HistoryEventDefs/DiseaseHistoryEventDefs.xml b/Common/Defs/HistoryEventDefs/DiseaseHistoryEventDefs.xml new file mode 100644 index 0000000..488fa5f --- /dev/null +++ b/Common/Defs/HistoryEventDefs/DiseaseHistoryEventDefs.xml @@ -0,0 +1,18 @@ + + + + rjw_genes_GoodwillChangedReason_StoleGene + + + + + rjw_genes_GoodwillChangedReason_infected_with_disease + + + + + rjw_genes_GoodwillChangedReason_spread_genetic_disease + + + + \ No newline at end of file diff --git a/Common/Defs/HistoryEventDefs/SpecialHistoryEventDefs.xml b/Common/Defs/HistoryEventDefs/SpecialHistoryEventDefs.xml new file mode 100644 index 0000000..c5668ad --- /dev/null +++ b/Common/Defs/HistoryEventDefs/SpecialHistoryEventDefs.xml @@ -0,0 +1,13 @@ + + + + rjw_genes_GoodwillChangedReason_aged_pawn_with_sex_gene + + + + + rjw_genes_GoodwillChangedReason_youthed_pawn_with_sex_gene + + + + \ No newline at end of file diff --git a/Source/Common/Helpers/FactionUtility.cs b/Source/Common/Helpers/FactionUtility.cs new file mode 100644 index 0000000..10a4e7c --- /dev/null +++ b/Source/Common/Helpers/FactionUtility.cs @@ -0,0 +1,42 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; + +namespace RJW_Genes +{ + public class FactionUtility + { + + /// + /// Tries to change the goodwill between the factions of two pawns. + /// Exceptions when nothing happens: + /// - Pawns, or Pawns Factions, are null + /// - The `actors` Faction is not the players faction + /// - Both pawns have the same faction + /// - The Event is not found + /// + /// The pawn that initiated a faction-goodwill change by his actions + /// The pawn that was harmed/affected by the action + /// The event defname, for proper reporting + /// How much (positive or negative) the goodwill will change + public static void HandleFactionGoodWillPenalties(Pawn actor, Pawn target, string HistoryEventDefname, int goodWillChange, bool canSendHostileLetter=true) + { + if (actor == null) return; + if (target == null) return; + if ( + target.Faction != null && actor.Faction != null + && target.Faction != actor.Faction + && target.Faction != Faction.OfPlayer) + { + HistoryEventDef reason = DefDatabase.GetNamedSilentFail(HistoryEventDefname); + if (reason == null) return; + + target.Faction.TryAffectGoodwillWith(actor.Faction, goodWillChange, true, canSendHostileLetter, reason, target); + } + } + } +} diff --git a/Source/GeneDefOf.cs b/Source/GeneDefOf.cs index 873df6f..f4a2d08 100644 --- a/Source/GeneDefOf.cs +++ b/Source/GeneDefOf.cs @@ -107,6 +107,7 @@ namespace RJW_Genes public static readonly GeneDef rjw_genes_sex_tamer; public static readonly GeneDef rjw_genes_sexual_genetic_swap; public static readonly GeneDef rjw_genes_sexual_genetic_thief; + public static readonly GeneDef rjw_genes_pregnancy_overwrite; // Cosmetic public static readonly GeneDef rjw_genes_succubus_tail; diff --git a/Source/Genes/Diseases/Patches/Patch_AfterSexUtility_ApplyGeneticInfectors.cs b/Source/Genes/Diseases/Patches/Patch_AfterSexUtility_ApplyGeneticInfectors.cs index 1ee1e9f..06b0998 100644 --- a/Source/Genes/Diseases/Patches/Patch_AfterSexUtility_ApplyGeneticInfectors.cs +++ b/Source/Genes/Diseases/Patches/Patch_AfterSexUtility_ApplyGeneticInfectors.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using RimWorld; using rjw; using System; using System.Collections.Generic; @@ -14,6 +15,9 @@ namespace RJW_Genes [HarmonyPatch(typeof(SexUtility), "Aftersex")] public class Patch_AfterSexUtility_ApplyGeneticInfectors { + + const int FACTION_GOODWILL_CHANGE = -3; + public static void Postfix(SexProps props) { if (props == null || props.pawn == null || props.partner == null) return; @@ -48,7 +52,10 @@ namespace RJW_Genes continue; if ((new Random()).NextDouble() < application_chance) + { partner.genes.AddGene(diseaseGeneDef, !RJW_Genes_Settings.rjw_genes_genetic_disease_as_endogenes); + FactionUtility.HandleFactionGoodWillPenalties(infector, partner, "rjw_genes_GoodwillChangedReason_infected_with_disease",FACTION_GOODWILL_CHANGE); + } } } } diff --git a/Source/Genes/Diseases/Patches/Patch_AftersexUtility_TransferGeneticDiseases.cs b/Source/Genes/Diseases/Patches/Patch_AftersexUtility_TransferGeneticDiseases.cs index e33079f..a00d40f 100644 --- a/Source/Genes/Diseases/Patches/Patch_AftersexUtility_TransferGeneticDiseases.cs +++ b/Source/Genes/Diseases/Patches/Patch_AftersexUtility_TransferGeneticDiseases.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using RimWorld; using rjw; using System; using System.Collections.Generic; @@ -13,6 +14,8 @@ namespace RJW_Genes public class Patch_AftersexUtility_TransferGeneticDiseases { + public const int FACTION_GOODWILL_CHANGE = -2; + public static void Postfix(SexProps props) { if (!RJW_Genes_Settings.rjw_genes_genetic_disease_spread) return; @@ -48,6 +51,7 @@ namespace RJW_Genes if ((new Random()).NextDouble() <= DiseaseHelper.LookupDiseaseInfectionChance(disease)) { infected.genes.AddGene(disease, !RJW_Genes_Settings.rjw_genes_genetic_disease_as_endogenes); + FactionUtility.HandleFactionGoodWillPenalties(infector, infected, "rjw_genes_GoodwillChangedReason_spread_genetic_disease", FACTION_GOODWILL_CHANGE); } } } diff --git a/Source/Genes/Special/Patches/Patch_AgeDrain.cs b/Source/Genes/Special/Patches/Patch_AgeDrain.cs index ab159b1..059baef 100644 --- a/Source/Genes/Special/Patches/Patch_AgeDrain.cs +++ b/Source/Genes/Special/Patches/Patch_AgeDrain.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using RimWorld; using rjw; using System; using System.Collections.Generic; @@ -24,6 +25,8 @@ namespace RJW_Genes.Genes.Special // 18 Years * 60 Days / Year * 60k Ticks/Day + 1 for safety const long MINIMUM_AGE_FALLBACK = 18 * 60 * 60000 + 1; + const int FACTION_GOODWILL_CHANGE = -1; + public static void Postfix(SexProps props) { if (props == null || props.pawn == null || props.partner == null || props.partner.IsAnimal() ) @@ -80,6 +83,9 @@ namespace RJW_Genes.Genes.Special if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"[Sexual Age Drainer] {receiver} was too young ({receiver.ageTracker.AgeBiologicalYears}), and remains unchanged."); } + + FactionUtility.HandleFactionGoodWillPenalties(receiver, giver, "rjw_genes_GoodwillChangedReason_aged_pawn_with_sex_gene",FACTION_GOODWILL_CHANGE); } + } } diff --git a/Source/Genes/Special/Patches/Patch_GeneticSexThief.cs b/Source/Genes/Special/Patches/Patch_GeneticSexThief.cs index ecc2201..d61f0bd 100644 --- a/Source/Genes/Special/Patches/Patch_GeneticSexThief.cs +++ b/Source/Genes/Special/Patches/Patch_GeneticSexThief.cs @@ -1,4 +1,6 @@ using HarmonyLib; +using RimWorld; +using RimWorld.Planet; using rjw; using System; using System.Collections.Generic; @@ -13,6 +15,9 @@ namespace RJW_Genes [HarmonyPatch(typeof(SexUtility), "Aftersex")] public class Patch_GeneticSexThief { + + public const int FACTION_GOODWILL_CHANGE = -10; + public static void Postfix(SexProps props) { if (props == null || props.pawn == null || props.partner == null || props.partner.IsAnimal()) @@ -62,6 +67,8 @@ namespace RJW_Genes stealer.genes.AddGene(stolenGene.def, AddAsXenogene); victim.genes.RemoveGene(stolenGene); + + FactionUtility.HandleFactionGoodWillPenalties(stealer, victim, "rjw_genes_GoodwillChangedReason_StoleGene", FACTION_GOODWILL_CHANGE); } } diff --git a/Source/Genes/Special/Patches/Patch_PregnancyOverwrite.cs b/Source/Genes/Special/Patches/Patch_PregnancyOverwrite.cs new file mode 100644 index 0000000..b7b35a6 --- /dev/null +++ b/Source/Genes/Special/Patches/Patch_PregnancyOverwrite.cs @@ -0,0 +1,80 @@ +using HarmonyLib; +using RimWorld; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using static HarmonyLib.Code; + +namespace RJW_Genes +{ + [HarmonyPatch(typeof(SexUtility), "Aftersex")] + public class Patch_PregnancyOverwrite + { + public const int FACTION_GOODWILL_CHANGE = -5; + + public static void Postfix(SexProps props) + { + if (props == null || props.pawn == null || props.partner == null || props.partner.IsAnimal()) + { + return; + } + + Pawn pawn = props.pawn; + Pawn partner = props.partner; + + if (pawn.genes == null || partner.genes == null) return; + + // If both have the swap gene, nothing happens + if (GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_pregnancy_overwrite) + && GeneUtility.HasGeneNullCheck(partner, GeneDefOf.rjw_genes_pregnancy_overwrite)) + return; + + // If both are pregnant, we have some weird interaction. Exit Early + if (pawn.IsPregnant() && partner.IsPregnant()) + return; + // If neither are pregnant, nothing can happen. + if (!pawn.IsPregnant() && !partner.IsPregnant()) + return; + + ModLog.Debug("Firing Pregnancy Overwrite Patch - Passed Simple NullChecks"); + + if (pawn.IsPregnant() + && GeneUtility.HasGeneNullCheck(partner, GeneDefOf.rjw_genes_pregnancy_overwrite)) + TryReplacePregnancy(partner, pawn); + + if (partner.IsPregnant() + && GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_pregnancy_overwrite)) + TryReplacePregnancy(pawn, partner); + } + + public static void TryReplacePregnancy(Pawn replacer, Pawn pregnant) + { + // TODO: This mostly works, but needs some more checks. + // - Check if there is a pregnancy occurring + // - Check for Disease Immunity + // - Add Faction Penalties + + ModLog.Debug($"Firing Pregnancy Overwrite for {replacer} and {pregnant}"); + + // The "CanImpregnate" does not work as I want, as the pawn is already pregnant, so it wont allow to be pregnated. + //PregnancyHelper.CanImpregnate(pawn, partner, props.sexType) + + Hediff pregnancyHediff = PregnancyUtility.GetPregnancyHediff(pregnant); + if (pregnancyHediff == null) + return; + + float gestationProgress = pregnancyHediff.Severity; + + PregnancyUtility.ForceEndPregnancy(pregnant); + + PregnancyHelper.StartVanillaPregnancy(pregnant, replacer); + Hediff replacementPregnancyHediff = PregnancyUtility.GetPregnancyHediff(pregnant); + replacementPregnancyHediff.Severity = gestationProgress; + } + + } +} diff --git a/Source/Genes/Special/Patches/Patch_Youth_Fountain.cs b/Source/Genes/Special/Patches/Patch_Youth_Fountain.cs index d810bc6..96ba204 100644 --- a/Source/Genes/Special/Patches/Patch_Youth_Fountain.cs +++ b/Source/Genes/Special/Patches/Patch_Youth_Fountain.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using RimWorld; using rjw; using System; using System.Collections.Generic; @@ -23,6 +24,8 @@ namespace RJW_Genes.Genes.Special // 18 Years * 60 Days / Year * 60k Ticks/Day + 1 for safety const long MINIMUM_AGE_FALLBACK = 18 * 60 * 60000 + 1; + const int FACTION_GOODWILL_CHANGE = 1; + public static void Postfix(SexProps props) { if (props == null || props.pawn == null || props.partner == null || props.partner.IsAnimal()) @@ -39,10 +42,12 @@ namespace RJW_Genes.Genes.Special if (GeneUtility.IsYouthFountain(props.pawn)) { ChangeAgeForPawn(props.partner, props.pawn); + FactionUtility.HandleFactionGoodWillPenalties(props.pawn, props.partner, "rjw_genes_GoodwillChangedReason_youthed_pawn_with_sex_gene",+1); } if (GeneUtility.IsYouthFountain(props.partner)) { ChangeAgeForPawn(props.pawn,props.partner); + FactionUtility.HandleFactionGoodWillPenalties(props.pawn, props.partner, "rjw_genes_GoodwillChangedReason_youthed_pawn_with_sex_gene", +1); } } @@ -65,6 +70,7 @@ namespace RJW_Genes.Genes.Special ModLog.Message($"[Youth Fountain] {ToYouth} was too young ({ToYouth.ageTracker.AgeBiologicalYears}), and remains unchanged."); } + } } diff --git a/Source/Rjw-Genes.csproj b/Source/Rjw-Genes.csproj index 306bcb7..8354632 100644 --- a/Source/Rjw-Genes.csproj +++ b/Source/Rjw-Genes.csproj @@ -61,6 +61,7 @@ + @@ -193,6 +194,7 @@ +