diff --git a/1.4/Defs/PreceptDefs/Precepts_Incest.xml b/1.4/Defs/PreceptDefs/Precepts_Incest.xml index df0e490..ddcc32a 100644 --- a/1.4/Defs/PreceptDefs/Precepts_Incest.xml +++ b/1.4/Defs/PreceptDefs/Precepts_Incest.xml @@ -320,9 +320,6 @@ High 0 1000 - -
  • Zoophile
  • -
  • RSI_NonIncestuosMarriage diff --git a/Languages/English/Keyed/RJW_Sexperience.xml b/Languages/English/Keyed/RJW_Sexperience.xml index 9550b00..92fe2bc 100644 --- a/Languages/English/Keyed/RJW_Sexperience.xml +++ b/Languages/English/Keyed/RJW_Sexperience.xml @@ -9,4 +9,6 @@ not animal capable of sex is required + + forbidden by ideology \ No newline at end of file diff --git a/Source/IdeologyAddon/BloodRelationDegree.cs b/Source/IdeologyAddon/BloodRelationDegree.cs new file mode 100644 index 0000000..e23f9ee --- /dev/null +++ b/Source/IdeologyAddon/BloodRelationDegree.cs @@ -0,0 +1,9 @@ +namespace RJWSexperience.Ideology +{ + public enum BloodRelationDegree + { + CloseRelative, + FarRelative, + NotRelated + } +} diff --git a/Source/IdeologyAddon/DebugAction.cs b/Source/IdeologyAddon/DebugAction.cs index 9655f50..91f5b20 100644 --- a/Source/IdeologyAddon/DebugAction.cs +++ b/Source/IdeologyAddon/DebugAction.cs @@ -1,5 +1,7 @@ using rjw; using RJWSexperience.Ideology.HistoryEvents; +using RJWSexperience.Ideology.Patches; +using System.Collections.Generic; using System.Linq; using Verse; @@ -16,5 +18,20 @@ namespace RJWSexperience.Ideology RsiHistoryEventDefOf.RSI_NonIncestuosMarriage.RecordEventWithPartner(hero, p); RsiHistoryEventDefOf.RSI_NonIncestuosMarriage.RecordEventWithPartner(p, hero); } + + [DebugAction("RJW Sexperience Ideology", "Manual romance check", false, true, actionType = DebugActionType.Action, allowedGameStates = AllowedGameStates.PlayingOnMap)] + public static void DisplayDebugTable() + { + IEnumerable pawns = Find.CurrentMap.mapPawns.AllPawnsSpawned.Where(pawn => pawn.IsColonist); + + IEnumerable> columns = pawns + .Select(pawn => new TableDataGetter(pawn.Name.ToStringShort, (Pawn p) => Rimworld_Patch_IncestuousManualRomance.RsiIncestuous(p, pawn))); + + var name = new TableDataGetter("Name", (Pawn pawn) => pawn.Name.ToStringShort); + + TableDataGetter[] getters = (new List>() { name }).Concat(columns).ToArray(); + + DebugTables.MakeTablesDialog(pawns, getters); + } } } diff --git a/Source/IdeologyAddon/IdeoUtility.cs b/Source/IdeologyAddon/IdeoUtility.cs index 4b44cce..206b8eb 100644 --- a/Source/IdeologyAddon/IdeoUtility.cs +++ b/Source/IdeologyAddon/IdeoUtility.cs @@ -12,9 +12,9 @@ namespace RJWSexperience.Ideology if (ideo == null) return false; - if (ideo.HasPrecept(VariousDefOf.Submissive_Female) && pawn.gender == Gender.Female) + if (ideo.HasPrecept(RsiPreceptDefOf.Submissive_Female) && pawn.gender == Gender.Female) return true; - else if (ideo.HasPrecept(VariousDefOf.Submissive_Male) && pawn.gender == Gender.Male) + else if (ideo.HasPrecept(RsiPreceptDefOf.Submissive_Male) && pawn.gender == Gender.Male) return true; return false; diff --git a/Source/IdeologyAddon/IdeologyAddon.csproj b/Source/IdeologyAddon/IdeologyAddon.csproj index 651dd5b..0636e40 100644 --- a/Source/IdeologyAddon/IdeologyAddon.csproj +++ b/Source/IdeologyAddon/IdeologyAddon.csproj @@ -42,6 +42,7 @@ + @@ -59,7 +60,10 @@ + + + @@ -94,7 +98,7 @@ - 1.4.3537 + 1.4.3542 2.2.2 diff --git a/Source/IdeologyAddon/Patches/RJW_Patch_Ideo.cs b/Source/IdeologyAddon/Patches/RJW_Patch_Ideo.cs index f387f14..e52b361 100644 --- a/Source/IdeologyAddon/Patches/RJW_Patch_Ideo.cs +++ b/Source/IdeologyAddon/Patches/RJW_Patch_Ideo.cs @@ -213,14 +213,14 @@ namespace RJWSexperience.Ideology.Patches Ideo mainideo = playerfaction.ideos.PrimaryIdeo; if (mainideo != null) { - if (mainideo.HasPrecept(VariousDefOf.BabyFaction_AlwaysFather)) + if (mainideo.HasPrecept(RsiPreceptDefOf.BabyFaction_AlwaysFather)) { Pawn parent = baby.GetFather() ?? baby.GetMother(); ideo = parent.Ideo; return parent.Faction; } - else if (mainideo.HasPrecept(VariousDefOf.BabyFaction_AlwaysColony)) + else if (mainideo.HasPrecept(RsiPreceptDefOf.BabyFaction_AlwaysColony)) { ideo = mainideo; return playerfaction; @@ -241,7 +241,7 @@ namespace RJWSexperience.Ideology.Patches if (props.pawn?.Ideo == null || !props.hasPartner()) return; - if (props.partner.Ideo?.HasPrecept(VariousDefOf.ProselyzingByOrgasm) == true) + if (props.partner.Ideo?.HasPrecept(RsiPreceptDefOf.ProselyzingByOrgasm) == true) { // Pawn is the one having the orgasm // Partner is "giving" the orgasm, hence the pawn will be converted towards the partners ideology diff --git a/Source/IdeologyAddon/Patches/Rimworld_Patch.cs b/Source/IdeologyAddon/Patches/Rimworld_Patch.cs index e50098e..55f3ba6 100644 --- a/Source/IdeologyAddon/Patches/Rimworld_Patch.cs +++ b/Source/IdeologyAddon/Patches/Rimworld_Patch.cs @@ -4,6 +4,7 @@ using rjw; using RJWSexperience.Ideology.HistoryEvents; using RJWSexperience.Ideology.Precepts; using System.Collections.Generic; +using System.Linq; using Verse; namespace RJWSexperience.Ideology.Patches @@ -53,4 +54,55 @@ namespace RJWSexperience.Ideology.Patches } } } + + public static class Rimworld_Patch_IncestuousManualRomance + { + /// + /// Override incestuous check in the manual romance + /// + /// Pawn to try do romance + /// Target for romance + /// Result of the original method + /// Run original method implementation + [HarmonyPatch(typeof(RelationsUtility), "Incestuous")] + public static bool Prefix(Pawn one, Pawn two, ref bool __result) + { + __result = RsiIncestuous(one, two); + return false; + } + + /// + /// Check if Ideology allows romance attempt + /// + /// Pawn to try do romance + /// Target for romance + /// Forbid romance option + public static bool RsiIncestuous(Pawn one, Pawn two) + { + PreceptDef incestuousPrecept = one.Ideo?.PreceptsListForReading.Select(precept => precept.def).FirstOrFallback(def => def.issue == VariousDefOf.Incestuos); + BloodRelationDegree relationDegree = RelationHelpers.GetBloodRelationDegree(one, two); + + if (incestuousPrecept == null || + incestuousPrecept == RsiPreceptDefOf.Incestuos_Disapproved || + incestuousPrecept == RsiPreceptDefOf.Incestuos_Forbidden) + { + return relationDegree < BloodRelationDegree.NotRelated; + } + else if (incestuousPrecept == RsiPreceptDefOf.Incestuos_Free) + { + return false; + } + else if (incestuousPrecept == RsiPreceptDefOf.Incestuos_Disapproved_CloseOnly) + { + return relationDegree == BloodRelationDegree.CloseRelative; + } + else if (incestuousPrecept == RsiPreceptDefOf.Incestuos_IncestOnly) + { + return relationDegree == BloodRelationDegree.NotRelated; + } + + // Modded incestuous precept? + return true; + } + } } diff --git a/Source/IdeologyAddon/RelationHelpers.cs b/Source/IdeologyAddon/RelationHelpers.cs new file mode 100644 index 0000000..2a5fe77 --- /dev/null +++ b/Source/IdeologyAddon/RelationHelpers.cs @@ -0,0 +1,47 @@ +using RimWorld; +using System.Linq; +using Verse; + +namespace RJWSexperience.Ideology +{ + public static class RelationHelpers + { + /// + /// Get degree of blood relation between two pawns + /// + public static BloodRelationDegree GetBloodRelationDegree(Pawn pawn, Pawn partner) + { + PawnRelationDef closestBloodRelation = pawn + .GetRelations(partner) + ?.Where(def => def.familyByBloodRelation) + ?.OrderByDescending(def => def.importance) + ?.FirstOrFallback(); + + if (closestBloodRelation == null) + { + return BloodRelationDegree.NotRelated; + } + + return GetBloodRelationDegree(closestBloodRelation); + } + + /// + /// Get degree of blood relation for a relationDef + /// + public static BloodRelationDegree GetBloodRelationDegree(PawnRelationDef relationDef) + { + if (!relationDef.familyByBloodRelation) + { + return BloodRelationDegree.NotRelated; + } + else if (relationDef.importance <= PawnRelationDefOf.Cousin.importance) + { + return BloodRelationDegree.FarRelative; + } + else + { + return BloodRelationDegree.CloseRelative; + } + } + } +} diff --git a/Source/IdeologyAddon/Rituals/RitualRoles.cs b/Source/IdeologyAddon/Rituals/RitualRoles.cs index 0d26048..691bb28 100644 --- a/Source/IdeologyAddon/Rituals/RitualRoles.cs +++ b/Source/IdeologyAddon/Rituals/RitualRoles.cs @@ -92,7 +92,7 @@ namespace RJWSexperience.Ideology public static bool CanBeBreeder(Pawn animal, Precept_Ritual precept) { - if (precept != null && precept.ideo.HasPrecept(VariousDefOf.Bestiality_OnlyVenerated) && !precept.ideo.IsVeneratedAnimal(animal)) + if (precept != null && precept.ideo.HasPrecept(RsiPreceptDefOf.Bestiality_OnlyVenerated) && !precept.ideo.IsVeneratedAnimal(animal)) { return false; } diff --git a/Source/IdeologyAddon/RomanceChanceFactorHelpers.cs b/Source/IdeologyAddon/RomanceChanceFactorHelpers.cs new file mode 100644 index 0000000..298916c --- /dev/null +++ b/Source/IdeologyAddon/RomanceChanceFactorHelpers.cs @@ -0,0 +1,108 @@ +using RimWorld; +using System.Collections.Generic; +using System.Linq; +using Verse; + +namespace RJWSexperience.Ideology +{ + public static class RomanceChanceFactorHelpers + { + /// + /// Default value for parent relation + /// + private const float parentRomanceChanceFactor = 0.03f; + + /// + /// Get ideology adjusted romanceChanceFactor + /// + public static float GetRomanceChanceFactor(Pawn pawn, Pawn partner) + { + IEnumerable relations = pawn.GetRelations(partner).Where(def => def.familyByBloodRelation); + PreceptDef incestuousPrecept = pawn.Ideo?.PreceptsListForReading.Select(precept => precept.def).FirstOrFallback(def => def.issue == VariousDefOf.Incestuos); + float romanceChanceFactor = 1f; + + if (!relations.Any()) + { + if (incestuousPrecept == RsiPreceptDefOf.Incestuos_IncestOnly) + { + return parentRomanceChanceFactor; + } + else + { + return romanceChanceFactor; + } + } + + foreach (PawnRelationDef relationDef in relations) + { + romanceChanceFactor *= GetRomanceChanceFactor(relationDef, incestuousPrecept); + } + + return romanceChanceFactor; + } + + /// + /// Get ideology adjusted romanceChanceFactor for the relation + /// + public static float GetRomanceChanceFactor(PawnRelationDef relationDef, PreceptDef incestuousPrecept) + { + if (incestuousPrecept == null || incestuousPrecept == RsiPreceptDefOf.Incestuos_Disapproved) // Default game setup + { + return relationDef.romanceChanceFactor; + } + + if (incestuousPrecept == RsiPreceptDefOf.Incestuos_Free) + { + return 1f; + } + else if (incestuousPrecept == RsiPreceptDefOf.Incestuos_Disapproved_CloseOnly) + { + if (relationDef.familyByBloodRelation && relationDef.importance > PawnRelationDefOf.Cousin.importance) + { + return relationDef.romanceChanceFactor; + } + else + { + return 1f; + } + } + else if (incestuousPrecept == RsiPreceptDefOf.Incestuos_Forbidden) + { + if (relationDef.familyByBloodRelation) + { + return parentRomanceChanceFactor; + } + } + else if (incestuousPrecept == RsiPreceptDefOf.Incestuos_IncestOnly) + { + if (!relationDef.familyByBloodRelation) + { + return parentRomanceChanceFactor; + } + else + { + return 1f; + } + } + + return relationDef.romanceChanceFactor; + } + + [DebugAction("RJW Sexperience Ideology", "Show romanceChanceFactors", false, true, actionType = DebugActionType.Action, allowedGameStates = AllowedGameStates.Entry)] + public static void DisplayDebugTable() + { + IEnumerable incestuousPrecepts = DefDatabase + .AllDefsListForReading + .Where(def => def.issue == VariousDefOf.Incestuos); + + IEnumerable> preceptGetters = incestuousPrecepts + .Select(precept => new TableDataGetter(precept.defName,(PawnRelationDef rel) => GetRomanceChanceFactor(rel, precept))); + + var relName = new TableDataGetter("Relation Def", (PawnRelationDef rel) => rel.defName); + + TableDataGetter[] getters = (new List>() { relName }).Concat(preceptGetters).ToArray(); + + DebugTables.MakeTablesDialog(DefDatabase.AllDefsListForReading, getters); + } + } +} \ No newline at end of file diff --git a/Source/IdeologyAddon/RsiHistoryEventDefOf.cs b/Source/IdeologyAddon/RsiHistoryEventDefOf.cs index 0155d66..4cb9bc7 100644 --- a/Source/IdeologyAddon/RsiHistoryEventDefOf.cs +++ b/Source/IdeologyAddon/RsiHistoryEventDefOf.cs @@ -5,14 +5,14 @@ namespace RJWSexperience.Ideology [DefOf] public static class RsiHistoryEventDefOf { - [MayRequireIdeology] public static readonly HistoryEventDef RSI_SexWithAnimal; - [MayRequireIdeology] public static readonly HistoryEventDef RSI_Raped; - [MayRequireIdeology] public static readonly HistoryEventDef RSI_NonIncestuosMarriage; - [MayRequireIdeology] public static readonly HistoryEventDef RSI_NonIncestuosSex; - [MayRequireIdeology] public static readonly HistoryEventDef RSI_SexWithCorpse; - [MayRequireIdeology] public static readonly HistoryEventDef RSI_VirginTaken; - [MayRequireIdeology] public static readonly HistoryEventDef RSI_VirginStolen; - [MayRequireIdeology] public static readonly HistoryEventDef RSI_TookVirgin; - [MayRequireIdeology] public static readonly HistoryEventDef RSI_Masturbated; + public static readonly HistoryEventDef RSI_SexWithAnimal; + public static readonly HistoryEventDef RSI_Raped; + public static readonly HistoryEventDef RSI_NonIncestuosMarriage; + public static readonly HistoryEventDef RSI_NonIncestuosSex; + public static readonly HistoryEventDef RSI_SexWithCorpse; + public static readonly HistoryEventDef RSI_VirginTaken; + public static readonly HistoryEventDef RSI_VirginStolen; + public static readonly HistoryEventDef RSI_TookVirgin; + public static readonly HistoryEventDef RSI_Masturbated; } } diff --git a/Source/IdeologyAddon/RsiPreceptDefOf.cs b/Source/IdeologyAddon/RsiPreceptDefOf.cs new file mode 100644 index 0000000..977954a --- /dev/null +++ b/Source/IdeologyAddon/RsiPreceptDefOf.cs @@ -0,0 +1,20 @@ +using RimWorld; + +namespace RJWSexperience.Ideology +{ + [DefOf] + public static class RsiPreceptDefOf + { + public static readonly PreceptDef Incestuos_Free; + public static readonly PreceptDef Incestuos_Disapproved_CloseOnly; + public static readonly PreceptDef Incestuos_Disapproved; + public static readonly PreceptDef Incestuos_Forbidden; + public static readonly PreceptDef Incestuos_IncestOnly; + public static readonly PreceptDef Bestiality_OnlyVenerated; + public static readonly PreceptDef BabyFaction_AlwaysFather; + public static readonly PreceptDef BabyFaction_AlwaysColony; + public static readonly PreceptDef Submissive_Male; + public static readonly PreceptDef Submissive_Female; + public static readonly PreceptDef ProselyzingByOrgasm; + } +} \ No newline at end of file diff --git a/Source/IdeologyAddon/VariousDefOf.cs b/Source/IdeologyAddon/VariousDefOf.cs index fb926ce..19a104d 100644 --- a/Source/IdeologyAddon/VariousDefOf.cs +++ b/Source/IdeologyAddon/VariousDefOf.cs @@ -13,15 +13,10 @@ namespace RJWSexperience.Ideology public static readonly JobDef GettinDrugSex; public static readonly JobDef DrugMasturbate; - [MayRequireIdeology] public static readonly MemeDef Zoophile; - [MayRequireIdeology] public static readonly MemeDef Rapist; - [MayRequireIdeology] public static readonly MemeDef Necrophile; - [MayRequireIdeology] public static readonly PreceptDef Bestiality_OnlyVenerated; - [MayRequireIdeology] public static readonly PreceptDef BabyFaction_AlwaysFather; - [MayRequireIdeology] public static readonly PreceptDef BabyFaction_AlwaysColony; - [MayRequireIdeology] public static readonly PreceptDef Submissive_Male; - [MayRequireIdeology] public static readonly PreceptDef Submissive_Female; - [MayRequireIdeology] public static readonly PreceptDef ProselyzingByOrgasm; + public static readonly MemeDef Zoophile; + public static readonly MemeDef Rapist; + public static readonly MemeDef Necrophile; + public static readonly IssueDef Incestuos; [MayRequireBiotech] public static readonly HediffDef PregnantHuman; } }