Compare commits

...

25 commits

Author SHA1 Message Date
Vegapnk
c4a64c345f Draft for Succubus Xenotype 2023-01-15 22:33:39 +01:00
Vegapnk
0c3af21c3a Really fixed merge conflicts,upsie 2023-01-15 21:14:26 +01:00
Vegapnk
0e20e00150 Resolved Merge Conflicts 2023-01-15 20:43:20 +01:00
Vegapnk
712bb909c6 Added a lot of debugging logs for Bestiality Gene Inheritance 2023-01-15 17:48:11 +01:00
vegapnk
0203cd92a9
Merge pull request #13 from Shabakur/main
Racesupport compatibility, settings and aphrodisiac pheromones
2023-01-15 16:44:01 +01:00
vegapnk
f3cc5e7ee2
Merge branch 'dev' into main 2023-01-15 16:43:21 +01:00
Shabakur
46436a9e04 Implemented racegroups as list
Added variable racegroups, which allows multiple racegroups to be selected (usefull for rjw race support). Racegroup is still present for backward compatibility.
2023-01-15 13:30:33 +01:00
Shabakur
209c149a5a Merge branch 'main' of https://github.com/Shabakur/RJW-Genes 2023-01-15 13:29:03 +01:00
Shabakur
09157e923d sexage check Fertilin and FertilinDraingene
Fertilin and all subgenes are only active if pawn is old enough to have sex, 13 if rjw teensex is enabled else 18.
Added a fertilindraingene which greatly increases fertilin burn, but gives a lot of metabolic efficiency
Also moved a few files into subfolders.
2023-01-09 14:14:51 +01:00
Shabakur
2e1e74e0b1 A fertilin alert and some label/description changes 2023-01-08 15:51:07 +01:00
Shabakur
6f2c4dc374
Merge branch 'dev' into dev 2023-01-08 14:12:58 +01:00
Shabakur
34bb5d3b2c Seduced ThoughtDef 2023-01-06 13:52:04 +01:00
Shabakur
ee1625306a
Merge branch 'vegapnk:dev' into dev 2023-01-06 12:46:20 +01:00
Shabakur
400b48787d Several genes and changes
- Succubus wings now have the flight abilty (same as longjump)
- Modified aphrodisiac pheromones to increase with strenght based on carrier's sexdrive.
- Added paralysing kiss, touch range stun which uses fertilin
- Added seduce, beckon like ability which results in sex if target reached caster. Uses fertilin
2023-01-06 12:42:04 +01:00
Shabakur
5555083bc2 Pawns will now seek for hemogen when below target
- Made a jobgiver similar to Jobgiver GetHemogen
	- currently only job is to eat cum from sexperience
	- other thinks are done via thinktree
- Made thinknodes and thinktrees so that a succubus will seek sex when below target value and try and rape when critically low.
2022-12-31 16:40:37 +01:00
Shabakur
2a124bfbb9 Drainer gene and missing crossreference to rjw_genes_likes_cumflation fixed 2022-12-31 11:42:00 +01:00
Shabakur
3c9e97beb6 Sexperience cum now gives fertilin 2022-12-29 20:42:39 +01:00
Shabakur
a64cecbab3 CockEater gene
CockEater gene with ability and negative thoughtdef for target
2022-12-29 18:03:02 +01:00
Shabakur
3cf2d44c82 Custom succubus tail sex interactions and modification to fertilin absorbtion 2022-12-29 16:08:22 +01:00
Shabakur
22892db8e0 Fertilin Tank hediff and Succubus tail 2022-12-29 11:20:17 +01:00
Shabakur
e642942c1e Anal/Vaginal Cumabsorption genes, fertilin category, pussyheal requires fertilin now 2022-12-28 13:37:27 +01:00
Shabakur
0d15873bd2 Healpussy gene and succubus wing retexture
Brought over the healpussy gene from my mod and changed the succubus wings to a lighter version
2022-12-28 10:30:26 +01:00
Shabakur
e8f9f94130 Adde some explanations in the code 2022-12-27 14:54:47 +01:00
Shabakur
1f865320b0 Adding Lifeforce and succubus wings gene
Adds lifeforce gene and functions for gaining lifeforce from oral sex and mental break if lifeforce reaches zero. Also add succubus wings drawn by me
2022-12-27 13:48:38 +01:00
Shabakur
f0a9cce9c9 Added Gene Aphrodisiac Pheromones and some settings 2022-12-25 12:38:05 +01:00
102 changed files with 4204 additions and 81 deletions

View file

