diff --git a/Common/Assemblies/Rjw-Genes.dll b/Common/Assemblies/Rjw-Genes.dll
index 73b206a..4a66aa4 100644
Binary files a/Common/Assemblies/Rjw-Genes.dll and b/Common/Assemblies/Rjw-Genes.dll differ
diff --git a/Common/Defs/AbilityDefs/Ability_CockEater.xml b/Common/Defs/AbilityDefs/Ability_CockEater.xml
new file mode 100644
index 0000000..4a8f2e3
--- /dev/null
+++ b/Common/Defs/AbilityDefs/Ability_CockEater.xml
@@ -0,0 +1,33 @@
+
+
+
+ rjw_genes_ability_cockeater
+ Eat Cock
+ Eat the cock of another pawn, restoring fertilin based on the size of the cock.
+ Genes/Icons/cockeater
+ true
+ true
+ false
+ Mote_CoagulateStencil
+ Coagulate
+ Coagulate_Cast
+ CastAbilityOnThingMelee
+ 402
+
+ Verb_CastAbilityTouch
+ false
+ -1
+ 10
+
+ true
+ false
+ false
+ false
+ true
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Common/Defs/AbilityDefs/Ability_NakedProwess.xml b/Common/Defs/AbilityDefs/Ability_NakedProwess.xml
new file mode 100644
index 0000000..292af25
--- /dev/null
+++ b/Common/Defs/AbilityDefs/Ability_NakedProwess.xml
@@ -0,0 +1,47 @@
+
+
+
+ rjw_genes_ability_naked_prowess
+ naked prowess
+ Enhance the strength and resilience of your naked body with fertilin.
+ Genes/Icons/rjw_naked_prowess
+ Things/Mote/Heart
+ CastAbilityOnThing
+ False
+ False
+ True
+
+ 126
+ 0
+
+
+ Verb_CastAbility
+ 2
+ 0
+ False
+ False
+
+ true
+ false
+ false
+ false
+ false
+ false
+
+
+
+
+ CompAbilityEffect_GiveHediff
+ rjw_genes_naked_prowess
+ True
+ true
+
+
+
+ 0.15
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Common/Defs/AbilityDefs/Ability_ParalysingKiss.xml b/Common/Defs/AbilityDefs/Ability_ParalysingKiss.xml
new file mode 100644
index 0000000..29e1588
--- /dev/null
+++ b/Common/Defs/AbilityDefs/Ability_ParalysingKiss.xml
@@ -0,0 +1,44 @@
+
+
+
+ rjw_genes_ability_paralysingkiss
+ paralysing kiss
+ Paralyse someone briefly with a kiss.
+ Genes/Icons/rjw_genes_lips
+ true
+ true
+ false
+
+ 5
+
+ Mote_CoagulateStencil
+ Coagulate
+ Coagulate_Cast
+ 402
+
+ Verb_CastAbilityTouch
+ false
+ -1
+ 1
+
+ true
+ false
+ false
+ false
+ true
+
+
+
+
+ CompAbilityEffect_Stun
+ -15
+
+
+ rjw_genes_lips
+
+
+ 0.1
+
+
+
+
\ No newline at end of file
diff --git a/Common/Defs/AbilityDefs/Ability_PussyHeal.xml b/Common/Defs/AbilityDefs/Ability_PussyHeal.xml
new file mode 100644
index 0000000..c31cb75
--- /dev/null
+++ b/Common/Defs/AbilityDefs/Ability_PussyHeal.xml
@@ -0,0 +1,49 @@
+
+
+
+ rjw_genes_ability_pussyheal
+ SexHeal
+ Rape another pawn, so you can heal them with your vagina's special healing power.
+ Things/Mote/Heart
+ false
+ true
+ false
+ Mote_CoagulateStencil
+ Coagulate
+ Coagulate_Cast
+ rjw_genes_lifeforce_healpussy
+ 401
+
+ Verb_CastAbilityTouch
+ false
+ -1
+ 0
+
+ true
+ false
+ false
+ false
+ true
+
+
+
+
+ 0.3
+
+
+ 0.4~0.8
+
+
+
+
+ Rape
+
+
+
+ Vagina
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Common/Defs/AbilityDefs/Ability_Seduce.xml b/Common/Defs/AbilityDefs/Ability_Seduce.xml
new file mode 100644
index 0000000..d4467e6
--- /dev/null
+++ b/Common/Defs/AbilityDefs/Ability_Seduce.xml
@@ -0,0 +1,43 @@
+
+
+
+ rjw_genes_ability_seduce
+ seduce
+ Seduce the target to approach the caster.
+ Genes/Icons/seduce
+ True
+ true
+ true
+ false
+
+ 10
+
+ Mote_CoagulateStencil
+ Coagulate
+ Coagulate_Cast
+
+ Verb_CastAbility
+ 10
+ 1
+
+ false
+ false
+ false
+ false
+ true
+
+
+
+
+ RJW_Genes.CompAbilityEffect_Seduce
+ Caster
+
+
+ Heart
+
+
+ 0.20
+
+
+
+
\ No newline at end of file
diff --git a/Common/Defs/DutyDefs/Duties_Succubus.xml b/Common/Defs/DutyDefs/Duties_Succubus.xml
new file mode 100644
index 0000000..bd67a24
--- /dev/null
+++ b/Common/Defs/DutyDefs/Duties_Succubus.xml
@@ -0,0 +1,67 @@
+
+
+
+ rjw_genes_flirt
+
+
+
+
+ SatisfyingNeeds
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.05
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Common/Defs/Effects/Fleck_Lifeforce.xml b/Common/Defs/Effects/Fleck_Lifeforce.xml
new file mode 100644
index 0000000..53ac7b5
--- /dev/null
+++ b/Common/Defs/Effects/Fleck_Lifeforce.xml
@@ -0,0 +1,14 @@
+
+
+
+ rjw_genes_lips
+
+ Genes/Icons/rjw_genes_lips
+
+ MetaOverlays
+ 0.08
+ 1.4
+ 1.5
+
+
+
\ No newline at end of file
diff --git a/Common/Defs/GeneDefs/GeneCategories.xml b/Common/Defs/GeneDefs/GeneCategories.xml
index 02c33dc..8106c8e 100644
--- a/Common/Defs/GeneDefs/GeneCategories.xml
+++ b/Common/Defs/GeneDefs/GeneCategories.xml
@@ -37,6 +37,12 @@
15
+
+ rjw_genes_fertilin
+ Fertilin
+ 14
+
+
rjw_genes_breeding
Breeding
diff --git a/Common/Defs/GeneDefs/GeneDefs_Cosmetic.xml b/Common/Defs/GeneDefs/GeneDefs_Cosmetic.xml
new file mode 100644
index 0000000..cfe7024
--- /dev/null
+++ b/Common/Defs/GeneDefs/GeneDefs_Cosmetic.xml
@@ -0,0 +1,108 @@
+
+
+
+ Miscellaneous
+ true
+
+ Wing
+
+
+
+
+ rjw_genes_succubus_wings
+ succubus wings
+ Carriers of this gene grow succubus wings.
+ Genes/Icons/Succubus_Wings
+ (0.75, 0.75, 0.75)
+ 1000
+
+ rjw_genes_ability_flight
+
+
+ rjw_genes_ability_flight
+
+ 1
+ -1
+ 0
+
+
+ PawnRenderNodeWorker_AttachmentBody
+ Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings
+ 1.5
+ Body
+ Skin
+
+
+ -2
+
+ true
+
+ 90
+
+
+
+
+
+
+
+ Genes/Icons/RJW_Genes_Endogene_Background
+ Genes/Icons/RJW_Genes_Xenogene_Background
+
+
+
+
+
+ rjw_genes_succubus_tail
+ succubus tail
+ Carriers of this gene grow a slender tail ending with a heart that can act as a dexterous fifth limb.
+ Genes/Icons/Succubus_Tail
+ (1, 0, 0)
+ 1000
+
+
+ Manipulation
+ 0.05
+
+
+ 1
+ -1
+ 0
+
+
+ PawnRenderNodeWorker_AttachmentBody
+ Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail
+ (1.5, 1.5)
+ Body
+ Skin
+ Fresh, Rotting
+
+ true
+
+ -2
+
+
+ (0, 0, -0.15)
+ 90
+
+
+ (-0, 0, -0.15)
+
+
+ (-0.2, 0, -0.15)
+
+
+ (0.2, 0, -0.15)
+
+
+
+
+ true
+
+
+
+ Genes/Icons/RJW_Genes_Endogene_Background
+ Genes/Icons/RJW_Genes_Xenogene_Background
+
+
+
+
\ No newline at end of file
diff --git a/Common/Defs/GeneDefs/GeneDefs_LifeForce.xml b/Common/Defs/GeneDefs/GeneDefs_LifeForce.xml
new file mode 100644
index 0000000..8c793e2
--- /dev/null
+++ b/Common/Defs/GeneDefs/GeneDefs_LifeForce.xml
@@ -0,0 +1,237 @@
+
+
+
+
+ rjw_genes_fertilin
+
+
+
+ Genes/Icons/RJW_Genes_Endogene_Background
+ Genes/Icons/RJW_Genes_Xenogene_Background
+
+
+
+
+
+ rjw_genes_lifeforce
+ fertilin
+ 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.
+ RJW_Genes.Gene_LifeForce
+ RJW_Genes.GeneGizmo_ResourceLifeForce
+ fertilin
+
+ 0.25
+ 0.5
+ 0.75
+
+ true
+ true
+ 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.
+ Genes/Icons/FertilinAlt
+ 0
+ -2
+ 18
+
+ Gives fertilin supply.
+
+
+
+ fert
+
+
+ 0.025
+ 1
+ 1
+
+
+
+ rjw_genes_lifeforce_drain
+ fertilin drain
+ draining
+ Carriers lose an additional 7.5 fertilin per day from biological entropy.
+ fertilin
+ RJW_Genes.Gene_LifeForceDrain
+ Genes/Icons/FertilinDrainAlt
+ rjw_genes_lifeforce
+ 0.075
+ 18
+ -1
+ 1
+ 6
+
+
+
+ rjw_genes_pussyhealing
+ Pussy Healer
+ pussyhealer
+ Carriers of this gene are able use vaginal sex to tend to other's wounds.
+ Genes/Icons/Healpussy
+ rjw_genes_lifeforce
+ 9
+
+ rjw_genes_ability_pussyheal
+
+
+ rjw_genes_ability_pussyheal
+
+ 1
+ -1
+
+
+ life
+ pussy
+ heal
+
+
+
+
+
+ rjw_genes_cockeater
+ Cockeater
+ cockeater
+ Carriers of this gene are able eat cocks to restore their fertilin supply. Cocks are consumed during that process.
+ Genes/Icons/cockeater
+ rjw_genes_lifeforce
+ 11
+
+ rjw_genes_ability_cockeater
+
+
+ rjw_genes_ability_cockeater
+
+ 1
+ -1
+
+
+ life
+ cock
+ eat
+
+
+
+
+
+ rjw_genes_paralysingkiss
+ paralysing kiss
+ paralysing kiss
+ Carriers of this gene are able to briefly stun an enemy with a kiss.
+ Genes/Icons/Paralysing_Kiss
+ rjw_genes_lifeforce
+ 12
+
+ rjw_genes_ability_paralysingkiss
+
+
+ rjw_genes_ability_paralysingkiss
+
+ 1
+ -1
+
+
+ stun
+ kiss
+
+
+
+
+
+ rjw_genes_seduce
+ seduction
+ seduction
+ Carriers of this gene are able to seduce a pawn into having sex with them.
+ Genes/Icons/seduce
+ rjw_genes_lifeforce
+ 13
+
+ rjw_genes_ability_seduce
+
+
+ rjw_genes_ability_seduce
+
+ 1
+ -1
+
+
+
+ stun
+ kiss
+
+
+
+
+
+ rjw_genes_naked_prowess
+ naked prowess
+ Carriers of this gene are able to temporarily increase their strength and resilience, while they are naked.
+ Genes/Icons/rjw_naked_prowess
+ rjw_genes_lifeforce
+ 14
+
+ rjw_genes_ability_naked_prowess
+
+
+ rjw_genes_ability_naked_prowess
+
+ 1
+ -1
+
+
+
+ rjw_genes_cum_eater
+ Cum eater
+ Carriers of this gene are able to absorb fertilin through eating cum. This includes oral sex, eating cum for food or sucking out cumflated pawns.
+ Genes/Icons/cumeater
+ rjw_genes_lifeforce
+ 1
+ 1
+
+
+
+ rjw_genes_fertilin_absorber
+ Fertilin Absorber
+ Carriers of this gene are able to absorb the fertilin inside sperm through their vagina and anus.
+ Genes/Icons/Vaginal_cum_absorption
+ rjw_genes_lifeforce
+ 2
+ 1
+
+
+
+ rjw_genes_lifeforce_empath
+ empathic lifeforce
+ RJW_Genes.Gene_LifeForce_Empath
+ Carriers of this gene generate lifeforce if nearby pawns are sexually satisfied. Be careful: Sexually frustrated pawns will make your empath loose lifeforce!
+ Genes/Icons/Hypersexual
+ rjw_genes_lifeforce
+ 3
+ 3
+ -2
+
+
+
+ 0.02
+ 0.01
+ -0.01
+
+
+
+ 2500
+
+
+
+ 25
+
+
+
+
+
+ rjw_genes_drainer
+ vitality drainer
+ Carriers of this gene are able to absorb a great amount of fertilin by draining the vitality of the partner. This is done passively through having sex with a non-drained pawn that does not have this gene.
+ Genes/Icons/Vitality_Drainer
+ rjw_genes_lifeforce
+ 4
+ 1
+ -1
+
+
\ No newline at end of file
diff --git a/Common/Defs/GeneDefs/Xenotype_Lifeforce.xml b/Common/Defs/GeneDefs/Xenotype_Lifeforce.xml
new file mode 100644
index 0000000..608a2f4
--- /dev/null
+++ b/Common/Defs/GeneDefs/Xenotype_Lifeforce.xml
@@ -0,0 +1,144 @@
+
+
+
+
+ rjw_genes_succubus
+ Succubus
+ Succubi are strongly enhanced xenohumans. These overnaturally beautiful creatures strive parasitically on the Fertilin found in semen.
+ Succubi are beautiful and extremely hungry Xenohumans. They strive on having sex and extracting their victims life-force through this.
+ Genes/Icons/Xenotypes/Xenotype-Succubus
+ PawnBecameSanguophage
+ 0.5
+ 0.1~140
+ 1
+ -1000
+ 0.005
+ false
+
+ 0.02
+ 0.02
+ 0.02
+ 0.02
+ 0.02
+ 0.02
+
+
+ rjw_genes_bisexual
+ rjw_genes_hypersexual
+ rjw_genes_female_only
+ rjw_genes_lifeforce
+ rjw_genes_lifeforce_drain
+ rjw_genes_demonic_genitalia
+
+ rjw_genes_cum_eater
+ rjw_genes_fertilin_absorber
+
+ rjw_genes_paralysingkiss
+ rjw_genes_seduce
+ AptitudeRemarkable_Sex
+
+ DominantGene
+ rjw_genes_elasticity
+ rjw_genes_succubus_wings
+ rjw_genes_succubus_tail
+ rjw_genes_aphrodisiac_pheromones
+ Beauty_Pretty
+ MoveSpeed_Quick
+ AptitudeStrong_Social
+ Ears_Pointed
+ Headbone_MiniHorns
+ Skin_Purple
+
+
+
+
+ rjw_genes_incubus
+ Incubus
+ Incubi are strongly enhanced xenohumans. These overnaturally beautiful creatures strive parasitically on the Fertilin found in semen.
+ Incubi are beautiful and extremely hungry Xenohumans. They strive on having sex and extracting their victims life-force through this.
+ Genes/Icons/Xenotypes/Xenotype-Incubus
+ PawnBecameSanguophage
+ 0.5
+ 0.1~140
+ 1
+ -1000
+ 0.005
+ false
+
+ 0.02
+ 0.02
+ 0.02
+ 0.02
+ 0.02
+ 0.02
+
+
+ rjw_genes_hypersexual
+ rjw_genes_male_only
+ rjw_genes_lifeforce
+ rjw_genes_lifeforce_drain
+ rjw_genes_drainer
+ rjw_genes_demonic_genitalia
+
+ AptitudeRemarkable_Sex
+
+
+ DominantGene
+ rjw_genes_seduce
+ rjw_genes_succubus_wings
+ rjw_genes_succubus_tail
+ rjw_genes_aphrodisiac_pheromones
+
+ Beauty_Pretty
+ MoveSpeed_Quick
+ Robust
+ UVSensitivity_Intense
+ AptitudeStrong_Intellectual
+ Ears_Pointed
+ Headbone_CenterHorn
+ Skin_InkBlack
+
+
+
+
+ rjw_genes_cumazone
+ Cumazone
+ Cumazone are a female only xenotype that excel at meele combat. Originally created as bodyguards for glitterworld amazon communities, they spred to other systems by mere strength and providing for some fetishes. They can use Fertilin to enhance their skin to overpower any combatant in meele. Their only source for Fertilin is biting of male genitalia - so be sure to have a steady supply of victim males or prepare to raid unsuspecting men of the rim.
+ Female only, strong meele fighters, that use Fertilin from bitten-off cocks for powerful buffs.
+ Genes/Icons/Xenotypes/Xenotype-Cumazon
+ 0.5
+ 0.1~140
+ 2.5
+ -1000
+ 0.01
+ false
+
+ WoundHealing_Fast
+ NakedSpeed
+ Aggression_Aggressive
+ MeleeDamage_Strong
+ KillThirst
+ Robust
+ Pain_Reduced
+ Beauty_Ugly
+ Hair_BaldOnly
+ Hair_ShortOnly
+ Brow_Heavy
+ Body_Hulk
+ AptitudeStrong_Shooting
+ AptitudeRemarkable_Melee
+ AptitudePoor_Crafting
+ AptitudePoor_Artistic
+ Unstoppable
+ rjw_genes_rapist
+ rjw_genes_female_only
+ rjw_genes_lifeforce
+ rjw_genes_lifeforce_drain
+ rjw_genes_pussyhealing
+ rjw_genes_cockeater
+ rjw_genes_naked_prowess
+ rjw_genes_orgasm_rush
+
+
+
+
\ No newline at end of file
diff --git a/Common/Defs/HediffDefs/Hediffs_Fertilin.xml b/Common/Defs/HediffDefs/Hediffs_Fertilin.xml
new file mode 100644
index 0000000..fdca8d4
--- /dev/null
+++ b/Common/Defs/HediffDefs/Hediffs_Fertilin.xml
@@ -0,0 +1,166 @@
+
+
+
+
+ rjw_genes_fertilin_lost
+ Hediff_HemogenCraving
+ lost fertilin
+ Percentage of fertilin lost.
+ (1,1,1)
+ 1
+
+
+ -0.5
+
+
+
+
+ true
+
+
+
+
+
+ rjw_genes_succubus_drained
+ HediffWithComps
+ Drained
+ The vitality of this pawn has been drained. Cannot be drained again until fully recovered.
+ (1,0,0.5)
+ 1.0
+ 1.0
+
+
+ -0.25
+
+
+
+
+ minor
+
+
+ Consciousness
+ -0.1
+
+
+ 0.1
+
+ -0.1
+
+
+
+ 0.5
+ moderate
+
+
+ Consciousness
+ -0.2
+
+
+ 0.05
+ 0.20
+
+ -0.1
+
+
+
+ 0.8
+ severe
+
+
+ Consciousness
+ -0.3
+
+
+
+ -0.2
+
+ 0.4
+ 0.1
+ 0.35
+
+
+
+
+
+ rjw_genes_fertilin_craving
+ fertilin craving
+ Hediff_HemogenCraving
+ weakened due to running out of fertilin.
+ (1,0,0.5)
+ 1.0
+ 0.01
+
+
+ minor
+ 0.05
+
+
+ Consciousness
+ 0.9
+
+
+
+
+ moderate
+ 0.35
+ 0.1
+
+
+ Consciousness
+ 0.8
+
+
+
+
+ major
+ 0.7
+ 0.15
+
+
+ Consciousness
+ 0.5
+
+
+
+
+
+
+ 0.05
+ -0.1
+
+
+
+
+
+ rjw_genes_naked_prowess
+ naked prowss
+ Driven by fertilin, this person has greatly increased strength and resilience.
+ HediffWithComps
+
+
+
+
+ 0.5
+ 0.5
+ 0.5
+
+
+
+ 0.5
+ 1.5
+
+
+
+
+
+ True
+ 5000
+
+
+
+
+ false
+
+
+
diff --git a/Common/Defs/InteractionDef/Interactions_Flirt.xml b/Common/Defs/InteractionDef/Interactions_Flirt.xml
new file mode 100644
index 0000000..27c5408
--- /dev/null
+++ b/Common/Defs/InteractionDef/Interactions_Flirt.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+ rjw_genes_flirt
+ flirt
+ Things/Mote/SpeechSymbols/Chitchat
+
+
+ r_logentry->[INITIATOR_nameDef] and [RECIPIENT_nameDef] [talkedabout] [TalkTopicLight].
+ r_logentry->[INITIATOR_nameDef] [talkedabout] [TalkTopicLight] with [RECIPIENT_nameDef].
+ r_logentry(p=0.8)->[INITIATOR_nameDef] [commentedabout] [TalkTopicLight] to [RECIPIENT_nameDef].
+
+ talkedabout(p=4)->chatted about
+ talkedabout->shared a word about
+ talkedabout->spoke about
+ talkedabout->gabbed about
+ talkedabout->talked about
+ talkedabout->joked about
+ talkedabout->quipped about
+
+ commentedabout->said something about
+ commentedabout->said a word about
+ commentedabout->made a comment about
+ commentedabout->commented about
+ commentedabout->told a joke about
+
+
+
+
+
diff --git a/Common/Defs/JobDefs/Jobs_LifeForce.xml b/Common/Defs/JobDefs/Jobs_LifeForce.xml
new file mode 100644
index 0000000..13dd1e3
--- /dev/null
+++ b/Common/Defs/JobDefs/Jobs_LifeForce.xml
@@ -0,0 +1,32 @@
+
+
+
+
+ rjw_genes_lifeforce_randomrape
+ rjw.JobDriver_RandomRape
+ Raping
+ false
+
+
+
+ rjw_genes_lifeforce_healpussy
+ RJW_Genes.JobDriver_CastAbilityAfterSex
+ Tending someones wounds with sex.
+ false
+
+
+
+ rjw_genes_lifeforce_seduced
+ RJW_Genes.JobDriver_Seduced
+ Seduced.
+ false
+ false
+
+
+
+ rjw_genes_flirt
+ RJW_Genes.JobDriver_Flirt
+ Seduced.
+ false
+
+
\ No newline at end of file
diff --git a/Common/Defs/JobDefs/Jobs_SexOnSpot.xml b/Common/Defs/JobDefs/Jobs_SexOnSpot.xml
new file mode 100644
index 0000000..e904f3e
--- /dev/null
+++ b/Common/Defs/JobDefs/Jobs_SexOnSpot.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ sex_on_spot
+ RJW_Genes.JobDriver_SexOnSpot
+ Making love on the spot.
+ false
+
+
+
+ sex_on_spot_reciever
+ RJW_Genes.JobDriver_SexOnSpotReciever
+ lovin'.
+ false
+
+
\ No newline at end of file
diff --git a/Common/Defs/MentalStateDefs/MentalState_Lifeforce.xml b/Common/Defs/MentalStateDefs/MentalState_Lifeforce.xml
new file mode 100644
index 0000000..392407b
--- /dev/null
+++ b/Common/Defs/MentalStateDefs/MentalState_Lifeforce.xml
@@ -0,0 +1,31 @@
+
+
+
+
+ rjw_genes_lifeforce_randomrape
+ rjw_genes_lifeforce_randomrape
+ 1.5
+ Extreme
+ RJW_Genes.LifeForceMentalBreakWorker
+
+
+
+ rjw_genes_lifeforce_randomrape
+ RJW_Genes.LifeForceMentalState
+ RJW_Genes.LifeForceMentalStateWorker
+ random rape
+ Malicious
+ true
+ false
+ 30000
+ 0.8
+ 80000
+ (0.5, 0.9, 0.5)
+ random rape
+ {0} has run out of lifeforce and is looking to obtain some.
+ ThreatSmall
+ {0} is no longer raping randomly.
+ Mental state: Random Rape
+ true
+
+
\ No newline at end of file
diff --git a/Common/Defs/ThinkTreeDefs/ThinkTrees_LifeForce.xml b/Common/Defs/ThinkTreeDefs/ThinkTrees_LifeForce.xml
new file mode 100644
index 0000000..574fe0f
--- /dev/null
+++ b/Common/Defs/ThinkTreeDefs/ThinkTrees_LifeForce.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+ SuccubusGetLifeForce
+ Humanlike_PostMain
+ 14
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 8
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Common/Defs/ThoughtDefs/Thoughts_LifeForce.xml b/Common/Defs/ThoughtDefs/Thoughts_LifeForce.xml
new file mode 100644
index 0000000..b3bf297
--- /dev/null
+++ b/Common/Defs/ThoughtDefs/Thoughts_LifeForce.xml
@@ -0,0 +1,56 @@
+
+
+
+
+ rjw_genes_cock_eaten
+ Thought_Memory
+ 30.0
+ 100
+ 0.4
+
+
+ cock eaten
+ My cock was eaten directly of my body, I am devestated. This is not what good head feels like.
+ -30
+
+
+
+
+
+ rjw_genes_seduced
+ Thought_Memory
+ 10.0
+ 100
+ 0.4
+
+
+ seduced
+ I was seduced into having sex. I regret what happened.
+ -10
+
+
+
+
+
+ rjw_genes_critical_fertilin
+ ThoughtWorker_Hediff
+ rjw_genes_fertilin_craving
+
+
+ fertilin craving
+ My bones ache. I really need fertilin.
+ -25
+
+
+ fertilin craving
+ This hurts bad and I can't stop thinking about sex. I would do anything for some cum.
+ -40
+
+
+ fertilin craving
+ Can't think. Sex. Sex. Must. Have. Cum.
+ -55
+
+
+
+
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_east.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_east.dds
deleted file mode 100644
index 070876e..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_east.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_east.png
deleted file mode 100644
index dc01479..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_east.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_north.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_north.dds
deleted file mode 100644
index 00d3c02..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_north.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_south.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_south.dds
deleted file mode 100644
index e67f410..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_south.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L1_east.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L1_east.dds
deleted file mode 100644
index 3103d85..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L1_east.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L1_north.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L1_north.dds
deleted file mode 100644
index 9fdbd21..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L1_north.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L1_south.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L1_south.dds
deleted file mode 100644
index afec4ca..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L1_south.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L2_east.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L2_east.dds
deleted file mode 100644
index e0f6747..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L2_east.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L2_north.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L2_north.dds
deleted file mode 100644
index 0a016f8..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L2_north.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L2_south.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L2_south.dds
deleted file mode 100644
index 3b16ee4..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_L2_south.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R1_east.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R1_east.dds
deleted file mode 100644
index 4cedb72..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R1_east.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R1_north.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R1_north.dds
deleted file mode 100644
index afec4ca..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R1_north.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R1_south.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R1_south.dds
deleted file mode 100644
index 99c788e..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R1_south.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R2_east.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R2_east.dds
deleted file mode 100644
index 4d97e53..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R2_east.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R2_north.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R2_north.dds
deleted file mode 100644
index 737d3b0..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R2_north.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R2_south.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R2_south.dds
deleted file mode 100644
index 61e5a0e..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/Succubus_Tail_R2_south.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail_east.png
new file mode 100644
index 0000000..ef191bf
Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail_east.png differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_north.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail_north.png
similarity index 100%
rename from Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_north.png
rename to Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail_north.png
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_south.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail_south.png
similarity index 100%
rename from Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail/RJW_Genes_Succubus_Tail_south.png
rename to Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Tail_south.png
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_east.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_east.dds
deleted file mode 100644
index fa092f7..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_east.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_north.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_north.dds
deleted file mode 100644
index 5620a67..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_north.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_south.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_south.dds
deleted file mode 100644
index 94bbe7e..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_south.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/Succubus_Wings_east.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/Succubus_Wings_east.dds
deleted file mode 100644
index 24496d0..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/Succubus_Wings_east.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/Succubus_Wings_north.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/Succubus_Wings_north.dds
deleted file mode 100644
index f2dcd83..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/Succubus_Wings_north.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/Succubus_Wings_south.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/Succubus_Wings_south.dds
deleted file mode 100644
index f2dcd83..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/Succubus_Wings_south.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings_east.png
similarity index 100%
rename from Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_east.png
rename to Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings_east.png
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_north.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings_north.png
similarity index 100%
rename from Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_north.png
rename to Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings_north.png
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_south.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings_south.png
similarity index 100%
rename from Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings/RJW_Genes_Succubus_Wings_south.png
rename to Common/Textures/Things/Pawn/Humanlike/BodyAttachments/RJW_Genes_Succubus_Wings_south.png
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_east.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_east.dds
deleted file mode 100644
index 3103d85..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_east.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_east.png
deleted file mode 100644
index 7f51811..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_east.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_north.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_north.dds
deleted file mode 100644
index 9fdbd21..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_north.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_north.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_north.png
deleted file mode 100644
index 25c4097..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_north.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_south.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_south.dds
deleted file mode 100644
index afec4ca..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_south.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_south.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_south.png
deleted file mode 100644
index 60aae1e..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L1_south.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_east.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_east.dds
deleted file mode 100644
index e0f6747..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_east.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_east.png
deleted file mode 100644
index f3be513..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_east.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_north.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_north.dds
deleted file mode 100644
index 0a016f8..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_north.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_north.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_north.png
deleted file mode 100644
index 7a54823..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_north.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_south.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_south.dds
deleted file mode 100644
index 3b16ee4..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_south.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_south.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_south.png
deleted file mode 100644
index 91b5641..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_L2_south.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_east.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_east.dds
deleted file mode 100644
index 4cedb72..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_east.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_east.png
deleted file mode 100644
index e08f0b3..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_east.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_north.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_north.dds
deleted file mode 100644
index afec4ca..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_north.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_north.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_north.png
deleted file mode 100644
index 60aae1e..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_north.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_south.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_south.dds
deleted file mode 100644
index 99c788e..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_south.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_south.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_south.png
deleted file mode 100644
index 0c9df93..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R1_south.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_east.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_east.dds
deleted file mode 100644
index 4d97e53..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_east.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_east.png
deleted file mode 100644
index ea33158..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_east.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_north.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_north.dds
deleted file mode 100644
index 737d3b0..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_north.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_north.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_north.png
deleted file mode 100644
index 30e0e28..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_north.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_south.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_south.dds
deleted file mode 100644
index 61e5a0e..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_south.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_south.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_south.png
deleted file mode 100644
index a9f56d7..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Tail_R2_south.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_east.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_east.dds
deleted file mode 100644
index 24496d0..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_east.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_east.png
deleted file mode 100644
index 71e3f53..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_east.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_north.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_north.dds
deleted file mode 100644
index f2dcd83..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_north.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_north.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_north.png
deleted file mode 100644
index ac55d17..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_north.png and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_south.dds b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_south.dds
deleted file mode 100644
index f2dcd83..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_south.dds and /dev/null differ
diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_south.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_south.png
deleted file mode 100644
index ac55d17..0000000
Binary files a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/deprecated_rjw_genes_succubus/Succubus_Wings_south.png and /dev/null differ
diff --git a/Source/GeneDefOf.cs b/Source/GeneDefOf.cs
index 0220ef6..afa8844 100644
--- a/Source/GeneDefOf.cs
+++ b/Source/GeneDefOf.cs
@@ -95,8 +95,29 @@ namespace RJW_Genes
public static readonly GeneDef rjw_genes_sexual_mytosis;
public static readonly GeneDef rjw_genes_hormonal_saliva;
-
+ // Cosmetic
+ public static readonly GeneDef rjw_genes_succubus_tail;
+ public static readonly GeneDef rjw_genes_succubus_wings;
- }
+ //life force
+ public static readonly GeneDef rjw_genes_lifeforce;
+ public static readonly GeneDef rjw_genes_pussyhealing;
+ public static readonly GeneDef rjw_genes_lifeforce_drain;
+ public static readonly GeneDef rjw_genes_cum_eater;
+ public static readonly GeneDef rjw_genes_fertilin_absorber;
+ public static readonly GeneDef rjw_genes_drainer;
+ public static readonly GeneDef rjw_genes_seduce;
+ public static readonly GeneDef rjw_genes_paralysingkiss;
+ public static readonly GeneDef rjw_genes_cockeater;
+ public static readonly GeneDef rjw_genes_lifeforce_empath;
+
+ //Other Defs
+ public static readonly XenotypeDef rjw_genes_succubus;
+ public static readonly DutyDef rjw_genes_flirt;
+ public static readonly MentalBreakDef rjw_genes_lifeforce_randomrape;
+
+
+
+ }
}
diff --git a/Source/Genes/GeneUtility.cs b/Source/Genes/GeneUtility.cs
index 8cbc816..efebb69 100644
--- a/Source/Genes/GeneUtility.cs
+++ b/Source/Genes/GeneUtility.cs
@@ -6,13 +6,77 @@ namespace RJW_Genes
{
public class GeneUtility
{
-
- public static float MaxEggSizeMul(Pawn pawn)
+
+ //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)
{
- float MaxEggSize = 1;
-
- return MaxEggSize;
+ Pawn_GeneTracker genes = pawn.genes;
+ Gene_LifeForce gene_LifeForce = genes.GetFirstGeneOfType();
+ return gene_LifeForce;
}
+
+ public static void OffsetLifeForce(IGeneResourceDrain drain, float offset)
+ {
+ if (drain.Resource != null && drain.Resource.Active)
+ {
+ float old_value = drain.Resource.Value;
+ drain.Resource.Value += offset;
+ PostOffSetLifeForce(drain, old_value);
+ }
+ }
+
+ public static void PostOffSetLifeForce(IGeneResourceDrain drain, float old_value)
+ {
+
+ if (drain.Resource != null && drain.Resource.Active)
+ {
+ if (old_value > 0.2f && drain.Resource.Value <= 0.2f)
+ {
+ //TODO: Mood debuff
+ }
+ else if (old_value > 0f && drain.Resource.Value <= 0f)
+ {
+ Pawn pawn = drain.Pawn;
+ if (!drain.Pawn.health.hediffSet.HasHediff(HediffDefOf.rjw_genes_fertilin_craving))
+ {
+ drain.Pawn.health.AddHediff(HediffDefOf.rjw_genes_fertilin_craving);
+ }
+ }
+ }
+ }
+
+
+ public static bool HasLowLifeForce(Pawn pawn)
+ {
+ if (HasLifeForce(pawn))
+ {
+ Gene_LifeForce gene = pawn.genes.GetFirstGeneOfType();
+ if (gene == null || !gene.Active)
+ return false;
+ 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();
+ if (gene == null || !gene.Active)
+ return false;
+ if (gene.Resource.Value < gene.MinLevelForAlert)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
public static List GetGenitaliaResizingGenes(Pawn pawn)
{
var ResizingGenes = new List();
@@ -44,13 +108,19 @@ namespace RJW_Genes
return pawn.genes.HasGene(genedef);
}
+ public static bool HasLifeForce(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_lifeforce); }
public static bool IsMechbreeder(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_mechbreeder); }
public static bool IsYouthFountain(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_youth_fountain); }
public static bool IsAgeDrainer(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_sex_age_drain); }
public static bool IsElastic(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_elasticity); }
public static bool IsCumflationImmune(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_cumflation_immunity); }
public static bool IsGenerousDonor(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_generous_donor); }
+ public static bool IsPussyHealer(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_pussyhealing); }
public static bool IsUnbreakable(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_unbreakable); }
+ public static bool HasParalysingKiss(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_paralysingkiss); }
+ public static bool HasSeduce(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_seduce); }
+ public static bool IsSexualDrainer(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_drainer); }
+ public static bool IsCumEater(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_cum_eater); }
}
}
diff --git a/Source/Genes/Life_Force/Abilities/AbilityUtility.cs b/Source/Genes/Life_Force/Abilities/AbilityUtility.cs
new file mode 100644
index 0000000..77fba03
--- /dev/null
+++ b/Source/Genes/Life_Force/Abilities/AbilityUtility.cs
@@ -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 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.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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Genes/Life_Force/Abilities/CompAbilityEffect_CasterIsNaked.cs b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_CasterIsNaked.cs
new file mode 100644
index 0000000..aa1d61a
--- /dev/null
+++ b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_CasterIsNaked.cs
@@ -0,0 +1,59 @@
+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
+{
+ //Summary//
+ //Returns invalid if a pawn is not naked
+ //Summary//
+ public class CompAbilityEffect_CasterIsNaked : CompAbilityEffect_WithDest
+ {
+ private new CompProperties_CasterIsNaked Props
+ {
+ get
+ {
+ return (CompProperties_CasterIsNaked)this.props;
+ }
+ }
+
+ public override bool GizmoDisabled(out string reason)
+ {
+ Pawn pawn = this.CasterPawn;
+ if (pawn != null)
+ {
+ //Copied from ThoughtWorker_NudistNude.CurrentStateInternal
+ List wornApparel = pawn.apparel.WornApparel;
+ for (int i = 0; i < wornApparel.Count; i++)
+ {
+ Apparel apparel = wornApparel[i];
+ if (apparel.def.apparel.countsAsClothingForNudity)
+ {
+ for (int j = 0; j < apparel.def.apparel.bodyPartGroups.Count; j++)
+ {
+ if (apparel.def.apparel.bodyPartGroups[j] == BodyPartGroupDefOf.Torso)
+ {
+ reason = pawn.Name + " is not naked";
+ return true;
+ }
+ if (apparel.def.apparel.bodyPartGroups[j] == BodyPartGroupDefOf.Legs)
+ {
+ reason = pawn.Name + " is not naked";
+ return true;
+
+ }
+ }
+ }
+ }
+ }
+ reason = null;
+ return false;
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/Abilities/CompAbilityEffect_CockEater.cs b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_CockEater.cs
new file mode 100644
index 0000000..977c77b
--- /dev/null
+++ b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_CockEater.cs
@@ -0,0 +1,121 @@
+using Verse;
+using RimWorld;
+using rjw;
+
+namespace RJW_Genes
+{
+ ///
+ /// The CockEater Ability bites off the first found non-artifical cock of an target pawn.
+ /// It will restore {MINIMUM_LIFEFORCE_GAIN} multiplied by up to 2-times the Cock-Size.
+ /// Consuming a "towering" cock will give 2*{MINIMUM_LIFEFORCE_GAIN}, resulting in default 0.5f LifeForce.
+ /// This number is reduced for consuming animals by Settings.
+ ///
+ /// Balancing note: With the Cock-Eaters a drain of 0.08 is normal per day. This means 1 average cock should hold for 3-4 days of fertilin-fuel and half a day for an animal.
+ ///
+ public class CompAbilityEffect_CockEater : CompAbilityEffect
+ {
+ private new CompProperties_AbilityCockEater Props
+ {
+ get
+ {
+ return (CompProperties_AbilityCockEater)this.props;
+ }
+ }
+
+ public const float MINIMUM_LIFEFORCE_GAIN = 0.25f;
+
+ public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
+ {
+ base.Apply(target, dest);
+ Pawn CockBiter = this.parent.pawn;
+ Pawn CockBittenPawn = target.Pawn;
+ if (CockBittenPawn == null)
+ {
+ return;
+ }
+ var partBPR = Genital_Helper.get_genitalsBPR(CockBittenPawn);
+ var parts = Genital_Helper.get_PartsHediffList(CockBittenPawn, partBPR);
+ if (!parts.NullOrEmpty())
+ {
+ foreach (Hediff part in parts)
+ {
+ if (GenitaliaChanger.IsArtificial(part))
+ continue;
+
+ if (Genital_Helper.is_penis(part))
+ {
+ float gained_lifeforce = MINIMUM_LIFEFORCE_GAIN * (1 + part.Severity);
+ if (CockBittenPawn.IsAnimal())
+ {
+ gained_lifeforce *= RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor;
+ }
+ // Increase LifeForce for Biter
+ GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(CockBiter), gained_lifeforce);
+ // Handle Damage for Bitten
+ CockBittenPawn.TakeDamage(new DamageInfo(DamageDefOf.Bite, 99999f, 999f, hitPart: Genital_Helper.get_genitalsBPR(CockBittenPawn)));
+ //CockBittenPawn.health.RemoveHediff(part);
+ CockBittenPawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.rjw_genes_cock_eaten, CockBittenPawn, null);
+
+ //Only one penis at the time
+ break;
+ }
+ }
+ }
+ }
+
+ ///
+ /// For validity, there are a few checks:
+ /// 1. Target has Penis
+ /// 2. Target is either Colonist / Prisoner
+ /// 3. If the Target is an enemy, it must be downed.
+ ///
+ public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
+ {
+ Pawn CockBiteTarget = target.Pawn;
+ if (CockBiteTarget != null)
+ {
+ bool CockBiteTargetIsColonistOrPrisoner = CockBiteTarget.Faction == this.parent.pawn.Faction || CockBiteTarget.IsPrisonerOfColony;
+ bool CockBiteTargetIsHostile = CockBiteTarget.HostileTo(this.parent.pawn);
+ bool CockBiteTargetIsDowned = CockBiteTarget.Downed;
+
+ if (!CockBiteTargetIsColonistOrPrisoner && !(CockBiteTargetIsHostile && CockBiteTargetIsDowned))
+ {
+ if (throwMessages)
+ {
+ if(CockBiteTargetIsHostile && !CockBiteTargetIsDowned)
+ {
+ Messages.Message(CockBiteTarget.Name + " is hostile, but not downed.", CockBiteTarget, MessageTypeDefOf.RejectInput, false);
+ }
+ else if (!CockBiteTargetIsColonistOrPrisoner)
+ {
+ Messages.Message(CockBiteTarget.Name + " is not a part of the colony or hostile.", CockBiteTarget, MessageTypeDefOf.RejectInput, false);
+ }
+ }
+ return false;
+ }
+ if (!Genital_Helper.has_penis_fertile(CockBiteTarget))
+ {
+ if (throwMessages)
+ {
+ Messages.Message(CockBiteTarget.Name + " has no penis", CockBiteTarget, 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() : null;
+ if (gene_LifeForce == null)
+ {
+ reason = "AbilityDisabledNoFertilinGene".Translate(this.parent.pawn);
+ return true;
+ }
+ reason = null;
+ return false;
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/Abilities/CompAbilityEffect_LifeForceCost.cs b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_LifeForceCost.cs
new file mode 100644
index 0000000..44aec81
--- /dev/null
+++ b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_LifeForceCost.cs
@@ -0,0 +1,107 @@
+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() : 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;
+ }
+
+
+ }
+}
diff --git a/Source/Genes/Life_Force/Abilities/CompAbilityEffect_PussyHeal.cs b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_PussyHeal.cs
new file mode 100644
index 0000000..fdb0c7c
--- /dev/null
+++ b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_PussyHeal.cs
@@ -0,0 +1,95 @@
+using System.Collections.Generic;
+using Verse;
+using RimWorld;
+using rjw;
+
+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 tended wounds", 3.65f);
+ }
+ }
+
+ //Not yet implemented, but the heal should also trigger after normal sex
+ public void AfterSex(Pawn pawn, Pawn target)
+ {
+ List 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;
+ }
+ //TODO: Only make pawns targetable that have tendable wounds
+
+ }
+ 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;
+ }
+
+
+ }
+}
diff --git a/Source/Genes/Life_Force/Abilities/CompAbilityEffect_Seduce.cs b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_Seduce.cs
new file mode 100644
index 0000000..b8819a8
--- /dev/null
+++ b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_Seduce.cs
@@ -0,0 +1,90 @@
+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 (GeneUtility.HasSeduce(pawn))
+ {
+ if (throwMessages)
+ {
+ Messages.Message(pawn.Name + " cannot be seduced, as they also have the Seduce-Ability", 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;
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/Abilities/CompProperties_AbilityCockEater.cs b/Source/Genes/Life_Force/Abilities/CompProperties_AbilityCockEater.cs
new file mode 100644
index 0000000..b64b346
--- /dev/null
+++ b/Source/Genes/Life_Force/Abilities/CompProperties_AbilityCockEater.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using RimWorld;
+
+namespace RJW_Genes
+{
+ public class CompProperties_AbilityCockEater : CompProperties_AbilityEffect
+ {
+ public CompProperties_AbilityCockEater()
+ {
+ this.compClass = typeof(CompAbilityEffect_CockEater);
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/Abilities/CompProperties_AbilityLifeForceCost.cs b/Source/Genes/Life_Force/Abilities/CompProperties_AbilityLifeForceCost.cs
new file mode 100644
index 0000000..5a05d5f
--- /dev/null
+++ b/Source/Genes/Life_Force/Abilities/CompProperties_AbilityLifeForceCost.cs
@@ -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 ExtraStatSummary()
+ {
+ yield return "AbilityFertilinCost" + ": " + Mathf.RoundToInt(this.fertilinCost * 100f);
+ yield break;
+ }
+
+ // Token: 0x040038CD RID: 14541
+ public float fertilinCost;
+ }
+}
diff --git a/Source/Genes/Life_Force/Abilities/CompProperties_AbilityPussyHeal.cs b/Source/Genes/Life_Force/Abilities/CompProperties_AbilityPussyHeal.cs
new file mode 100644
index 0000000..16ba74d
--- /dev/null
+++ b/Source/Genes/Life_Force/Abilities/CompProperties_AbilityPussyHeal.cs
@@ -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;
+ }
+}
diff --git a/Source/Genes/Life_Force/Abilities/CompProperties_CasterIsNaked.cs b/Source/Genes/Life_Force/Abilities/CompProperties_CasterIsNaked.cs
new file mode 100644
index 0000000..8cb300e
--- /dev/null
+++ b/Source/Genes/Life_Force/Abilities/CompProperties_CasterIsNaked.cs
@@ -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
+{
+ public class CompProperties_CasterIsNaked : CompProperties_EffectWithDest
+ {
+ public CompProperties_CasterIsNaked()
+ {
+ this.compClass = typeof(CompAbilityEffect_CasterIsNaked);
+ }
+ }
+}
+
diff --git a/Source/Genes/Life_Force/Abilities/CompProperties_Seduce.cs b/Source/Genes/Life_Force/Abilities/CompProperties_Seduce.cs
new file mode 100644
index 0000000..21e0cde
--- /dev/null
+++ b/Source/Genes/Life_Force/Abilities/CompProperties_Seduce.cs
@@ -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;
+ }
+}
+
diff --git a/Source/Genes/Life_Force/Defs/LifeForceEmpathExtension.cs b/Source/Genes/Life_Force/Defs/LifeForceEmpathExtension.cs
new file mode 100644
index 0000000..ccc037b
--- /dev/null
+++ b/Source/Genes/Life_Force/Defs/LifeForceEmpathExtension.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace RJW_Genes
+{
+ public class LifeForceEmpathExtension : DefModExtension
+ {
+ public float aheagoIncrement;
+ public float satisfactionIncrement;
+ public float frustratedDecrement;
+ }
+}
diff --git a/Source/Genes/Life_Force/Genes/Gene_LifeForce.cs b/Source/Genes/Life_Force/Genes/Gene_LifeForce.cs
new file mode 100644
index 0000000..8cac6b3
--- /dev/null
+++ b/Source/Genes/Life_Force/Genes/Gene_LifeForce.cs
@@ -0,0 +1,140 @@
+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(ref this.StoredCumAllowed, "StoredCumAllowed", true, false);
+ }
+
+ public bool ShouldConsumeLifeForceNow()
+ {
+ return this.Value < this.targetValue;
+ }
+
+ //Same as Gene_Hemogen
+ public override IEnumerable GetGizmos()
+ {
+ foreach (Gizmo gizmo in base.GetGizmos())
+ {
+ yield return gizmo;
+ }
+ yield break;
+ }
+
+ //every tick it decreases fertilin value and everyday if fertilin is below alert minimum there a ~50 chance for mental break
+ public override void Tick()
+ {
+ base.Tick();
+ if (this.CanOffset && this.Resource != null)
+ {
+ GeneUtility.OffsetLifeForce(this, -this.ResourceLossPerDay / 60000f);
+
+ }
+
+ }
+
+ 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;
+ }
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/Genes/Gene_LifeForceDrain.cs b/Source/Genes/Life_Force/Genes/Gene_LifeForceDrain.cs
new file mode 100644
index 0000000..c50dae5
--- /dev/null
+++ b/Source/Genes/Life_Force/Genes/Gene_LifeForceDrain.cs
@@ -0,0 +1,68 @@
+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();
+ }
+ 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);
+ }
+ }
+
+ [Unsaved(false)]
+ private Gene_LifeForce cachedLifeForceGene;
+
+ private const float MinAgeForDrain = 3f;
+ }
+}
diff --git a/Source/Genes/Life_Force/Genes/Gene_LifeForce_Empath.cs b/Source/Genes/Life_Force/Genes/Gene_LifeForce_Empath.cs
new file mode 100644
index 0000000..e355fb4
--- /dev/null
+++ b/Source/Genes/Life_Force/Genes/Gene_LifeForce_Empath.cs
@@ -0,0 +1,118 @@
+using System.Collections.Generic;
+using Verse;
+using RimWorld;
+
+namespace RJW_Genes
+{
+ public class Gene_LifeForce_Empath : Gene
+ {
+
+ const int EMPATH_DISTANCE_FALLBACK = 25;
+ const int TICK_INTERVAL_FALLBACK = 60000 / 48;
+
+ const float AHEAGO_FALLBACK = 0.02f, SATISFIED_FALLBACK = 0.01f, FRUSTRATED_FALLBACK = -0.01f;
+
+ int empathDistance = 25;
+ int tickInterval = 60000 / 48 ; // 60k = 1 day, we want 0.5h which is 1/48th of 1 day.
+
+ float aheagoIncrement = 0.02f;
+ float satisfiedIncrement = 0.01f;
+ float frustratedDecrement = -0.01f;
+
+
+ public Gene_LifeForce_Empath() : base()
+ {
+ SetValuesFromExtension();
+ }
+
+ private void SetValuesFromExtension()
+ {
+ LifeForceEmpathExtension empathExt = GeneDefOf.rjw_genes_lifeforce_empath.GetModExtension();
+
+ tickInterval = ModExtensionHelper.GetTickIntervalFromModExtension(GeneDefOf.rjw_genes_lifeforce_empath, TICK_INTERVAL_FALLBACK);
+ empathDistance = ModExtensionHelper.GetTickIntervalFromModExtension(GeneDefOf.rjw_genes_lifeforce_empath, EMPATH_DISTANCE_FALLBACK);
+
+ aheagoIncrement = empathExt?.aheagoIncrement ?? AHEAGO_FALLBACK;
+ satisfiedIncrement = empathExt?.satisfactionIncrement ?? SATISFIED_FALLBACK;
+ frustratedDecrement = empathExt?.frustratedDecrement ?? FRUSTRATED_FALLBACK;
+ }
+
+ public override void Tick()
+ {
+ base.Tick();
+ if (this.pawn.IsHashIntervalTick(tickInterval) && this.pawn.Map != null)
+ {
+ foreach (Pawn pawn in this.AffectedPawns(this.pawn.Position, this.pawn.Map))
+ {
+ this.FarmLifeForce(pawn);
+ }
+
+ }
+ }
+
+ ///
+ /// Creates an IEnumerable of all pawns which are closeby and in lineofsight, self and other pawns with lifeforce gene are skipped (to prevent loops).
+ ///
+ /// The position of the empath on the map
+ /// The map the empath is on
+ /// A list of all pawns that are close enough for the empath to connect.
+ private IEnumerable AffectedPawns(IntVec3 pos, Map map)
+ {
+ foreach (Pawn pawn in map.mapPawns.AllPawns)
+ {
+ // Return for trivial errors
+ if (pawn == null || this.pawn == null || pawn == this.pawn)
+ continue;
+ // Check for position-existance
+ if (pawn.Position == null || pos == null || pawn.Map == null)
+ continue;
+ // Do nothing if pawn is carried
+ if (pawn.CarriedBy != null)
+ continue;
+ // Do nothing if Pawn is Baby or Child (#25)
+ if (!pawn.ageTracker.Adult)
+ continue;
+ // Do nothing for pawns that also have lifeforce
+ if (GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_lifeforce))
+ continue;
+
+ // Actual Logic:
+ // Pawn qualifies in right distance and needs line of sight.
+ if (pos.DistanceTo(pawn.Position) < empathDistance && GenSight.LineOfSight(pos, pawn.Position, pawn.Map))
+ {
+ yield return pawn;
+ }
+ }
+
+ yield break;
+ }
+
+ ///
+ /// Adjust the empaths lifeforce depending on the farmed pawns sexneed.
+ ///
+ /// The pawn affecting the empath, increasing or decreasing his lifeforce.
+ private void FarmLifeForce(Pawn farmedPawn)
+ {
+ // Short rename to make rest more obvious.
+ Pawn empath = pawn;
+
+ if (farmedPawn == null)
+ return;
+
+ var sexneed = farmedPawn.needs.TryGetNeed();
+
+ // Shortwire: do nothing on no sexneed.
+ if (sexneed == null)
+ return;
+
+ if (sexneed.CurLevel >= sexneed.thresh_ahegao())
+ GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(empath), aheagoIncrement);
+ else if (sexneed.CurLevel >= sexneed.thresh_satisfied())
+ GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(empath), satisfiedIncrement);
+ else if (sexneed.CurLevel <= sexneed.thresh_frustrated())
+ GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(empath), frustratedDecrement);
+
+ }
+
+ }
+}
diff --git a/Source/Genes/Life_Force/HediffCompProperties_SeverityFromFertilin.cs b/Source/Genes/Life_Force/HediffCompProperties_SeverityFromFertilin.cs
new file mode 100644
index 0000000..558c3e0
--- /dev/null
+++ b/Source/Genes/Life_Force/HediffCompProperties_SeverityFromFertilin.cs
@@ -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 HediffCompProperties_SeverityFromFertilin : HediffCompProperties
+ {
+ public HediffCompProperties_SeverityFromFertilin()
+ {
+ this.compClass = typeof(HediffComp_SeverityFromFertilin);
+ }
+
+ // Token: 0x04001162 RID: 4450
+ public float severityPerHourEmpty;
+
+ // Token: 0x04001163 RID: 4451
+ public float severityPerHourHemogen;
+ }
+}
diff --git a/Source/Genes/Life_Force/HediffComp_SeverityFromFertilin.cs b/Source/Genes/Life_Force/HediffComp_SeverityFromFertilin.cs
new file mode 100644
index 0000000..4b8b3a7
--- /dev/null
+++ b/Source/Genes/Life_Force/HediffComp_SeverityFromFertilin.cs
@@ -0,0 +1,66 @@
+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 HediffComp_SeverityFromFertilin : HediffComp
+ {
+ public HediffCompProperties_SeverityFromFertilin Props
+ {
+ get
+ {
+ return (HediffCompProperties_SeverityFromFertilin)this.props;
+ }
+ }
+ public override bool CompShouldRemove
+ {
+ get
+ {
+ Pawn_GeneTracker genes = base.Pawn.genes;
+ return ((genes != null) ? genes.GetFirstGeneOfType() : null) == null;
+ }
+ }
+ private Gene_LifeForce LifeForce
+ {
+ get
+ {
+ if (this.cachedLifeForceGene == null)
+ {
+ this.cachedLifeForceGene = base.Pawn.genes.GetFirstGeneOfType();
+ }
+ return this.cachedLifeForceGene;
+ }
+ }
+ public override void CompPostTick(ref float severityAdjustment)
+ {
+ base.CompPostTick(ref severityAdjustment);
+ severityAdjustment += ((this.LifeForce.Value > 0f) ? this.Props.severityPerHourHemogen : this.Props.severityPerHourEmpty) / 2500f;
+ this.MentalBreak();
+ }
+
+ public void MentalBreak()
+ {
+ if (cachedLifeForceGene.Resource.Value <= cachedLifeForceGene.Resource.MinLevelForAlert && this.Pawn.IsHashIntervalTick(2500) && Rand.Chance(0.03f)) //~50% chance each day for mental break
+ {
+ if (this.Pawn.genes.HasGene(GeneDefOf.rjw_genes_cum_eater)
+ || this.Pawn.genes.HasGene(GeneDefOf.rjw_genes_fertilin_absorber) || this.Pawn.genes.HasGene(GeneDefOf.rjw_genes_drainer))
+ {
+ //TODO: use mentalstatedef instead of mentalbreakdef
+ MentalBreakDef randomrape = GeneDefOf.rjw_genes_lifeforce_randomrape;
+ if (ModsConfig.BiotechActive &&
+ this.Pawn.Spawned && !this.Pawn.InMentalState && !this.Pawn.Downed &&
+ randomrape.Worker.BreakCanOccur(this.Pawn))
+ {
+ randomrape.Worker.TryStart(this.Pawn, "MentalBreakNoFertilin".Translate(), false);
+ }
+ }
+ }
+ }
+
+ private Gene_LifeForce cachedLifeForceGene;
+ }
+}
diff --git a/Source/Genes/Life_Force/IngestionOutcomeDoer_LifeForceOffset.cs b/Source/Genes/Life_Force/IngestionOutcomeDoer_LifeForceOffset.cs
new file mode 100644
index 0000000..feae482
--- /dev/null
+++ b/Source/Genes/Life_Force/IngestionOutcomeDoer_LifeForceOffset.cs
@@ -0,0 +1,24 @@
+using RimWorld;
+using Verse;
+
+namespace RJW_Genes
+{
+ ///
+ /// This class checks for pawns with LifeForce and Cumeater Gene to add Fertilin when eating cum (the Item from RJW-Sexperience).
+ ///
+ public class IngestionOutcomeDoer_LifeForceOffset : IngestionOutcomeDoer
+ {
+ public const float DEFAULT_FERTILIN_PER_UNIT = 1f;
+ public float FertilinPerUnit = 1f;
+
+ protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested, int ingestedCount)
+ {
+ if (GeneUtility.HasLifeForce(pawn) && GeneUtility.IsCumEater(pawn))
+ {
+ float num = ingestedCount * this.FertilinPerUnit / 100;
+ GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(pawn), num);
+ }
+ }
+
+ }
+}
diff --git a/Source/Genes/Life_Force/JobDrivers/JobDriver_CastAbilityAfterSex.cs b/Source/Genes/Life_Force/JobDrivers/JobDriver_CastAbilityAfterSex.cs
new file mode 100644
index 0000000..d604cca
--- /dev/null
+++ b/Source/Genes/Life_Force/JobDrivers/JobDriver_CastAbilityAfterSex.cs
@@ -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 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;
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/JobDrivers/JobDriver_Flirt.cs b/Source/Genes/Life_Force/JobDrivers/JobDriver_Flirt.cs
new file mode 100644
index 0000000..337a9b2
--- /dev/null
+++ b/Source/Genes/Life_Force/JobDrivers/JobDriver_Flirt.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using Verse.AI;
+using RimWorld;
+using rjw;
+namespace RJW_Genes
+{
+ public class JobDriver_Flirt : JobDriver
+ {
+ private Pawn Target
+ {
+ get
+ {
+ return (Pawn)((Thing)this.pawn.CurJob.GetTarget(TargetIndex.A));
+ }
+ }
+ public override bool TryMakePreToilReservations(bool errorOnFailed)
+ {
+ return true;
+ }
+
+ //Some wait toils to induce delay
+ protected override IEnumerable MakeNewToils()
+ {
+ this.FailOnDespawnedOrNull(TargetIndex.A);
+ yield return Toils_Interpersonal.GotoInteractablePosition(TargetIndex.A);
+ yield return Toils_General.Wait(300, TargetIndex.A);
+ yield return Toils_Interpersonal.WaitToBeAbleToInteract(this.pawn);
+ Toil toil = Toils_Interpersonal.GotoInteractablePosition(TargetIndex.A);
+ toil.socialMode = RandomSocialMode.Off;
+ yield return toil;
+ yield return this.InteractToil();
+ Toil toil1 = Toils_General.Wait(300, TargetIndex.A);
+ toil1.socialMode = RandomSocialMode.Off;
+ yield return toil1;
+ yield break;
+ }
+ private Toil InteractToil()
+ {
+ return Toils_General.Do(delegate
+ {
+ if (this.pawn.interactions.TryInteractWith(this.Target, ThoughtDefOf.rjw_genes_flirt))
+ {
+ Need_Sex need_Sex = this.Target.needs.TryGetNeed();
+ need_Sex.CurLevel += -0.01f;
+ }
+ });
+ }
+
+ private const TargetIndex TargetInd = TargetIndex.A;
+ }
+}
+
diff --git a/Source/Genes/Life_Force/JobDrivers/JobDriver_Seduced.cs b/Source/Genes/Life_Force/JobDrivers/JobDriver_Seduced.cs
new file mode 100644
index 0000000..2d38d75
--- /dev/null
+++ b/Source/Genes/Life_Force/JobDrivers/JobDriver_Seduced.cs
@@ -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 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);
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/JobDrivers/JobDriver_SexOnSpot.cs b/Source/Genes/Life_Force/JobDrivers/JobDriver_SexOnSpot.cs
new file mode 100644
index 0000000..05c9d5b
--- /dev/null
+++ b/Source/Genes/Life_Force/JobDrivers/JobDriver_SexOnSpot.cs
@@ -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 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;
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/JobDrivers/JobDriver_SexOnSpotReceiver.cs b/Source/Genes/Life_Force/JobDrivers/JobDriver_SexOnSpotReceiver.cs
new file mode 100644
index 0000000..82967d6
--- /dev/null
+++ b/Source/Genes/Life_Force/JobDrivers/JobDriver_SexOnSpotReceiver.cs
@@ -0,0 +1,80 @@
+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 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;
+ }
+
+ 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
+ {
+
+ 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;
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/JobGivers/JobGiver_Flirt.cs b/Source/Genes/Life_Force/JobGivers/JobGiver_Flirt.cs
new file mode 100644
index 0000000..a629e0e
--- /dev/null
+++ b/Source/Genes/Life_Force/JobGivers/JobGiver_Flirt.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using Verse.AI;
+using RimWorld;
+namespace RJW_Genes
+{
+ public class JobGiver_Flirt : ThinkNode_JobGiver
+ {
+ // Token: 0x0600405A RID: 16474 RVA: 0x0017271C File Offset: 0x0017091C
+ protected override Job TryGiveJob(Pawn pawn)
+ {
+ Pawn target = pawn.mindState.duty.focus.Pawn;
+ if (pawn.CanReach(target, PathEndMode.InteractionCell, Danger.Deadly) && !target.jobs.curDriver.asleep)
+ {
+ return JobMaker.MakeJob(JobDefOf.rjw_genes_flirt, target);
+ }
+ return null;
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/JobGivers/JobGiver_GetLifeForce.cs b/Source/Genes/Life_Force/JobGivers/JobGiver_GetLifeForce.cs
new file mode 100644
index 0000000..fdd7279
--- /dev/null
+++ b/Source/Genes/Life_Force/JobGivers/JobGiver_GetLifeForce.cs
@@ -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() : null;
+ if (gene_lifeforce == null)
+ {
+ return null;
+ }
+ if (!gene_lifeforce.ShouldConsumeLifeForceNow())
+ {
+ return null;
+ }
+
+
+ if (ModsConfig.IsActive("rjw.sexperience") && gene_lifeforce.StoredCumAllowed && genes.HasGene(GeneDefOf.rjw_genes_cum_eater))
+ {
+ 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_LifeForceOffset.DEFAULT_FERTILIN_PER_UNIT);
+ 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() : 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);
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/JobGivers/JobGiver_LifeForce_RandomRape.cs b/Source/Genes/Life_Force/JobGivers/JobGiver_LifeForce_RandomRape.cs
new file mode 100644
index 0000000..f710c62
--- /dev/null
+++ b/Source/Genes/Life_Force/JobGivers/JobGiver_LifeForce_RandomRape.cs
@@ -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)))));
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/JobGivers/JobGiver_TryQuickieWith.cs b/Source/Genes/Life_Force/JobGivers/JobGiver_TryQuickieWith.cs
new file mode 100644
index 0000000..6c17b75
--- /dev/null
+++ b/Source/Genes/Life_Force/JobGivers/JobGiver_TryQuickieWith.cs
@@ -0,0 +1,175 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using rjw;
+using RJWSexperience;
+using RimWorld;
+using Verse;
+using Verse.AI;
+using Verse.AI.Group;
+using UnityEngine;
+namespace RJW_Genes
+{
+ public class JobGiver_TryQuickieWith : ThinkNode_JobGiver
+ {
+ protected override Job TryGiveJob(Pawn pawn)
+ {
+ Pawn target = pawn.mindState.duty.focus.Pawn;
+ Pawn_JobTracker jobs = target.jobs;
+ string pawn_name = xxx.get_pawnname(pawn);
+ string target_name = xxx.get_pawnname(target);
+ //can reserve eachother
+ if (pawn.CanReserveAndReach(target, PathEndMode.InteractionCell, Danger.Some) && target.CanReserve(pawn, 1, 0, null, false))
+ {
+ //Dont interrupt player
+ if (!(((jobs != null) ? jobs.curJob : null) != null && jobs.curJob.playerForced))
+ {
+ float willingness = TargetWillingness(pawn, target);
+ if (Rand.Chance(willingness))
+ {
+ Job newJob =JobMaker.MakeJob(xxx.quick_sex, target);
+
+
+ return newJob;
+ }
+ else
+ {
+ if (RJWSettings.DebugLogJoinInBed) //change this when we have our own settigns
+ {
+ ModLog.Message(string.Format("{0} was not interested in having sex with {1}: ({2} chance)", pawn_name, target_name, willingness));
+ }
+ }
+ }
+ else
+ {
+ if (RJWSettings.DebugLogJoinInBed) //change this when we have our own settigns
+ {
+ //ModLog.Message(string.Format(" find_pawn_to_fuck({0}): lover has important job ({1}), skipping", pawn_name, target.jobs.curJob.def));
+ }
+ }
+ }
+ else
+ {
+ if (RJWSettings.DebugLogJoinInBed) //change this when we have our own settigns
+ {
+ ModLog.Message(" (" + pawn_name + "): cannot reach or reserve " + target_name);
+ }
+ }
+ return null;
+ }
+ public static float TargetWillingness(Pawn pawn, Pawn target)
+ {
+ string pawn_name = xxx.get_pawnname(pawn);
+ float willingness = SexAppraiser.would_fuck(target,pawn);
+ bool nymph = xxx.is_nympho(target);
+ bool loverelation = LovePartnerRelationUtility.LovePartnerRelationExists(pawn, target);
+ if (nymph || loverelation)
+ {
+ willingness *= 2;
+ }
+ if (xxx.HasNonPolyPartner(pawn, false) && !loverelation)
+ {
+ if (RJWHookupSettings.NymphosCanCheat && nymph && xxx.is_frustrated(pawn))
+ {
+ if (RJWSettings.DebugLogJoinInBed)
+ {
+ ModLog.Message(" find_partner(" + pawn_name + "): I'm a nympho and I'm so frustrated that I'm going to cheat");
+ }
+ }
+ else
+ {
+ if (!pawn.health.hediffSet.HasHediff(HediffDef.Named("AlcoholHigh"), false))
+ {
+ if (RJWSettings.DebugLogJoinInBed)
+ {
+ ModLog.Message(" find_partner(" + pawn_name + "): I interested in banging but that's cheating");
+ }
+ //Succubus has a small chance to seduce even if target is in relationship
+ willingness *= 0.1f;
+ }
+ else
+ {
+ if (RJWSettings.DebugLogJoinInBed)
+ {
+ ModLog.Message(" find_partner(" + pawn_name + "): I want to bang and im too drunk to care if its cheating");
+ }
+ //No change
+ }
+ }
+ }
+ return willingness;
+ }
+
+ public static float JoinChance(Pawn pawn ,Pawn target)
+ {
+
+ float chance = 0.1f;
+
+ //Sex satisfaction, how good the target is at sex
+ chance *= xxx.get_sex_satisfaction(target);
+
+ //Succubus mood
+ if (pawn.needs != null && pawn.needs.mood != null)
+ {
+ chance *= pawn.needs.mood.CurLevelPercentage + 0.5f;
+ }
+
+ //Size of genitals
+ bool size_matters = true; //To be placed in modsettings
+ if (size_matters)
+ {
+ //The larger the penis to greater the chance
+ if (RelationsUtility.AttractedToGender(pawn, Gender.Male))
+ {
+ chance *= GetGenitalSize(target, true) + 0.5f;
+ }
+
+ //The tighter the vagine the greater the chance, a size above 1 is considered as 1
+ if (RelationsUtility.AttractedToGender(pawn, Gender.Female))
+ {
+ chance *= 1f - Mathf.Min(GetGenitalSize(target, false),1f) + 0.5f;
+ }
+ }
+
+ //Sex ability from sexperience
+ if (ModsConfig.IsActive("rjw.sexperience"))
+ {
+ chance *= RJWSexperience.PawnExtensions.GetSexStat(pawn);
+ }
+ return Mathf.Max(chance,0f);
+ }
+
+ //Gets the size of the largest penis or the tightest vagina
+ public static float GetGenitalSize(Pawn pawn, bool penis_else_vagina)
+ {
+ List genitals = rjw.PawnExtensions.GetGenitalsList(pawn);
+ if(!genitals.NullOrEmpty())
+ {
+ if (penis_else_vagina)
+ {
+ List penises = genitals.Where(genital => Genital_Helper.is_penis(genital)).ToList();
+ {
+ if (!penises.NullOrEmpty())
+ {
+ return penises.Max(genital => genital.Severity);
+ }
+ }
+ }
+ else
+ {
+ List vaginas = genitals.Where(genital => Genital_Helper.is_vagina(genital)).ToList();
+ {
+ if (!vaginas.NullOrEmpty())
+ {
+ return vaginas.Min(genital => genital.Severity);
+ }
+ }
+ }
+ }
+ return 0f;
+
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/LordToil_Flirt.cs b/Source/Genes/Life_Force/LordToil_Flirt.cs
new file mode 100644
index 0000000..0bd1e38
--- /dev/null
+++ b/Source/Genes/Life_Force/LordToil_Flirt.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using Verse.AI;
+using Verse.AI.Group;
+using RimWorld;
+namespace RJW_Genes
+{
+ //Based on LordToil_EscortPawn
+ public class LordToil_Flirt : LordToil
+ {
+ public LordToil_Flirt(Pawn victim, float followRadius)
+ {
+ this.victim = victim;
+ this.followRadius = followRadius;
+ }
+
+
+ public override void UpdateAllDuties()
+ {
+ for (int i = 0; i < this.lord.ownedPawns.Count; i++)
+ {
+ PawnDuty duty = new PawnDuty(GeneDefOf.rjw_genes_flirt, this.victim, this.followRadius);
+ this.lord.ownedPawns[i].mindState.duty = duty;
+ }
+ }
+
+ public Pawn victim;
+ public float followRadius;
+ }
+}
diff --git a/Source/Genes/Life_Force/MentalStates/LifeForceMentalBreakWorker.cs b/Source/Genes/Life_Force/MentalStates/LifeForceMentalBreakWorker.cs
new file mode 100644
index 0000000..36b47b0
--- /dev/null
+++ b/Source/Genes/Life_Force/MentalStates/LifeForceMentalBreakWorker.cs
@@ -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();
+ if( gene.Resource.Value <= 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/MentalStates/LifeForceMentalState.cs b/Source/Genes/Life_Force/MentalStates/LifeForceMentalState.cs
new file mode 100644
index 0000000..9c22f4e
--- /dev/null
+++ b/Source/Genes/Life_Force/MentalStates/LifeForceMentalState.cs
@@ -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();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Genes/Life_Force/MentalStates/LifeForceMentalStateWorker.cs b/Source/Genes/Life_Force/MentalStates/LifeForceMentalStateWorker.cs
new file mode 100644
index 0000000..eaeaf89
--- /dev/null
+++ b/Source/Genes/Life_Force/MentalStates/LifeForceMentalStateWorker.cs
@@ -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));
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/Patches/Patch_SatisfyPersonal_LifeForceGain.cs b/Source/Genes/Life_Force/Patches/Patch_SatisfyPersonal_LifeForceGain.cs
new file mode 100644
index 0000000..6ea0a62
--- /dev/null
+++ b/Source/Genes/Life_Force/Patches/Patch_SatisfyPersonal_LifeForceGain.cs
@@ -0,0 +1,203 @@
+using HarmonyLib;
+using rjw;
+using RimWorld;
+using Verse;
+
+namespace RJW_Genes
+{
+ ///
+ /// This Patch hooks after "SatisfyPersonal"(i.E. when the pawn finished fucking) and covers LifeForceGain.
+ /// If the pawn has LifeForce, all relevant Genes are checked and applied.
+ ///
+ [HarmonyPatch(typeof(SexUtility), nameof(SexUtility.SatisfyPersonal))]
+ public static class Patch_SatisfyPersonal_LifeForceGain
+ {
+ public const float LIFEFORCE_GAINED_FROM_DRAINER_GENE = 0.25f;
+
+ 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 PawnWithLifeForce = props.partner;
+
+ if (!props.isRevese)
+ {
+ if (props.isReceiver)
+ {
+ // Scenario Dom Succubus, normal
+ absorb_factor = BaseDom(props, PawnWithLifeForce);
+ }
+ else
+ {
+ // Scenario Sub Succubus, normal
+ absorb_factor = BaseSub(props, PawnWithLifeForce);
+ }
+ }
+ else
+ {
+ if (props.isReceiver)
+ {
+ // Scenario Dom Succubus, Reverse
+ absorb_factor = BaseSub(props, PawnWithLifeForce);
+ }
+ else
+ {
+ // Scenario Sub Succubus, Reverse
+ absorb_factor = BaseDom(props, PawnWithLifeForce);
+ }
+ }
+
+ // If we remove this check fertilin is always lost, but the succubus doesn't always gain any
+ if (absorb_factor != 0f)
+ {
+ TransferFertilin(props, absorb_factor);
+ }
+
+ // Handle Gene: Sexual_Drainer
+ // to be drained, a pawn must not-be-drained-already and drainers cannot be drained either.
+ if (GeneUtility.IsSexualDrainer(PawnWithLifeForce)
+ && !props.pawn.health.hediffSet.HasHediff(HediffDefOf.rjw_genes_succubus_drained)
+ && !GeneUtility.IsSexualDrainer(props.pawn))
+ {
+ if (GeneUtility.IsGenerousDonor(props.pawn) && RJW_Genes_Settings.rjw_genes_generous_donor_cheatmode)
+ {
+ // Cheatmode is on, do not drain but give life
+ GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(PawnWithLifeForce), LIFEFORCE_GAINED_FROM_DRAINER_GENE);
+ if (RJW_Genes_Settings.rjw_genes_detailed_debug)
+ ModLog.Message($"{props.pawn.Name} was not (sexually) drained by {PawnWithLifeForce.Name}, because Cheatmode for Generous Donors is on");
+ } else
+ {
+ if (RJW_Genes_Settings.rjw_genes_detailed_debug)
+ ModLog.Message($"{props.pawn.Name} has been (sexually) drained by {PawnWithLifeForce.Name}");
+ props.pawn.health.AddHediff(HediffDefOf.rjw_genes_succubus_drained);
+ GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(PawnWithLifeForce), LIFEFORCE_GAINED_FROM_DRAINER_GENE);
+ }
+ }
+ }
+ }
+
+ public static void TransferFertilin(SexProps props, float absorb_percentage = 1f)
+ {
+ Pawn_GeneTracker genes = props.partner.genes;
+ Gene_LifeForce gene = genes.GetFirstGeneOfType();
+
+ Hediff fertilin_lost = props.pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.rjw_genes_fertilin_lost);
+ //Around quarter get ejected everytime pawn cums
+ float multiplier = Rand.Range(0.10f, 0.40f);
+
+ if (GeneUtility.IsGenerousDonor(props.pawn) && RJW_Genes_Settings.rjw_genes_generous_donor_cheatmode)
+ {
+ // Do nothing, Cheatmode is on
+ multiplier = 1;
+ }
+ else
+ {
+ //Create a new ferilin_lost hediff or increase it
+ if (fertilin_lost == null)
+ {
+ Hediff new_fertilin_lost = HediffMaker.MakeHediff(HediffDefOf.rjw_genes_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;
+ }
+ }
+
+ multiplier *= absorb_percentage;
+ //Currently taking the sum of all penises, maybe I should just consider one at random
+ float valuechange = TotalFertilinAmount(props, multiplier);
+
+ if (props.partner.IsAnimal())
+ {
+ if (RJW_Genes_Settings.rjw_genes_detailed_debug)
+ ModLog.Message($"Fertilin-Source of {props.pawn.Name} was an Animal, Fertilin-Gain is being adjusted by {RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor}%");
+ valuechange *= RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor;
+ }
+
+ GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(props.partner), valuechange);
+ }
+
+ public static float TotalFertilinAmount(SexProps props, float multiplier)
+ {
+ float total_fluid = CumUtility.GetTotalFluidAmount(props.pawn) / 100;
+
+ //More in the tank means more to give
+ if (props.pawn.Has(Quirk.Messy))
+ {
+ total_fluid *= 2;
+ }
+ if (props.pawn.RaceProps.Animal)
+ {
+ total_fluid *= 0.1f; //Should make this settable in settings
+ }
+
+ return total_fluid;
+ }
+
+ ///
+ /// Handles the Case that the Life-Force wielder initiated the Sex (They are "Dom").
+ ///
+ /// The summary of the sex act, used for checking conditions.
+ /// The pawn that might gain LifeForce through this method.
+ /// A factor between 0 and 1 how much of output-fertilin will be used for input-lifeforce
+ public static float BaseDom(SexProps props, Pawn PawnWithLifeForce)
+ {
+ float absorb_factor = 0f;
+ if (props.sexType == xxx.rjwSextype.Sixtynine && GeneUtility.IsCumEater(PawnWithLifeForce))
+ {
+ absorb_factor += 1f;
+ }
+ return absorb_factor;
+ }
+
+ ///
+ /// Handles the Case that the Life-Force wielder got initiated into sex (They are "Sub").
+ ///
+ /// The summary of the sex act, used for checking conditions.
+ /// The pawn that might gain LifeForce through this method.
+ /// A factor between 0 and 1 how much of output-fertilin will be used for input-lifeforce
+ public static float BaseSub(SexProps props, Pawn PawnWithLifeForce)
+ {
+ float absorb_factor = 0f;
+ if ((props.sexType == xxx.rjwSextype.Oral || props.sexType == xxx.rjwSextype.Fellatio || props.sexType == xxx.rjwSextype.Sixtynine)
+ && GeneUtility.IsCumEater(PawnWithLifeForce))
+ {
+ absorb_factor += 1f;
+ }
+ else if (props.sexType == xxx.rjwSextype.Vaginal && GeneUtility.HasGeneNullCheck(PawnWithLifeForce, GeneDefOf.rjw_genes_fertilin_absorber))
+ {
+ absorb_factor += 1f;
+ }
+ else if (props.sexType == xxx.rjwSextype.Anal && GeneUtility.HasGeneNullCheck(PawnWithLifeForce, GeneDefOf.rjw_genes_fertilin_absorber))
+ {
+ absorb_factor += 1f;
+ }
+ else if (props.sexType == xxx.rjwSextype.DoublePenetration && GeneUtility.HasGeneNullCheck(PawnWithLifeForce, GeneDefOf.rjw_genes_fertilin_absorber))
+ {
+ absorb_factor += 1f;
+ }
+ else if (props.sexType == xxx.rjwSextype.Scissoring || props.sexType == xxx.rjwSextype.Cunnilingus)
+ {
+ //with vaginal cum absorbtion
+ //absorb_factor += 1f;
+ }
+ return absorb_factor;
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/Patches/Patch_SexTicks_ChangePsyfocus.cs b/Source/Genes/Life_Force/Patches/Patch_SexTicks_ChangePsyfocus.cs
new file mode 100644
index 0000000..dfc359b
--- /dev/null
+++ b/Source/Genes/Life_Force/Patches/Patch_SexTicks_ChangePsyfocus.cs
@@ -0,0 +1,62 @@
+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
+{
+
+ ///
+ /// This patch enables cum-eater pawns to drain cumflations for more fertilin drain by passively having sex.
+ /// It is hooked after RJWs Change-Psyfocus so that pawns that are having prolonged sex (e.g. by overdrive) can fully drain the cumflation over time.
+ ///
+ /// It is conditionally loaded only when LicentiaLabs is enabled, as this is the necessary source for cumflation-hediffs.
+ /// The patched function is: [HarmonyPatch(typeof(JobDriver_Sex), nameof(JobDriver_Sex.ChangePsyfocus))]
+ ///
+ public static class Patch_SexTicks_ChangePsyfocus
+ {
+ public const float LIFEFORCE_GAIN_PER_TICK = 0.05f;
+ public const float CUMFLATION_SEVERITY_LOSS_PER_TICK = 0.1f;
+
+ //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)
+ {
+ SexProps props = __instance.Sexprops;
+ if (props != null && props.sexType == xxx.rjwSextype.Cunnilingus && props.partner != null && target != null)
+ {
+ Pawn pawn2 = target as Pawn;
+ // Case 1: Pawn is "drinking" and has CumEater Gene
+ if (props.isRevese && GeneUtility.IsCumEater(pawn))
+ {
+ if (RJW_Genes_Settings.rjw_genes_detailed_debug)
+ ModLog.Message($"{pawn.Name} is draining {pawn2.Name}'s cumflation for additional fertilin (CumEater-Gene ChangePsyFocus-Trigger).");
+ DrinkCumflation(pawn2, pawn);
+ }
+ // Case 2: Pawn2 is "drinking" and has CumEater Gene
+ else if (GeneUtility.IsCumEater(pawn2))
+ {
+ if (RJW_Genes_Settings.rjw_genes_detailed_debug)
+ ModLog.Message($"{pawn.Name} is draining {pawn2.Name}'s cumflation for additional fertilin (CumEater-Gene ChangePsyFocus-Trigger).");
+ DrinkCumflation(pawn, pawn2);
+ }
+ }
+ }
+
+ public static void DrinkCumflation(Pawn source, Pawn consumer)
+ {
+ if (GeneUtility.HasLifeForce(consumer) && GeneUtility.IsCumEater(consumer)
+ && source.health.hediffSet.HasHediff(HediffDef.Named("Cumflation")))
+ {
+ Hediff cumflation = source.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("Cumflation"));
+ Gene_LifeForce gene_LifeForce = consumer.genes.GetFirstGeneOfType();
+ cumflation.Severity = Math.Max(0f,cumflation.Severity - CUMFLATION_SEVERITY_LOSS_PER_TICK);
+ gene_LifeForce.Resource.Value += LIFEFORCE_GAIN_PER_TICK;
+ }
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/Patches/Patch_Vanilla_Inheritance_Fertilin.cs b/Source/Genes/Life_Force/Patches/Patch_Vanilla_Inheritance_Fertilin.cs
new file mode 100644
index 0000000..b4b327c
--- /dev/null
+++ b/Source/Genes/Life_Force/Patches/Patch_Vanilla_Inheritance_Fertilin.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HarmonyLib;
+using RimWorld;
+using Verse;
+
+namespace RJW_Genes
+{
+ ///
+ /// This Patch is applied to add a absorption gene for fertilin if it has none, but it does have the fertilin gene
+ /// First tries to get one from the parents else chooses one of them at random
+ /// the genes are determined and "simply added".
+ ///
+ /// This fixes the potential problem that Pawns could inherit Fertilin, but no gene to gain Fertilin.
+ ///
+ [HarmonyPatch(typeof(PregnancyUtility), "GetInheritedGeneSet", new Type[]
+ {
+ typeof(Pawn),
+ typeof(Pawn)
+ }
+ )]
+ public static class Patch_Vanilla_Inheritance_Fertilin
+ {
+ [HarmonyPostfix]
+ public static void InheritedGenes(Pawn father, Pawn mother, ref GeneSet __result)
+ {
+ //Also make a setting for this
+ if (__result.GenesListForReading.Contains(GeneDefOf.rjw_genes_lifeforce))
+ {
+ List babies_genes = __result.GenesListForReading;
+
+ //If there is no absorption gene get one from the parents, else a random one
+ if(!Has_Fertilin_Source_Gene(babies_genes))
+ {
+ if (RJW_Genes_Settings.rjw_genes_detailed_debug)
+ ModLog.Message($"Child of ({father.Name};{mother.Name}) has Genes with LifeForce-Resource but no Source-Gene, adding one of parents random if possible or any random otherwise.");
+ // Gather Parents Source-Genes
+ List absorption_genes_parents = new List();
+ foreach (GeneDef geneDef in FertilinSourceGenes)
+ {
+ if(mother.genes != null && mother.genes.HasGene(geneDef))
+ absorption_genes_parents.Add(geneDef);
+
+ if (father.genes != null && father.genes.HasGene(geneDef))
+ absorption_genes_parents.Add(geneDef);
+ }
+ // Parents had Genes - Pick a random one of them
+ if (!absorption_genes_parents.NullOrEmpty())
+ __result.AddGene(absorption_genes_parents.RandomElement());
+ // Create a fully random one for your little Cumfueled missbreed
+ else
+ __result.AddGene(FertilinSourceGenes.RandomElement());
+ }
+ }
+ }
+
+ private static List FertilinSourceGenes = new List() {
+ GeneDefOf.rjw_genes_drainer,
+ GeneDefOf.rjw_genes_cum_eater,
+ GeneDefOf.rjw_genes_fertilin_absorber,
+ GeneDefOf.rjw_genes_cockeater
+ };
+
+ private static bool Has_Fertilin_Source_Gene(List genes)
+ {
+ foreach (GeneDef gene in genes)
+ {
+ if (FertilinSourceGenes.Contains(gene))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ }
+}
diff --git a/Source/Genes/Life_Force/ThinkNodes/ThinkNode_ConditionalCannotInteract.cs b/Source/Genes/Life_Force/ThinkNodes/ThinkNode_ConditionalCannotInteract.cs
new file mode 100644
index 0000000..06e05b4
--- /dev/null
+++ b/Source/Genes/Life_Force/ThinkNodes/ThinkNode_ConditionalCannotInteract.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using Verse.AI;
+namespace RJW_Genes
+{
+ public class ThinkNode_ConditionalCannotInteract : ThinkNode_Conditional
+ {
+ protected override bool Satisfied(Pawn pawn)
+ {
+ Pawn target = pawn.mindState.duty.focus.Pawn;
+ if (target == null)
+ {
+ return true;
+ }
+ return (target.jobs != null && target.jobs.curDriver.asleep) || !pawn.CanReach(target, PathEndMode.InteractionCell, Danger.Deadly);
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/ThinkNodes/ThinkNode_ConditionalCritcalLifeForce.cs b/Source/Genes/Life_Force/ThinkNodes/ThinkNode_ConditionalCritcalLifeForce.cs
new file mode 100644
index 0000000..dbb3f6b
--- /dev/null
+++ b/Source/Genes/Life_Force/ThinkNodes/ThinkNode_ConditionalCritcalLifeForce.cs
@@ -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);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Genes/Life_Force/ThinkNodes/ThinkNode_ConditionalLowLifeForce.cs b/Source/Genes/Life_Force/ThinkNodes/ThinkNode_ConditionalLowLifeForce.cs
new file mode 100644
index 0000000..0e71ce7
--- /dev/null
+++ b/Source/Genes/Life_Force/ThinkNodes/ThinkNode_ConditionalLowLifeForce.cs
@@ -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);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Genes/Life_Force/ThinkNodes/ThinkNode_NewFlirtTarget.cs b/Source/Genes/Life_Force/ThinkNodes/ThinkNode_NewFlirtTarget.cs
new file mode 100644
index 0000000..9dee5ad
--- /dev/null
+++ b/Source/Genes/Life_Force/ThinkNodes/ThinkNode_NewFlirtTarget.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+using Verse.AI;
+using rjw;
+namespace RJW_Genes
+{
+ public class ThinkNode_NewFlirtTarget : ThinkNode
+ {
+ public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams)
+ {
+ List validTargets = ValidTargets(pawn, pawn.Map).ToList();
+ Pawn new_target = validTargets.NullOrEmpty() ? null : validTargets.RandomElement();
+ if (new_target != null)
+ {
+ pawn.mindState.duty.focus = new_target;
+ }
+ return ThinkResult.NoJob;
+ }
+
+ private IEnumerable ValidTargets(Pawn pawn, Map map)
+ {
+ foreach (Pawn pawn2 in map.mapPawns.FreeAdultColonistsSpawned)
+ {
+ if (pawn != null && pawn2 != null && pawn != pawn2 && !pawn2.jobs.curDriver.asleep && SexAppraiser.would_fuck(pawn, pawn2) > 0.1f)
+ {
+ yield return pawn2;
+ }
+ }
+ //IEnumerator enumerator = null;
+ yield break;
+ }
+ }
+}
diff --git a/Source/Genes/Life_Force/UI/Alert_LowFertilin.cs b/Source/Genes/Life_Force/UI/Alert_LowFertilin.cs
new file mode 100644
index 0000000..09601de
--- /dev/null
+++ b/Source/Genes/Life_Force/UI/Alert_LowFertilin.cs
@@ -0,0 +1,68 @@
+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 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() : null;
+ if (gene_Lifeforce != null && gene_Lifeforce.Active && 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);
+ }
+
+ private List targets = new List();
+
+ private List targetLabels = new List();
+ }
+}
diff --git a/Source/Genes/Life_Force/UI/GeneGizmo_ResourceLifeForce.cs b/Source/Genes/Life_Force/UI/GeneGizmo_ResourceLifeForce.cs
new file mode 100644
index 0000000..edd2e5f
--- /dev/null
+++ b/Source/Genes/Life_Force/UI/GeneGizmo_ResourceLifeForce.cs
@@ -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 drainGenes, Color barColor, Color barhighlightColor) : base(gene, drainGenes, barColor, barhighlightColor)
+ {
+
+ }
+
+ 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())
+ {
+ float num = 0f;
+ foreach (IGeneResourceDrain geneResourceDrain in this.drainGenes)
+ {
+ if (geneResourceDrain.CanOffset)
+ {
+ this.tmpDrainGenes.Add(new Pair(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 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> tmpDrainGenes = new List>();
+ }
+}
diff --git a/Source/HediffDefOf.cs b/Source/HediffDefOf.cs
index e9be87d..30e34df 100644
--- a/Source/HediffDefOf.cs
+++ b/Source/HediffDefOf.cs
@@ -12,9 +12,10 @@ namespace RJW_Genes
public static class HediffDefOf
{
public static readonly HediffDef rjw_genes_aphrodisiac_pheromone;
-
+ public static readonly HediffDef rjw_genes_fertilin_lost;
+ public static readonly HediffDef rjw_genes_succubus_drained;
public static readonly HediffDef rjw_genes_orgasm_rush_hediff;
-
+ public static readonly HediffDef rjw_genes_fertilin_craving;
public static readonly HediffDef rjw_genes_evergrowth_sideeffect;
diff --git a/Source/JobDefOf.cs b/Source/JobDefOf.cs
new file mode 100644
index 0000000..b077aa3
--- /dev/null
+++ b/Source/JobDefOf.cs
@@ -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 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;
+ public static readonly JobDef rjw_genes_flirt;
+ }
+}
diff --git a/Source/Rjw-Genes.csproj b/Source/Rjw-Genes.csproj
index 91ee066..a55766a 100644
--- a/Source/Rjw-Genes.csproj
+++ b/Source/Rjw-Genes.csproj
@@ -106,6 +106,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -124,6 +164,7 @@
+
diff --git a/Source/Settings/RJW_Genes_Settings.cs b/Source/Settings/RJW_Genes_Settings.cs
index 6f0171d..f6e2f83 100644
--- a/Source/Settings/RJW_Genes_Settings.cs
+++ b/Source/Settings/RJW_Genes_Settings.cs
@@ -17,12 +17,58 @@ namespace RJW_Genes
listing_Standard.ColumnWidth = rect.width / 2.05f;
listing_Standard.Begin(rect);
listing_Standard.Gap(24f);
+ listing_Standard.Label("Fertilin-Gain from Animals" + ": " +
+ Math.Round((double)(RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor * 100f), 0).ToString() + "%", -1f, "of fertilin gained (compared to human-baseline).");
+ RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor = listing_Standard.Slider(RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor, 0f, 3f);
+
+ listing_Standard.Gap(5f);
+ listing_Standard.CheckboxLabeled("Sexdemon Visits", ref rjw_genes_sexdemon_visit, "If enabled, incubi and succubi can spawn in through an event.", 0f, 1f);
+ if (rjw_genes_sexdemon_visit)
+ {
+ listing_Standard.Gap(3f);
+ listing_Standard.CheckboxLabeled(" Size matters", ref rjw_genes_sexdemon_join_size_matters, "Incubi and succubi will consider size/tightness of partners genital for deciding if they want to join", 0f, 1f);
+ listing_Standard.Gap(3f);
+ listing_Standard.CheckboxLabeled(" Sexdemon groups", ref rjw_genes_sexdemon_visit_groups, "Multiple sexdemons can spawn during a event", 0f, 1f);
+ listing_Standard.Gap(3f);
+ listing_Standard.CheckboxLabeled(" Succubi", ref rjw_genes_sexdemon_visit_succubi, "Allow incubi to spawn through this even", 0f, 1f);
+ listing_Standard.Gap(3f);
+ listing_Standard.CheckboxLabeled(" Incubi", ref rjw_genes_sexdemon_visit_incubi, "Allow incubi to spawn through this even", 0f, 1f);
+
+ }
+
+ listing_Standard.Gap(5f);
+ listing_Standard.CheckboxLabeled("generous-donor cheatmode", ref rjw_genes_generous_donor_cheatmode, "When enabled, pawns with the 'generous donor' are not drained and not fertilin exhausted. Hence they can fuel succubi and incubi non-stop. This makes them drastically easier to keep, and you should not do it.", 0f, 1f);
+
+ listing_Standard.Gap(5f);
listing_Standard.CheckboxLabeled("detailed-debug", ref rjw_genes_detailed_debug, "Adds detailed information to the log about interactions and genes.", 0f, 1f);
listing_Standard.End();
}
+ public override void ExposeData()
+ {
+ base.ExposeData();
+ Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor, "rjw_genes_fertilin_from_animals_factor", RJW_Genes_Settings.rjw_genes_fertilin_from_animals_factor, true);
+ Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_detailed_debug, "rjw_genes_detailed_debug", RJW_Genes_Settings.rjw_genes_detailed_debug, true);
+
+ Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_sexdemon_visit, "rjw_genes_sexdemon_visit", RJW_Genes_Settings.rjw_genes_sexdemon_visit, true);
+ Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_sexdemon_join_size_matters, "rjw_genes_sexdemon_join_size_matters", RJW_Genes_Settings.rjw_genes_sexdemon_join_size_matters, true);
+ Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_sexdemon_visit_groups, "rjw_genes_sexdemon_groups", RJW_Genes_Settings.rjw_genes_sexdemon_visit_groups, true);
+ Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_sexdemon_visit_succubi, "rjw_genes_sexdemon_succubi", RJW_Genes_Settings.rjw_genes_sexdemon_visit_succubi, true);
+ Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_sexdemon_visit_incubi, "rjw_genes_sexdemon_incubi", RJW_Genes_Settings.rjw_genes_sexdemon_visit_incubi, true);
+
+ Scribe_Values.Look(ref RJW_Genes_Settings.rjw_genes_generous_donor_cheatmode, "rjw_genes_generous_donor_cheatmode", RJW_Genes_Settings.rjw_genes_generous_donor_cheatmode, true);
+ }
public static bool rjw_genes_detailed_debug = false;
+ public static float rjw_genes_fertilin_from_animals_factor = 0.1f;
+
+ public static bool rjw_genes_sexdemon_visit = true;
+ public static bool rjw_genes_sexdemon_join_size_matters = true;
+ public static bool rjw_genes_sexdemon_visit_groups = true;
+ public static bool rjw_genes_sexdemon_visit_succubi = true;
+ public static bool rjw_genes_sexdemon_visit_incubi = true;
+
+ public static bool rjw_genes_generous_donor_cheatmode = false;
}
}
diff --git a/Source/ThoughtDefOf.cs b/Source/ThoughtDefOf.cs
index 1d49bd9..f884d4a 100644
--- a/Source/ThoughtDefOf.cs
+++ b/Source/ThoughtDefOf.cs
@@ -8,13 +8,14 @@ using Verse;
namespace RJW_Genes
{
[DefOf]
- public static class ThoughtDefOf
+ public static class ThoughtDefOf
{
-
+ public static readonly ThoughtDef rjw_genes_cock_eaten;
+ public static readonly ThoughtDef rjw_genes_seduced;
public static readonly ThoughtDef rjw_genes_pheromone_carrier_nearby;
//Others with same names but other defs than in genedefof
-
+ public static readonly InteractionDef rjw_genes_flirt;
}
}