diff --git a/About/Manifest.xml b/About/Manifest.xml index 522aa5e..2589c5d 100644 --- a/About/Manifest.xml +++ b/About/Manifest.xml @@ -1,7 +1,7 @@ RJW-Genes - 1.3.1 + 2.0.0
  • RimJobWorld
  • HugsLib
  • diff --git a/CHANGELOG.md b/CHANGELOG.md index ecc3cd5..6baf611 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # 2.0.0 +**Summary**: + +- 1.5 Support +- Femboys, MPReg +- Couple Implants around Fertility / Sex / Pregnancy +- Hive Removal (to be reintroduced somewhere else) +- Licentia Genes became placeholders, no functions until Licentia is on 1.5 + **Additions**: - initial Rimworld 1.5 thanks to @jaaldabaoth @@ -12,7 +20,7 @@ - LimbicStimulator / Scrambler thanks to @jaaldabaoth. See [Scrambler Description](Common/Defs/ThingDefs/Scrambler.xml) and [Limbic Stimulator](./Common/Defs/ThingDefs/LimbicStimulator.xml) - Bioscaffold that allows for faster pregnancies. thanks to @jaaldabaoth. See [its description](./Common/Defs/ThingDefs/Bioscaffold.xml) - Multi-Pregnancy Gene thanks to @jaaldabaoth - +- Many genes have settings configurable in their xml - tick speeds and distances. **Changes**: @@ -21,16 +29,19 @@ - Highmates "Initiate Loving" uses Succubus "Seduce" ability, thanks to @jaaldabaoth - Slider for Evergrowth Tick-Speed, thanks to @jaaldabaoth - Resizing Age for resizing Genes can be set in Settings @jaaldabaoth -- Licentia-Stretching related genes are only placeholders, as Licentia is not 1.5 yet +- **Licentia related genes are only placeholders**, as Licentia is not 1.5 yet +- InsectIncubator only does self-fertilization now, but does not increase storage capacities for eggs anymore +- Some Genes (GenitaliaTypes, Cum, some others) cannot be in quest-rewards anymore. Special, Size, Breeding and Lifeforce genes still can be quest rewards. **Fixes:** - Small changes to drawing Succubus Wings - Minor Format changes to lots of XML files +- Pawns with ONLY an Archotech penis will not give Fertilin, and will not receive debuffs (Fixes #71) **Hidden Changes:** -- Patches for "Same Mother" / "Same Father" to account for Male-Pregs. This should only extend behaviour but be warned. +- Patches for "Same Mother" / "Same Father" to account for Male-Pregs. This should only extend behaviour but be warned a bit. - Patches to RJW-Pregnancy Helper to account for Male Pregs. - Some replacements from `hasGene` to `hasActiveGene` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 486a3b9..b596a24 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,6 +17,8 @@ But please consider also the following: - Shabalox (MechBreeding, InsectBreeding, Animal Gene Inheritance) - WasMachenDennSachen (Various Icons) +- Jaaldabaoth (1.5 Migration, MPreg, Femboys) +- Flock-of-Birds (Cosmetic Genitalia per XML) ## Other Credits diff --git a/Common/Assemblies/Rjw-Genes.dll b/Common/Assemblies/Rjw-Genes.dll index 7322e25..fac437a 100644 Binary files a/Common/Assemblies/Rjw-Genes.dll and b/Common/Assemblies/Rjw-Genes.dll differ diff --git a/Common/Defs/AbilityDefs/Ability_CocoonWeaver.xml b/Common/Defs/AbilityDefs/Ability_CocoonWeaver.xml new file mode 100644 index 0000000..2a1577a --- /dev/null +++ b/Common/Defs/AbilityDefs/Ability_CocoonWeaver.xml @@ -0,0 +1,34 @@ + + + + rjw_genes_ability_cocoonweaver + + Weaves the victim into a (self-sustaining) cocoon. The victim cannot move, but can be bred. + Genes/Icons/Cocoon + true + true + false + Mote_CocoonStencil + CocoonWeave + CastAbilityOnThingMelee + 404 + + 30000 + + Verb_CastAbilityTouch + false + -1 + 15 + + true + false + false + false + true + + + +
  • + + + \ No newline at end of file diff --git a/Common/Defs/Effects/cocoonweave.xml b/Common/Defs/Effects/cocoonweave.xml new file mode 100644 index 0000000..573ccd2 --- /dev/null +++ b/Common/Defs/Effects/cocoonweave.xml @@ -0,0 +1,37 @@ + + + + + CocoonWeave + +
  • + SubEffecter_SprayerChance + BloodSplash + 0.15 + 2~3 + 0.75~1.5 + (244, 244, 244) + RandomDrawPosOnTarget + true +
  • + + + + + Mote_CocoonStencil + MoteAttached + Terrain + + 0.1 + 0.4 + 999999 + True + + + Graphic_PawnBodySilhouette + PawnSilhouetteStencil + Things/Mote/Transparent + + + +
    \ No newline at end of file diff --git a/Common/Defs/GeneDefs/GeneDefs_Breeding.xml b/Common/Defs/GeneDefs/GeneDefs_Breeding.xml index 1495b43..6d16ee6 100644 --- a/Common/Defs/GeneDefs/GeneDefs_Breeding.xml +++ b/Common/Defs/GeneDefs/GeneDefs_Breeding.xml @@ -2,28 +2,31 @@ - + + rjw_genes_breeding + + +
  • + Genes/Icons/RJW_Genes_Endogene_Background + Genes/Icons/RJW_Genes_Xenogene_Background +
  • +
    +
    + + + rjw_genes_mechbreeder Pawns with this gene are able to birth mechanoids unharmed. World/WorldObjects/Expanding/Mechanoids 51 - rjw_genes_breeding 1 -1 - - -
  • - Genes/Icons/RJW_Genes_Endogene_Background - Genes/Icons/RJW_Genes_Xenogene_Background -
  • -
    - + rjw_genes_zoophile - rjw_genes_breeding Xenotypes with this Gene are Zoophile. Genes/Icons/Zoophile 54 @@ -32,22 +35,46 @@ Zoophile - - -
  • - Genes/Icons/RJW_Genes_Endogene_Background - Genes/Icons/RJW_Genes_Xenogene_Background -
  • -
    - + rjw_genes_fertile_anus - rjw_genes_breeding Xenotypes with this gene have a functional uterus connected to the anal cavity even for males Genes/Icons/Fertile_anus 54 + + rjw_genes_insectincubator + + RJW_Genes.Gene_InsectIncubator + Pawns with this gene fertilize insect eggs that are placed inside them. + Genes/Icons/Egg + 52 + 1 + -1 + + + + rjw_genes_insectbreeder + + Pawns with this gene are able to fertilize eggs with any fertile penis. + Genes/Icons/Insect_Breeder + 53 + 1 + -1 + + + + rjw_genes_fervent_ovipositor + + RJW_Genes.Gene_FerventOvipositor + Pawns that have a female (egg producing) ovipositor produce eggs at drastically increased speed. + Genes/Icons/Fervent_Ovipositor + 55 + 1 + -1 + +
    \ No newline at end of file diff --git a/Common/Defs/GeneDefs/GeneDefs_Cum.xml b/Common/Defs/GeneDefs/GeneDefs_Cum.xml index 28b841a..c031645 100644 --- a/Common/Defs/GeneDefs/GeneDefs_Cum.xml +++ b/Common/Defs/GeneDefs/GeneDefs_Cum.xml @@ -5,7 +5,7 @@
  • CumAmount
  • - + false
  • Genes/Icons/RJW_Genes_Endogene_Background diff --git a/Common/Defs/GeneDefs/GeneDefs_ExtraGenitalia.xml b/Common/Defs/GeneDefs/GeneDefs_ExtraGenitalia.xml index 9cbbb50..c9d3c17 100644 --- a/Common/Defs/GeneDefs/GeneDefs_ExtraGenitalia.xml +++ b/Common/Defs/GeneDefs/GeneDefs_ExtraGenitalia.xml @@ -3,6 +3,7 @@ rjw_genes_genitalia_extras + false
  • Genes/Icons/RJW_Genes_Endogene_Background diff --git a/Common/Defs/GeneDefs/GeneDefs_GenitaliaTypes.xml b/Common/Defs/GeneDefs/GeneDefs_GenitaliaTypes.xml index d637209..6d173b9 100644 --- a/Common/Defs/GeneDefs/GeneDefs_GenitaliaTypes.xml +++ b/Common/Defs/GeneDefs/GeneDefs_GenitaliaTypes.xml @@ -7,7 +7,7 @@
  • GenitalType
  • - true + false 0 diff --git a/Common/Defs/GeneDefs/GeneDefs_Reproduction.xml b/Common/Defs/GeneDefs/GeneDefs_Reproduction.xml index 63b1100..3dbc43e 100644 --- a/Common/Defs/GeneDefs/GeneDefs_Reproduction.xml +++ b/Common/Defs/GeneDefs/GeneDefs_Reproduction.xml @@ -14,6 +14,7 @@ + false
  • Genes/Icons/RJW_Genes_Endogene_Background @@ -36,6 +37,7 @@
  • + false
  • Genes/Icons/RJW_Genes_Endogene_Background @@ -44,6 +46,7 @@ + + rjw_genes_masochist @@ -80,6 +84,7 @@
  • + false
  • Genes/Icons/RJW_Genes_Endogene_Background @@ -105,6 +110,7 @@
  • rjw_genes_sexual_orientation
  • + false
  • Genes/Icons/RJW_Genes_Endogene_Background @@ -130,6 +136,7 @@
  • rjw_genes_sexual_orientation
  • + false
  • Genes/Icons/RJW_Genes_Endogene_Background @@ -151,6 +158,7 @@ -1 2 + false
  • rjw_genes_sexual_orientation
  • diff --git a/Common/Defs/GeneDefs/GeneDefs_SexSpecial.xml b/Common/Defs/GeneDefs/GeneDefs_SexSpecial.xml index c3c042f..6cd34be 100644 --- a/Common/Defs/GeneDefs/GeneDefs_SexSpecial.xml +++ b/Common/Defs/GeneDefs/GeneDefs_SexSpecial.xml @@ -109,4 +109,21 @@
    + + rjw_genes_cocoonweaver + + cocooner + Carriers of this gene can produce a cocoon to prepare helpless (or willing) victims for breeding. + Genes/Icons/Cocoon + 11 + +
  • rjw_genes_ability_cocoonweaver
  • +
    + + rjw_genes_ability_cocoonweaver + + 1 + -1 +
    + \ No newline at end of file diff --git a/Common/Defs/IncidentsDefs/Incidents_LifeForce.xml b/Common/Defs/IncidentsDefs/Incidents_LifeForce.xml new file mode 100644 index 0000000..297aca5 --- /dev/null +++ b/Common/Defs/IncidentsDefs/Incidents_LifeForce.xml @@ -0,0 +1,16 @@ + + + + + SuccubusDreamVisit + + Misc + +
  • Map_PlayerHome
  • +
    + RJW_Genes.IncidentWorker_SuccubusDreamVisit + 1.0 + 10 + false +
    +
    \ No newline at end of file diff --git a/Common/Defs/PawnKindDefs/PawnKind_LifeForce.xml b/Common/Defs/PawnKindDefs/PawnKind_LifeForce.xml new file mode 100644 index 0000000..9d48cdc --- /dev/null +++ b/Common/Defs/PawnKindDefs/PawnKind_LifeForce.xml @@ -0,0 +1,87 @@ + + + + + rjw_genes_succubus + + 50 + Human + + + 999 + + + 0.5 + false + 18 + 27 + Poor + 0.0 + false + + 0.3 + 0.9 + + true + +
  • Tribal
  • +
    + + 0 + 0 + + 0 + + 0 + 0 + + +
  • Poor
  • +
    + 0.0 + 2~4 + 28~44 +
    + + + rjw_genes_incubus + + 50 + Human + + + 999 + + + 0.5 + false + 18 + 27 + Poor + 0.0 + false + + 0.3 + 0.9 + + true + +
  • Tribal
  • +
    + + 0 + 0 + + 0 + + 0 + 0 + + +
  • Poor
  • +
    + 0.0 + 2~4 + 28~44 +
    +
    \ No newline at end of file diff --git a/Common/Defs/TraitDefs/Traits_Singular.xml b/Common/Defs/TraitDefs/Traits_Singular.xml deleted file mode 100644 index 3f739cf..0000000 --- a/Common/Defs/TraitDefs/Traits_Singular.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - rjw_genes_sadist - 0.5 - -
  • - - {PAWN_nameDef} is a sadist, enjoying blood and hurting others, may also be a little rapy. - 2 -
  • Morbid
  • - - 0.1 - - RandomRape - - -
  • (0, 15)
  • -
  • (50, 50)
  • -
  • (100, 100)
  • -
    -
    - -
    - -
  • Violent
  • -
    -
    - - -
    diff --git a/Common/Languages/English/Keyed/Dialog_StatsReport.xml b/Common/Languages/English/Keyed/Dialog_StatsReport.xml deleted file mode 100644 index 53837f8..0000000 --- a/Common/Languages/English/Keyed/Dialog_StatsReport.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - queen in proximity - queen absent - multiple queens present - - \ No newline at end of file diff --git a/Common/Languages/English/Keyed/Hive.xml b/Common/Languages/English/Keyed/Hive.xml deleted file mode 100644 index 60cff64..0000000 --- a/Common/Languages/English/Keyed/Hive.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - New Queen - A new Queen was born! Make sure to adress inheritance before the new queen reaches adolesence. - - \ No newline at end of file diff --git a/Common/Patches/ThingDefs/RJW_Used_Condoms.xml b/Common/Patches/ThingDefs/RJW_Used_Condoms.xml new file mode 100644 index 0000000..56ae1d2 --- /dev/null +++ b/Common/Patches/ThingDefs/RJW_Used_Condoms.xml @@ -0,0 +1,36 @@ + + + + + + Defs/ThingDef[defName="UsedCondom"]/ingestible/outcomeDoers + + /Defs/ThingDef[defName="UsedCondom"]/ingestible + + +
  • + 1 +
  • +
    +
    +
    + + Defs/ThingDef[defName="UsedCondom"]/ingestible/outcomeDoers + +
  • + 1 +
  • +
    +
    +
    + +
    \ No newline at end of file diff --git a/Common/Patches/ThingDefs/Sexperience_Cum.xml b/Common/Patches/ThingDefs/Sexperience_Cum.xml new file mode 100644 index 0000000..f7387bf --- /dev/null +++ b/Common/Patches/ThingDefs/Sexperience_Cum.xml @@ -0,0 +1,42 @@ + + + + + + +
  • RJW Sexperience
  • +
    + + Defs/ThingDef[defName="GatheredCum"]/ingestible/outcomeDoers + + /Defs/ThingDef[defName="GatheredCum"]/ingestible + + +
  • + 1 +
  • +
    +
    +
    + + Defs/ThingDef[defName="GatheredCum"]/ingestible/outcomeDoers + +
  • + 1 +
  • +
    +
    +
    +
    + +
    \ No newline at end of file diff --git a/Common/Patches/ThinkTree/MentalStateCritical_LifeForceRandomRape.xml b/Common/Patches/ThinkTree/MentalStateCritical_LifeForceRandomRape.xml new file mode 100644 index 0000000..9532df8 --- /dev/null +++ b/Common/Patches/ThinkTree/MentalStateCritical_LifeForceRandomRape.xml @@ -0,0 +1,35 @@ + + + + + Defs/ThinkTreeDef[defName="MentalStateCritical"]/thinkRoot[@Class="ThinkNode_Tagger"]/subNodes + +
  • + rjw_genes_lifeforce_randomrape + +
  • + Rest + 0.05 + true + +
  • + +
  • +
  • + 0.5 + +
  • +
  • + +
  • + +
  • + + +
  • +
  • + +
  • +
    +
    +
    \ No newline at end of file diff --git a/Common/Patches/Traits/Patch_Sadist.xml b/Common/Patches/Traits/Patch_Sadist.xml deleted file mode 100644 index c7591d2..0000000 --- a/Common/Patches/Traits/Patch_Sadist.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - - Defs/ThoughtDef[defName="KnowGuestExecuted"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="KnowPrisonerDiedInnocent"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="KnowColonistDied"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - - - - - Defs/ThoughtDef[defName="HarvestedOrgan_Bloodlust"]/requiredTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="KnowGuestOrganHarvested"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="KnowColonistOrganHarvested"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="ButcheredHumanlikeCorpse"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="KnowButcheredHumanlikeCorpse"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="ButcheredHumanlikeCorpseOpinion"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="ObservedLayingCorpse"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="ObservedLayingRottingCorpse"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="WitnessedDeathNonAlly"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="KilledHumanlikeBloodlust"]/requiredTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="DeadMansApparel"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="HumanLeatherApparelSad"]/nullifyingTraits - -
  • rjw_genes_sadist
  • -
    -
    - - Defs/ThoughtDef[defName="HumanLeatherApparelHappy"]/requiredTraits - -
  • rjw_genes_sadist
  • -
    -
    - -
    \ No newline at end of file diff --git a/README.md b/README.md index 77d3e7d..9ea66bc 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,10 @@ This mod adds genes related and based on RJW to Rimworld. - Different Genitalia Types - Genitalia Size Scaling -- Extra Genitalia (and a Futa Attempt) -- Most RJW Traits, Cumflation Immunity, Elasticity +- Extra Genitalia, Male Pregnancy, Futas, Femboys +- Most RJW Traits - Cum-Amount Changes, Transfer Nutrition Boosts +- Sexual Vampires that need Cum, Cocks or some other sources. - Mech Breeding Additions & Orgasmic Mytosis - Human-Animal Gene Inheritance merged from [Shabakur](https://github.com/Shabakur/RJW_Animal_Gene_Inheritance) - Patches for some popular / common Xenotypes from other Mods. @@ -20,3 +21,11 @@ This mod adds genes related and based on RJW to Rimworld. 4. Alpha Genes "Female / Male Only" Genes might overwrite later Genitalia-Changes and should be avoided in combination with RJW-Genes features. 5. rjw.sexperience.cumgenes removes fertilin-gain from Cum item - I hope I addressed this by adding a load order but keep me posted (Issue #41) 6. [Consistent Gene Inheritance](https://steamcommunity.com/sharedfiles/filedetails/?id=2881479142&searchtext=Consistent+Gene+Inheritance) alters inheritance - it messes a bit with the Insect-Caste Logic. Your game will not crash, but the insect xenotypes will be a bit messed up. + +## Structure + +- Toplevel: By Function (i.E. "Genes", "Animal Inheritance", "Utility") +- Then: By Domain, following the Gene-Categories ("Cosmetic","Special", "Damage",...) +- Last: By Type of Action (Def, Patch, etc.) + +So if you want to change / add a gene about shrinking cocks you were to go: `Genes -> GenitaliaSize -> Defs`. \ No newline at end of file diff --git a/Source/Common/Helpers/MapUtility.cs b/Source/Common/Helpers/MapUtility.cs new file mode 100644 index 0000000..79e45a6 --- /dev/null +++ b/Source/Common/Helpers/MapUtility.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Verse; + +namespace RJW_Genes +{ + public class MapUtility + { + /// + /// Checks if the pawn is on the players home map. + /// + /// Reason is that drones should only be punished for absence of queen if they are on the map and there is no queen. + /// If they are on a mission, transport-pod etc. they should not get boni or mali. + /// + /// The pawn for which to check map-presence. + /// True if the pawn is on the home-map, False otherwise. + public static bool PawnIsOnHomeMap(Pawn pawn) + { + if (Find.Maps.NullOrEmpty() || !Find.Maps.Where(mapCandidate => mapCandidate.IsPlayerHome).Any()) + { + return false; + } + Map homeMap = Find.Maps.Where(mapCandidate => mapCandidate.IsPlayerHome).First(); + return + homeMap != null && pawn != null + && pawn.Spawned + && pawn.Map == homeMap; + } + + } +} diff --git a/Source/Common/patches/PatchImplants.cs b/Source/Common/patches/PatchImplants.cs index 5cd3c8c..037e081 100644 --- a/Source/Common/patches/PatchImplants.cs +++ b/Source/Common/patches/PatchImplants.cs @@ -18,7 +18,7 @@ namespace RJW_Genes public static readonly ThoughtDef stoleSomeLovin = DefDatabase.GetNamed("StoleSomeLovin"); public static readonly ThoughtDef bloodlustStoleSomeLovin = DefDatabase.GetNamed("BloodlustStoleSomeLovin"); public static readonly TraitDef rapist = DefDatabase.GetNamed("Rapist"); - public static readonly TraitDef sadist = DefDatabase.GetNamed("rjw_genes_sadist"); + static Dictionary laborStateMap = new Dictionary(); static public void would_rape_PostFix(ref bool __result, Pawn rapist) { @@ -54,7 +54,7 @@ namespace RJW_Genes { if (RJW_Genes_Settings.regretStealingLovinThoughtDisabled) return; - if (pawn.health.hediffSet.HasHediff(HediffDef.Named("LimbicStimulator")) && (__result == stoleSomeLovin || __result == bloodlustStoleSomeLovin) && !pawn.story.traits.HasTrait(rapist) && !pawn.story.traits.HasTrait(sadist)) + if (pawn.health.hediffSet.HasHediff(HediffDef.Named("LimbicStimulator")) && (__result == stoleSomeLovin || __result == bloodlustStoleSomeLovin) && !pawn.story.traits.HasTrait(rapist)) { __result = regretsStealingLovin; } diff --git a/Source/Genes/Breeding/Gene_FerventOvipositor.cs b/Source/Genes/Breeding/Gene_FerventOvipositor.cs new file mode 100644 index 0000000..3d8f612 --- /dev/null +++ b/Source/Genes/Breeding/Gene_FerventOvipositor.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Verse; +using rjw; + +namespace RJW_Genes +{ + + /// + /// Manages the rjw_genes_fervent_ovipositor to grow eggs much faster. + /// + /// TODO: Move the Multiplier into XML + /// TODO: This gene only works after the first egg, the first egg for two new pawns spawns at the same time (strange). + /// + public class Gene_FerventOvipositor : Gene + { + + const int MULTIPLIER = 3; // Tick 3 times as much, making a pawn with this Gene Produce Eggs 4 times as fast as the normal. + + public override void Tick() + { + base.Tick(); + + if (pawn == null) return; + + Hediff_PartBaseNatural OvipositorF = (Hediff_PartBaseNatural)pawn.health.hediffSet.GetFirstHediffOfDef(rjw.Genital_Helper.ovipositorF); + + if (OvipositorF == null) return; + + OvipositorF.nextEggTick = Math.Max(OvipositorF.nextEggTick - MULTIPLIER, -1); + + // DevNote: I first had a for-loop calling OviPositorF.tick(), but I fear that would be a performance sink. + // Also, it would double other aspects as well, such as bleeding out through your insect-PP or dropping out the eggs. + } + + + } +} \ No newline at end of file diff --git a/Source/Genes/Breeding/Gene_InsectIncubator.cs b/Source/Genes/Breeding/Gene_InsectIncubator.cs new file mode 100644 index 0000000..ce53827 --- /dev/null +++ b/Source/Genes/Breeding/Gene_InsectIncubator.cs @@ -0,0 +1,67 @@ +using RimWorld; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; + +namespace RJW_Genes +{ + + /// + /// This Gene checks for all parasitic Insect-Eggs in a Pawn: + /// 1. Is it fertilized ? => tick it down "extra". + /// 2. Is it not fertilized? => fertilize it with the Incubator as parent + /// + /// To save performance, this gene fires (default) every 0.5h, which also means a slight delay until fertilization happens. + /// + public class Gene_InsectIncubator : Gene + { + const int TICK_INTERVAL = 60000 / 48; // 60k = 1 day, we want 0.5h which is 1/48th of 1 day. + + public override void Tick() + { + base.Tick(); + + // Don't check too often, only in the HashTickInterval to safe some computing power + if (this.pawn.IsHashIntervalTick(TICK_INTERVAL) && this.pawn.Map != null) + { + List eggs = new List(); + pawn.health.hediffSet.GetHediffs(ref eggs); + // This part works as intended and shows Non-Human Eggs too + //if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"Gene_InsectIncubator: Found {eggs.Count} Hediff_InsectEgg in {pawn}"); + + + foreach (Hediff_InsectEgg egg in eggs) + { + // The implanter check checks if the egg is still in an ovipositor. + if (egg.implanter == null || egg.implanter == pawn) + continue; + + if (!egg.fertilized && egg.implanter != null) + { + egg.Fertilize(pawn); + // DevNote Issue 38: Sometimes Eggs are not fertilized here, because the normal Fertilize Function is called which has an upper Limit on Gestation. + // I will not do anything about it here, maybe upstream, but I print here. + if (RJW_Genes_Settings.rjw_genes_detailed_debug) + { + if (egg.fertilized) + ModLog.Message($"Gene_InsectIncubator: fertilized egg {egg} in {pawn}"); + else if (egg.GestationProgress > 0.5) + ModLog.Message($"Gene_InsectIncubator: Failed to fertilize {egg} in {pawn} due to high gestation progress"); + else + ModLog.Message($"Gene_InsectIncubator: failed to fertiliz egg {egg} in {pawn}"); + } + } + // DevNote: There is an issue with Eggs reaching too much gestation progress (>100%), which causes DownStream bugs. To avoid this, there are some extra checks in place. + else if (egg.fertilized && egg.GestationProgress <= .93) + { + egg.lastTick += TICK_INTERVAL; + } + } + } + } + } +} diff --git a/Source/Genes/Cum/Patch_TransferNutrition.cs b/Source/Genes/Cum/Patch_TransferNutrition.cs index 9c17d2a..1f3f0bb 100644 --- a/Source/Genes/Cum/Patch_TransferNutrition.cs +++ b/Source/Genes/Cum/Patch_TransferNutrition.cs @@ -29,6 +29,17 @@ namespace RJW_Genes // I could have done some transpiler stuff, but that is scary and might need to be adjusted quite a lot // Hence, I simply re-book the nutrition back to the giver in the Postfix. That should be robust and easy. + /* + TODO: Move this back in, once Licentia is 1.5 compatible. It should not drastically change. + if (GeneUtility.IsGenerousDonor(giver)) + { + float donatedNutrition = CumflationHelper.CalculateNutritionAmount(giver, cumAmount); + // TODO: In theory, there could be something weird happening if the donor has food less than X and the "IgnoreThermodynamics" is set on. + // Then it can happen that the donor ends up with more food than he had before cumshot, but I think that is somewhat funny given that you have ignore Thermodynamics on. + Need_Food inflatorFood = giver.needs.TryGetNeed(); + inflatorFood.CurLevel += donatedNutrition; + } + */ } } } \ No newline at end of file diff --git a/Source/Genes/Damage/Gene_Elasticity.cs b/Source/Genes/Damage/Gene_Elasticity.cs new file mode 100644 index 0000000..5d26c07 --- /dev/null +++ b/Source/Genes/Damage/Gene_Elasticity.cs @@ -0,0 +1,56 @@ +//using LicentiaLabs; +using Verse; + + +// TODO: Re-Introduce this once Licentia is 1.5 +// It should be rather simple +namespace RJW_Genes +{ + /// + /// This Gene adds Licentia-Labs Elasticised Hediff to a Pawn. + /// Note: I had a HarmonyPatch first, similar to skipping cumflation, but the Stretching Logic is called quite a lot and for both pawns actually. + /// Hence, I think choosing the Elasticiced Hediff was good as then everything is covered by "Licentia-Logic". + /// + public class Gene_Elasticity : Gene + { + private const int RESET_INTERVAL = 60000; // 60k should be 1 day + + /* + public override void PostAdd() + { + base.PostAdd(); + // Doing it like this will add the hediff with a severity of ~0.5, but it will decay. + // Hence we check with the Ticks to update. + this.pawn.health.AddHediff(Licentia.HediffDefs.Elasticised); + ResetSeverity(); + } + + public override void Tick() + { + base.Tick(); + if (pawn.IsHashIntervalTick(RESET_INTERVAL)) + ResetSeverity(); + } + + public override void PostRemove() + { + Hediff candidate = pawn.health.hediffSet.GetFirstHediffOfDef(Licentia.HediffDefs.Elasticised); + if (candidate != null) + { + pawn.health.RemoveHediff(candidate); + } + base.PostRemove(); + } + + + private void ResetSeverity(float severity = 0.7f) + { + Hediff candidate = pawn.health.hediffSet.GetFirstHediffOfDef(Licentia.HediffDefs.Elasticised); + if (candidate != null) + { + candidate.Severity = severity; + } + } + */ + } +} \ No newline at end of file diff --git a/Source/Genes/Life_Force/Events/SuccubusVisit/IncidentWorker_SuccubusVisit.cs b/Source/Genes/Life_Force/Events/SuccubusVisit/IncidentWorker_SuccubusVisit.cs new file mode 100644 index 0000000..22808f8 --- /dev/null +++ b/Source/Genes/Life_Force/Events/SuccubusVisit/IncidentWorker_SuccubusVisit.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; +using Verse.AI.Group; +using RimWorld; +using rjw; +namespace RJW_Genes +{ + public class IncidentWorker_SuccubusDreamVisit : IncidentWorker + { + //This incidint will only fire if there is a pawn asleep and sexneed is lower than 0.25 + protected override bool CanFireNowSub(IncidentParms parms) + { + if (!base.CanFireNowSub(parms)) + { + return false; + } + Map map = (Map)parms.target; + if (!map.mapTemperature.SeasonAcceptableFor(ThingDefOf.Human)) + { + return false; + } + if (!RJW_Genes_Settings.rjw_genes_sexdemon_visit_incubi && !RJW_Genes_Settings.rjw_genes_sexdemon_visit_succubi) + { + return false; + } + + foreach (Pawn pawn in map.mapPawns.FreeColonistsAndPrisonersSpawned) + { + if (pawn.jobs.curDriver.asleep && xxx.need_some_sex(pawn) > 1f) + { + return true; + } + } + return false; + + } + + protected override bool TryExecuteWorker(IncidentParms parms) + { + Map map = (Map)parms.target; + List victims = ValidVictims(map).ToList(); + if (victims.NullOrEmpty()) + { + return false; + } + Faction faction; + if (!this.TryFindFormerFaction(out faction)) + { + return false; + } + int pawn_amount = RJW_Genes_Settings.rjw_genes_sexdemon_visit_groups ? Rand.Range(1, victims.Count) : 1; + List new_sexdemons = new List(); + for (int i = 0; i < pawn_amount; i++) + { + Pawn victim = victims.RandomElement(); + IntVec3 loc = victim.Position; + + PawnKindDef pawnKindDef; + Gender gender; + if (victim.gender == Gender.Male || !RJW_Genes_Settings.rjw_genes_sexdemon_visit_incubi) + { + + } + if ((Rand.Bool && RJW_Genes_Settings.rjw_genes_sexdemon_visit_succubi) || !RJW_Genes_Settings.rjw_genes_sexdemon_visit_incubi) + { + pawnKindDef = PawnKindDef.Named("rjw_genes_succubus"); + gender = Gender.Female; + } + else + { + pawnKindDef = PawnKindDef.Named("rjw_genes_incubus"); + gender = Gender.Male; + } + + //Spawn succubus at pawn + Pawn sexdemon = PawnGenerator.GeneratePawn(new PawnGenerationRequest(pawnKindDef, faction, PawnGenerationContext.NonPlayer, -1, + false, false, false, true, false, 1f, false, true, false, true, true, false, false, false, false, 0f, 0f, null, 1f, null, null, + null, null, null, null, null, gender, null, null, null, null, false, false, false, false, null, null, null, null, null, 0f, + DevelopmentalStage.Adult, null, null, null, false)); + sexdemon.SetFaction(null, null); + GenSpawn.Spawn(sexdemon, loc, map, WipeMode.Vanish); + List sexdemons = new List { sexdemon }; + new_sexdemons.Add(sexdemon); + + + LordMaker.MakeNewLord(Faction.OfPlayer, this.CreateLordJob(parms, sexdemon, victim), map, sexdemons); + + //Make succubus rape victim. + if (RJWSettings.rape_enabled) + { + //follow rjw rules + if (SexAppraiser.would_fuck(sexdemon, victim) > 0f) + { + sexdemon.pather.StopDead(); + sexdemon.jobs.StopAll(); + Job newJob = JobMaker.MakeJob(xxx.RapeRandom, victim); + sexdemon.jobs.StartJob(newJob, JobCondition.InterruptForced, null, false, true, null, null, false, false, null, false, true); + } + + } + } + Find.LetterStack.ReceiveLetter("rjw_genes_sexdemon_visit_incident_label".Translate(), "rjw_genes_sexdemon_visit_incident_description".Translate(), RimWorld.LetterDefOf.PositiveEvent, new_sexdemons, null, null, null, null); + + return true; + } + + private IEnumerable ValidVictims(Map map) + { + foreach (Pawn pawn in map.mapPawns.FreeColonistsAndPrisonersSpawned) + { + if (pawn.jobs.curDriver.asleep && xxx.need_some_sex(pawn) > 1f) + { + yield return pawn; + } + } + yield break; + } + + private bool TryFindFormerFaction(out Faction formerFaction) + { + return Find.FactionManager.TryGetRandomNonColonyHumanlikeFaction(out formerFaction, false, true, TechLevel.Undefined, false); + } + + protected virtual LordJob_SuccubusVisit CreateLordJob(IncidentParms parms, Pawn succubus, Pawn target) + { + return new LordJob_SuccubusVisit(target); + } + } +} \ No newline at end of file diff --git a/Source/Genes/Life_Force/Events/SuccubusVisit/LordJob_SuccubusVisit.cs b/Source/Genes/Life_Force/Events/SuccubusVisit/LordJob_SuccubusVisit.cs new file mode 100644 index 0000000..887a324 --- /dev/null +++ b/Source/Genes/Life_Force/Events/SuccubusVisit/LordJob_SuccubusVisit.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using Verse; +using Verse.AI.Group; +using RimWorld; +using rjw; +namespace RJW_Genes +{ + //Based on LordJob_VisitColony + public class LordJob_SuccubusVisit : LordJob + { + public LordJob_SuccubusVisit() { } + public LordJob_SuccubusVisit(Pawn target) + { + this.target = target; + } + + // + //Stategraph has lordtoils which say what a pawn should be doing + //Transitions say when active lordtoil for pawn should change + // + public override StateGraph CreateGraph() + { + StateGraph stateGraph = new StateGraph(); + + //Flirt + LordToil_Flirt lordToil_Flirt = new LordToil_Flirt(this.target, 7f); + stateGraph.AddToil(lordToil_Flirt); + stateGraph.StartingToil = lordToil_Flirt; + + //Leave + LordToil_ExitMapRandom lordToil_ExitMapRandom = new LordToil_ExitMapRandom(); + stateGraph.AddToil(lordToil_ExitMapRandom); + LordToil_ExitMapAndDefendSelf lordToil_ExitMapAndDefendSelf = new LordToil_ExitMapAndDefendSelf(); + stateGraph.AddToil(lordToil_ExitMapAndDefendSelf); + + //Leave after some time + Transition transition1 = new Transition(lordToil_Flirt, lordToil_ExitMapRandom, false, true); + int tickLimit; + if (this.durationTicks != null) + { + tickLimit = this.durationTicks.Value; + } + else + { + tickLimit = Rand.Range(60000, 180000); //~1-3 days + } + transition1.AddTrigger(new Trigger_TicksPassed(tickLimit)); + transition1.AddPreAction(new TransitionAction_Custom(new Action(this.SuccubiLeave))); //Join or leave colony + stateGraph.AddTransition(transition1); + + //If they become hostile + Transition transition3 = new Transition(lordToil_Flirt, lordToil_ExitMapAndDefendSelf, false, true); + transition3.AddSource(lordToil_ExitMapRandom); //Not sure what this does + transition3.AddTrigger(new Trigger_BecamePlayerEnemy()); + transition3.AddTrigger(new Trigger_PawnKilled()); + transition3.AddPostAction(new TransitionAction_EndAllJobs()); + stateGraph.AddTransition(transition3, false); + + Transition transition4 = new Transition(lordToil_ExitMapRandom, lordToil_ExitMapAndDefendSelf, false, true); + transition4.AddSource(lordToil_Flirt); //Not sure what this does + transition4.AddTrigger(new Trigger_PawnHarmed(1f, true, Faction.OfPlayer)); + stateGraph.AddTransition(transition4, false); + + return stateGraph; + } + + //add toggleable gizmo to allow playes to have colonists sex the succubus into joining your colony + //comfort pawn? cooldown? + public override IEnumerable GetPawnGizmos(Pawn p) + { + return base.GetPawnGizmos(p); + } + + public override void ExposeData() + { + Scribe_Values.Look(ref this.durationTicks, "durationTicks", null, false); + Scribe_References.Look(ref this.target, "target", false); + } + + public void SuccubiLeave() + { + foreach (Pawn pawn in this.lord.ownedPawns) + { + if (colonyJoiners.Contains(pawn)) + { + RecruitUtility.Recruit(pawn, Faction.OfPlayer); + Find.LetterStack.ReceiveLetter("rjw_genes_succubus_joins_letter_label".Translate(), string.Format("rjw_genes_succubus_joins_letter_description".Translate(), xxx.get_pawnname(pawn)), RimWorld.LetterDefOf.PositiveEvent, pawn, null, null, null, null); + } + else + { + Messages.Message("SuccubusLeaving".Translate(xxx.get_pawnname(pawn)), pawn, MessageTypeDefOf.NeutralEvent, true); + } + } + + } + + public Pawn target; + private int? durationTicks; + public List colonyJoiners = new List(); + } +} \ No newline at end of file diff --git a/Source/Genes/Life_Force/Interactions/SuccubusTailjob/DomSuccubusTailCustomRequirementHandler.cs b/Source/Genes/Life_Force/Interactions/SuccubusTailjob/DomSuccubusTailCustomRequirementHandler.cs new file mode 100644 index 0000000..67fafae --- /dev/null +++ b/Source/Genes/Life_Force/Interactions/SuccubusTailjob/DomSuccubusTailCustomRequirementHandler.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; +using rjw.Modules.Interactions; +using rjw.Modules.Interactions.Internals.Implementation; +using rjw.Modules.Interactions.Objects; +using rjw; +using rjw.Modules.Interactions.Enums; + +//Modefied code based of RJW-AI code at https://gitgud.io/Ed86/rjw-ia/-/tree/master/ +namespace RJW_Genes +{ + [StaticConstructorOnStartup] + public class DomSuccubusTailCustomRequirementHandler : ICustomRequirementHandler + { + public string HandlerKey + { + get + { + return "DomSuccubusTailCustomRequirementHandler"; + } + } + + + static DomSuccubusTailCustomRequirementHandler() + { + Register(); + } + public static void Register() + { + InteractionRequirementService.CustomRequirementHandlers.Add(new DomSuccubusTailCustomRequirementHandler()); + if (Prefs.DevMode) + { + Log.Message("DomSuccubusTailCustomRequirementHandler registered: "); + } + } + + public bool FufillRequirements(InteractionWithExtension interaction, InteractionPawn dominant, InteractionPawn submissive) + { + if (GeneUtility.HasGeneNullCheck(dominant.Pawn, GeneDefOf.rjw_genes_succubus_tail)) + { + return true; + } + return false; + } + } +} \ No newline at end of file diff --git a/Source/Genes/Life_Force/Interactions/SuccubusTailjob/GenesPartKindUsageRule.cs b/Source/Genes/Life_Force/Interactions/SuccubusTailjob/GenesPartKindUsageRule.cs new file mode 100644 index 0000000..371f06d --- /dev/null +++ b/Source/Genes/Life_Force/Interactions/SuccubusTailjob/GenesPartKindUsageRule.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using rjw; +using rjw.Modules.Interactions.Contexts; +using rjw.Modules.Interactions.Enums; +using rjw.Modules.Interactions.Rules.PartKindUsageRules; +using rjw.Modules.Shared; +using Verse; + +namespace RJW_Genes.Interactions +{ + //Summary// + //Set custom preferences for pawn. Gets integrated into rjw by AddtoIPartPreferenceRule in First + //Depending on the level of lifeforce increase the chance for using the mouth. + public class GenesPartKindUsageRule : IPartPreferenceRule + { + public IEnumerable> ModifiersForDominant(InteractionContext context) + { + Pawn pawn = context.Internals.Dominant.Pawn; + Gene_LifeForce gene = pawn.genes.GetFirstGeneOfType(); + if (gene != null) + { + float weight = 2f; + if (gene.Value < gene.MinLevelForAlert) + { + weight *= 10; + } + else if (gene.Value < gene.targetValue) + { + weight *= 2.5f; + } + if (pawn.genes.HasGene(GeneDefOf.rjw_genes_cum_eater)) + { + yield return new Weighted(weight, LewdablePartKind.Mouth); + yield return new Weighted(weight, LewdablePartKind.Beak); + } + + if (pawn.genes.HasGene(GeneDefOf.rjw_genes_fertilin_absorber)) + { + yield return new Weighted(weight, LewdablePartKind.Vagina); + yield return new Weighted(weight, LewdablePartKind.Anus); + } + } + yield break; + } + + public IEnumerable> ModifiersForSubmissive(InteractionContext context) + { + Pawn pawn = context.Internals.Dominant.Pawn; + Gene_LifeForce gene = pawn.genes.GetFirstGeneOfType(); + if (gene != null) + { + float weight = 2f; + if (gene.Value < gene.MinLevelForAlert) + { + weight *= 10; + } + else if (gene.Value < gene.targetValue) + { + weight *= 2.5f; + } + yield return new Weighted(weight, LewdablePartKind.Mouth); + yield return new Weighted(weight, LewdablePartKind.Beak); + + if (pawn.genes.HasGene(GeneDefOf.rjw_genes_fertilin_absorber)) + { + yield return new Weighted(weight, LewdablePartKind.Vagina); + yield return new Weighted(weight, LewdablePartKind.Anus); + } + } + yield break; + } + } +} \ No newline at end of file diff --git a/Source/Genes/Life_Force/Interactions/SuccubusTailjob/SubSuccubusTailCustomRequirementHandler.cs b/Source/Genes/Life_Force/Interactions/SuccubusTailjob/SubSuccubusTailCustomRequirementHandler.cs new file mode 100644 index 0000000..04d7657 --- /dev/null +++ b/Source/Genes/Life_Force/Interactions/SuccubusTailjob/SubSuccubusTailCustomRequirementHandler.cs @@ -0,0 +1,43 @@ +using Verse; +using rjw.Modules.Interactions; +using rjw.Modules.Interactions.Internals.Implementation; +using rjw.Modules.Interactions.Objects; + +//Modified code based of RJW-AI code at https://gitgud.io/Ed86/rjw-ia/-/tree/master/ +namespace RJW_Genes +{ + [StaticConstructorOnStartup] + public class SubSuccubusTailCustomRequirementHandler : ICustomRequirementHandler + { + public string HandlerKey + { + get + { + return "SubSuccubusTailCustomRequirementHandler"; + } + } + + static SubSuccubusTailCustomRequirementHandler() + { + Register(); + } + public static void Register() + { + InteractionRequirementService.CustomRequirementHandlers.Add(new SubSuccubusTailCustomRequirementHandler()); + if (Prefs.DevMode) + { + Log.Message("SubSuccubusTailCustomRequirementHandler registered: "); + } + } + + public bool FufillRequirements(InteractionWithExtension interaction, InteractionPawn dominant, InteractionPawn submissive) + { + if (GeneUtility.HasGeneNullCheck(submissive.Pawn, GeneDefOf.rjw_genes_succubus_tail)) + { + return true; + } + return false; + } + } +} + diff --git a/Source/Genes/Life_Force/Patches/Patch_SatisfyPersonal_LifeForceGain.cs b/Source/Genes/Life_Force/Patches/Patch_SatisfyPersonal_LifeForceGain.cs index 6ea0a62..4388cf0 100644 --- a/Source/Genes/Life_Force/Patches/Patch_SatisfyPersonal_LifeForceGain.cs +++ b/Source/Genes/Life_Force/Patches/Patch_SatisfyPersonal_LifeForceGain.cs @@ -25,6 +25,12 @@ namespace RJW_Genes { return; } + // Exit if the pawn has ONLY an archotech penis, and no other penises. Issue #72 + if (props.pawn.health.hediffSet.hediffs.Any(x => x.def == rjw.Genital_Helper.archotech_penis) + && !(Genital_Helper.has_multipenis(props.pawn))) + { + return; + } //Summary// //We use the positions of the pawn (dom or sub) and based on that which interactions will transfer fertilin diff --git a/Source/Genes/Special/Abilities/CompAbilityEffect_CocoonWeaver.cs b/Source/Genes/Special/Abilities/CompAbilityEffect_CocoonWeaver.cs new file mode 100644 index 0000000..a3af363 --- /dev/null +++ b/Source/Genes/Special/Abilities/CompAbilityEffect_CocoonWeaver.cs @@ -0,0 +1,81 @@ +using Verse; +using RimWorld; +using rjw; + +namespace RJW_Genes +{ + /// + /// The CocoonWeaver Ability applies the RJW-Cocoon to a pawn. + /// Friendly Pawns can always be cocooned, neutral and hostile pawns must be downed. + /// + public class CompAbilityEffect_CocoonWeaver : CompAbilityEffect + { + private new CompProperties_AbilityCocoonWeaver Props + { + get + { + return (CompProperties_AbilityCocoonWeaver)this.props; + } + } + + + public override void Apply(LocalTargetInfo target, LocalTargetInfo dest) + { + base.Apply(target, dest); + + Pawn CocooningPawn = this.parent.pawn; + Pawn PawnToCocoon = target.Pawn; + + // Error Case - Null Pawn + if (PawnToCocoon == null) + { + return; + } + + PawnToCocoon.health.AddHediff(HediffDef.Named("RJW_Cocoon")); + + } + + /// + /// For validity, there are a few checks: + /// 0. Target is not already cocooned + /// 1. Target is either Colonist / Prisoner + /// 2. If the Target is an enemy or neutral, it must be downed. + /// + public override bool Valid(LocalTargetInfo target, bool throwMessages = false) + { + Pawn cocoonTarget = target.Pawn; + if (cocoonTarget != null) + { + bool CocoonTargetIsColonistOrPrisoner = cocoonTarget.Faction == this.parent.pawn.Faction || cocoonTarget.IsPrisonerOfColony; + bool CocoonTargetIsHostile = cocoonTarget.HostileTo(this.parent.pawn); + bool CocoonTargetIsDowned = cocoonTarget.Downed; + + if (cocoonTarget.health.hediffSet.hediffs.Any(t => t.def.defName == "RJW_Cocoon")) + { + if (throwMessages) + Messages.Message(cocoonTarget.Name + " is already cocooned.", cocoonTarget, MessageTypeDefOf.RejectInput, false); + return false; + } + + if (!CocoonTargetIsColonistOrPrisoner && !(CocoonTargetIsHostile && CocoonTargetIsDowned)) + { + if (throwMessages) + { + if (CocoonTargetIsHostile && !CocoonTargetIsDowned) + { + Messages.Message(cocoonTarget.Name + " is hostile, but not downed.", cocoonTarget, MessageTypeDefOf.RejectInput, false); + } + else if (!CocoonTargetIsColonistOrPrisoner) + { + Messages.Message(cocoonTarget.Name + " is not a part of the colony or hostile.", cocoonTarget, MessageTypeDefOf.RejectInput, false); + } + } + return false; + } + } + return base.Valid(target, throwMessages); + } + + } +} \ No newline at end of file diff --git a/Source/Genes/Special/Abilities/CompProperties_AbilityCocoonWeaver.cs b/Source/Genes/Special/Abilities/CompProperties_AbilityCocoonWeaver.cs new file mode 100644 index 0000000..caa63b6 --- /dev/null +++ b/Source/Genes/Special/Abilities/CompProperties_AbilityCocoonWeaver.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; + +namespace RJW_Genes +{ + public class CompProperties_AbilityCocoonWeaver : CompProperties_AbilityEffect + { + public CompProperties_AbilityCocoonWeaver() + { + this.compClass = typeof(CompAbilityEffect_CocoonWeaver); + } + } +} \ No newline at end of file diff --git a/Source/Genes/Special/Thoughts/ThoughtWorker_Aphrodisiac_Pheromones_Social.cs b/Source/Genes/Special/Thoughts/ThoughtWorker_Aphrodisiac_Pheromones_Social.cs index 4f3a03f..b236fc9 100644 --- a/Source/Genes/Special/Thoughts/ThoughtWorker_Aphrodisiac_Pheromones_Social.cs +++ b/Source/Genes/Special/Thoughts/ThoughtWorker_Aphrodisiac_Pheromones_Social.cs @@ -33,15 +33,15 @@ namespace RJW_Genes if (!other.RaceProps.Humanlike) return (ThoughtState)false; + // Pawns that have not "met" wont give each other Mali + // Known-Each-Other is a key-word for Rimworld that shows they have had any interaction and stored each other in relations. if (!RelationsUtility.PawnsKnowEachOther(pawn, other)) return (ThoughtState)false; // If the pawn is not on Map (e.g. caravan), no mali - - - + if (!MapUtility.PawnIsOnHomeMap(pawn)) + return (ThoughtState)false; // Do nothing for pawns that also have pheromones if (GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_aphrodisiac_pheromones)) - return (ThoughtState)false; // Actual Logic: diff --git a/Source/Rjw-Genes.csproj b/Source/Rjw-Genes.csproj index 32b5494..757086f 100644 --- a/Source/Rjw-Genes.csproj +++ b/Source/Rjw-Genes.csproj @@ -27,7 +27,24 @@ - + + + + + + + + + + + + + + + + + + @@ -43,9 +60,18 @@ + + + + + + + + + @@ -135,6 +161,8 @@ + + diff --git a/Source/Settings/RJW_Genes_Settings.cs b/Source/Settings/RJW_Genes_Settings.cs index 53e5d51..4180532 100644 --- a/Source/Settings/RJW_Genes_Settings.cs +++ b/Source/Settings/RJW_Genes_Settings.cs @@ -12,30 +12,46 @@ namespace RJW_Genes //Copied from RJW settings mostly Rect outRect = new Rect(0f, 30f, inRect.width, inRect.height - 30f); Rect rect = new Rect(0f, 0f, inRect.width - 16f, inRect.height + 300f); - //Widgets.BeginScrollView(outRect, ref RJWSettings.scrollPosition, rect, true); + Listing_Standard listing_Standard = new Listing_Standard(); listing_Standard.maxOneColumn = true; listing_Standard.ColumnWidth = rect.width / 2.05f; listing_Standard.Begin(rect); listing_Standard.Gap(24f); + // Genitalia Resizing Age listing_Standard.Label("Genitalia resizing age" + ": " + Math.Round((double)(RJW_Genes_Settings.rjw_genes_resizing_age), 0).ToString() , -1f, "years."); RJW_Genes_Settings.rjw_genes_resizing_age = listing_Standard.Slider(RJW_Genes_Settings.rjw_genes_resizing_age, 18f, 100f); listing_Standard.Gap(4f); - listing_Standard.Label("Fertilin-Gain from Animals" + ": " + + // Evergrowth Speed + listing_Standard.Label("number of ticks between genitalia evergrowth updates (60000 ticks are 1 day)" + ": " + Math.Round((double)(RJW_Genes_Settings.rjw_genes_evergrowth_ticks), 0).ToString() , -1f, "ticks."); RJW_Genes_Settings.rjw_genes_evergrowth_ticks = (int) listing_Standard.Slider(RJW_Genes_Settings.rjw_genes_evergrowth_ticks, 600, 60000); - listing_Standard.Gap(4f); - listing_Standard.Label("nunmber of ticks between genitalia evergrowth updates (600 tick for ~2cm/day)" + ": " + - Math.Round((double)(RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor * 100f), 0).ToString() + "%", -1f, "of fertilin gained (compared to human-baseline)."); + // Fertilin Gain From Animals + listing_Standard.Label("Fertilin-Gain from Animals" + ": " + + Math.Round((double)(RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor * 100f), 0).ToString() + "", -1f, "of fertilin gained (compared to human-baseline)."); RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor = listing_Standard.Slider(RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor, 0f, 3f); + listing_Standard.Gap(5f); + listing_Standard.CheckboxLabeled("Sexdemon Visits", ref rjw_genes_sexdemon_visit, "If enabled, incubi and succubi can spawn in through an event.", 0f, 1f); + if (rjw_genes_sexdemon_visit) + { + listing_Standard.Gap(3f); + listing_Standard.CheckboxLabeled(" Size matters", ref rjw_genes_sexdemon_join_size_matters, "Incubi and succubi will consider size/tightness of partners genital for deciding if they want to join", 0f, 1f); + listing_Standard.Gap(3f); + listing_Standard.CheckboxLabeled(" Sexdemon groups", ref rjw_genes_sexdemon_visit_groups, "Multiple sexdemons can spawn during a event", 0f, 1f); + listing_Standard.Gap(3f); + listing_Standard.CheckboxLabeled(" Succubi", ref rjw_genes_sexdemon_visit_succubi, "Allow incubi to spawn through this even", 0f, 1f); + listing_Standard.Gap(3f); + listing_Standard.CheckboxLabeled(" Incubi", ref rjw_genes_sexdemon_visit_incubi, "Allow incubi to spawn through this even", 0f, 1f); + } + listing_Standard.Gap(4f); listing_Standard.Gap(4f); - listing_Standard.CheckboxLabeled("RegretStealingLovinThoughtDisabled".Translate(), ref regretStealingLovinThoughtDisabled, "RegretStealingLovinThoughtDisabledDesc".Translate()); + listing_Standard.CheckboxLabeled("Regret Stealing Love", ref regretStealingLovinThoughtDisabled, "If off, pawns will not get bad thoughts for seduction."); listing_Standard.Gap(5f); listing_Standard.CheckboxLabeled("generous-donor cheatmode", ref rjw_genes_generous_donor_cheatmode, "When enabled, pawns with the 'generous donor' are not drained and not fertilin exhausted. Hence they can fuel succubi and incubi non-stop. This makes them drastically easier to keep, and you should not do it.", 0f, 1f); @@ -53,7 +69,12 @@ namespace RJW_Genes Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor, "rjw_genes_fertilin_from_animals_factor", RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor, true); Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_detailed_debug, "rjw_genes_detailed_debug", RJW_Genes_Settings.rjw_genes_detailed_debug, true); Scribe_Values.Look(ref regretStealingLovinThoughtDisabled, "regretStealingLovinThoughtDisabled", regretStealingLovinThoughtDisabled, true); - Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_generous_donor_cheatmode, "rjw_genes_generous_donor_cheatmode", RJW_Genes_Settings.rjw_genes_generous_donor_cheatmode, true); + Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_generous_donor_cheatmode, "rjw_genes_generous_donor_cheatmode", RJW_Genes_Settings.rjw_genes_generous_donor_cheatmode, true); + Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_sexdemon_visit, "rjw_genes_sexdemon_visit", RJW_Genes_Settings.rjw_genes_sexdemon_visit, true); + Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_sexdemon_join_size_matters, "rjw_genes_sexdemon_join_size_matters", RJW_Genes_Settings.rjw_genes_sexdemon_join_size_matters, true); + Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_sexdemon_visit_groups, "rjw_genes_sexdemon_groups", RJW_Genes_Settings.rjw_genes_sexdemon_visit_groups, true); + Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_sexdemon_visit_succubi, "rjw_genes_sexdemon_succubi", RJW_Genes_Settings.rjw_genes_sexdemon_visit_succubi, true); + Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_sexdemon_visit_incubi, "rjw_genes_sexdemon_incubi", RJW_Genes_Settings.rjw_genes_sexdemon_visit_incubi, true); } public static bool rjw_genes_detailed_debug = false; @@ -62,6 +83,11 @@ namespace RJW_Genes public static int rjw_genes_evergrowth_ticks = 60000; public static bool regretStealingLovinThoughtDisabled = false; + public static bool rjw_genes_sexdemon_visit = true; + public static bool rjw_genes_sexdemon_join_size_matters = true; + public static bool rjw_genes_sexdemon_visit_groups = true; + public static bool rjw_genes_sexdemon_visit_succubi = true; + public static bool rjw_genes_sexdemon_visit_incubi = true;