@ -8,6 +8,10 @@ Features:
- Age-Transfer and Youth-Fountain per Sex Gene
- Bisexual and Homosexual Genes with Placeholder Icon
- Balancing some Genes by changing metabolism and complexity
- Pheromone Gene (#13, Shabakur)
- RJW Race-Support Compatibility (#12,#13, Shabakur)
- Animal Gene Inheritance Gene-Chance Multiplier per Setting (#13, Shabakur)
- Lots of Debug-Only Logging for Animal Gene Inheritance
Succubus:
@ -17,6 +21,7 @@ Fixes:
- Error on Game Load when Licentia Genes are tried to be added to Xenotypes for players without Licentia (#5)
- Futa Gene only triggers if Pawn is not a futa already (#2)
- Genitalia Resizing triggers on 20th Birthday (#11)
- RJW-Gene-Inheritance Settings now do things (#13, Shabakur)
# 1.0.1 (2022-12-20)

Binary file not shown.

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<AbilityDef ParentName="AbilityTouchBase">
<defName>rjw_genes_cockeater</defName>
<label>Eat Cock</label>
<description>Eat the cock of another pawn, restoring fertilin based on the size of the cock.</description>
<iconPath>Things/Mote/Heart</iconPath>
<stunTargetWhileCasting>true</stunTargetWhileCasting>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<warmupMote>Mote_CoagulateStencil</warmupMote>
<warmupEffecter>Coagulate</warmupEffecter>
<warmupStartSound>Coagulate_Cast</warmupStartSound>
<jobDef>CastAbilityOnThingMelee</jobDef>
<displayOrder>402</displayOrder>
<verbProperties>
<verbClass>Verb_CastAbilityTouch</verbClass>
<drawAimPie>false</drawAimPie>
<range>-1</range>
<warmupTime>10</warmupTime>
<targetParams>
<canTargetAnimals>true</canTargetAnimals>
<canTargetSelf>false</canTargetSelf>
<canTargetBuildings>false</canTargetBuildings>
<canTargetMechs>false</canTargetMechs>
<canTargetBloodfeeders>true</canTargetBloodfeeders>
</targetParams>
</verbProperties>
<comps>
<li Class="RJW_Genes.CompProperties_AbilityCockEater"> <!-- namespace needs to be changed when copied to another mod-->
</li>
</comps>
</AbilityDef>
</Defs>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<AbilityDef>
<defName>rjw_genes_flight</defName>
<label>fly</label>
<description>Fly to a distant location using wings.</description>
<iconPath>Genes/Icons/Succubus_Wings</iconPath>
<cooldownTicksRange>1250</cooldownTicksRange>
<hostile>false</hostile>
<verbProperties>
<verbClass>Verb_CastAbilityJump</verbClass>
<label>fly</label>
<violent>false</violent>
<forceNormalTimeSpeed>false</forceNormalTimeSpeed>
<warmupTime>0.5</warmupTime>
<range>19.9</range>
<requireLineOfSight>true</requireLineOfSight>
<soundCast>Longjump_Jump</soundCast>
<soundLanding>Longjump_Land</soundLanding>
<targetParams>
<canTargetLocations>true</canTargetLocations>
<canTargetPawns>false</canTargetPawns>
<canTargetBuildings>false</canTargetBuildings>
</targetParams>
</verbProperties>
<jobDef>CastJump</jobDef>
</AbilityDef>
</Defs>

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<AbilityDef ParentName="AbilityTouchBase">
<defName>rjw_genes_paralysingkiss</defName>
<label>paralysing kiss</label>
<description>Paralyse someone briefly with a kiss.</description>
<iconPath>Things/Mote/Heart</iconPath>
<stunTargetWhileCasting>true</stunTargetWhileCasting>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<statBases>
<Ability_Duration>5</Ability_Duration>
</statBases>
<warmupMote>Mote_CoagulateStencil</warmupMote>
<warmupEffecter>Coagulate</warmupEffecter>
<warmupStartSound>Coagulate_Cast</warmupStartSound>
<displayOrder>402</displayOrder>
<verbProperties>
<verbClass>Verb_CastAbilityTouch</verbClass>
<drawAimPie>false</drawAimPie>
<range>-1</range>
<warmupTime>1</warmupTime>
<targetParams>
<canTargetAnimals>true</canTargetAnimals>
<canTargetSelf>false</canTargetSelf>
<canTargetBuildings>false</canTargetBuildings>
<canTargetMechs>false</canTargetMechs>
<canTargetBloodfeeders>true</canTargetBloodfeeders>
</targetParams>
</verbProperties>
<comps>
<li Class = "CompProperties_AbilityEffectWithDuration">
<compClass>CompAbilityEffect_Stun</compClass>
<goodwillImpact>-15</goodwillImpact>
</li>
<li Class="CompProperties_AbilityFleckOnTarget">
<fleckDef>Heart</fleckDef> <!--Will change to kiss when I have a good icon/fleck for it-->
</li>
<li Class="RJW_Genes.CompProperties_AbilityLifeForceCost">
<fertilinCost>0.05</fertilinCost>
</li>
</comps>
</AbilityDef>
</Defs>

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<AbilityDef ParentName="AbilityTouchBase">
<defName>rjw_genes_pussyheal</defName>
<label>SexHeal</label>
<description>Rape another pawn, so you can heal them with your vagina's special healing power.</description>
<iconPath>Things/Mote/Heart</iconPath>
<stunTargetWhileCasting>false</stunTargetWhileCasting>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<warmupMote>Mote_CoagulateStencil</warmupMote>
<warmupEffecter>Coagulate</warmupEffecter>
<warmupStartSound>Coagulate_Cast</warmupStartSound>
<jobDef>rjw_genes_lifeforce_healpussy</jobDef>
<displayOrder>401</displayOrder>
<verbProperties>
<verbClass>Verb_CastAbilityTouch</verbClass>
<drawAimPie>false</drawAimPie>
<range>-1</range>
<warmupTime>0</warmupTime>
<targetParams>
<canTargetAnimals>true</canTargetAnimals>
<canTargetSelf>false</canTargetSelf>
<canTargetBuildings>false</canTargetBuildings>
<canTargetMechs>false</canTargetMechs>
<canTargetBloodfeeders>true</canTargetBloodfeeders>
</targetParams>
</verbProperties>
<comps>
<li Class="RJW_Genes.CompProperties_AbilityLifeForceCost">
<fertilinCost>0.2</fertilinCost>
</li>
<li Class="RJW_Genes.CompProperties_AbilityPussyHeal"> <!-- namespace needs to be changed when copied to another mod-->
<tendQualityRange>0.4~0.8</tendQualityRange>
</li>
<li Class="RJW_Genes.CompProperties_SexInteractionRequirements">
<tags>
<!-- <li>Consensual</li> -->
<li>Rape</li>
</tags>
<dominantRequirement>
<families>
<li>Vagina</li>
</families>
</dominantRequirement>
</li>
</comps>
</AbilityDef>
</Defs>

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<AbilityDef>
<defName>rjw_genes_seduce</defName>
<label>seduce</label>
<description>Seduce the target to approach the caster.</description>
<iconPath>Things/Mote/Heart</iconPath>
<writeCombatLog>True</writeCombatLog>
<stunTargetWhileCasting>true</stunTargetWhileCasting>
<displayGizmoWhileUndrafted>true</displayGizmoWhileUndrafted>
<disableGizmoWhileUndrafted>false</disableGizmoWhileUndrafted>
<statBases>
<Ability_Duration>10</Ability_Duration>
</statBases>
<warmupMote>Mote_CoagulateStencil</warmupMote>
<warmupEffecter>Coagulate</warmupEffecter>
<warmupStartSound>Coagulate_Cast</warmupStartSound>
<verbProperties>
<verbClass>Verb_CastAbility</verbClass>
<range>10</range>
<warmupTime>1</warmupTime>
<targetParams>
<canTargetAnimals>false</canTargetAnimals>
<canTargetSelf>false</canTargetSelf>
<canTargetBuildings>false</canTargetBuildings>
<canTargetMechs>false</canTargetMechs>
<canTargetBloodfeeders>true</canTargetBloodfeeders>
</targetParams>
</verbProperties>
<comps>
<li Class = "RJW_Genes.CompProperties_Seduce">
<compClass>RJW_Genes.CompAbilityEffect_Seduce</compClass>
<destination>Caster</destination>
</li>
<li Class="CompProperties_AbilityFleckOnTarget">
<fleckDef>Heart</fleckDef>
</li>
<li Class="RJW_Genes.CompProperties_AbilityLifeForceCost">
<fertilinCost>0.1</fertilinCost>
</li>
</comps>
</AbilityDef>
</Defs>

View file

@ -37,6 +37,12 @@
<displayPriorityInXenotype>15</displayPriorityInXenotype>
</GeneCategoryDef>
<GeneCategoryDef>
<defName>rjw_genes_fertilin</defName>
<label>Fertilin</label>
<displayPriorityInXenotype>14</displayPriorityInXenotype>
</GeneCategoryDef>
<GeneCategoryDef>
<defName>rjw_genes_breeding</defName>
<label>Breeding</label>
@ -61,4 +67,6 @@
<displayPriorityInXenotype>8</displayPriorityInXenotype>
</GeneCategoryDef>
</Defs>

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<GeneDef Name="rjw_genes_wings" Abstract="True">
<displayCategory>Miscellaneous</displayCategory>
<randomChosen>true</randomChosen>
<exclusionTags>
<li>Wing</li>
<li>Wings</li>
</exclusionTags>
<graphicData>
<drawLoc>Tailbone</drawLoc>
</graphicData>
</GeneDef>
<GeneDef ParentName="rjw_genes_wings">
<defName>rjw_genes_succubus_wings</defName>
<label>succubus wings</label>
<description>Carriers of this gene grow succubus wings.</description>
<iconPath>Genes/Icons/Succubus_Wings</iconPath>
<iconColor>(0.75, 0.75, 0.75)</iconColor>
<displayOrderInCategory>1000</displayOrderInCategory>
<abilities>
<li>rjw_genes_flight</li>
</abilities>
<descriptionHyperlinks>
<AbilityDef>rjw_genes_flight</AbilityDef>
</descriptionHyperlinks>
<biostatCpx>1</biostatCpx>
<graphicData>
<graphicPath>Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Wings/Succubus_Wings</graphicPath>
<colorType>Skin</colorType>
<drawScale>2</drawScale>
<drawOffsetNorth>(0.0, 0.01, -0.1)</drawOffsetNorth>
<drawOffsetSouth>(0.0, 0.0, -0.1)</drawOffsetSouth>
<drawOffsetEast>(0.1, 0.0, 0.0)</drawOffsetEast>
</graphicData>
</GeneDef>
<GeneDef ParentName="GeneTailBase">
<defName>rjw_genes_succubus_tail</defName>
<label>succubus tail</label>
<description>Carriers of this gene grow a slender tail ending with a heart that can act as a dexterous fifth limb.</description>
<iconPath>Genes/Icons/Succubus_Tail</iconPath>
<iconColor>(1, 0, 0)</iconColor>
<displayOrderInCategory>1000</displayOrderInCategory>
<capMods>
<li>
<capacity>Manipulation</capacity>
<offset>0.05</offset>
</li>
</capMods>
<biostatCpx>1</biostatCpx>
<biostatMet>-1</biostatMet>
<graphicData>
<graphicPaths>
<li>Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L1</li>
<li>Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R1</li>
<li>Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L2</li>
<li>Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R2</li>
</graphicPaths>
<colorType>Skin</colorType>
<drawScale>2</drawScale>
<drawOffsetNorth>(0, 0.2, -0.1)</drawOffsetNorth>
<drawOffsetSouth>(0, -0.1, 0.1)</drawOffsetSouth>
<drawOffsetEast>(0.2, 0.2, 0.1)</drawOffsetEast>
</graphicData>
<randomChosen>true</randomChosen>
</GeneDef>
</Defs>

View file

@ -0,0 +1,188 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<GeneDef>
<defName>rjw_genes_lifeforce</defName>
<label>fertilin</label>
<description>Carriers of this gene have a reserve of biological strength powered by a resource called fertilin. The resource can be gained and spent in various ways, some of which are unlocked by other genes.\n\nCarriers lose 5 fertilin per day from biological entropy. \n\nGene is inactive until carrier is able to have sex.</description>
<geneClass>RJW_Genes.Gene_LifeForce</geneClass>
<resourceGizmoType>RJW_Genes.GeneGizmo_ResourceLifeForce</resourceGizmoType>
<resourceLabel>fertilin</resourceLabel>
<resourceGizmoThresholds>
<li>0.25</li>
<li>0.5</li>
<li>0.75</li>
</resourceGizmoThresholds>
<showGizmoOnWorldView>true</showGizmoOnWorldView>
<showGizmoWhenDrafted>true</showGizmoWhenDrafted>
<resourceDescription>A reserve of biological strength which can be gained and spent in a variety of ways. \n\nFertilin can be increased by absorbing cum, typically through oral sex or stored cum. \n\nIf fertilin reaches zero, {PAWN_nameDef} will become very unhappy and may try to obtain some forcefully.</resourceDescription>
<iconPath>UI/Icons/Genes/Gene_Hemogenic</iconPath>
<selectionWeight>0</selectionWeight>
<displayCategory>rjw_genes_fertilin</displayCategory>
<displayOrderInCategory>-2</displayOrderInCategory>
<customEffectDescriptions>
<li>Gives fertilin supply.</li>
</customEffectDescriptions>
<symbolPack>
<prefixSymbols>
<li><symbol>fert</symbol></li>
</prefixSymbols>
</symbolPack>
<mentalBreakDef>rjw_genes_lifeforce_randomrape</mentalBreakDef>
<resourceLossPerDay>0.05</resourceLossPerDay>
<biostatCpx>1</biostatCpx>
<biostatMet>1</biostatMet>
</GeneDef>
<GeneDef>
<defName>rjw_genes_lifeforce_drain</defName>
<label>fertilin drain</label>
<labelShortAdj>draining</labelShortAdj>
<description>Carriers lose an additional 15 fertilin per day from biological entropy.</description>
<resourceLabel>fertilin</resourceLabel>
<geneClass>RJW_Genes.Gene_LifeForceDrain</geneClass>
<iconPath>UI/Icons/Genes/Gene_HemogenDrain</iconPath>
<prerequisite>rjw_genes_lifeforce</prerequisite>
<resourceLossPerDay>0.15</resourceLossPerDay>
<displayCategory>rjw_genes_fertilin</displayCategory>
<displayOrderInCategory>-1</displayOrderInCategory>
<biostatCpx>1</biostatCpx>
<biostatMet>6</biostatMet>
</GeneDef>
<GeneDef>
<defName>rjw_genes_pussyhealer</defName>
<label>Pussy Healer</label>
<labelShortAdj>pussyhealer</labelShortAdj>
<description>Carriers of this gene are able use vaginal sex to tend to other's wounds.</description>
<iconPath>Things/Mote/Heart</iconPath>
<prerequisite>rjw_genes_lifeforce</prerequisite>
<displayOrderInCategory>9</displayOrderInCategory>
<displayCategory>rjw_genes_fertilin</displayCategory>
<abilities>
<li>rjw_genes_pussyheal</li>
</abilities>
<descriptionHyperlinks>
<AbilityDef>rjw_genes_pussyheal</AbilityDef>
</descriptionHyperlinks>
<biostatCpx>1</biostatCpx>
<biostatMet>-1</biostatMet>
<symbolPack>
<suffixSymbols>
<li><symbol>life</symbol></li>
<li><symbol>pussy</symbol></li>
<li><symbol>heal</symbol></li>
</suffixSymbols>
</symbolPack>
</GeneDef>
<GeneDef>
<defName>rjw_genes_cockeater</defName>
<label>Cockeater</label>
<labelShortAdj>cockeater</labelShortAdj>
<description>Carriers of this gene are able eat cocks to restore their fertilin supply.</description>
<iconPath>Things/Mote/Heart</iconPath>
<prerequisite>rjw_genes_lifeforce</prerequisite>
<displayOrderInCategory>11</displayOrderInCategory>
<displayCategory>rjw_genes_fertilin</displayCategory>
<abilities>
<li>rjw_genes_cockeater</li>
</abilities>
<descriptionHyperlinks>
<AbilityDef>rjw_genes_cockeater</AbilityDef>
</descriptionHyperlinks>
<biostatCpx>1</biostatCpx>
<biostatMet>-1</biostatMet>
<symbolPack>
<suffixSymbols>
<li><symbol>life</symbol></li>
<li><symbol>cock</symbol></li>
<li><symbol>eat</symbol></li>
</suffixSymbols>
</symbolPack>
</GeneDef>
<GeneDef>
<defName>rjw_genes_paralysingkiss</defName>
<label>paralysing kiss</label>
<labelShortAdj>paralysing kiss</labelShortAdj>
<description>Carriers of this gene are able to briefly stun an enemy with a kiss.</description>
<iconPath>Things/Mote/Heart</iconPath>
<prerequisite>rjw_genes_lifeforce</prerequisite>
<displayOrderInCategory>12</displayOrderInCategory>
<displayCategory>rjw_genes_fertilin</displayCategory>
<abilities>
<li>rjw_genes_paralysingkiss</li>
</abilities>
<descriptionHyperlinks>
<AbilityDef>rjw_genes_paralysingkiss</AbilityDef>
</descriptionHyperlinks>
<biostatCpx>1</biostatCpx>
<biostatMet>-1</biostatMet>
<symbolPack>
<suffixSymbols>
<li><symbol>stun</symbol></li>
<li><symbol>kiss</symbol></li>
</suffixSymbols>
</symbolPack>
</GeneDef>
<GeneDef>
<defName>rjw_genes_seduce</defName>
<label>seduction</label>
<labelShortAdj>seduction</labelShortAdj>
<description>Carriers of this gene are able to seduce a pawn into having sex with them.</description>
<iconPath>Things/Mote/Heart</iconPath>
<prerequisite>rjw_genes_lifeforce</prerequisite>
<displayOrderInCategory>13</displayOrderInCategory>
<displayCategory>rjw_genes_fertilin</displayCategory>
<abilities>
<li>rjw_genes_seduce</li>
</abilities>
<descriptionHyperlinks>
<AbilityDef>rjw_genes_seduce</AbilityDef>
</descriptionHyperlinks>
<biostatCpx>1</biostatCpx>
<biostatMet>-1</biostatMet>
<symbolPack>
<suffixSymbols>
<li><symbol>stun</symbol></li>
<li><symbol>kiss</symbol></li>
</suffixSymbols>
</symbolPack>
</GeneDef>
<GeneDef>
<defName>rjw_genes_vaginal_absorber</defName>
<label>Vaginal Fertilin Absorber</label>
<description>Carriers of this gene are able to absorb fertilin through their vagina.</description>
<iconPath>Things/Mote/Heart</iconPath>
<prerequisite>rjw_genes_lifeforce</prerequisite>
<displayOrderInCategory>2</displayOrderInCategory>
<displayCategory>rjw_genes_fertilin</displayCategory>
<biostatCpx>1</biostatCpx>
</GeneDef>
<GeneDef>
<defName>rjw_genes_anal_absorber</defName>
<label>Anal Fertilin Absorber</label>
<description>Carriers of this gene are able to absorb fertilin through their anus.</description>
<iconPath>Things/Mote/Heart</iconPath>
<prerequisite>rjw_genes_lifeforce</prerequisite>
<displayOrderInCategory>3</displayOrderInCategory>
<displayCategory>rjw_genes_fertilin</displayCategory>
<biostatCpx>1</biostatCpx>
</GeneDef>
<GeneDef>
<defName>rjw_genes_drainer</defName>
<label>vitality drainer</label>
<description>Carriers of this gene are able to absorb a great amount of fertilin by draining the vitality of the partner.</description>
<iconPath>Things/Mote/Heart</iconPath>
<prerequisite>rjw_genes_lifeforce</prerequisite>
<displayOrderInCategory>4</displayOrderInCategory>
<displayCategory>rjw_genes_fertilin</displayCategory>
<biostatCpx>1</biostatCpx>
<biostatMet>-1</biostatMet>
</GeneDef>
</Defs>

View file

@ -33,4 +33,16 @@
<displayOrderInCategory>3</displayOrderInCategory>
</GeneDef>
<GeneDef>
<defName>rjw_genes_aphrodisiac_pheromones</defName>
<label>Aphrodisiac Pheromones</label>
<displayCategory>rjw_genes_special</displayCategory>
<geneClass>RJW_Genes.Gene_Aphrodisiac_Pheromones</geneClass>
<description>Pheremones of this pawn induce an incressed sexdrive to others nearby.</description>
<iconPath>UI/Memes/FleshPurity</iconPath>
<displayOrderInCategory>4</displayOrderInCategory>
<biostatCpx>1</biostatCpx>
<biostatMet>1</biostatMet>
</GeneDef>
</Defs>

View file

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<HediffDef>
<defName>Aphrodisiac_Pheromone</defName>
<hediffClass>HediffWithComps</hediffClass>
<label>induced libido</label>
<description>Aphrodisiac pheromone effects.</description>
<defaultLabelColor>(1,0,0.5)</defaultLabelColor>
<maxSeverity>1.0</maxSeverity>
<comps>
<li Class="HediffCompProperties_SeverityPerDay">
<severityPerDay>-24.0</severityPerDay>
</li>
</comps>
<stages>
<li>
<becomeVisible>true</becomeVisible>
<statFactors>
<SexFrequency>2</SexFrequency>
</statFactors>
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>Fertilin_Lost</defName>
<hediffClass>RJW_Genes.HediffWithComps_tank</hediffClass>
<label>lost fertilin</label>
<description>Percentage of fertilin lost.</description>
<defaultLabelColor>(1,1,1)</defaultLabelColor>
<maxSeverity>1</maxSeverity>
<comps>
<li Class="HediffCompProperties_SeverityPerDay">
<severityPerDay>-0.5</severityPerDay>
</li>
</comps>
<stages>
<li>
<becomeVisible>true</becomeVisible>
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>Succubus_Drained</defName>
<hediffClass>HediffWithComps</hediffClass>
<label>Drained</label>
<description>The vitality of this pawn has been drained.</description>
<defaultLabelColor>(1,0,0.5)</defaultLabelColor>
<maxSeverity>1.0</maxSeverity>
<initialSeverity>1.0</initialSeverity>
<comps>
<li Class="HediffCompProperties_SeverityPerDay">
<severityPerDay>-1.0</severityPerDay>
</li>
</comps>
<stages>
<li>
<label>minor</label>
<capMods>
<li>
<capacity>Consciousness</capacity>
<offset>-0.1</offset>
</li>
</capMods>
</li>
<li>
<minSeverity>0.5</minSeverity>
<label>moderate</label>
<capMods>
<li>
<capacity>Consciousness</capacity>
<offset>-0.2</offset>
</li>
</capMods>
</li>
<li>
<minSeverity>0.8</minSeverity>
<label>severe</label>
<capMods>
<li>
<capacity>Consciousness</capacity>
<offset>-0.4</offset>
</li>
</capMods>
</li>
</stages>
</HediffDef>
</Defs>

View file

@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Rape_SuccubusTail_Tailjob</defName>
<label>succubustail tailjob</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Was given tailjob by [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Gave tailjob to [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Tailjob</RMBLabel>
<rjwSextype>Handjob</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Tailjob_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>SubSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Rape</li>
</tags>
<dominantRequirement>
<tags>
<li>CanPenetrate</li>
</tags>
</dominantRequirement>
<submissiveRequirement>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Rape_SuccubusTail_Vaginal</defName>
<label>succubustail vaginal</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Gave vaginal tailsex to [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Was given vaginal tailsex by [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Vaginal Tailsex</RMBLabel>
<rjwSextype>Vaginal</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Vaginal_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>DomSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Rape</li>
</tags>
<dominantRequirement>
</dominantRequirement>
<submissiveRequirement>
<families>
<li>Vagina</li>
</families>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Rape_SuccubusTail_Anal</defName>
<label>succubustail anal</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Gave anal tailsex to [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Was given anal tailsex by [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Anal Tailsex</RMBLabel>
<rjwSextype>Anal</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Anal_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>DomSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Rape</li>
</tags>
<dominantRequirement>
</dominantRequirement>
<submissiveRequirement>
<families>
<li>Anus</li>
</families>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
<!--Top of tail opens up and evelops the penis-->
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Rape_SuccubusTail_Envelop</defName>
<label>succubustail envelop</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Was given special tailjob by [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Gave special tailjob to [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Envelop</RMBLabel>
<rjwSextype>Vaginal</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Envelop_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>SubSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Rape</li>
</tags>
<dominantRequirement>
<tags>
<li>CanPenetrate</li>
</tags>
</dominantRequirement>
<submissiveRequirement>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
</Defs>

View file

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Rape_SuccubusTail_Reverse_Tailjob</defName>
<label>succubustail tailjob</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Gave tailjob to [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Was given tailjob by [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Tailjob</RMBLabel>
<rjwSextype>Handjob</rjwSextype>
<rulepack_defs>
<li>SubSuccubusTail_Tailjob_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>DomSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Reverse</li>
<li>Rape</li>
</tags>
<dominantRequirement>
</dominantRequirement>
<submissiveRequirement>
<tags>
<li>CanPenetrate</li>
</tags>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Rape_SuccubusTail_Reverse_Vaginal</defName>
<label>succubustail vaginal</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Was given vaginal tailsex by [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Gave vaginal tailsex to [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Vaginal Tailsex</RMBLabel>
<rjwSextype>Vaginal</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Vaginal_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>SubSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Reverse</li>
<li>Rape</li>
</tags>
<dominantRequirement>
<families>
<li>Vagina</li>
</families>
</dominantRequirement>
<submissiveRequirement>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Rape_SuccubusTail_Reverse_Anal</defName>
<label>succubustail anal</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Was given anal tailsex by [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Gave anal tailsex to [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Anal Tailsex</RMBLabel>
<rjwSextype>Anal</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Anal_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>SubSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Reverse</li>
<li>Rape</li>
</tags>
<dominantRequirement>
<families>
<li>Anus</li>
</families>
</dominantRequirement>
<submissiveRequirement>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
<!--Top of tail opens up and evelops the penis-->
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Rape_SuccubusTail_Reverse_Envelop</defName>
<label>succubustail envelop</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Gave special tailjob to [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Was given special tailjob by [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Envelop</RMBLabel>
<rjwSextype>Vaginal</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Envelop_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>DomSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Reverse</li>
<li>Rape</li>
</tags>
<dominantRequirement>
</dominantRequirement>
<submissiveRequirement>
<tags>
<li>CanPenetrate</li>
</tags>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
</Defs>

View file

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Sex_SuccubusTail_Reverse_Tailjob</defName>
<label>succubustail tailjob</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Gave tailjob to [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Was given tailjob by [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Tailjob</RMBLabel>
<rjwSextype>Handjob</rjwSextype>
<rulepack_defs>
<li>SubSuccubusTail_Tailjob_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>DomSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Reverse</li>
<li>Consensual</li>
</tags>
<dominantRequirement>
</dominantRequirement>
<submissiveRequirement>
<tags>
<li>CanPenetrate</li>
</tags>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Sex_SuccubusTail_Reverse_Vaginal</defName>
<label>succubustail vaginal</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Was given vaginal tailsex by [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Gave vaginal tailsex to [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Vaginal Tailsex</RMBLabel>
<rjwSextype>Vaginal</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Vaginal_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>SubSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Reverse</li>
<li>Consensual</li>
</tags>
<dominantRequirement>
<families>
<li>Vagina</li>
</families>
</dominantRequirement>
<submissiveRequirement>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Sex_SuccubusTail_Reverse_Anal</defName>
<label>succubustail anal</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Was given anal tailsex by [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Gave anal tailsex to [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Anal Tailsex</RMBLabel>
<rjwSextype>Anal</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Anal_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>SubSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Reverse</li>
<li>Consensual</li>
</tags>
<dominantRequirement>
<families>
<li>Anus</li>
</families>
</dominantRequirement>
<submissiveRequirement>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
<!--Top of tail opens up and evelops the penis-->
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Sex_SuccubusTail_Reverse_Envelop</defName>
<label>succubustail envelop</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Gave special tailjob to [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Was given special tailjob by [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Envelop</RMBLabel>
<rjwSextype>Vaginal</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Envelop_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>DomSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Reverse</li>
<li>Consensual</li>
</tags>
<dominantRequirement>
</dominantRequirement>
<submissiveRequirement>
<tags>
<li>CanPenetrate</li>
</tags>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
</Defs>

View file

@ -0,0 +1,154 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Sex_SuccubusTail_Tailjob</defName>
<label>succubustail tailjob</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Was given tailjob by [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Gave tailjob to [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Tailjob</RMBLabel>
<rjwSextype>Handjob</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Tailjob_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>SubSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Consensual</li>
</tags>
<dominantRequirement>
<tags>
<li>CanPenetrate</li>
</tags>
</dominantRequirement>
<submissiveRequirement>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Sex_SuccubusTail_Vaginal</defName>
<label>succubustail vaginal</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Gave vaginal tailsex to [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Was given vaginal tailsex by [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Vaginal Tailsex</RMBLabel>
<rjwSextype>Vaginal</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Vaginal_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>DomSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Consensual</li>
</tags>
<dominantRequirement>
</dominantRequirement>
<submissiveRequirement>
<families>
<li>Vagina</li>
</families>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Sex_SuccubusTail_Anal</defName>
<label>succubustail anal</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Gave anal tailsex to [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Was given anal tailsex by [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Anal Tailsex</RMBLabel>
<rjwSextype>Anal</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Anal_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>DomSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Consensual</li>
</tags>
<dominantRequirement>
</dominantRequirement>
<submissiveRequirement>
<families>
<li>Anus</li>
</families>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
<!--Top of tail opens up and evelops the penis-->
<InteractionDef ParentName="RJW_InteractionDefBaseSex">
<defName>Sex_SuccubusTail_Envelop</defName>
<label>succubustail envelop</label>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->Was given special tailjob by [RECIPIENT_nameDef].</li>
</rulesStrings>
</logRulesInitiator>
<logRulesRecipient>
<rulesStrings>
<li>r_logentry->Gave special tailjob to [INITIATOR_nameDef].</li>
</rulesStrings>
</logRulesRecipient>
<modExtensions>
<li Class="rjw.InteractionExtension">
<RMBLabel>Envelop</RMBLabel>
<rjwSextype>Vaginal</rjwSextype>
<rulepack_defs>
<li>DomSuccubusTail_Envelop_RP</li>
</rulepack_defs>
</li>
<li Class="rjw.Modules.Interactions.DefModExtensions.InteractionSelectorExtension">
<customRequirementHandler>SubSuccubusTailCustomRequirementHandler</customRequirementHandler>
<tags>
<li>Consensual</li>
</tags>
<dominantRequirement>
<tags>
<li>CanPenetrate</li>
</tags>
</dominantRequirement>
<submissiveRequirement>
</submissiveRequirement>
</li>
</modExtensions>
</InteractionDef>
</Defs>

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<JobDef>
<defName>rjw_genes_lifeforce_randomrape</defName>
<driverClass>rjw.JobDriver_RandomRape</driverClass>
<reportString>Raping</reportString>
<casualInterruptible>false</casualInterruptible>
</JobDef>
<JobDef>
<defName>rjw_genes_lifeforce_healpussy</defName>
<driverClass>RJW_Genes.JobDriver_CastAbilityAfterSex</driverClass>
<reportString>Healing someone with sex.</reportString>
<casualInterruptible>false</casualInterruptible>
</JobDef>
<JobDef>
<defName>rjw_genes_lifeforce_seduced</defName>
<driverClass>RJW_Genes.JobDriver_Seduced</driverClass>
<reportString>Seduced.</reportString>
<casualInterruptible>false</casualInterruptible>
<playerInterruptible>false</playerInterruptible>
</JobDef>
</Defs>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<JobDef>
<defName>sex_on_spot</defName>
<driverClass>RJW_Genes.JobDriver_SexOnSpot</driverClass>
<reportString>Making love on the spot.</reportString>
<casualInterruptible>false</casualInterruptible>
</JobDef>
<JobDef>
<defName>sex_on_spot_reciever</defName>
<driverClass>RJW_Genes.JobDriver_SexOnSpotReciever</driverClass>
<reportString>lovin'.</reportString>
<casualInterruptible>false</casualInterruptible>
</JobDef>
</Defs>

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<MentalBreakDef>
<defName>rjw_genes_lifeforce_randomrape</defName>
<mentalState>rjw_genes_lifeforce_randomrape</mentalState>
<baseCommonality>1.5</baseCommonality>
<intensity>Extreme</intensity>
</MentalBreakDef>
<MentalStateDef ParentName="BaseMentalState">
<defName>rjw_genes_lifeforce_randomrape</defName>
<stateClass>RJW_Genes.LifeForceMentalState</stateClass>
<workerClass>RJW_Genes.LifeForceMentalStateWorker</workerClass>
<label>random rape</label>
<category>Malicious</category>
<prisonersCanDo>true</prisonersCanDo>
<colonistsOnly>false</colonistsOnly>
<minTicksBeforeRecovery>30000</minTicksBeforeRecovery>
<recoveryMtbDays>0.8</recoveryMtbDays>
<maxTicksBeforeRecovery>80000</maxTicksBeforeRecovery>
<nameColor>(0.5, 0.9, 0.5)</nameColor>
<beginLetterLabel>random rape</beginLetterLabel>
<beginLetter>{0} has run out of lifeforce and is looking to obtain some.</beginLetter>
<beginLetterDef>ThreatSmall</beginLetterDef>
<recoveryMessage>{0} is no longer raping randomly.</recoveryMessage>
<baseInspectLine>Mental state: Random Rape</baseInspectLine>
<recoverFromSleep>true</recoverFromSleep>
</MentalStateDef>
</Defs>

View file

@ -2,7 +2,12 @@
<Defs>
<RJW_BGS.RaceGeneDef Name = "Canine">
<defName>Canine</defName>
<raceGroup>Canine_Group</raceGroup>
<raceGroups>
<li>Canine_Group</li>
<li>CanineAnimal</li>
<li>CanineSingleGenderAnimal</li>
<li>CanineSkinAnimal</li>
</raceGroups>
<genes>
<li>
<defName>Ears_Floppy</defName>
@ -38,7 +43,11 @@
<RJW_BGS.RaceGeneDef>
<defName>Insect</defName>
<raceGroup>Insect_Group</raceGroup>
<raceGroups>
<li>Insect_Group</li>
<li>ArthropodOvipositorAnimal</li>
<li>ArthropodOvipositorHornyAnimal</li>
</raceGroups>
<genes>
<li>
<defName>Beauty_Ugly</defName>
@ -73,7 +82,14 @@
<RJW_BGS.RaceGeneDef>
<defName>Feline</defName>
<raceGroup>Feline_Group</raceGroup>
<raceGroups>
<li>Feline_Group</li>
<li>FelineAnimal</li>
<li>FelineHornyAnimal</li>
<li>FelineSingleGenderAnimal</li>
<li>AA_SandProwlerAnimal</li>
</raceGroups>
<genes>
<li>
<defName>Tail_Furry</defName>
@ -108,7 +124,10 @@
<RJW_BGS.RaceGeneDef>
<defName>Equine</defName>
<raceGroup>Equine_Group</raceGroup>
<raceGroups>
<li>Equine_Group</li>
<li>HorseAnimal</li>
</raceGroups>
<genes>
<li>
<defName>Furskin</defName>
@ -143,7 +162,12 @@
<RJW_BGS.RaceGeneDef>
<defName>Dragon</defName>
<raceGroup>Dragon_Group</raceGroup>
<raceGroups>
<li>Dragon_Group</li>
<li>ThrumboAnimal</li>
<li>DragonAnimal</li>
<li>DragonSingleGenderAnimal</li>
</raceGroups>
<genes>
<li>
<defName>Unstoppable</defName>
@ -166,7 +190,7 @@
<chance>0.1</chance>
</li>
<li>
<defName>rjw_genes_draconic_genitalia</defName>
<defName>rjw_genes_dragon_genitalia</defName>
<chance>0.6</chance>
</li>
<li>
@ -190,7 +214,12 @@
<RJW_BGS.RaceGeneDef>
<defName>Rodent</defName>
<raceGroup>Rodent_Group</raceGroup>
<raceGroups>
<li>Rodent_Group</li>
<li>RodentAnimal</li>
<li>RodentSingleGenderAnimal</li>
<li>DragonSingleGenderAnimal</li>
</raceGroups>
<genes>
<li>
<defName>Furskin</defName>
@ -225,7 +254,10 @@
<RJW_BGS.RaceGeneDef>
<defName>Racoon</defName>
<raceGroup>Raccon_Group</raceGroup>
<raceGroups>
<li>Raccon_Group</li>
<li>RaccoonAnimal</li>
</raceGroups>
<genes>
<li>
<defName>Furskin</defName>

View file

@ -1,12 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<!--
<!-- this is to disable the xml, remove it for your own xml
<RJW_BGS.RaceGeneDef>
<defName>Canine</defName>
defName can be anything you want, as long as it is unique
<raceGroup>Canine_Group</raceGroup>
RJW.Racegroupdef, all animals in the raceGroup will be part of this group, RJW race support uses this so those can be used to quickly add a group
<raceGroups>
<li>Canine_Group</li>
<li>CanineAnimal</li> from racesupport
<li>CanineSingleGenderAnimal</li> from racesupport
<li>CanineSkinAnimal</li> from racesupport
</raceGroups>
RJW.Racegroupdef, all animals in the added raceGroups will be part of this group, RJW race support uses other defnames and overwrite vanilla ones, so add them to if you use it.
<raceNames>
<li> </li>
@ -38,10 +43,10 @@
For each gene you need to find the defname and give it a chance to appear. Each gene is rolled independently.
</RJW_BGS.RaceGeneDef>
this is to disable the xml, remove it for your own xml -->
-->
<!-- You can use parents to have animals get specific genes in addition to the group. So warg children will have a chance for Ears_Floppy, rjw_genes_slime_genitalia and StrongStomach
<!-- this is to disable the xml, remove it for your own xml
You can use parents to have animals get specific genes in addition to the group. So warg children will have a chance for Ears_Floppy, rjw_genes_slime_genitalia and StrongStomach
<RJW_BGS.RaceGeneDef ParentName = "Canine">
<defName>Warg</defName>
<raceNames>
@ -54,5 +59,7 @@
</li>
</genes>
</RJW_BGS.RaceGeneDef>
-->
this is to disable the xml, remove it for your own xml -->
</Defs>

View file

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<RulePackDef>
<defName>DomSuccubusTail_Tailjob_RP</defName>
<rulePack>
<rulesStrings>
<li>sent-> [INITIATOR_nameDef] gave [RECIPIENT_nameDef] a tailjob.</li>
</rulesStrings>
</rulePack>
</RulePackDef>
<RulePackDef>
<defName>DomSuccubusTail_Vaginal_RP</defName>
<rulePack>
<rulesStrings>
<li>sent-> [INITIATOR_nameDef] [INITIATOR_possessive] tail was vaginally inserted into [RECIPIENT_nameDef].</li>
</rulesStrings>
</rulePack>
</RulePackDef>
<RulePackDef>
<defName>DomSuccubusTail_Anal_RP</defName>
<rulePack>
<rulesStrings>
<li>sent-> [INITIATOR_nameDef] [INITIATOR_possessive] tail was anally inserted into [RECIPIENT_nameDef].</li>
</rulesStrings>
</rulePack>
</RulePackDef>
<!--Top of tail opens up and evelops the penis-->
<RulePackDef>
<defName>DomSuccubusTail_Envelop_RP</defName>
<rulePack>
<rulesStrings>
<li>sent-> [RECIPIENT_nameDef] dick was enveloped by [INITIATOR_nameDef] [INITIATOR_possessive] tail.</li>
</rulesStrings>
</rulePack>
</RulePackDef>
<RulePackDef>
<defName>SubSuccubusTail_Tailjob_RP</defName>
<rulePack>
<rulesStrings>
<li>sent-> [RECIPIENT_nameDef] gave [INITIATOR_nameDef] a tailjob.</li>
</rulesStrings>
</rulePack>
</RulePackDef>
<RulePackDef>
<defName>SubSuccubusTail_Vaginal_RP</defName>
<rulePack>
<rulesStrings>
<li>sent-> [RECIPIENT_nameDef] [RECIPIENT_possessive] tail was vaginally inserted into [INITIATOR_nameDef].</li>
</rulesStrings>
</rulePack>
</RulePackDef>
<RulePackDef>
<defName>SubSuccubusTail_Anal_RP</defName>
<rulePack>
<rulesStrings>
<li>sent-> [RECIPIENT_nameDef] [RECIPIENT_possessive] tail was anally inserted into [INITIATOR_nameDef].</li>
</rulesStrings>
</rulePack>
</RulePackDef>
<!--Top of tail opens up and evelops the penis-->
<RulePackDef>
<defName>SubSuccubusTail_Envelop_RP</defName>
<rulePack>
<rulesStrings>
<li>sent-> [INITIATOR_nameDef] dick was enveloped by [RECIPIENT_nameDef] [RECIPIENT_possessive] tail.</li>
</rulesStrings>
</rulePack>
</RulePackDef>
</Defs>

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<!--If below low try get some, if critical also consider rape, also a chance to do bestiality
First try and obtain by normal sex, then try to eat gathercum (sexperience)
If these fail try rape and a small chance for bestiality
-->
<ThinkTreeDef>
<defName>SuccubusGetLifeForce</defName>
<insertTag>Humanlike_PostMain</insertTag>
<insertPriority>14</insertPriority>
<thinkRoot Class="ThinkNode_Priority">
<subNodes>
<li Class="RJW_Genes.ThinkNode_ConditionalLowLifeForce">
<subNodes>
<li Class="rjw.ThinkNode_ConditionalSexChecks">
<subNodes>
<li Class="JobGiver_DoLovin"/>
<li Class="rjw.JobGiver_JoininBed"/>
<li Class="rjw.JobGiver_ComfortPrisonerRape" />
<li Class="RJW_Genes.JobGiver_GetLifeForce"/>
<li Class="rjw.ThinkNode_ConditionalCanRapeCP">
<subNodes>
<li Class="RJW_Genes.ThinkNode_ConditionalCritcalLifeForce">
<subNodes>
<!--Maybe make a custom chance per hour to determine if pawn would consider rape-->
<li Class="ThinkNode_ChancePerHour_Constant">
<mtbHours>8</mtbHours>
<subNodes>
<li Class="rjw.JobGiver_RandomRape" />
</subNodes>
</li>
<li Class="rjw.ThinkNode_ConditionalBestiality">
<subNodes>
<li Class="rjw.ThinkNode_ChancePerHour_Bestiality">
<subNodes>
<li Class="rjw.JobGiver_Bestiality" />
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</li>
</subNodes>
</thinkRoot>
</ThinkTreeDef>
</Defs>

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThoughtDef>
<defName>rjw_genes_cock_eaten</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>30.0</durationDays>
<stackLimit>100</stackLimit>
<stackedEffectMultiplier>0.4</stackedEffectMultiplier>
<stages>
<li>
<label>cock eaten</label>
<description>My cock was eaten directly of my body, I am devestated.</description>
<baseMoodEffect>-30</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>rjw_genes_seduced</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>10.0</durationDays>
<stackLimit>100</stackLimit>
<stackedEffectMultiplier>0.4</stackedEffectMultiplier>
<stages>
<li>
<label>seduced</label>
<description>I was seduced into having sex. I regret what happened.</description>
<baseMoodEffect>-10</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>rjw_critical_fertilin</defName>
<stages>
<li>
<label>low on fertilin</label>
<description>I'm almost out of fertilin. I'm scared of losing control.</description>
<baseMoodEffect>-10</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
</Defs>

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<XenotypeDef>
<defName>rjw_genes_succubus</defName>
<label>Succubus</label>
<description>Succubi are strongly enhanced xenohumans. Powered by archites, their abilities go far beyond normal genetic enhancements. These overnaturally beautiful creatures strive parasitically on the Fertilin found in semen. </description>
<descriptionShort>Succubi are beautiful and extremely hungry Xenohumans. They strive on having sex and extracting their victims life-force through this. </descriptionShort>
<iconPath>UI/Icons/Xenotypes/Sanguophage</iconPath>
<soundDefOnImplant>PawnBecameSanguophage</soundDefOnImplant>
<generateWithXenogermReplicatingHediffChance>0.5</generateWithXenogermReplicatingHediffChance>
<xenogermReplicatingDurationLeftDaysRange>0.1~140</xenogermReplicatingDurationLeftDaysRange>
<combatPowerFactor>1</combatPowerFactor>
<displayPriority>-1000</displayPriority>
<factionlessGenerationWeight>0.005</factionlessGenerationWeight>
<doubleXenotypeChances>
<Pigskin>0.02</Pigskin>
<Impid>0.02</Impid>
<Yttakin>0.02</Yttakin>
<Neanderthal>0.02</Neanderthal>
<Waster>0.02</Waster>
<Dirtmole>0.02</Dirtmole>
</doubleXenotypeChances>
<genes>
<li>rjw_genes_bisexual</li>
<li>rjw_genes_hypersexual</li>
<li>rjw_genes_female_only</li>
<li>rjw_genes_lifeforce</li>
<li>rjw_genes_lifeforce_drain</li>
<li>rjw_genes_vaginal_absorber</li>
<li>rjw_genes_anal_absorber</li>
<li>rjw_genes_drainer</li>
<li>rjw_genes_pussyhealer</li>
<li>rjw_genes_paralysingkiss</li>
<li>rjw_genes_seduce</li>
<li>rjw_genes_elasticity</li>
<li>rjw_genes_succubus_tail</li>
<li>rjw_genes_aphrodisiac_pheromones</li>
<li>Beauty_Pretty</li>
<li>MoveSpeed_Quick</li>
<li>Robust</li>
<li>UVSensitivity_Intense</li>
<li>AptitudeStrong_Social</li>
<li>Ears_Pointed</li>
<li>Headbone_MiniHorns</li>
<li>Skin_Purple</li>
</genes>
</XenotypeDef>
</Defs>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
<!-- Fertilin strings -->
<AbilityDisabledNoFertilinGene>Pawn doesn't have required fertilin gene.</AbilityDisabledNoFertilinGene>
<AbilityDisabledNoFertilin>Not enough fertilin to cast.</AbilityDisabledNoFertilin>
<AlertLowFertilin>Low fertilin</AlertLowFertilin>
<AlertLowFertilinDesc>A colonist has low fertilin. At this point they are becoming desperate enough to consider rape and bestiality to obtain fertilin (if they didn't already). At zero fertilin they will lose all sense and start raping randomly</AlertLowFertilinDesc>
</LanguageData>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
<!-- Add RJW Sex meditation focus icon to VanillaPsycastsExpanded -->
<Operation Class="PatchOperationFindMod">
<mods>
<li>RJW Sexperience</li>
</mods>
<match Class="PatchOperationAdd">
<xpath>/Defs/ThingDef[defName="GatheredCum"]/ingestible/outcomeDoers</xpath>
<value>
<li Class="RJW_Genes.IngestionOutcomeDoer_LifeForceOffset">
<FertilinPerUnit>1</FertilinPerUnit>
</li>
</value>
</match>
</Operation>
</Patch>

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
<!-- Copied from Vanilla BingingDrug. live selfish till rape someone. In the future add others ways to obtain lifeforce. -->
<Operation Class="PatchOperationAdd">
<xpath>Defs/ThinkTreeDef[defName="MentalStateCritical"]/thinkRoot[@Class="ThinkNode_Tagger"]/subNodes</xpath>
<value>
<li Class="ThinkNode_ConditionalMentalState">
<state>rjw_genes_lifeforce_randomrape</state>
<subNodes>
<li Class="ThinkNode_ConditionalNeedPercentageAbove">
<need>Rest</need>
<threshold>0.05</threshold>
<invert>true</invert>
<subNodes>
<li Class="JobGiver_GetRest"/>
</subNodes>
</li>
<li Class="ThinkNode_PrioritySorter">
<minPriority>0.5</minPriority>
<subNodes>
<li Class="JobGiver_GetFood"/>
<li Class="ThinkNode_Priority_GetJoy">
<subNodes>
<li Class="JobGiver_GetJoy"/>
</subNodes>
</li>
</subNodes>
</li>
<li Class="rjw.JobGiver_RandomRape"/>
<li Class="JobGiver_WanderColony" />
</subNodes>
</li>
</value>
</Operation>
</Patch>

View file

@ -42,15 +42,15 @@
<!-- Conditional Patch, only add these Genes for players with Licentia
I tried "mayRequire" but that cannot be put so fine-grained into the <li> -->
<Operation Class="PatchOperationFindMod">
<mods>
<li>LustLicentia.RJWLabs</li>
</mods>
<match Class="PatchOperationAddModExtension">
<xpath>Defs/XenotypeDef[defName="Highmate"]/genes</xpath>
<value>
<li>rjw_genes_likes_cumflation</li>
</value>
</match>
<mods>
<li>LustLicentia.RJWLabs</li>
</mods>
<match Class="PatchOperationAddModExtension">
<xpath>Defs/XenotypeDef[defName="Highmate"]/genes</xpath>
<value>
<li>rjw_genes_likes_cumflation</li>
</value>
</match>
</Operation>
<Operation Class="PatchOperationAdd">

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,015 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -5,6 +5,8 @@ VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rjw-Genes", "Source\Rjw-Genes.csproj", "{D7D21B4A-1DA7-41D8-B202-C58CA8FA62AA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FB09ADF4-FC35-4C1F-9135-2B4C4E4ED347}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU

View file

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RJW_BGS
namespace RJW_BGS
{
public class BestialityGeneInheritanceDef
{

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using Verse;
using RimWorld;
using rjw;
@ -20,14 +16,18 @@ namespace RJW_BGS
if (mother.RaceProps.Humanlike && father.RaceProps.Humanlike)
return genelist;
ModLog.Message($"Trigger an Animal-Gene-Inheritance for {father.Name} and {mother.Name}");
//One parent must be an animal and the other must be human, so only one needs to return
if (father != null && !father.RaceProps.Humanlike)
{
if (RJW_BGSSettings.rjw_bgs_detailed_debug)
ModLog.Message($"Father was found to be animal - looking up genes for {father.Name}");
return SelectGenes(father);
}
if (mother != null && !mother.RaceProps.Humanlike)
{
if (RJW_BGSSettings.rjw_bgs_detailed_debug)
ModLog.Message($"Mother was found to be animal - looking up genes for {mother.Name}");
return SelectGenes(mother);
}
@ -48,25 +48,48 @@ namespace RJW_BGS
{
foreach (BestialityGeneInheritanceDef gene in raceGeneDef.genes)
{
if (gene.chance >= Rand.Range(0.01f,1f))
if (gene.chance * RJW_BGSSettings.rjw_bgs_global_gene_chance >= Rand.Range(0.01f,1f))
{
genelist.Add(DefDatabase<GeneDef>.GetNamed(gene.defName));
}
}
}
if (RJW_BGSSettings.rjw_bgs_detailed_debug)
ModLog.Message($"From {raceGeneDef.genes.Count} possible genes in {raceGeneDef.defName}, {genelist.Count} were added by chance ({RJW_BGSSettings.rjw_bgs_global_gene_chance} chance multiplier from Settings).");
return genelist;
}
/// <summary>
/// Adds a list of Genes to the pawns existing GeneSet.
/// Whether it is added as a Xenogene or Endogene is configured in Mod-Settings.
/// </summary>
/// <param name="pawn">The pawn for which Genes will be added</param>
/// <param name="genes">The Genes to add (Endogene by default, Xenogene with Mod Settings)</param>
public static void AddGenes(Pawn pawn, List<GeneDef> genes)
{
foreach (GeneDef gene in genes)
{
pawn.genes.AddGene(gene, false);
pawn.genes.AddGene(gene, RJW_BGSSettings.rjw_bgs_animal_genes_as_xenogenes);
}
}
/// <summary>
/// Initiates a bestiality baby with genes if the baby does not exist earlier.
/// This is used to make rjw-egg-pregnancies work.
/// Related file: PatchRJWHediffInsect_Egg.cs
/// </summary>
/// <param name="mother">The mother of the baby.</param>
/// <param name="dad">The father of the baby.</param>
/// <param name="baby">The baby created in non-pregnancy-way (has 0 Genes yet)</param>
public static void NewGenes(Pawn mother, Pawn dad, Pawn baby)
{
if (!RJW_BGSSettings.rjw_bgs_enabled)
{
return;
}
ModLog.Message($"Triggering an New-Gene Animal-Gene-Inheritance for {baby.Name} ({dad.Name} + {mother.Name})");
if (baby.RaceProps.Humanlike)
{
if (baby.genes == null)

View file

@ -16,6 +16,10 @@ namespace RJW_BGS
[HarmonyPostfix]
public static void AddGenes(Pawn mother, Pawn dad, ref Hediff_BasePregnancy __instance)
{
if (!RJW_BGSSettings.rjw_bgs_enabled)
{
return;
}
foreach (Pawn baby in __instance.babies)
{
if (baby.RaceProps.Humanlike)

View file

@ -1,14 +1,8 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using rjw;
using RimWorld;
using Verse;
namespace RJW_BGS
{

View file

@ -1,15 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using RimWorld;
using Verse;
using rjw;
namespace RJW_BGS
{
/// <summary>
/// This Patch is applied to change the normal pregnancy to add animal-inheritance.
/// If the settings allow animal gene inheritance,
/// the genes are determined and "simply added".
/// </summary>
[HarmonyPatch(typeof(PregnancyUtility), "GetInheritedGeneSet", new Type[]
{
typeof(Pawn),
@ -22,6 +24,10 @@ namespace RJW_BGS
[HarmonyPostfix]
public static void AnimalInheritedGenes(Pawn father, Pawn mother, ref GeneSet __result)
{
if (!RJW_BGSSettings.rjw_bgs_enabled)
{
return;
}
List<GeneDef> genes = InheritanceUtility.AnimalInheritedGenes(father, mother);
if (genes.Any())
{

View file

@ -6,7 +6,7 @@ using System.Threading.Tasks;
using Verse;
using UnityEngine;
namespace RJW_Genes.Animal_Inheritance
namespace RJW_BGS
{
public class RJW_BGSSettings : ModSettings
{
@ -21,17 +21,31 @@ namespace RJW_Genes.Animal_Inheritance
listing_Standard.ColumnWidth = rect.width / 2.05f;
listing_Standard.Begin(rect);
listing_Standard.Gap(24f);
listing_Standard.CheckboxLabeled("enabled", ref enabled, "no function yet", 0f, 1f);
listing_Standard.CheckboxLabeled("enabled", ref rjw_bgs_enabled, "If toggled, Animal Pregnancies will try inherit genes.", 0f, 1f);
//listing_Standard.CheckboxLabeled("sexfrenzy", ref sexfrenzy, "disable the effects", 0f, 1f);
listing_Standard.Gap(5f);
listing_Standard.Label("gene inheritance chance"+ ": " +
Math.Round((double)(RJW_BGSSettings.rjw_bgs_global_gene_chance * 100f), 0).ToString() + "%", -1f, "modify chance for a gene to be inherited.");
RJW_BGSSettings.rjw_bgs_global_gene_chance = listing_Standard.Slider(RJW_BGSSettings.rjw_bgs_global_gene_chance, 0f, 5f);
listing_Standard.Gap(5f);
listing_Standard.CheckboxLabeled("genes as xenogenes", ref rjw_bgs_animal_genes_as_xenogenes, "If toggled, animal genes will be added as xenogenes.", 0f, 1f);
listing_Standard.Gap(5f);
listing_Standard.CheckboxLabeled("detailed-debug", ref rjw_bgs_detailed_debug, "Adds detailed information to the log about pregnancies and genes.", 0f, 1f);
listing_Standard.End();
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look<bool>(ref RJW_BGSSettings.enabled, "enabled", RJW_BGSSettings.enabled, true);
Scribe_Values.Look<bool>(ref RJW_BGSSettings.rjw_bgs_enabled, "rjw_bgs_enabled", RJW_BGSSettings.rjw_bgs_enabled, true);
Scribe_Values.Look<float>(ref RJW_BGSSettings.rjw_bgs_global_gene_chance, "rjw_bgs_global_gene_chance", RJW_BGSSettings.rjw_bgs_global_gene_chance, true);
Scribe_Values.Look<bool>(ref RJW_BGSSettings.rjw_bgs_animal_genes_as_xenogenes, "rjw_bgs_animal_genes_as_xenogenes", RJW_BGSSettings.rjw_bgs_animal_genes_as_xenogenes, true);
Scribe_Values.Look<bool>(ref RJW_BGSSettings.rjw_bgs_detailed_debug, "rjw_bgs_detailed_debug", RJW_BGSSettings.rjw_bgs_detailed_debug, true);
}
public static bool enabled;
public static float rjw_bgs_global_gene_chance = 1f;
public static bool rjw_bgs_enabled = true;
public static bool rjw_bgs_animal_genes_as_xenogenes = false;
public static bool rjw_bgs_detailed_debug = false;
}
}

View file

@ -6,7 +6,7 @@ using System.Threading.Tasks;
using Verse;
using UnityEngine;
namespace RJW_Genes.Animal_Inheritance
namespace RJW_BGS
{
public class RJW_BGSSettingsController : Mod
{

View file

@ -11,11 +11,11 @@ namespace RJW_BGS
public class RaceGeneDef : Def
{
public int priority;
public String raceGroup;
public string raceGroup; //keeping this for backwards compatibility
public List<string> raceGroups; //racegroup, but in list form so multiple can be entered, preference to use this over racegroup
public List<string> raceNames;
public List<string> pawnKindNames;
public List<BestialityGeneInheritanceDef> genes;
//public List<float> genechances;
public String hybridName;
}
}

View file

@ -18,14 +18,14 @@ namespace RJW_BGS
return result;
}
return null;
//First check if there is a matching pawnkinddef then race, then racegroup
}
public static List<RaceGeneDef> ValidRaceGeneDefs(Pawn pawn)
{
PawnKindDef kindDef = pawn.kindDef;
if (kindDef == null)
{
ModLog.Warning($"Error looking up PawnKindDef for {pawn.Name} - Could not lookup Animal Inheritance Genes");
return null;
}
string raceName = kindDef.race.defName;
@ -33,6 +33,9 @@ namespace RJW_BGS
PawnData pawnData = SaveStorage.DataStore.GetPawnData(pawn);
RaceGroupDef raceGroupDef = pawnData.RaceSupportDef;
if (RJW_BGSSettings.rjw_bgs_detailed_debug)
ModLog.Message($"Looking up Animal-Inheritable Genes for {pawn.Name} with KindDef {kindDef.defName},RaceName {raceName}, PawnKind {pawnKindName} and RaceGroup {raceGroupDef.defName}");
IEnumerable<RaceGeneDef> allDefs = DefDatabase<RaceGeneDef>.AllDefs;
List<RaceGeneDef> pawnKindDefs = allDefs.Where(delegate (RaceGeneDef group)
{
@ -40,7 +43,12 @@ namespace RJW_BGS
return pawnKindNames != null && pawnKindNames.Contains(pawnKindName);
}).ToList<RaceGeneDef>();
if (pawnKindDefs.Count() > 0)
{
DebugPrintRaceGeneDefs("PawnKindDefs",pawn.Name.ToStringFull,pawnKindDefs);
return pawnKindDefs;
}
else if (RJW_BGSSettings.rjw_bgs_detailed_debug)
ModLog.Message($"Did not find PawnKindDefs for {pawn.Name.ToStringFull}");
List<RaceGeneDef> raceKindDefs = allDefs.Where(delegate (RaceGeneDef group)
{
@ -48,22 +56,47 @@ namespace RJW_BGS
return raceNames != null && raceNames.Contains(raceName);
}).ToList<RaceGeneDef>();
if (raceKindDefs.Count() > 0)
{
DebugPrintRaceGeneDefs("PawnKindDefs", pawn.Name.ToStringFull, raceKindDefs);
return raceKindDefs;
}
else if (RJW_BGSSettings.rjw_bgs_detailed_debug)
ModLog.Message($"Did not find RaceKindDefs for {pawn.Name.ToStringFull}");
List<RaceGeneDef> raceGroupDefs = new List<RaceGeneDef>();
if (raceGroupDef != null)
{
raceGroupDefs = allDefs.Where(delegate (RaceGeneDef group)
{
String raceGroupDefName = group.raceGroup;
return raceGroupDefName != null && raceGroupDefName == raceGroupDef.defName;
string raceGroupDefName = group.raceGroup;
List<string> list_raceGroupDefName = group.raceGroups;
return (raceGroupDefName != null && raceGroupDefName == raceGroupDef.defName)
|| (list_raceGroupDefName != null && list_raceGroupDefName.Contains(raceGroupDef.defName));
}).ToList<RaceGeneDef>();
}
if (raceGroupDefs.Count() > 0)
{
DebugPrintRaceGeneDefs("RaceKindDefs", pawn.Name.ToStringFull, raceGroupDefs);
return raceGroupDefs;
}
else if (RJW_BGSSettings.rjw_bgs_detailed_debug)
ModLog.Message($"Did not find RaceGroupDefs for {pawn.Name.ToStringFull}");
ModLog.Message($"Did not find any Genes inheritable for {pawn.Name.ToStringFull}");
return new List<RaceGeneDef>();
}
private static void DebugPrintRaceGeneDefs(String header,String identifier,List<RaceGeneDef> defs)
{
if (RJW_BGSSettings.rjw_bgs_detailed_debug)
{
var defString = "[";
foreach (RaceGeneDef raceGeneDef in defs)
defString += $"({raceGeneDef.priority}:{raceGeneDef.defName} - {raceGeneDef.genes.Count} Genes)";
defString += "]";
ModLog.Message($"Found the following {header}-Genes for {identifier}: {defString}");
}
}
}
}

32
Source/First.cs Normal file
View file

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using rjw;
using Verse;
using RimWorld;
using rjw.Modules.Interactions.Rules.PartKindUsageRules;
using rjw.Modules.Interactions.Internals.Implementation;
namespace RJW_Genes
{
[StaticConstructorOnStartup]
internal static class First
{
static First()
{
AddtoIPartPreferenceRule();
}
//Modified code from https://gitgud.io/lutepickle/rjw_menstruation/-/tree/main/1.4/source/RJW_Menstruation/RJW_Menstruation
//Summary//
//Adds our own partpreferences to rjw's list. Our partpreferences are under Interactions.GenesPartKindUsageRule
//
private static void AddtoIPartPreferenceRule()
{
List<IPartPreferenceRule> partPreferenceRules = Unprivater.GetProtectedValue<List<IPartPreferenceRule>>("_partKindUsageRules", typeof(PartPreferenceDetectorService));
partPreferenceRules.Add(new Interactions.GenesPartKindUsageRule());
}
}
}

View file

@ -75,8 +75,20 @@ namespace RJW_Genes
public static readonly GeneDef rjw_genes_orgasm_rush;
public static readonly GeneDef rjw_genes_youth_fountain;
public static readonly GeneDef rjw_genes_sex_age_drain;
public static readonly GeneDef rjw_genes_aphrodisiac_pheromones;
// LifeForce
public static readonly GeneDef rjw_genes_lifeforce;
public static readonly GeneDef rjw_genes_lifeforce_drain;
public static readonly GeneDef rjw_genes_pussyhealer;
public static readonly GeneDef rjw_genes_vaginal_absorber;
public static readonly GeneDef rjw_genes_anal_absorber;
public static readonly GeneDef rjw_genes_drainer;
public static readonly HediffDef rjw_genes_orgasm_rush_hediff;
// Cosmetic
public static readonly GeneDef rjw_genes_succubus_tail;
public static readonly GeneDef rjw_genes_succubus_wings;
// Others & Non-Genes
}
}

View file

@ -33,5 +33,35 @@ namespace RJW_Genes
}
}
//Get total fluidamount a person has.
public static float GetTotalFluidAmount(Pawn pawn, float multiplier = 1f)
{
var partBPR = Genital_Helper.get_genitalsBPR(pawn);
var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR);
float total_cum = 0;
if (!parts.NullOrEmpty())
{
CompHediffBodyPart CompHediff;
foreach (Hediff part in parts)
{
if (GenitaliaChanger.IsArtificial(part))
continue;
if (rjw.Genital_Helper.is_penis(part))
{
CompHediff = part.TryGetComp<rjw.CompHediffBodyPart>();
if (CompHediff != null)
{
total_cum += CompHediff.FluidAmmount * CompHediff.FluidModifier * multiplier;
}
}
}
}
return total_cum;
}
}
}

View file

@ -1,5 +1,4 @@
using LicentiaLabs;
using rjw;
using rjw;
using Verse;
namespace RJW_Genes

View file

@ -1,11 +1,46 @@
using System;
using System.Collections.Generic;
using Verse;
using RimWorld;
namespace RJW_Genes
{
public class GeneUtility
{
//Instead of seperate functions this should be simpeler
public static bool HasGeneNullCheck(Pawn pawn, GeneDef genedef)
{
if (pawn.genes == null)
{
return false;
}
return pawn.genes.HasGene(genedef);
}
//Split function so I can offsetlifeforce from gene without needing to look for the gene agian (for the constant drain tick)
public static Gene_LifeForce GetLifeForceGene(Pawn pawn)
{
Pawn_GeneTracker genes = pawn.genes;
Gene_LifeForce gene_LifeForce = genes.GetFirstGeneOfType<Gene_LifeForce>();
return gene_LifeForce;
}
public static void OffsetLifeForce(IGeneResourceDrain drain, float offset)
{
float old_value = drain.Resource.Value;
drain.Resource.Value += offset;
//PostOffSetLifeForce(drain, old_value);
}
public static void PostOffSetLifeForce(IGeneResourceDrain drain, float old_value)
{
if (old_value > 0.2f && drain.Resource.Value <= 0.2f)
{
Pawn pawn = drain.Pawn;
//Do things
}
}
public static bool IsMechbreeder(Pawn pawn)
{
if (pawn.genes == null)
@ -15,6 +50,41 @@ namespace RJW_Genes
return pawn.genes.HasGene(GeneDefOf.rjw_genes_mechbreeder);
}
public static bool HasLifeForce(Pawn pawn)
{
if (pawn.genes == null)
{
return false;
}
return pawn.genes.HasGene(GeneDefOf.rjw_genes_lifeforce);
}
public static bool HasLowLifeForce(Pawn pawn)
{
if (HasLifeForce(pawn))
{
Gene_LifeForce gene = pawn.genes.GetFirstGeneOfType<Gene_LifeForce>();
if (gene.Resource.Value < gene.targetValue)
{
return true;
}
}
return false;
}
public static bool HasCriticalLifeForce(Pawn pawn)
{
if (HasLifeForce(pawn))
{
Gene_LifeForce gene = pawn.genes.GetFirstGeneOfType<Gene_LifeForce>();
if (gene.Resource.Value < gene.MinLevelForAlert)
{
return true;
}
}
return false;
}
public static bool IsInsectIncubator(Pawn pawn)
{
if (pawn.genes == null)
@ -87,6 +157,15 @@ namespace RJW_Genes
return pawn.genes.HasGene(GeneDefOf.rjw_genes_generous_donor);
}
public static bool isPussyHealer(Pawn pawn)
{
if (pawn.genes == null)
{
return false;
}
return pawn.genes.HasGene(GeneDefOf.rjw_genes_pussyhealer);
}
public static bool IsUnbreakable(Pawn pawn)
{
if (pawn.genes == null)
@ -96,12 +175,6 @@ namespace RJW_Genes
return pawn.genes.HasGene(GeneDefOf.rjw_genes_unbreakable);
}
public static bool HasGenitaliaResizingGenes(Pawn pawn)
{
return !GetGenitaliaResizingGenes(pawn).NullOrEmpty();
}
public static List<Gene_GenitaliaResizingGene> GetGenitaliaResizingGenes(Pawn pawn)
{
var ResizingGenes = new List<Gene_GenitaliaResizingGene>();

View file

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse.Sound;
using Verse;
using RimWorld;
using rjw;
using rjw.Modules.Interactions.Helpers;
using rjw.Modules.Interactions.Enums;
namespace RJW_Genes
{
public class AbilityUtility
{
public static void PussyHeal(SexProps props)
{
if (InteractionHelper.GetWithExtension(props.dictionaryKey).DominantHasFamily(GenitalFamily.Vagina) || InteractionHelper.GetWithExtension(props.dictionaryKey).SubmissiveHasFamily(GenitalFamily.Vagina))
{
Pawn pawn = props.pawn;
Pawn partner = props.partner;
FloatRange tendQualityRange;
tendQualityRange.min = 0.4f;
tendQualityRange.max = 0.8f;
if (GeneUtility.isPussyHealer(pawn))
{
Heal(partner, tendQualityRange);
}
if (GeneUtility.isPussyHealer(partner))
{
Heal(pawn, tendQualityRange);
}
}
}
public static bool Heal(Pawn pawn, FloatRange tendQualityRange)
{
bool any_wound_tended = false;
List<Hediff> hediffs = pawn.health.hediffSet.hediffs;
for (int i = hediffs.Count - 1; i >= 0; i--)
{
if ((hediffs[i] is Hediff_Injury || hediffs[i] is Hediff_MissingPart) && hediffs[i].TendableNow(false))
{
hediffs[i].Tended(tendQualityRange.RandomInRange, tendQualityRange.TrueMax, 1);
any_wound_tended = true;
}
}
return any_wound_tended;
}
public static float LifeForceCost(Ability ability)
{
if (ability.comps != null)
{
using (List<AbilityComp>.Enumerator enumerator = ability.comps.GetEnumerator())
{
while (enumerator.MoveNext())
{
CompAbilityEffect_LifeForceCost compAbilityEffect_HemogenCost;
if ((compAbilityEffect_HemogenCost = (enumerator.Current as CompAbilityEffect_LifeForceCost)) != null)
{
return compAbilityEffect_HemogenCost.Props.fertilinCost;
}
}
}
}
return 0f;
}
}
}

View file

@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using UnityEngine;
using RimWorld;
using rjw;
using rjw.Modules.Interactions.Helpers;
namespace RJW_Genes
{
public class CompAbilityEffect_CockEater : CompAbilityEffect
{
private new CompProperties_AbilityCockEater Props
{
get
{
return (CompProperties_AbilityCockEater)this.props;
}
}
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
Pawn pawn = target.Pawn;
if (pawn == null)
{
return;
}
var partBPR = Genital_Helper.get_genitalsBPR(pawn);
var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR);
if (!parts.NullOrEmpty())
{
foreach (Hediff part in parts)
{
if (GenitaliaChanger.IsArtificial(part))
continue;
if (Genital_Helper.is_penis(part))
{
GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(this.parent.pawn), part.Severity); ;
pawn.health.RemoveHediff(part);
pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.rjw_genes_cock_eaten, pawn, null);
break; //Only one penis at the time
}
}
}
}
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
{
Pawn pawn = target.Pawn;
if (pawn != null)
{
bool flag = pawn.Faction == this.parent.pawn.Faction || pawn.IsPrisonerOfColony;
bool flag2 = pawn.HostileTo(this.parent.pawn);
bool flag3 = pawn.Downed;
if (!flag && !(flag2 && flag3))
{
if (throwMessages)
{
if(flag2 && !flag3)
{
Messages.Message(pawn.Name + " is hostile, but not downed.", pawn, MessageTypeDefOf.RejectInput, false);
}
else if (!flag)
{
Messages.Message(pawn.Name + " is not a part of the colony or hostile.", pawn, MessageTypeDefOf.RejectInput, false);
}
}
return false;
}
if (!Genital_Helper.has_penis_fertile(pawn))
{
if (throwMessages)
{
Messages.Message(pawn.Name + " has no penis", pawn, MessageTypeDefOf.RejectInput, false);
}
return false;
}
}
return base.Valid(target, throwMessages);
}
public override bool GizmoDisabled(out string reason)
{
Pawn_GeneTracker genes = this.parent.pawn.genes;
Gene_LifeForce gene_LifeForce = (genes != null) ? genes.GetFirstGeneOfType<Gene_LifeForce>() : null;
if (gene_LifeForce == null)
{
reason = "AbilityDisabledNoFertilinGene".Translate(this.parent.pawn);
return true;
}
reason = null;
return false;
}
}
}

View file

@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using Verse;
using Verse.AI;
using RimWorld;
namespace RJW_Genes
{
public class CompAbilityEffect_LifeForceCost : CompAbilityEffect
{
public new CompProperties_AbilityLifeForceCost Props
{
get
{
return (CompProperties_AbilityLifeForceCost)this.props;
}
}
private bool HasEnoughFertilin
{
get
{
Pawn_GeneTracker genes = this.parent.pawn.genes;
Gene_LifeForce gene_lifeforce = (genes != null) ? genes.GetFirstGeneOfType < Gene_LifeForce>() : null;
return gene_lifeforce != null && gene_lifeforce.Value >= this.Props.fertilinCost;
}
}
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(this.parent.pawn), -this.Props.fertilinCost);
}
public override bool GizmoDisabled(out string reason)
{
Pawn_GeneTracker genes = this.parent.pawn.genes;
Gene_LifeForce gene_LifeForce = (genes != null) ? genes.GetFirstGeneOfType<Gene_LifeForce>() : null;
if (gene_LifeForce == null)
{
reason = "AbilityDisabledNoFertilinGene".Translate(this.parent.pawn);
return true;
}
if (gene_LifeForce.Value < this.Props.fertilinCost)
{
reason = "AbilityDisabledNoFertilin".Translate(this.parent.pawn);
return true;
}
float num = this.TotalLifeForceCostOfQueuedAbilities();
float num2 = this.Props.fertilinCost + num;
if (this.Props.fertilinCost > 1E-45f && num2 > gene_LifeForce.Value)
{
reason = "AbilityDisabledNoFertilin".Translate(this.parent.pawn);
return true;
}
reason = null;
return false;
}
public override bool AICanTargetNow(LocalTargetInfo target)
{
return this.HasEnoughFertilin;
}
private float TotalLifeForceCostOfQueuedAbilities()
{
Pawn_JobTracker jobs = this.parent.pawn.jobs;
object obj;
if (jobs == null)
{
obj = null;
}
else
{
Job curJob = jobs.curJob;
obj = ((curJob != null) ? curJob.verbToUse : null);
}
Verb_CastAbility verb_CastAbility = obj as Verb_CastAbility;
float num;
if (verb_CastAbility == null)
{
num = 0f;
}
else
{
Ability ability = verb_CastAbility.ability;
num = ((ability != null) ? AbilityUtility.LifeForceCost(ability) : 0f);
}
float num2 = num;
if (this.parent.pawn.jobs != null)
{
for (int i = 0; i < this.parent.pawn.jobs.jobQueue.Count; i++)
{
Verb_CastAbility verb_CastAbility2;
if ((verb_CastAbility2 = (this.parent.pawn.jobs.jobQueue[i].job.verbToUse as Verb_CastAbility)) != null)
{
float num3 = num2;
Ability ability2 = verb_CastAbility2.ability;
num2 = num3 + ((ability2 != null) ? AbilityUtility.LifeForceCost(ability2) : 0f);
}
}
}
return num2;
}
}
}

View file

@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using UnityEngine;
using RimWorld;
using rjw;
using rjw.Modules.Interactions.Helpers;
namespace RJW_Genes
{
public class CompAbilityEffect_PussyHeal : CompAbilityEffect
{
private new CompProperties_AbilityPussyHeal Props
{
get
{
return (CompProperties_AbilityPussyHeal)this.props;
}
}
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
Pawn pawn = target.Pawn;
if (pawn == null)
{
return;
}
bool any_wound_tended = AbilityUtility.Heal(pawn, this.Props.tendQualityRange);
if (any_wound_tended)
{
MoteMaker.ThrowText(pawn.DrawPos, pawn.Map, "Sex healed wounds", 3.65f);
//pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.Pussy_Healed, pawn, null);
}
//this.AfterSex(any_wound_tended);
//FleckMaker.AttachedOverlay(pawn, FleckDefOf.FlashHollow, Vector3.zero, 1.5f, -1f);
}
//Not yet implemented, but the heal should also trigger after normal sex
public void AfterSex(Pawn pawn, Pawn target)
{
List<Hediff> hediffs = target.health.hediffSet.hediffs;
for (int i = 0; i < hediffs.Count; i++)
{
if ((hediffs[i] is Hediff_Injury || hediffs[i] is Hediff_MissingPart) && hediffs[i].TendableNow(false))
{
//target.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.Pussy_Healed, pawn, null);
break;
}
}
//InteractionHelper.GetWithExtension(dictionaryKey).DominantHasTag("CanBePenetrated")
}
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
{
Pawn pawn = target.Pawn;
if (pawn != null)
{
//to be replaced with severel checks to make it clear why target is unable to have sex
if (!CasualSex_Helper.CanHaveSex(pawn))
{
if (throwMessages)
{
Messages.Message(pawn.Name + " is unable to have sex", pawn, MessageTypeDefOf.RejectInput, false);
}
return false;
}
else if (pawn.IsAnimal() && !RJWSettings.bestiality_enabled)
{
if (throwMessages)
{
Messages.Message("bestiality is disabled", pawn, MessageTypeDefOf.RejectInput, false);
}
return false;
}
//AbilityUtility.ValidateHasTendableWound(pawn, throwMessages, this.parent);
}
return base.Valid(target, throwMessages);
}
public override bool GizmoDisabled(out string reason)
{
reason = null;
if (!Genital_Helper.has_vagina(this.parent.pawn))
{
reason = this.parent.pawn.Name + " has no vagina to use.";
return true;
}
else if (!RJWSettings.rape_enabled)
{
reason = "Rape is disabled";
return true;
}
return false;
}
}
}

View file

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
using Verse.AI;
using rjw;
namespace RJW_Genes
{
public class CompAbilityEffect_Seduce : CompAbilityEffect_WithDest
{
private new CompProperties_Seduce Props
{
get
{
return (CompProperties_Seduce)this.props;
}
}
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
Pawn pawn = target.Thing as Pawn;
Pawn pawn2 = this.parent.pawn;
if (pawn != null && pawn2 != null && !pawn.Downed)
{
Job job = JobMaker.MakeJob(JobDefOf.rjw_genes_lifeforce_seduced, pawn2);
job.mote = MoteMaker.MakeThoughtBubble(pawn, this.parent.def.iconPath, true);
pawn.jobs.StopAll(false, true);
pawn.jobs.StartJob(job, JobCondition.InterruptForced, null, false, true, null, null, false, false, null, false, true);
}
}
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
{
Pawn pawn = target.Pawn;
if (pawn != null)
{
if (!xxx.can_be_fucked(pawn))
{
if (throwMessages)
{
Messages.Message(pawn.Name + " is unable to have sex", pawn, MessageTypeDefOf.RejectInput, false);
}
return false;
}
else if (pawn.IsAnimal() && !RJWSettings.bestiality_enabled)
{
if (throwMessages)
{
Messages.Message("bestiality is disabled", pawn, MessageTypeDefOf.RejectInput, false);
}
return false;
}
else if (pawn.Downed)
{
if (throwMessages)
{
Messages.Message(pawn.Name + " is unable to move", pawn, MessageTypeDefOf.RejectInput, false);
}
return false;
}
}
return base.Valid(target, throwMessages);
}
public override bool GizmoDisabled(out string reason)
{
reason = null;
if (!RJWSettings.rape_enabled)
{
reason = "Rape is disabled";
return true;
}
return false;
}
}
}

View file

@ -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_AbilityCockEater : CompProperties_AbilityEffect
{
public CompProperties_AbilityCockEater()
{
this.compClass = typeof(CompAbilityEffect_CockEater);
}
}
}

View file

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using Verse;
using RimWorld;
namespace RJW_Genes
{
// Token: 0x02000F65 RID: 3941
public class CompProperties_AbilityLifeForceCost : CompProperties_AbilityEffect
{
// Token: 0x06005D16 RID: 23830 RVA: 0x001FA73F File Offset: 0x001F893F
public CompProperties_AbilityLifeForceCost()
{
this.compClass = typeof(CompAbilityEffect_LifeForceCost);
}
// Token: 0x06005D17 RID: 23831 RVA: 0x001FA757 File Offset: 0x001F8957
public override IEnumerable<string> ExtraStatSummary()
{
yield return "AbilityFertilinCost" + ": " + Mathf.RoundToInt(this.fertilinCost * 100f);
yield break;
}
// Token: 0x040038CD RID: 14541
public float fertilinCost;
}
}

View file

@ -0,0 +1,20 @@
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_AbilityPussyHeal : CompProperties_AbilityEffect
{
public CompProperties_AbilityPussyHeal()
{
this.compClass = typeof(CompAbilityEffect_PussyHeal);
}
public FloatRange tendQualityRange;
}
}

View file

@ -0,0 +1,21 @@
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_Seduce : CompProperties_EffectWithDest
{
public CompProperties_Seduce()
{
this.compClass = typeof(CompAbilityEffect_Seduce);
}
public StatDef durationMultiplier;
}
}

View file

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld.Planet;
using Verse;
using RimWorld;
namespace RJW_Genes
{
public class Alert_CriticalFertilin : Alert
{
private List<GlobalTargetInfo> Targets
{
get
{
this.CalculateTargets();
return this.targets;
}
}
public override string GetLabel()
{
if (this.Targets.Count == 1)
{
return "AlertLowFertilin".Translate() + ": " + this.targetLabels[0];
}
return "AlertLowFertilin".Translate();
}
private void CalculateTargets()
{
this.targets.Clear();
this.targetLabels.Clear();
if (!ModsConfig.BiotechActive)
{
return;
}
foreach (Pawn pawn in PawnsFinder.AllMapsCaravansAndTravelingTransportPods_Alive)
{
if (pawn.RaceProps.Humanlike && pawn.Faction == Faction.OfPlayer)
{
Pawn_GeneTracker genes = pawn.genes;
Gene_LifeForce gene_Lifeforce = (genes != null) ? genes.GetFirstGeneOfType<Gene_LifeForce>() : null;
if (gene_Lifeforce != null && gene_Lifeforce.Value < gene_Lifeforce.MinLevelForAlert)
{
this.targets.Add(pawn);
this.targetLabels.Add(pawn.NameShortColored.Resolve());
}
}
}
}
public override TaggedString GetExplanation()
{
return "AlertLowFertilinDesc".Translate() + ":\n" + this.targetLabels.ToLineList(" - ");
}
public override AlertReport GetReport()
{
return AlertReport.CulpritsAre(this.Targets);
}
// Token: 0x04004B5C RID: 19292
private List<GlobalTargetInfo> targets = new List<GlobalTargetInfo>();
// Token: 0x04004B5D RID: 19293
private List<string> targetLabels = new List<string>();
}
}

View file

@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
using UnityEngine;
namespace RJW_Genes
{
//Copied from GeneGizmo_ResourceHemogen, with small modifications
public class GeneGizmo_ResourceLifeForce : GeneGizmo_Resource
{
public GeneGizmo_ResourceLifeForce(Gene_Resource gene, List<IGeneResourceDrain> drainGenes, Color barColor, Color barhighlightColor) : base(gene, drainGenes, barColor, barhighlightColor)
{
this.draggableBar = true;
}
public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
{
return base.GizmoOnGUI(topLeft, maxWidth, parms);
}
protected override string GetTooltip()
{
this.tmpDrainGenes.Clear();
string text = string.Format("{0}: {1} / {2}\n", this.gene.ResourceLabel.CapitalizeFirst().Colorize(ColoredText.TipSectionTitleColor), this.gene.ValueForDisplay, this.gene.MaxForDisplay);
if (this.gene.pawn.IsColonistPlayerControlled || this.gene.pawn.IsPrisonerOfColony)
{
if (this.gene.targetValue <= 0f)
{
text += "NeverSeekFertilin";
}
else
{
text = text + ("SeekFertilinBelow" + ": ") + this.gene.PostProcessValue(this.gene.targetValue);
}
}
if (!this.drainGenes.NullOrEmpty<IGeneResourceDrain>())
{
float num = 0f;
foreach (IGeneResourceDrain geneResourceDrain in this.drainGenes)
{
if (geneResourceDrain.CanOffset)
{
this.tmpDrainGenes.Add(new Pair<IGeneResourceDrain, float>(geneResourceDrain, geneResourceDrain.ResourceLossPerDay));
num += geneResourceDrain.ResourceLossPerDay;
}
}
if (num != 0f)
{
string text2 = (num < 0f) ? "RegenerationRate".Translate() : "DrainRate".Translate();
text = string.Concat(new string[]
{
text,
"\n\n",
text2,
": ",
"PerDay".Translate(Mathf.Abs(this.gene.PostProcessValue(num))).Resolve()
});
foreach (Pair<IGeneResourceDrain, float> pair in this.tmpDrainGenes)
{
text = string.Concat(new string[]
{
text,
"\n - ",
pair.First.DisplayLabel.CapitalizeFirst(),
": ",
"PerDay".Translate(this.gene.PostProcessValue(-pair.Second).ToStringWithSign()).Resolve()
});
}
}
}
if (!this.gene.def.resourceDescription.NullOrEmpty())
{
text = text + "\n\n" + this.gene.def.resourceDescription.Formatted(this.gene.pawn.Named("PAWN")).Resolve();
}
return text;
}
private List<Pair<IGeneResourceDrain, float>> tmpDrainGenes = new List<Pair<IGeneResourceDrain, float>>();
}
}

View file

@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Verse;
using RimWorld;
using rjw;
namespace RJW_Genes
{
public class Gene_LifeForce : Gene_Resource, IGeneResourceDrain
{
//Gene should only be active if sex is allowed for this pawn
public override bool Active
{
get
{
if (this.Overridden)
{
return false;
}
Pawn pawn = this.pawn;
return ((pawn != null) ? pawn.ageTracker : null) == null ||
((float)this.pawn.ageTracker.AgeBiologicalYears >= this.def.minAgeActive);
}
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look<bool>(ref this.StoredCumAllowed, "StoredCumAllowed", true, false);
}
public bool ShouldConsumeLifeForceNow()
{
return this.Value < this.targetValue;
}
//Same as Gene_Hemogen
public override IEnumerable<Gizmo> GetGizmos()
{
foreach (Gizmo gizmo in base.GetGizmos())
{
yield return gizmo;
}
foreach (Gizmo gizmo2 in GeneResourceDrainUtility.GetResourceDrainGizmos(this))
{
yield return gizmo2;
}
yield break;
}
//Depending on how low the value is it will increase sexdrive and if it reaches zero it will create a mental break which will make the pawn rape others.
//Not using base.Tick() as it is used to start mental breaks, but we have another way to do it.
public override void Tick()
{
//base.Tick();
if (this.CanOffset && this.Resource != null)
{
GeneUtility.OffsetLifeForce(this, -this.ResourceLossPerDay / 60000f);
//this.Resource.Value -= this.ResourceLossPerDay / 60000;
if (this.Resource.Value <= 0 && this.pawn.IsHashIntervalTick(300))
{
if (ModsConfig.BiotechActive && this.def.mentalBreakDef != null &&
this.pawn.Spawned && !this.pawn.InMentalState && !this.pawn.Downed &&
this.def.mentalBreakDef.Worker.BreakCanOccur(this.pawn))
{
this.def.mentalBreakDef.Worker.TryStart(this.pawn, "MentalStateReason_Gene".Translate() + ": " + this.LabelCap, false);
}
}
}
}
public bool StoredCumAllowed = true;
public Gene_Resource Resource
{
get
{
return this;
}
}
public Pawn Pawn
{
get
{
return this.pawn;
}
}
public bool CanOffset
{
get
{
return this.pawn.Spawned && this.Active;
}
}
public float ResourceLossPerDay
{
get
{
return this.def.resourceLossPerDay;
}
}
public string DisplayLabel
{
get
{
return this.def.resourceLabel;
}
}
public override float InitialResourceMax
{
get
{
return 1f;
}
}
public override float MinLevelForAlert
{
get
{
return 0.2f;
}
}
public override float MaxLevelOffset
{
get
{
return base.MaxLevelOffset;
}
}
protected override Color BarColor
{
get
{
return Color.grey;
}
}
protected override Color BarHighlightColor
{
get
{
return Color.white;
}
}
}
}

View file

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using Verse;
using RimWorld;
namespace RJW_Genes
{
public class Gene_LifeForceDrain : Gene, IGeneResourceDrain
{
public Gene_Resource Resource
{
get
{
if (this.cachedLifeForceGene == null || !this.cachedLifeForceGene.Active)
{
this.cachedLifeForceGene = this.pawn.genes.GetFirstGeneOfType<Gene_LifeForce>();
}
return this.cachedLifeForceGene;
}
}
public bool CanOffset
{
get
{
return this.Active && this.Resource != null && this.Resource.Active;
}
}
public float ResourceLossPerDay
{
get
{
return this.def.resourceLossPerDay;
}
}
public Pawn Pawn
{
get
{
return this.pawn;
}
}
public string DisplayLabel
{
get
{
return this.Label + " (" + "Gene".Translate() + ")";
}
}
public override void Tick()
{
base.Tick();
if (this.CanOffset && this.Resource != null)
{
GeneUtility.OffsetLifeForce(this, -this.ResourceLossPerDay / 60000);
}
}
public override IEnumerable<Gizmo> GetGizmos()
{
foreach (Gizmo gizmo in GeneResourceDrainUtility.GetResourceDrainGizmos(this))
{
yield return gizmo;
}
IEnumerator<Gizmo> enumerator = null;
yield break;
yield break;
}
[Unsaved(false)]
private Gene_LifeForce cachedLifeForceGene;
private const float MinAgeForDrain = 3f;
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
namespace RJW_Genes
{
internal class HediffWithComps_tank : HediffWithComps
{
public override string LabelInBrackets
{
get
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(base.LabelInBrackets);
stringBuilder.Append(this.Severity.ToStringPercent());
return stringBuilder.ToString();
}
}
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
namespace RJW_Genes
{
public class IngestionOutcomeDoer_LifeForceOffset : IngestionOutcomeDoer
{
protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
{
if (GeneUtility.HasLifeForce(pawn))
{
float num = ingested.stackCount * this.FertilinPerUnit / 100;
GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(pawn), num);
}
}
public float FertilinPerUnit = 1f;
}
}

View file

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
using Verse.AI;
using rjw;
namespace RJW_Genes
{
public class JobDriver_CastAbilityAfterSex : JobDriver_SexBaseInitiator
{
//Summary//
//Similar to jobdriver rape, but it cast an ability after sex and tries to limit what kind of sexinteractions are allowed.
protected override IEnumerable<Toil> MakeNewToils()
{
base.setup_ticks();
//this.FailOnDespawnedOrNull(TargetIndex.A);
//this.FailOnCannotTouch(TargetIndex.B, PathEndMode.OnCell);
this.FailOnDespawnedNullOrForbidden(this.iTarget);
//this.FailOn(() => !target.health.capacities.CanBeAwake);
JobDef PartnerJob = xxx.gettin_raped;
yield return Toils_Goto.Goto(TargetIndex.A, PathEndMode.OnCell);
yield return new Toil
{
defaultCompleteMode = ToilCompleteMode.Instant,
socialMode = RandomSocialMode.Off,
initAction = delegate ()
{
Job newJob = JobMaker.MakeJob(PartnerJob, this.pawn, this.Partner);
this.Partner.jobs.StartJob(newJob, JobCondition.InterruptForced, null, false, true, null, null, false, false, null, false, true);
}
};
Toil toil = new Toil();
toil.defaultCompleteMode = ToilCompleteMode.Never;
toil.socialMode = RandomSocialMode.Off;
toil.defaultDuration = this.duration;
toil.handlingFacing = true;
toil.FailOn(() => this.Partner.CurJob.def != PartnerJob);
toil.initAction = delegate ()
{
this.Partner.pather.StopDead();
this.Partner.jobs.curDriver.asleep = false;
//Tries to find CompProperties_SexInteractionRequirements and if it finds it it will try and generate sexprops based on the sexpropsrequirements.
foreach (AbilityComp comp in this.job.ability.comps)
{
if (comp.props is CompProperties_SexInteractionRequirements)
{
CompProperties_SexInteractionRequirements sexpropsreq = comp.props as CompProperties_SexInteractionRequirements;
this.Sexprops = CustomSexInteraction_Helper.GenerateSexProps(this.pawn, this.Partner, sexpropsreq);
}
}
this.Start();
this.Sexprops.usedCondom = (CondomUtility.TryUseCondom(this.pawn) || CondomUtility.TryUseCondom(this.Partner));
};
toil.AddPreTickAction(delegate
{
if (this.pawn.IsHashIntervalTick(this.ticks_between_hearts))
{
this.ThrowMetaIconF(this.pawn.Position, this.pawn.Map, FleckDefOf.Heart);
}
this.SexTick(this.pawn, this.Partner, true, true);
SexUtility.reduce_rest(this.Partner, 1f);
SexUtility.reduce_rest(this.pawn, 1f);
if (this.ticks_left <= 0)
{
this.ReadyForNextToil();
}
});
toil.AddFinishAction(delegate
{
this.End();
});
yield return toil;
yield return new Toil
{
initAction = delegate ()
{
SexUtility.ProcessSex(this.Sexprops);
},
defaultCompleteMode = ToilCompleteMode.Instant
};
yield return Toils_Combat.CastVerb(TargetIndex.A, TargetIndex.B, false);
yield break;
}
}
}

View file

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
using Verse.AI;
using rjw;
using rjw.Modules.Interactions.Enums;
using rjw.Modules.Interactions.Helpers;
using rjw.Modules.Interactions.Objects;
using rjw.Modules.Interactions.Contexts;
using rjw.Modules.Interactions.Implementation;
namespace RJW_Genes
{
public class JobDriver_Seduced : JobDriver
{
//Summary//
//Makes a pawn move to seducing pawn and then tries to rape them.
protected override IEnumerable<Toil> MakeNewToils()
{
this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
this.FailOn(() => !this.pawn.CanReserve(TargetA, xxx.max_rapists_per_prisoner, 0, null, false));
this.FailOn(() => this.pawn.IsFighting());
this.FailOn(() => this.pawn.Drafted);
Pawn partner = this.job.GetTarget(TargetIndex.A).Pawn;
yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch);
yield return new Toil
{
defaultCompleteMode = ToilCompleteMode.Instant,
socialMode = RandomSocialMode.Off,
initAction = delegate ()
{
if(partner != null)
{
partner.drafter.Drafted = false;
this.pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.rjw_genes_seduced, partner, null);
Job newJob = JobMaker.MakeJob(JobDefOf.sex_on_spot, pawn);
partner.jobs.StartJob(newJob, JobCondition.InterruptForced, null, false, true, null, null, false, false, null, false, true);
}
}
};
yield break;
}
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
return this.pawn.Reserve(TargetA, this.job, xxx.max_rapists_per_prisoner, 0, null, errorOnFailed);
}
}
}

View file

@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
using Verse.AI;
using rjw;
using rjw.Modules.Interactions.Enums;
using rjw.Modules.Interactions.Helpers;
using rjw.Modules.Interactions.Objects;
using rjw.Modules.Interactions.Contexts;
using rjw.Modules.Interactions.Implementation;
namespace RJW_Genes
{
public class JobDriver_SexOnSpot : JobDriver_SexBaseInitiator
{
protected override IEnumerable<Toil> MakeNewToils()
{
if (RJWSettings.DebugRape)
{
ModLog.Message(base.GetType().ToString() + "::MakeNewToils() called");
}
base.setup_ticks();
JobDef PartnerJob = JobDefOf.sex_on_spot_reciever;
this.FailOnDespawnedNullOrForbidden(this.iTarget);
this.FailOn(() => !this.pawn.CanReserve(this.Partner, xxx.max_rapists_per_prisoner, 0, null, false));
this.FailOn(() => this.pawn.IsFighting());
this.FailOn(() => this.Partner.IsFighting());
this.FailOn(() => this.pawn.Drafted);
yield return Toils_Goto.GotoThing(this.iTarget, PathEndMode.Touch);
if (this.pawn.HostileTo(this.Partner))
{
Partner.health.AddHediff(xxx.submitting);
}
yield return Toils_Goto.GotoThing(this.iTarget, PathEndMode.OnCell);
//Give thought malus to partner (I was seduced into having sex against my will)
yield return new Toil
{
defaultCompleteMode = ToilCompleteMode.Instant,
socialMode = RandomSocialMode.Off,
initAction = delegate ()
{
if (!(this.Partner.jobs.curDriver is JobDriver_SexOnSpotReciever))
{
Job newJob = JobMaker.MakeJob(PartnerJob, this.pawn);
Building_Bed building_Bed = null;
if (this.Partner.GetPosture() == PawnPosture.LayingInBed)
{
building_Bed = this.Partner.CurrentBed();
}
this.Partner.jobs.StartJob(newJob, JobCondition.InterruptForced, null, false, true, null, null, false, false, null, false, true);
if (building_Bed != null)
{
JobDriver_SexOnSpotReciever jobDriver_SexOnSpotReciever = this.Partner.jobs.curDriver as JobDriver_SexOnSpotReciever;
if (jobDriver_SexOnSpotReciever == null)
{
return;
}
jobDriver_SexOnSpotReciever.Set_bed(building_Bed);
}
}
}
};
Toil toil = new Toil();
toil.defaultCompleteMode = ToilCompleteMode.Never;
toil.defaultDuration = this.duration;
toil.handlingFacing = true;
toil.FailOn(() => this.Partner.CurJob.def != PartnerJob);
toil.initAction = delegate ()
{
this.Partner.pather.StopDead();
this.Partner.jobs.curDriver.asleep = false;
this.Start();
};
toil.tickAction = delegate ()
{
if (this.pawn.IsHashIntervalTick(this.ticks_between_hearts))
{
this.ThrowMetaIconF(this.pawn.Position, this.pawn.Map, FleckDefOf.Heart);
}
this.SexTick(this.pawn, this.Partner, true, true);
SexUtility.reduce_rest(this.Partner, 1f);
SexUtility.reduce_rest(this.pawn, 2f);
if (this.ticks_left <= 0)
{
this.ReadyForNextToil();
}
};
toil.AddFinishAction(delegate
{
this.End();
});
yield return toil;
yield return new Toil
{
initAction = delegate ()
{
SexUtility.ProcessSex(this.Sexprops);
},
defaultCompleteMode = ToilCompleteMode.Instant
};
yield break;
}
}
}

View file

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
using Verse.AI;
using rjw;
using rjw.Modules.Interactions.Enums;
using rjw.Modules.Interactions.Helpers;
using rjw.Modules.Interactions.Objects;
using rjw.Modules.Interactions.Contexts;
using rjw.Modules.Interactions.Implementation;
namespace RJW_Genes
{
//Modified JobDriver_SexBaseRecieverLoved from rjw
public class JobDriver_SexOnSpotReciever : JobDriver_SexBaseReciever
{
protected override IEnumerable<Toil> MakeNewToils()
{
base.setup_ticks();
this.parteners.Add(base.Partner);
if (this.pawn.relations.OpinionOf(base.Partner) < 0)
{
this.ticks_between_hearts += 50;
}
else if (this.pawn.relations.OpinionOf(base.Partner) > 60)
{
this.ticks_between_hearts -= 25;
}
this.FailOnDespawnedOrNull(this.iTarget);
this.FailOn(() => !base.Partner.health.capacities.CanBeAwake);
this.FailOn(() => this.pawn.Drafted);
this.FailOn(() => base.Partner.Drafted);
yield return Toils_Reserve.Reserve(this.iTarget, 1, 0, null);
Toil toil2 = this.MakeSexToil();
toil2.handlingFacing = false;
yield return toil2;
yield break;
}
// Token: 0x06000420 RID: 1056 RVA: 0x00024190 File Offset: 0x00022390
private Toil MakeSexToil()
{
Toil toil = new Toil();
toil.defaultCompleteMode = ToilCompleteMode.Never;
toil.socialMode = RandomSocialMode.Off;
toil.handlingFacing = true;
toil.tickAction = delegate ()
{
if (this.pawn.IsHashIntervalTick(this.ticks_between_hearts))
{
base.ThrowMetaIconF(this.pawn.Position, this.pawn.Map, FleckDefOf.Heart);
}
};
toil.AddEndCondition(delegate
{
if (this.parteners.Count <= 0)
{
return JobCondition.Succeeded;
}
return JobCondition.Ongoing;
});
toil.AddFinishAction(delegate
{
if (xxx.is_human(this.pawn))
{
this.pawn.Drawer.renderer.graphics.ResolveApparelGraphics();
}
GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(this.pawn);
Hediff submitting = this.pawn.health.hediffSet.GetFirstHediffOfDef(xxx.submitting);
if (submitting != null)
{
this.pawn.health.RemoveHediff(submitting);
this.pawn.stances.stunner.StunFor(60, this.pawn, true, true);
}
});
toil.socialMode = RandomSocialMode.Off;
return toil;
}
}
}

View file

@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Verse;
using Verse.AI;
using RimWorld;
using rjw;
namespace RJW_Genes
{
public class JobGiver_GetLifeForce : ThinkNode_JobGiver
{
protected override Job TryGiveJob(Pawn pawn)
{
Pawn_GeneTracker genes = pawn.genes;
Gene_LifeForce gene_lifeforce = (genes != null) ? genes.GetFirstGeneOfType<Gene_LifeForce>() : null;
if (gene_lifeforce == null)
{
return null;
}
if (!gene_lifeforce.ShouldConsumeLifeForceNow())
{
return null;
}
if (ModsConfig.IsActive("LustLicentia.RJWLabs") && gene_lifeforce.StoredCumAllowed)
{
Thing gatheredCum = this.GetStoredCum(pawn);
if (gatheredCum == null)
{
return null;
}
IngestionOutcomeDoer_LifeForceOffset ingestionOutcomeDoer = (IngestionOutcomeDoer_LifeForceOffset)gatheredCum.def.ingestible.outcomeDoers.First((IngestionOutcomeDoer x) => x is IngestionOutcomeDoer_LifeForceOffset);
if (ingestionOutcomeDoer == null)
{
return null;
}
int num = Mathf.RoundToInt(((gene_lifeforce.targetValue - gene_lifeforce.Value) * 100 + 10) / ingestionOutcomeDoer.FertilinPerUnit);
if (gatheredCum != null && num > 0)
{
Job job = JobMaker.MakeJob(RimWorld.JobDefOf.Ingest, gatheredCum);
job.count = Mathf.Min(gatheredCum.stackCount, num);
job.ingestTotalCount = true;
return job;
}
}
return null;
}
//From JobGiver_GetHemogen, dont know exactly what this influences
public override float GetPriority(Pawn pawn)
{
if (!ModsConfig.BiotechActive)
{
return 0f;
}
Pawn_GeneTracker genes = pawn.genes;
if (((genes != null) ? genes.GetFirstGeneOfType<Gene_LifeForce>() : null) == null)
{
return 0f;
}
return 9.1f;
}
private Thing GetStoredCum(Pawn pawn)
{
Thing carriedThing = pawn.carryTracker.CarriedThing;
ThingDef gatheredCum = ThingDef.Named("GatheredCum");
if (carriedThing != null && carriedThing.def == gatheredCum)
{
return carriedThing;
}
for (int i = 0; i < pawn.inventory.innerContainer.Count; i++)
{
if (pawn.inventory.innerContainer[i].def == gatheredCum)
{
return pawn.inventory.innerContainer[i];
}
}
return GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, pawn.Map.listerThings.ThingsOfDef(gatheredCum), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false, false, false), 9999f, (Thing t) => pawn.CanReserve(t, 1, -1, null, false) && !t.IsForbidden(pawn), null);
}
}
}

View file

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Verse;
using Verse.AI;
using RimWorld;
using rjw;
namespace RJW_Genes
{
public class JobGiver_LifeForce_RandomRape : JobGiver_RandomRape
{
protected override Job TryGiveJob(Pawn pawn)
{
if (!can_rape(pawn, false))
{
return null;
}
Pawn pawn2 = this.find_victim(pawn, pawn.Map);
if (pawn2 == null)
{
return null;
}
return JobMaker.MakeJob(JobDefOf.rjw_genes_lifeforce_randomrape, pawn2);
}
//same as xxx.canrape from rjw, but without last requirements.
public static bool can_rape(Pawn pawn, bool forced = false)
{
return RJWSettings.rape_enabled && (xxx.is_mechanoid(pawn) || ((xxx.can_fuck(pawn) ||
(!xxx.is_male(pawn) && xxx.get_vulnerability(pawn) < RJWSettings.nonFutaWomenRaping_MaxVulnerability &&
xxx.can_be_fucked(pawn))) && (!xxx.is_human(pawn) || ((pawn.ageTracker.Growth >= 1f || pawn.ageTracker.CurLifeStage.reproductive)))));
}
}
}

View file

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Verse;
using RimWorld;
using Verse.AI;
namespace RJW_Genes
{
public class LifeForceMentalBreakWorker : MentalBreakWorker
{
public override bool BreakCanOccur(Pawn pawn)
{
if (pawn.Spawned && base.BreakCanOccur(pawn))
{
if (!GeneUtility.HasLifeForce(pawn))
{
return false;
}
Gene_LifeForce gene = pawn.genes.GetFirstGeneOfType<Gene_LifeForce>();
if( gene.Resource.Value <= 0)
{
return true;
}
}
return false;
}
}
}

View file

@ -0,0 +1,23 @@
using System;
using Verse;
using Verse.AI;
using rjw;
namespace RJW_Genes
{
public class LifeForceMentalState : MentalState
{
public override void MentalStateTick()
{
if (this.pawn.IsHashIntervalTick(150) && !GeneUtility.HasCriticalLifeForce(this.pawn))
{
Pawn_JobTracker jobs = this.pawn.jobs;
if (!(((jobs != null) ? jobs.curDriver : null) is JobDriver_Sex))
{
base.RecoverFromState();
return;
}
}
base.MentalStateTick();
}
}
}

View file

@ -0,0 +1,14 @@
using System;
using Verse;
using Verse.AI;
using rjw;
namespace RJW_Genes
{
public class LifeForceMentalStateWorker : MentalStateWorker
{
public override bool StateCanOccur(Pawn pawn)
{
return base.StateCanOccur(pawn) && (xxx.is_human(pawn) && JobGiver_LifeForce_RandomRape.can_rape(pawn));
}
}
}

View file

@ -0,0 +1,180 @@
using HarmonyLib;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
namespace RJW_Genes
{
[HarmonyPatch(typeof(SexUtility), nameof(SexUtility.SatisfyPersonal))]
public static class Patch_LifeForce
{
public static void Postfix(SexProps props)
{
// ShortCuts: Exit Early if Pawn or Partner are null (can happen with Animals or Masturbation)
if (props.pawn == null || !props.hasPartner())
return;
// Exit if pawn has fertilin themself, it won't give any if it has lifeforce themself.
if (GeneUtility.HasLifeForce(props.pawn))
{
return;
}
//Summary//
//We use the positions of the pawn (dom or sub) and based on that which interactions will transfer fertilin
//By checking isreceiver we know if the succubus is the dom or the sub and if the situation is reverse we also swap the function we use
//
float absorb_factor = 0f;
if (GeneUtility.HasLifeForce(props.partner))
{
Pawn succubus = props.partner;
if (!props.isRevese)
{
if (props.isReceiver)
{
// Scenario Dom Succubus, normal
absorb_factor = BaseDom(props, succubus);
}
else
{
// Scenario Sub Succubus, normal
absorb_factor = BaseSub(props, succubus);
}
}
else
{
if (props.isReceiver)
{
// Scenario Dom Succubus, Reverse
absorb_factor = BaseSub(props, succubus);
}
else
{
// Scenario Sub Succubus, Reverse
absorb_factor = BaseDom(props, succubus);
}
}
//If we remove this check fertelin is always lost, but the succubus doesn't always gain any
if (absorb_factor != 0f)
{
AbsorbFertilin(props, absorb_factor);
}
if (GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_drainer) && !props.pawn.health.hediffSet.HasHediff(HediffDefOf.Succubus_Drained))
{
props.pawn.health.AddHediff(HediffDefOf.Succubus_Drained);
GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(succubus), 0.25f);
}
}
}
public static void AbsorbFertilin(SexProps props, float absorb_factor = 1f)
{
Pawn_GeneTracker genes = props.partner.genes;
Gene_LifeForce gene = genes.GetFirstGeneOfType<Gene_LifeForce>();
Hediff fertilin_lost = props.pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Fertilin_Lost);
//Around quarter get ejected everytime pawn cums
float multiplier = Rand.Range(0.10f, 0.40f);
//Create a new ferilin_lost hediff or reduce multiplier
if (fertilin_lost == null)
{
Hediff new_fertilin_lost = HediffMaker.MakeHediff(HediffDefOf.Fertilin_Lost, props.pawn);
props.pawn.health.AddHediff(new_fertilin_lost);
new_fertilin_lost.Severity = multiplier;
}
else
{
multiplier *= 1 - fertilin_lost.Severity;
fertilin_lost.Severity += multiplier;
}
//More in the tank means more to give
if (props.pawn.Has(Quirk.Messy))
{
multiplier *= 2;
}
//Currently taking the sum of all penises, maybe I should just consider one at random
float valuechange = CumUtility.GetTotalFluidAmount(props.pawn) / 100 * absorb_factor * multiplier;
GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(props.partner), valuechange);
//gene.Resource.Value += CumUtility.GetTotalFluidAmount(props.pawn) / 100 * absorb_factor * multiplier;
}
public static float BaseDom(SexProps props, Pawn succubus)
{
float absorb_factor = 0f;
if (props.sexType == xxx.rjwSextype.Sixtynine)
{
absorb_factor += 1f;
}
else if (props.sexType == xxx.rjwSextype.Vaginal)
{
//with insertion absorbtion or vaginal cum absorbtion
//absorb_factor += 1f;
}
else if (props.sexType == xxx.rjwSextype.DoublePenetration)
{
if (GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_vaginal_absorber))
{
//with insertion absorbtion?
//absorb_factor += 0.5f;
}
if (GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_anal_absorber))
{
//with insertion absorbtion?
//absorb_factor += 0.5f;
}
}
else if (props.sexType == xxx.rjwSextype.Scissoring)
{
//with vaginal cum absorption && vaginal absorbtion
//absorb_factor += 1f;
}
return absorb_factor;
}
public static float BaseSub(SexProps props, Pawn succubus)
{
float absorb_factor = 0f;
if (props.sexType == xxx.rjwSextype.Oral || props.sexType == xxx.rjwSextype.Fellatio || props.sexType == xxx.rjwSextype.Sixtynine)
{
absorb_factor += 1f;
}
else if (props.sexType == xxx.rjwSextype.Vaginal && GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_vaginal_absorber))
{
absorb_factor += 1f;
}
else if (props.sexType == xxx.rjwSextype.Anal && GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_anal_absorber))
{
absorb_factor += 1f;
}
else if (props.sexType == xxx.rjwSextype.DoublePenetration)
{
if (GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_vaginal_absorber))
{
absorb_factor += 0.5f;
}
if (GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_anal_absorber))
{
absorb_factor += 0.5f;
}
}
else if (props.sexType == xxx.rjwSextype.Scissoring || props.sexType == xxx.rjwSextype.Cunnilingus)
{
//with vaginal cum absorbtion
//absorb_factor += 1f;
}
return absorb_factor;
}
}
}

View file

@ -0,0 +1,57 @@
using HarmonyLib;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
namespace RJW_Genes
{
//[HarmonyPatch(typeof(JobDriver_Sex), nameof(JobDriver_Sex.ChangePsyfocus))]
public static class Patch_SexTicks_ChangePsyfocus
{
//Using ChangePsyfocus as it is something that fires every 60 ticks
public static void Postfix(ref JobDriver_Sex __instance, ref Pawn pawn, ref Thing target)
{
if (__instance.Sexprops.sexType == xxx.rjwSextype.Cunnilingus)
{
if (target != null)
{
Pawn pawn2 = target as Pawn;
if (pawn2 != null)
{
//We need who the pawn on top is and if reverse we need to make the sub the pawn on top
if (__instance.Sexprops.isRevese)
{
DrinkCumflation(pawn2, pawn);
}
else
{
//
DrinkCumflation(pawn, pawn2);
return;
}
}
}
}
}
public static void DrinkCumflation(Pawn dom, Pawn sub)
{
if (GeneUtility.HasLifeForce(sub) && dom.health.hediffSet.HasHediff(HediffDef.Named("Cumflation")))
{
Hediff cumflation = dom.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("Cumflation"));
Gene_LifeForce gene_LifeForce = sub.genes.GetFirstGeneOfType<Gene_LifeForce>();
cumflation.Severity -= 0.1f;
gene_LifeForce.Resource.Value += 0.05f;
}
}
//Maybe I can store gene and hediff so I dont need to look them up every time
}
}

View file

@ -0,0 +1,14 @@
using System;
using Verse;
using Verse.AI;
namespace RJW_Genes
{
public class ThinkNode_ConditionalCritcalLifeForce : ThinkNode_Conditional
{
protected override bool Satisfied(Pawn p)
{
return GeneUtility.HasCriticalLifeForce(p);
}
}
}

View file

@ -0,0 +1,14 @@
using System;
using Verse;
using Verse.AI;
namespace RJW_Genes
{
public class ThinkNode_ConditionalLowLifeForce : ThinkNode_Conditional
{
protected override bool Satisfied(Pawn p)
{
return GeneUtility.HasLowLifeForce(p);
}
}
}

View file

@ -0,0 +1,80 @@
using HarmonyLib;
using rjw;
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 Gene_Aphrodisiac_Pheromones : Gene
{
//Summary one every one check for all pawns nearby and in line of sight and add/renew a hediff which increases sexdrive for six hours.
public override void Tick()
{
base.Tick();
if (this.pawn.IsHashIntervalTick(2500))
{
//Only spread pheromones if sexdrive above 1
float sexfrequency = this.pawn.GetStatValue(StatDef.Named("SexFrequency"));
if(sexfrequency > 1f)
{
foreach (Pawn pawn in this.AffectedPawns(this.pawn.Position, this.pawn.Map))
{
this.InduceAphrodisiac(pawn, sexfrequency);
}
}
}
}
//Creatus an IEnumerable of all pawns which are closeby and in lineofsight, self and other pawns with aphrodisiac pheromones gene are skipped.
private IEnumerable<Pawn> AffectedPawns(IntVec3 pos, Map map)
{
foreach (Pawn pawn in map.mapPawns.AllPawns)
{
if (this.pawn != null && pawn != this.pawn && pos.DistanceTo(pawn.Position) < 5 && GenSight.LineOfSight(pos, pawn.Position, pawn.Map) && !GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_aphrodisiac_pheromones))
{
yield return pawn;
}
}
//IEnumerator<Pawn> enumerator = null;
yield break;
}
//Applies er renews a hediff which increases sexdrive for 6 hours
private void InduceAphrodisiac(Pawn pawn, float sexfrequency)
{
Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Aphrodisiac_Pheromone);
if (hediff != null)
{
hediff.Severity = 1f;
}
else
{
Hediff aphrodisiac = HediffMaker.MakeHediff(HediffDefOf.Aphrodisiac_Pheromone, pawn);
foreach (StatModifier stat in aphrodisiac.CurStage.statFactors)
{
//Log.Message(pawn.Name.ToString());
//Log.Message(stat.stat.defName);
//Log.Message(stat.value.ToString());
if (stat.stat.defName == "SexFrequency")
{
stat.value = ModifySexfrequency(pawn, sexfrequency);
pawn.health.AddHediff(aphrodisiac);
}
}
}
}
//Function to modify aphrodisiac strength, currently has no effect, but it's an easy hook for other modders.
public float ModifySexfrequency(Pawn pawn, float sexfrequency)
{
return sexfrequency;
}
}
}

View file

@ -46,10 +46,10 @@ namespace RJW_Genes
/// <returns></returns>
public static Hediff GetOrgasmRushHediff(Pawn orgasmed)
{
Hediff orgasmRushHediff = orgasmed.health.hediffSet.GetFirstHediffOfDef(GeneDefOf.rjw_genes_orgasm_rush_hediff);
Hediff orgasmRushHediff = orgasmed.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.rjw_genes_orgasm_rush_hediff);
if (orgasmRushHediff == null)
{
orgasmRushHediff = HediffMaker.MakeHediff(GeneDefOf.rjw_genes_orgasm_rush_hediff, orgasmed);
orgasmRushHediff = HediffMaker.MakeHediff(HediffDefOf.rjw_genes_orgasm_rush_hediff, orgasmed);
orgasmRushHediff.Severity = 0;
orgasmed.health.AddHediff(orgasmRushHediff);
}

View file

@ -27,6 +27,8 @@ namespace RJW_Genes
// Gene: Generous Donor [Postfix Patch]
harmony.Patch(AccessTools.Method(typeof(LicentiaLabs.CumflationHelper), nameof(LicentiaLabs.CumflationHelper.TransferNutrition)),
postfix: new HarmonyMethod(typeof(Patch_TransferNutrition), nameof(Patch_TransferNutrition.Postfix)));
harmony.Patch(AccessTools.Method(typeof(rjw.JobDriver_Sex), nameof(rjw.JobDriver_Sex.ChangePsyfocus)),
postfix: new HarmonyMethod(typeof(Patch_SexTicks_ChangePsyfocus), nameof(Patch_SexTicks_ChangePsyfocus.Postfix)));
}
}))();
}

19
Source/HediffDefOf.cs Normal file
View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
namespace RJW_Genes
{
[DefOf]
public static class HediffDefOf
{
public static readonly HediffDef Aphrodisiac_Pheromone;
public static readonly HediffDef Fertilin_Lost;
public static readonly HediffDef Succubus_Drained;
public static readonly HediffDef rjw_genes_orgasm_rush_hediff;
}
}

View file

@ -0,0 +1,23 @@
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 CompAbility_SexInteractionRequirements : AbilityComp
{
public CompProperties_SexInteractionRequirements Props
{
get
{
return (CompProperties_SexInteractionRequirements)this.props;
}
}
}
}

View file

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
using rjw;
using rjw.Modules.Interactions.Defs.DefFragment;
using rjw.Modules.Interactions.Enums;
namespace RJW_Genes
{
public class CompProperties_SexInteractionRequirements : AbilityCompProperties
{
public CompProperties_SexInteractionRequirements()
{
this.compClass = typeof(CompAbility_SexInteractionRequirements);
}
public List<InteractionTag> tags = new List<InteractionTag>();
public InteractionRequirement dominantRequirement;
public InteractionRequirement submissiveRequirement;
}
}

View file

@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
using rjw;
using rjw.Modules.Interactions.Objects;
using rjw.Modules.Interactions.Helpers;
using rjw.Modules.Interactions.Enums;
using rjw.Modules.Interactions.Implementation;
using rjw.Modules.Interactions.Defs.DefFragment;
namespace RJW_Genes
{
public class CustomSexInteraction_Helper
{
public static List<InteractionDef> GenerateInteractionDefList(Pawn pawn, Pawn pawn2, CompProperties_SexInteractionRequirements sexpropsreq)
{
List<InteractionTag> tags = new List<InteractionTag>();
if (pawn2.IsAnimal())
{
tags.Add(InteractionTag.Animal);
}
else
{
tags = sexpropsreq.tags;
}
InteractionRequirement dominantRequirement = sexpropsreq.dominantRequirement;
InteractionRequirement submissiveRequirement = sexpropsreq.submissiveRequirement;
List<InteractionDef> list = new List<InteractionDef>();
//List<InteractionDef> a = from interaction in sexinteractions
//where InteractionHelper.GetWithExtension(interaction).DominantHasFamily(dominantRequirement.families.)
// select interaction;
//should use where select but dont fully understand that, so I am using this.
foreach (InteractionDef interactionDef in SexUtility.SexInterractions)
{
//Use rjw function to check if the interaction would be valid
if (!LewdInteractionValidatorService.Instance.IsValid(interactionDef, pawn, pawn2))
{
continue;
}
InteractionWithExtension withExtension = InteractionHelper.GetWithExtension(interactionDef);
bool add_interaction = false;
//only add interactions which have a correct tag
foreach (InteractionTag tag in tags)
{
if (withExtension.HasInteractionTag(tag))
{
add_interaction = true;
break;
}
}
//In case of failure go to next interaction
if (!add_interaction)
{
continue;
}
//goes to next interaction if it doesn't have the required genitals
if (dominantRequirement != null)
{
foreach (GenitalFamily genitalFamily in dominantRequirement.families)
{
if (!withExtension.DominantHasFamily(genitalFamily))
{
add_interaction = false;
break;
}
}
if (!add_interaction)
{
continue;
}
foreach (GenitalTag tag in dominantRequirement.tags)
{
if (!withExtension.DominantHasTag(tag))
{
add_interaction = false;
break;
}
}
}
//goes to next interaction if it doesn't have the required genitals
if (submissiveRequirement != null)
{
foreach (GenitalFamily genitalFamily in submissiveRequirement.families)
{
if (!withExtension.SubmissiveHasFamily(genitalFamily))
{
add_interaction = false;
break;
}
}
if (!add_interaction)
{
continue;
}
foreach (GenitalTag tag in submissiveRequirement.tags)
{
if (!withExtension.SubmissiveHasTag(tag))
{
add_interaction = false;
break;
}
}
}
if (add_interaction)
{
list.Add(interactionDef);
}
}
return list;
}
//Generates a valid interaction for the requirements and assigns sexprops based on that
public static SexProps GenerateSexProps(Pawn pawn, Pawn pawn2, CompProperties_SexInteractionRequirements sexpropsreq)
{
List<InteractionDef> interactionlist = GenerateInteractionDefList(pawn, pawn2, sexpropsreq);
if (!interactionlist.Any())
{
return null;
}
InteractionDef dictionaryKey = interactionlist.RandomElement();
bool rape = InteractionHelper.GetWithExtension(dictionaryKey).HasInteractionTag(InteractionTag.Rape);
SexProps sexProps = new SexProps();
sexProps.pawn = pawn;
sexProps.partner = pawn2;
sexProps.sexType = SexUtility.rjwSextypeGet(dictionaryKey);
sexProps.isRape = rape;
sexProps.isRapist = rape;
sexProps.canBeGuilty = false;
sexProps.dictionaryKey = dictionaryKey;
sexProps.rulePack = SexUtility.SexRulePackGet(dictionaryKey);
return sexProps;
}
}
}

View file

@ -0,0 +1,52 @@
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;
}
//public static readonly StringListDef filter = DefDatabase<StringListDef>.GetNamed("DomSuccubusTailFilter");
}
}

View file

@ -0,0 +1,53 @@
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 to rjw by AddtoIPartPreferenceRule in First
//Depending on the level of lifeforce increase the chance for using the mouth.
public class GenesPartKindUsageRule : IPartPreferenceRule
{
public IEnumerable<Weighted<LewdablePartKind>> ModifiersForDominant(InteractionContext context)
{
Pawn pawn = context.Internals.Dominant.Pawn;
if (GeneUtility.HasCriticalLifeForce(pawn))
{
yield return new Weighted<LewdablePartKind>(50f, LewdablePartKind.Mouth);
}
else if (GeneUtility.HasLowLifeForce(pawn))
{
yield return new Weighted<LewdablePartKind>(10f, LewdablePartKind.Mouth);
}
else if (GeneUtility.HasLifeForce(pawn))
{
yield return new Weighted<LewdablePartKind>(2f, LewdablePartKind.Mouth);
}
yield break;
}
public IEnumerable<Weighted<LewdablePartKind>> ModifiersForSubmissive(InteractionContext context)
{
Pawn pawn = context.Internals.Submissive.Pawn;
if (GeneUtility.HasCriticalLifeForce(pawn))
{
yield return new Weighted<LewdablePartKind>(50f, LewdablePartKind.Mouth);
}
else if (GeneUtility.HasLowLifeForce(pawn))
{
yield return new Weighted<LewdablePartKind>(10f, LewdablePartKind.Mouth);
}
else if (GeneUtility.HasLifeForce(pawn))
{
yield return new Weighted<LewdablePartKind>(2f, LewdablePartKind.Mouth);
}
yield break;
}
}
}

View file

@ -0,0 +1,52 @@
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 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;
}
//public static readonly StringListDef filter = DefDatabase<StringListDef>.GetNamed("SubSuccubusTailFilter");
}
}

18
Source/JobDefOf.cs Normal file
View file

@ -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
{
[DefOf]
public static class JobDefOf
{
public static readonly JobDef rjw_genes_lifeforce_randomrape;
public static readonly JobDef rjw_genes_lifeforce_seduced;
public static readonly JobDef sex_on_spot;
public static readonly JobDef sex_on_spot_reciever;
}
}

Some files were not shown because too many files have changed in this diff Show more