diff --git a/Common/Assemblies/Rjw-Genes.dll b/Common/Assemblies/Rjw-Genes.dll index d3be5b0..4b6ffe9 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..d333c1d --- /dev/null +++ b/Common/Defs/AbilityDefs/Ability_CockEater.xml @@ -0,0 +1,34 @@ + + + + rjw_genes_cockeater + + Eat the cock of another pawn, restoring fertilin based on the size of the cock. + Things/Mote/Heart + 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_Flight.xml b/Common/Defs/AbilityDefs/Ability_Flight.xml new file mode 100644 index 0000000..7829d10 --- /dev/null +++ b/Common/Defs/AbilityDefs/Ability_Flight.xml @@ -0,0 +1,28 @@ + + + + rjw_genes_flight + + Fly to a distant location using wings. + Genes/Icons/Succubus_Wings + 1250 + false + + Verb_CastAbilityJump + + false + false + 0.5 + 19.9 + true + Longjump_Jump + Longjump_Land + + true + false + false + + + CastJump + + \ 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..09245a0 --- /dev/null +++ b/Common/Defs/AbilityDefs/Ability_ParalysingKiss.xml @@ -0,0 +1,44 @@ + + + + rjw_genes_paralysingkiss + + Paralyse someone briefly with a kiss. + Things/Mote/Heart + true + true + false + + 5 + + Mote_CoagulateStencil + Coagulate + Coagulate_Cast + 402 + + Verb_CastAbilityTouch + false + -1 + 1 + + true + false + false + false + true + + + +
  • + CompAbilityEffect_Stun + -15 +
  • +
  • + Heart +
  • +
  • + 0.05 +
  • +
    +
    +
    \ 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..1887160 --- /dev/null +++ b/Common/Defs/AbilityDefs/Ability_PussyHeal.xml @@ -0,0 +1,49 @@ + + + + rjw_genes_pussyheal + + 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.2 +
  • +
  • + 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..fb87fea --- /dev/null +++ b/Common/Defs/AbilityDefs/Ability_Seduce.xml @@ -0,0 +1,43 @@ + + + + rjw_genes_seduce + + Seduce the target to approach the caster. + Things/Mote/Heart + 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.1 +
  • +
    +
    +
    \ No newline at end of file diff --git a/Common/Defs/Genes/GeneCategories.xml b/Common/Defs/Genes/GeneCategories.xml index 81208b9..06b31cc 100644 --- a/Common/Defs/Genes/GeneCategories.xml +++ b/Common/Defs/Genes/GeneCategories.xml @@ -37,6 +37,12 @@ 15 + + rjw_genes_fertilin + + 14 + + rjw_genes_breeding @@ -61,4 +67,6 @@ 8 + + \ No newline at end of file diff --git a/Common/Defs/Genes/GeneDefs_Cosmetic.xml b/Common/Defs/Genes/GeneDefs_Cosmetic.xml new file mode 100644 index 0000000..a4460d2 --- /dev/null +++ b/Common/Defs/Genes/GeneDefs_Cosmetic.xml @@ -0,0 +1,69 @@ + + + + Miscellaneous + true + +
  • Wing
  • +
  • Wings
  • +
    + + Tailbone + +
    + + + rjw_genes_Succubus_Wings + + Carriers of this gene grow succubus wings. + Genes/Icons/Succubus_Wings + (0.75, 0.75, 0.75) + 1000 + +
  • rjw_genes_flight
  • +
    + + rjw_genes_flight + + 1 + + Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Wings/Succubus_Wings + Skin + 2 + (0.0, 0.01, -0.1) + (0.0, 0.0, -0.1) + (0.1, 0.0, 0.0) + +
    + + + rjw_genes_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 + + +
  • Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L1
  • +
  • Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R1
  • +
  • Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L2
  • +
  • Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R2
  • +
    + Skin + 2 + (0, 0.2, -0.1) + (0, -0.1, 0.1) + (0.2, 0.2, 0.1) +
    + true +
    +
    \ No newline at end of file diff --git a/Common/Defs/Genes/GeneDefs_LifeForce.xml b/Common/Defs/Genes/GeneDefs_LifeForce.xml new file mode 100644 index 0000000..ed1ea9a --- /dev/null +++ b/Common/Defs/Genes/GeneDefs_LifeForce.xml @@ -0,0 +1,188 @@ + + + + rjw_genes_lifeforce + + 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. + UI/Icons/Genes/Gene_Hemogenic + 0 + rjw_genes_fertilin + -2 + +
  • Gives fertilin supply.
  • +
    + + +
  • fert
  • +
    +
    + rjw_genes_lifeforce_randomrape + 0.05 + 1 + 1 +
    + + + LifeForceDrain + + draining + Carriers lose an additional 15 fertilin per day from biological entropy. + fertilin + RJW_Genes.Gene_LifeForceDrain + UI/Icons/Genes/Gene_HemogenDrain + rjw_genes_lifeforce + 0.15 + rjw_genes_fertilin + -1 + 1 + 6 + + + + rjw_genes_pussyhealer + + pussyhealer + Carriers of this gene are able use vaginal sex to tend to other's wounds. + Things/Mote/Heart + rjw_genes_lifeforce + 9 + rjw_genes_fertilin + +
  • rjw_genes_pussyheal
  • +
    + + rjw_genes_pussyheal + + 1 + -1 + + +
  • life
  • +
  • pussy
  • +
  • heal
  • +
    +
    +
    + + + rjw_genes_cockeater + + cockeater + Carriers of this gene are able eat cocks to restore their fertilin supply. + Things/Mote/Heart + rjw_genes_lifeforce + 11 + rjw_genes_fertilin + +
  • rjw_genes_cockeater
  • +
    + + rjw_genes_cockeater + + 1 + -1 + + +
  • life
  • +
  • cock
  • +
  • eat
  • +
    +
    +
    + + + rjw_genes_paralysingkiss + + paralysing kiss + Carriers of this gene are able to briefly stun an enemy with a kiss. + Things/Mote/Heart + rjw_genes_lifeforce + 12 + rjw_genes_fertilin + +
  • rjw_genes_paralysingkiss
  • +
    + + rjw_genes_paralysingkiss + + 1 + -1 + + +
  • stun
  • +
  • kiss
  • +
    +
    +
    + + + rjw_genes_seduce + + seduction + Carriers of this gene are able to seduce a pawn into having sex with them. + Things/Mote/Heart + rjw_genes_lifeforce + 13 + rjw_genes_fertilin + +
  • rjw_genes_seduce
  • +
    + + rjw_genes_seduce + + 1 + -1 + + + +
  • stun
  • +
  • kiss
  • +
    +
    +
    + + + rjw_genes_vaginal_absorber + + Carriers of this gene are able to absorb fertilin through their vagina. + Things/Mote/Heart + rjw_genes_lifeforce + 2 + rjw_genes_fertilin + 1 + + + + rjw_genes_anal_absorber + + Carriers of this gene are able to absorb fertilin through their anus. + Things/Mote/Heart + rjw_genes_lifeforce + 3 + rjw_genes_fertilin + 1 + + + + rjw_genes_drainer + + Carriers of this gene are able to absorb a great amount of fertilin by draining the vitality of the partner. + Things/Mote/Heart + rjw_genes_lifeforce + 4 + rjw_genes_fertilin + 1 + -1 + +
    \ No newline at end of file diff --git a/Common/Defs/Genes/GeneDefs_SexSpecial.xml b/Common/Defs/Genes/GeneDefs_SexSpecial.xml index 6c27711..1e0e8c9 100644 --- a/Common/Defs/Genes/GeneDefs_SexSpecial.xml +++ b/Common/Defs/Genes/GeneDefs_SexSpecial.xml @@ -11,7 +11,6 @@ 1 - rjw_genes_youth_fountain diff --git a/Common/Defs/HediffDefs/Hediffs_Genes.xml b/Common/Defs/HediffDefs/Hediffs_Genes.xml index bebfce9..b0a9cc9 100644 --- a/Common/Defs/HediffDefs/Hediffs_Genes.xml +++ b/Common/Defs/HediffDefs/Hediffs_Genes.xml @@ -1,6 +1,4 @@  - - Aphrodisiac_Pheromone @@ -8,19 +6,83 @@ Aphrodisiac pheromone effects. (1,0,0.5) - true 1.0
  • - -4.0 + -24.0
  • - false - + true + 2 - + +
  • +
    +
    + + + Fertilin_Lost + RJW_Genes.HediffWithComps_tank + + Percentage of fertilin lost. + (1,1,1) + 1 + +
  • + -0.5 +
  • +
    + +
  • + true +
  • +
    +
    + + + Succubus_Drained + HediffWithComps + + The vitality of this pawn has been drained. + (1,0,0.5) + 1.0 + 1.0 + +
  • + -1.0 +
  • +
    + +
  • + + +
  • + Consciousness + -0.1 +
  • + + +
  • + 0.5 + + +
  • + Consciousness + -0.2 +
  • + + +
  • + 0.8 + + +
  • + Consciousness + -0.4 +
  • +
    diff --git a/Common/Defs/InteractionDef/Rape/Rape_SuccubusTail.xml b/Common/Defs/InteractionDef/Rape/Rape_SuccubusTail.xml new file mode 100644 index 0000000..be8905c --- /dev/null +++ b/Common/Defs/InteractionDef/Rape/Rape_SuccubusTail.xml @@ -0,0 +1,153 @@ + + + + + Rape_SuccubusTail_Tailjob + + + +
  • r_logentry->Was given tailjob by [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Gave tailjob to [INITIATOR_nameDef].
  • +
    +
    + +
  • + Tailjob + Handjob + +
  • DomSuccubusTail_Tailjob_RP
  • + + +
  • + SubSuccubusTailCustomRequirementHandler + +
  • Rape
  • + + + +
  • CanPenetrate
  • +
    +
    + + + + +
    +
    + + + Rape_SuccubusTail_Vaginal + + + +
  • r_logentry->Gave vaginal tailsex to [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Was given vaginal tailsex by [INITIATOR_nameDef].
  • +
    +
    + +
  • + Vaginal Tailsex + Vaginal + +
  • DomSuccubusTail_Vaginal_RP
  • + + +
  • + DomSuccubusTailCustomRequirementHandler + +
  • Rape
  • + + + + + +
  • Vagina
  • +
    +
    + +
    +
    + + + Rape_SuccubusTail_Anal + + + +
  • r_logentry->Gave anal tailsex to [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Was given anal tailsex by [INITIATOR_nameDef].
  • +
    +
    + +
  • + Anal Tailsex + Anal + +
  • DomSuccubusTail_Anal_RP
  • + + +
  • + DomSuccubusTailCustomRequirementHandler + +
  • Rape
  • + + + + + +
  • Anus
  • +
    +
    + +
    +
    + + + + Rape_SuccubusTail_Envelop + + + +
  • r_logentry->Was given special tailjob by [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Gave special tailjob to [INITIATOR_nameDef].
  • +
    +
    + +
  • + Envelop + Vaginal + +
  • DomSuccubusTail_Envelop_RP
  • + + +
  • + SubSuccubusTailCustomRequirementHandler + +
  • Rape
  • + + + +
  • CanPenetrate
  • +
    +
    + + + +
    +
    +
    \ No newline at end of file diff --git a/Common/Defs/InteractionDef/Rape/Reverse/Rape_Reverse_SuccubusTail.xml b/Common/Defs/InteractionDef/Rape/Reverse/Rape_Reverse_SuccubusTail.xml new file mode 100644 index 0000000..ce679d6 --- /dev/null +++ b/Common/Defs/InteractionDef/Rape/Reverse/Rape_Reverse_SuccubusTail.xml @@ -0,0 +1,159 @@ + + + + + Rape_SuccubusTail_Reverse_Tailjob + + + +
  • r_logentry->Gave tailjob to [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Was given tailjob by [INITIATOR_nameDef].
  • +
    +
    + +
  • + Tailjob + Handjob + +
  • SubSuccubusTail_Tailjob_RP
  • + + +
  • + DomSuccubusTailCustomRequirementHandler + +
  • Reverse
  • +
  • Rape
  • + + + + + + +
  • CanPenetrate
  • +
    +
    + +
    +
    + + + Rape_SuccubusTail_Reverse_Vaginal + + + +
  • r_logentry->Was given vaginal tailsex by [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Gave vaginal tailsex to [INITIATOR_nameDef].
  • +
    +
    + +
  • + Vaginal Tailsex + Vaginal + +
  • DomSuccubusTail_Vaginal_RP
  • + + +
  • + SubSuccubusTailCustomRequirementHandler + +
  • Reverse
  • +
  • Rape
  • + + + +
  • Vagina
  • +
    +
    + + + + +
    +
    + + + Rape_SuccubusTail_Reverse_Anal + + + +
  • r_logentry->Was given anal tailsex by [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Gave anal tailsex to [INITIATOR_nameDef].
  • +
    +
    + +
  • + Anal Tailsex + Anal + +
  • DomSuccubusTail_Anal_RP
  • + + +
  • + SubSuccubusTailCustomRequirementHandler + +
  • Reverse
  • +
  • Rape
  • + + + +
  • Anus
  • +
    +
    + + + + +
    +
    + + + + Rape_SuccubusTail_Reverse_Envelop + + + +
  • r_logentry->Gave special tailjob to [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Was given special tailjob by [INITIATOR_nameDef].
  • +
    +
    + +
  • + Envelop + Vaginal + +
  • DomSuccubusTail_Envelop_RP
  • + + +
  • + DomSuccubusTailCustomRequirementHandler + +
  • Reverse
  • +
  • Rape
  • + + + + + +
  • CanPenetrate
  • +
    +
    + +
    +
    +
    \ No newline at end of file diff --git a/Common/Defs/InteractionDef/Sex/Reverse/Sex_Reverse_SuccubusTail.xml b/Common/Defs/InteractionDef/Sex/Reverse/Sex_Reverse_SuccubusTail.xml new file mode 100644 index 0000000..a6e98c5 --- /dev/null +++ b/Common/Defs/InteractionDef/Sex/Reverse/Sex_Reverse_SuccubusTail.xml @@ -0,0 +1,159 @@ + + + + + Sex_SuccubusTail_Reverse_Tailjob + + + +
  • r_logentry->Gave tailjob to [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Was given tailjob by [INITIATOR_nameDef].
  • +
    +
    + +
  • + Tailjob + Handjob + +
  • SubSuccubusTail_Tailjob_RP
  • + + +
  • + DomSuccubusTailCustomRequirementHandler + +
  • Reverse
  • +
  • Consensual
  • + + + + + + +
  • CanPenetrate
  • +
    +
    + +
    +
    + + + Sex_SuccubusTail_Reverse_Vaginal + + + +
  • r_logentry->Was given vaginal tailsex by [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Gave vaginal tailsex to [INITIATOR_nameDef].
  • +
    +
    + +
  • + Vaginal Tailsex + Vaginal + +
  • DomSuccubusTail_Vaginal_RP
  • + + +
  • + SubSuccubusTailCustomRequirementHandler + +
  • Reverse
  • +
  • Consensual
  • + + + +
  • Vagina
  • +
    +
    + + + + +
    +
    + + + Sex_SuccubusTail_Reverse_Anal + + + +
  • r_logentry->Was given anal tailsex by [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Gave anal tailsex to [INITIATOR_nameDef].
  • +
    +
    + +
  • + Anal Tailsex + Anal + +
  • DomSuccubusTail_Anal_RP
  • + + +
  • + SubSuccubusTailCustomRequirementHandler + +
  • Reverse
  • +
  • Consensual
  • + + + +
  • Anus
  • +
    +
    + + + + +
    +
    + + + + Sex_SuccubusTail_Reverse_Envelop + + + +
  • r_logentry->Gave special tailjob to [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Was given special tailjob by [INITIATOR_nameDef].
  • +
    +
    + +
  • + Envelop + Vaginal + +
  • DomSuccubusTail_Envelop_RP
  • + + +
  • + DomSuccubusTailCustomRequirementHandler + +
  • Reverse
  • +
  • Consensual
  • + + + + + +
  • CanPenetrate
  • +
    +
    + +
    +
    +
    \ No newline at end of file diff --git a/Common/Defs/InteractionDef/Sex/Sex_SuccubusTail.xml b/Common/Defs/InteractionDef/Sex/Sex_SuccubusTail.xml new file mode 100644 index 0000000..dda1ffe --- /dev/null +++ b/Common/Defs/InteractionDef/Sex/Sex_SuccubusTail.xml @@ -0,0 +1,154 @@ + + + + + Sex_SuccubusTail_Tailjob + + + +
  • r_logentry->Was given tailjob by [RECIPIENT_nameDef].
  • + +
    +
    + + +
  • r_logentry->Gave tailjob to [INITIATOR_nameDef].
  • +
    +
    + +
  • + Tailjob + Handjob + +
  • DomSuccubusTail_Tailjob_RP
  • + + +
  • + SubSuccubusTailCustomRequirementHandler + +
  • Consensual
  • + + + +
  • CanPenetrate
  • +
    +
    + + + + +
    +
    + + + Sex_SuccubusTail_Vaginal + + + +
  • r_logentry->Gave vaginal tailsex to [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Was given vaginal tailsex by [INITIATOR_nameDef].
  • +
    +
    + +
  • + Vaginal Tailsex + Vaginal + +
  • DomSuccubusTail_Vaginal_RP
  • + + +
  • + DomSuccubusTailCustomRequirementHandler + +
  • Consensual
  • + + + + + +
  • Vagina
  • +
    +
    + +
    +
    + + + Sex_SuccubusTail_Anal + + + +
  • r_logentry->Gave anal tailsex to [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Was given anal tailsex by [INITIATOR_nameDef].
  • +
    +
    + +
  • + Anal Tailsex + Anal + +
  • DomSuccubusTail_Anal_RP
  • + + +
  • + DomSuccubusTailCustomRequirementHandler + +
  • Consensual
  • + + + + + +
  • Anus
  • +
    +
    + +
    +
    + + + + Sex_SuccubusTail_Envelop + + + +
  • r_logentry->Was given special tailjob by [RECIPIENT_nameDef].
  • +
    +
    + + +
  • r_logentry->Gave special tailjob to [INITIATOR_nameDef].
  • +
    +
    + +
  • + Envelop + Vaginal + +
  • DomSuccubusTail_Envelop_RP
  • + + +
  • + SubSuccubusTailCustomRequirementHandler + +
  • Consensual
  • + + + +
  • CanPenetrate
  • +
    +
    + + + +
    +
    +
    \ No newline at end of file diff --git a/Common/Defs/JobDefs/Jobs_LifeForce.xml b/Common/Defs/JobDefs/Jobs_LifeForce.xml new file mode 100644 index 0000000..6992ddd --- /dev/null +++ b/Common/Defs/JobDefs/Jobs_LifeForce.xml @@ -0,0 +1,25 @@ + + + + + rjw_genes_lifeforce_randomrape + rjw.JobDriver_RandomRape + Raping + false + + + + rjw_genes_lifeforce_healpussy + RJW_Genes.JobDriver_CastAbilityAfterSex + Healing someone with sex. + false + + + + rjw_genes_lifeforce_seduced + RJW_Genes.JobDriver_Seduced + Seduced. + false + 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..1da6e15 --- /dev/null +++ b/Common/Defs/MentalStateDefs/MentalState_Lifeforce.xml @@ -0,0 +1,30 @@ + + + + + rjw_genes_lifeforce_randomrape + rjw_genes_lifeforce_randomrape + 1.5 + Extreme + + + + rjw_genes_lifeforce_randomrape + RJW_Genes.LifeForceMentalState + RJW_Genes.LifeForceMentalStateWorker + + 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/RulePackDefs/Sex/RulePacks_SuccubTail.xml b/Common/Defs/RulePackDefs/Sex/RulePacks_SuccubTail.xml new file mode 100644 index 0000000..21e75a1 --- /dev/null +++ b/Common/Defs/RulePackDefs/Sex/RulePacks_SuccubTail.xml @@ -0,0 +1,77 @@ + + + + + DomSuccubusTail_Tailjob_RP + + +
  • sent-> [INITIATOR_nameDef] gave [RECIPIENT_nameDef] a tailjob.
  • +
    +
    +
    + + + DomSuccubusTail_Vaginal_RP + + +
  • sent-> [INITIATOR_nameDef] [INITIATOR_possessive] tail was vaginally inserted into [RECIPIENT_nameDef].
  • +
    +
    +
    + + + DomSuccubusTail_Anal_RP + + +
  • sent-> [INITIATOR_nameDef] [INITIATOR_possessive] tail was anally inserted into [RECIPIENT_nameDef].
  • +
    +
    +
    + + + + DomSuccubusTail_Envelop_RP + + +
  • sent-> [RECIPIENT_nameDef] dick was enveloped by [INITIATOR_nameDef] [INITIATOR_possessive] tail.
  • +
    +
    +
    + + + SubSuccubusTail_Tailjob_RP + + +
  • sent-> [RECIPIENT_nameDef] gave [INITIATOR_nameDef] a tailjob.
  • +
    +
    +
    + + + SubSuccubusTail_Vaginal_RP + + +
  • sent-> [RECIPIENT_nameDef] [RECIPIENT_possessive] tail was vaginally inserted into [INITIATOR_nameDef].
  • +
    +
    +
    + + + SubSuccubusTail_Anal_RP + + +
  • sent-> [RECIPIENT_nameDef] [RECIPIENT_possessive] tail was anally inserted into [INITIATOR_nameDef].
  • +
    +
    +
    + + + + SubSuccubusTail_Envelop_RP + + +
  • sent-> [INITIATOR_nameDef] dick was enveloped by [RECIPIENT_nameDef] [RECIPIENT_possessive] tail.
  • +
    +
    +
    +
    \ 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..bca1f93 --- /dev/null +++ b/Common/Defs/ThoughtDefs/Thoughts_LifeForce.xml @@ -0,0 +1,44 @@ + + + + + rjw_genes_cock_eaten + Thought_Memory + 30.0 + 100 + 0.4 + +
  • + + My cock was eaten directly of my body, I am devestated. + -30 +
  • +
    +
    + + + rjw_genes_seduced + Thought_Memory + 10.0 + 100 + 0.4 + +
  • + + I was seduced into having sex. I regret what happened. + -10 +
  • +
    +
    + + + rjw_critical_fertilin + +
  • + + I'm almost out of fertilin. I'm scared of losing control. + -10 +
  • +
    +
    +
    diff --git a/Common/Languages/English/Keyed/Lifeforce.xml b/Common/Languages/English/Keyed/Lifeforce.xml new file mode 100644 index 0000000..23d3f75 --- /dev/null +++ b/Common/Languages/English/Keyed/Lifeforce.xml @@ -0,0 +1,10 @@ + + + + Pawn doesn't have required fertilin gene. + Not enough fertilin to cast. + + + Low fertilin + A colonist has low fertilin. At this point they are becoming desperate enough to consider rape and bestiality to obtain fertilin (if they didn't already). At zero fertilin they will lose all sense and start raping randomly + \ No newline at end of file diff --git a/Common/Patches/ThingDefs/Sexperience_Cum.xml b/Common/Patches/ThingDefs/Sexperience_Cum.xml new file mode 100644 index 0000000..b905d4b --- /dev/null +++ b/Common/Patches/ThingDefs/Sexperience_Cum.xml @@ -0,0 +1,17 @@ + + + + + +
  • RJW Sexperience
  • +
    + + /Defs/ThingDef[defName="GatheredCum"]/ingestible/outcomeDoers + +
  • + 1 +
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/Common/Patches/ThinkTree/MentalStateCritical_LifeForceRandomRape.xml b/Common/Patches/ThinkTree/MentalStateCritical_LifeForceRandomRape.xml new file mode 100644 index 0000000..9532df8 --- /dev/null +++ b/Common/Patches/ThinkTree/MentalStateCritical_LifeForceRandomRape.xml @@ -0,0 +1,35 @@ + + + + + Defs/ThinkTreeDef[defName="MentalStateCritical"]/thinkRoot[@Class="ThinkNode_Tagger"]/subNodes + +
  • + rjw_genes_lifeforce_randomrape + +
  • + Rest + 0.05 + true + +
  • + +
  • +
  • + 0.5 + +
  • +
  • + +
  • + +
  • + + +
  • +
  • + +
  • +
    +
    +
    \ No newline at end of file diff --git a/Common/Patches/Xenotypes/GenitaliaUpdate.xml b/Common/Patches/Xenotypes/GenitaliaUpdate.xml index 0a1f3e9..fd6e360 100644 --- a/Common/Patches/Xenotypes/GenitaliaUpdate.xml +++ b/Common/Patches/Xenotypes/GenitaliaUpdate.xml @@ -42,15 +42,15 @@ - -
  • LustLicentia.RJWLabs
  • -
    - - Defs/XenotypeDef[defName="Highmate"]/genes - -
  • rjw_genes_likes_cumflation
  • -
    -
    + +
  • LustLicentia.RJWLabs
  • +
    + + Defs/XenotypeDef[defName="Highmate"]/genes + +
  • rjw_genes_likes_cumflation
  • +
    +
    diff --git a/Common/Textures/Genes/Icons/Succubus_Tail.png b/Common/Textures/Genes/Icons/Succubus_Tail.png new file mode 100644 index 0000000..cc86056 Binary files /dev/null and b/Common/Textures/Genes/Icons/Succubus_Tail.png differ diff --git a/Common/Textures/Genes/Icons/Succubus_Wings.png b/Common/Textures/Genes/Icons/Succubus_Wings.png new file mode 100644 index 0000000..0665f1a Binary files /dev/null and b/Common/Textures/Genes/Icons/Succubus_Wings.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L1_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L1_east.png new file mode 100644 index 0000000..7f51811 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L1_east.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L1_north.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L1_north.png new file mode 100644 index 0000000..25c4097 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L1_north.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L1_south.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L1_south.png new file mode 100644 index 0000000..60aae1e Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L1_south.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L2_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L2_east.png new file mode 100644 index 0000000..f3be513 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L2_east.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L2_north.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L2_north.png new file mode 100644 index 0000000..7a54823 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L2_north.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L2_south.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L2_south.png new file mode 100644 index 0000000..91b5641 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_L2_south.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R1_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R1_east.png new file mode 100644 index 0000000..e08f0b3 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R1_east.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R1_north.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R1_north.png new file mode 100644 index 0000000..60aae1e Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R1_north.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R1_south.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R1_south.png new file mode 100644 index 0000000..0c9df93 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R1_south.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R2_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R2_east.png new file mode 100644 index 0000000..ea33158 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R2_east.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R2_north.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R2_north.png new file mode 100644 index 0000000..30e0e28 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R2_north.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R2_south.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R2_south.png new file mode 100644 index 0000000..a9f56d7 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Tail/Succubus_Tail_R2_south.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Wings/Succubus_Wings_east.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Wings/Succubus_Wings_east.png new file mode 100644 index 0000000..71e3f53 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Wings/Succubus_Wings_east.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Wings/Succubus_Wings_north.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Wings/Succubus_Wings_north.png new file mode 100644 index 0000000..ac55d17 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Wings/Succubus_Wings_north.png differ diff --git a/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Wings/Succubus_Wings_south.png b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Wings/Succubus_Wings_south.png new file mode 100644 index 0000000..ac55d17 Binary files /dev/null and b/Common/Textures/Things/Pawn/Humanlike/BodyAttachments/rjw_genes_Succubus_Wings/Succubus_Wings_south.png differ diff --git a/Rjw-Genes.sln b/Rjw-Genes.sln index 858f9a2..3706653 100644 --- a/Rjw-Genes.sln +++ b/Rjw-Genes.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 17.0.32014.148 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rjw-Genes", "Source\Rjw-Genes.csproj", "{D7D21B4A-1DA7-41D8-B202-C58CA8FA62AA}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FB09ADF4-FC35-4C1F-9135-2B4C4E4ED347}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/Source/Animal_Inheritance/PatchVanillaPregnancyUtility.cs b/Source/Animal_Inheritance/PatchVanillaPregnancyUtility.cs index a076b6e..afbfa09 100644 --- a/Source/Animal_Inheritance/PatchVanillaPregnancyUtility.cs +++ b/Source/Animal_Inheritance/PatchVanillaPregnancyUtility.cs @@ -35,7 +35,7 @@ namespace RJW_BGS { __result.AddGene(gene); } - } + } } } } diff --git a/Source/First.cs b/Source/First.cs new file mode 100644 index 0000000..e322c58 --- /dev/null +++ b/Source/First.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using rjw; +using Verse; +using RimWorld; +using rjw.Modules.Interactions.Rules.PartKindUsageRules; +using rjw.Modules.Interactions.Internals.Implementation; + +namespace RJW_Genes +{ + [StaticConstructorOnStartup] + internal static class First + { + static First() + { + AddtoIPartPreferenceRule(); + } + + //Modified code from https://gitgud.io/lutepickle/rjw_menstruation/-/tree/main/1.4/source/RJW_Menstruation/RJW_Menstruation + //Summary// + //Adds our own partpreferences to rjw's list. Our partpreferences are under Interactions.GenesPartKindUsageRule + // + private static void AddtoIPartPreferenceRule() + { + List partPreferenceRules = Unprivater.GetProtectedValue>("_partKindUsageRules", typeof(PartPreferenceDetectorService)); + partPreferenceRules.Add(new Interactions.GenesPartKindUsageRule()); + } + } +} diff --git a/Source/GeneDefOf.cs b/Source/GeneDefOf.cs index 00299e4..a1df81a 100644 --- a/Source/GeneDefOf.cs +++ b/Source/GeneDefOf.cs @@ -76,8 +76,21 @@ namespace RJW_Genes public static readonly GeneDef rjw_genes_youth_fountain; public static readonly GeneDef rjw_genes_sex_age_drain; public static readonly GeneDef rjw_genes_aphrodisiac_pheromones; + public static readonly GeneDef rjw_genes_aphrodisiac_pheromones; + public static readonly GeneDef rjw_genes_youth_fountain; + public static readonly GeneDef rjw_genes_sex_age_drain; - // Others & Non-Genes + // LifeForce + public static readonly GeneDef rjw_genes_lifeforce; + public static readonly GeneDef rjw_genes_pussyhealer; + public static readonly GeneDef rjw_genes_vaginal_absorber; + public static readonly GeneDef rjw_genes_anal_absorber; + public static readonly GeneDef rjw_genes_drainer; + + // Cosmetic + public static readonly GeneDef rjw_genes_succubus_tail; + + // Others & Non-Genes public static readonly HediffDef rjw_genes_orgasm_rush_hediff; } } diff --git a/Source/Genes/Cum/CumUtility.cs b/Source/Genes/Cum/CumUtility.cs index ea049cc..b483aed 100644 --- a/Source/Genes/Cum/CumUtility.cs +++ b/Source/Genes/Cum/CumUtility.cs @@ -33,5 +33,35 @@ namespace RJW_Genes } } + + //Get total fluidamount a person has. + public static float GetTotalFluidAmount(Pawn pawn, float multiplier = 1f) + { + var partBPR = Genital_Helper.get_genitalsBPR(pawn); + var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR); + float total_cum = 0; + if (!parts.NullOrEmpty()) + { + CompHediffBodyPart CompHediff; + + foreach (Hediff part in parts) + { + if (GenitaliaChanger.IsArtificial(part)) + continue; + + if (rjw.Genital_Helper.is_penis(part)) + { + CompHediff = part.TryGetComp(); + if (CompHediff != null) + { + total_cum += CompHediff.FluidAmmount * CompHediff.FluidModifier * multiplier; + } + } + } + + } + return total_cum; + + } } } diff --git a/Source/Genes/GeneUtility.cs b/Source/Genes/GeneUtility.cs index 284aab2..7a987fe 100644 --- a/Source/Genes/GeneUtility.cs +++ b/Source/Genes/GeneUtility.cs @@ -1,11 +1,46 @@ using System; using System.Collections.Generic; using Verse; - +using RimWorld; namespace RJW_Genes { public class GeneUtility { + //Instead of seperate functions this should be simpeler + public static bool HasGeneNullCheck(Pawn pawn, GeneDef genedef) + { + if (pawn.genes == null) + { + return false; + } + return pawn.genes.HasGene(genedef); + } + + //Split function so I can offsetlifeforce from gene without needing to look for the gene agian (for the constant drain tick) + public static Gene_LifeForce GetLifeForceGene(Pawn pawn) + { + Pawn_GeneTracker genes = pawn.genes; + Gene_LifeForce gene_LifeForce = genes.GetFirstGeneOfType(); + return gene_LifeForce; + } + + public static void OffsetLifeForce(IGeneResourceDrain drain, float offset) + { + float old_value = drain.Resource.Value; + drain.Resource.Value += offset; + //PostOffSetLifeForce(drain, old_value); + } + + public static void PostOffSetLifeForce(IGeneResourceDrain drain, float old_value) + { + if (old_value > 0.2f && drain.Resource.Value <= 0.2f) + { + Pawn pawn = drain.Pawn; + + //Do things + } + } + public static bool IsMechbreeder(Pawn pawn) { if (pawn.genes == null) @@ -15,6 +50,41 @@ namespace RJW_Genes return pawn.genes.HasGene(GeneDefOf.rjw_genes_mechbreeder); } + public static bool HasLifeForce(Pawn pawn) + { + if (pawn.genes == null) + { + return false; + } + return pawn.genes.HasGene(GeneDefOf.rjw_genes_lifeforce); + } + + public static bool HasLowLifeForce(Pawn pawn) + { + if (HasLifeForce(pawn)) + { + Gene_LifeForce gene = pawn.genes.GetFirstGeneOfType(); + 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.Resource.Value < gene.MinLevelForAlert) + { + return true; + } + } + return false; + } + public static bool IsInsectIncubator(Pawn pawn) { if (pawn.genes == null) @@ -87,6 +157,15 @@ namespace RJW_Genes return pawn.genes.HasGene(GeneDefOf.rjw_genes_generous_donor); } + public static bool isPussyHealer(Pawn pawn) + { + if (pawn.genes == null) + { + return false; + } + return pawn.genes.HasGene(GeneDefOf.rjw_genes_pussyhealer); + } + public static bool IsUnbreakable(Pawn pawn) { if (pawn.genes == null) @@ -95,6 +174,7 @@ namespace RJW_Genes } return pawn.genes.HasGene(GeneDefOf.rjw_genes_unbreakable); } +<<<<<<< HEAD public static bool HasGenitaliaResizingGenes(Pawn pawn) @@ -116,5 +196,7 @@ namespace RJW_Genes return ResizingGenes; } +======= +>>>>>>> 09157e923d5c4c4cf71d79cb0af665ffd6a7c536 } } \ No newline at end of file diff --git a/Source/Genes/Life_Force/Abilities/AbilityUtility.cs b/Source/Genes/Life_Force/Abilities/AbilityUtility.cs new file mode 100644 index 0000000..3f18b71 --- /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_CockEater.cs b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_CockEater.cs new file mode 100644 index 0000000..d4d12ea --- /dev/null +++ b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_CockEater.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using UnityEngine; +using RimWorld; +using rjw; +using rjw.Modules.Interactions.Helpers; + +namespace RJW_Genes +{ + public class CompAbilityEffect_CockEater : CompAbilityEffect + { + private new CompProperties_AbilityCockEater Props + { + get + { + return (CompProperties_AbilityCockEater)this.props; + } + } + public override void Apply(LocalTargetInfo target, LocalTargetInfo dest) + { + base.Apply(target, dest); + Pawn pawn = target.Pawn; + if (pawn == null) + { + return; + } + var partBPR = Genital_Helper.get_genitalsBPR(pawn); + var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR); + if (!parts.NullOrEmpty()) + { + foreach (Hediff part in parts) + { + if (GenitaliaChanger.IsArtificial(part)) + continue; + + if (Genital_Helper.is_penis(part)) + { + GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(this.parent.pawn), part.Severity); ; + pawn.health.RemoveHediff(part); + pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.rjw_genes_cock_eaten, pawn, null); + break; //Only one penis at the time + } + } + + } + } + + public override bool Valid(LocalTargetInfo target, bool throwMessages = false) + { + Pawn pawn = target.Pawn; + if (pawn != null) + { + bool flag = pawn.Faction == this.parent.pawn.Faction || pawn.IsPrisonerOfColony; + bool flag2 = pawn.HostileTo(this.parent.pawn); + bool flag3 = pawn.Downed; + if (!flag && !(flag2 && flag3)) + { + if (throwMessages) + { + if(flag2 && !flag3) + { + Messages.Message(pawn.Name + " is hostile, but not downed.", pawn, MessageTypeDefOf.RejectInput, false); + } + else if (!flag) + { + Messages.Message(pawn.Name + " is not a part of the colony or hostile.", pawn, MessageTypeDefOf.RejectInput, false); + } + } + return false; + } + if (!Genital_Helper.has_penis_fertile(pawn)) + { + if (throwMessages) + { + Messages.Message(pawn.Name + " has no penis", pawn, MessageTypeDefOf.RejectInput, false); + } + return false; + } + } + return base.Valid(target, throwMessages); + } + public override bool GizmoDisabled(out string reason) + { + Pawn_GeneTracker genes = this.parent.pawn.genes; + Gene_LifeForce gene_LifeForce = (genes != null) ? genes.GetFirstGeneOfType() : 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..d291185 --- /dev/null +++ b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_LifeForceCost.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using Verse; +using Verse.AI; +using RimWorld; +namespace RJW_Genes +{ + public class CompAbilityEffect_LifeForceCost : CompAbilityEffect + { + + public new CompProperties_AbilityLifeForceCost Props + { + get + { + return (CompProperties_AbilityLifeForceCost)this.props; + } + } + + private bool HasEnoughFertilin + { + get + { + Pawn_GeneTracker genes = this.parent.pawn.genes; + Gene_LifeForce gene_lifeforce = (genes != null) ? genes.GetFirstGeneOfType < Gene_LifeForce>() : null; + return gene_lifeforce != null && gene_lifeforce.Value >= this.Props.fertilinCost; + } + } + + public override void Apply(LocalTargetInfo target, LocalTargetInfo dest) + { + base.Apply(target, dest); + GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(this.parent.pawn), -this.Props.fertilinCost); + } + + + public override bool GizmoDisabled(out string reason) + { + Pawn_GeneTracker genes = this.parent.pawn.genes; + Gene_LifeForce gene_LifeForce = (genes != null) ? genes.GetFirstGeneOfType() : 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..009588d --- /dev/null +++ b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_PussyHeal.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using UnityEngine; +using RimWorld; +using rjw; +using rjw.Modules.Interactions.Helpers; + +namespace RJW_Genes +{ + public class CompAbilityEffect_PussyHeal : CompAbilityEffect + { + private new CompProperties_AbilityPussyHeal Props + { + get + { + return (CompProperties_AbilityPussyHeal)this.props; + } + } + public override void Apply(LocalTargetInfo target, LocalTargetInfo dest) + { + base.Apply(target, dest); + Pawn pawn = target.Pawn; + if (pawn == null) + { + return; + } + bool any_wound_tended = AbilityUtility.Heal(pawn, this.Props.tendQualityRange); + if (any_wound_tended) + { + MoteMaker.ThrowText(pawn.DrawPos, pawn.Map, "Sex healed wounds", 3.65f); + //pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.Pussy_Healed, pawn, null); + } + //this.AfterSex(any_wound_tended); + //FleckMaker.AttachedOverlay(pawn, FleckDefOf.FlashHollow, Vector3.zero, 1.5f, -1f); + } + + //Not yet implemented, but the heal should also trigger after normal sex + public void AfterSex(Pawn pawn, Pawn target) + { + List hediffs = target.health.hediffSet.hediffs; + for (int i = 0; i < hediffs.Count; i++) + { + if ((hediffs[i] is Hediff_Injury || hediffs[i] is Hediff_MissingPart) && hediffs[i].TendableNow(false)) + { + //target.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.Pussy_Healed, pawn, null); + break; + } + } + //InteractionHelper.GetWithExtension(dictionaryKey).DominantHasTag("CanBePenetrated") + + + } + + public override bool Valid(LocalTargetInfo target, bool throwMessages = false) + { + Pawn pawn = target.Pawn; + if (pawn != null) + { + //to be replaced with severel checks to make it clear why target is unable to have sex + if (!CasualSex_Helper.CanHaveSex(pawn)) + { + if (throwMessages) + { + Messages.Message(pawn.Name + " is unable to have sex", pawn, MessageTypeDefOf.RejectInput, false); + } + return false; + } + else if (pawn.IsAnimal() && !RJWSettings.bestiality_enabled) + { + if (throwMessages) + { + Messages.Message("bestiality is disabled", pawn, MessageTypeDefOf.RejectInput, false); + } + return false; + } + //AbilityUtility.ValidateHasTendableWound(pawn, throwMessages, this.parent); + + } + return base.Valid(target, throwMessages); + } + + public override bool GizmoDisabled(out string reason) + { + reason = null; + if (!Genital_Helper.has_vagina(this.parent.pawn)) + { + reason = this.parent.pawn.Name + " has no vagina to use."; + return true; + } + else if (!RJWSettings.rape_enabled) + { + reason = "Rape is disabled"; + return true; + } + return false; + } + + + } +} 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..678ab48 --- /dev/null +++ b/Source/Genes/Life_Force/Abilities/CompAbilityEffect_Seduce.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; +using Verse.AI; +using rjw; + +namespace RJW_Genes +{ + public class CompAbilityEffect_Seduce : CompAbilityEffect_WithDest + { + private new CompProperties_Seduce Props + { + get + { + return (CompProperties_Seduce)this.props; + } + } + public override void Apply(LocalTargetInfo target, LocalTargetInfo dest) + { + base.Apply(target, dest); + Pawn pawn = target.Thing as Pawn; + Pawn pawn2 = this.parent.pawn; + if (pawn != null && pawn2 != null && !pawn.Downed) + { + Job job = JobMaker.MakeJob(JobDefOf.rjw_genes_lifeforce_seduced, pawn2); + job.mote = MoteMaker.MakeThoughtBubble(pawn, this.parent.def.iconPath, true); + pawn.jobs.StopAll(false, true); + pawn.jobs.StartJob(job, JobCondition.InterruptForced, null, false, true, null, null, false, false, null, false, true); + } + } + + public override bool Valid(LocalTargetInfo target, bool throwMessages = false) + { + + Pawn pawn = target.Pawn; + if (pawn != null) + { + if (!xxx.can_be_fucked(pawn)) + { + if (throwMessages) + { + Messages.Message(pawn.Name + " is unable to have sex", pawn, MessageTypeDefOf.RejectInput, false); + } + return false; + } + else if (pawn.IsAnimal() && !RJWSettings.bestiality_enabled) + { + if (throwMessages) + { + Messages.Message("bestiality is disabled", pawn, MessageTypeDefOf.RejectInput, false); + } + return false; + } + else if (pawn.Downed) + { + if (throwMessages) + { + Messages.Message(pawn.Name + " is unable to move", pawn, MessageTypeDefOf.RejectInput, false); + } + return false; + } + + } + return base.Valid(target, throwMessages); + } + + public override bool GizmoDisabled(out string reason) + { + reason = null; + if (!RJWSettings.rape_enabled) + { + reason = "Rape is disabled"; + return true; + } + return false; + } + } +} 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_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/Alert_LowFertilin.cs b/Source/Genes/Life_Force/Alert_LowFertilin.cs new file mode 100644 index 0000000..2fb9fdc --- /dev/null +++ b/Source/Genes/Life_Force/Alert_LowFertilin.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RimWorld.Planet; +using Verse; +using RimWorld; +namespace RJW_Genes +{ + public class Alert_CriticalFertilin : Alert + { + private List 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.Value < gene_Lifeforce.MinLevelForAlert) + { + this.targets.Add(pawn); + this.targetLabels.Add(pawn.NameShortColored.Resolve()); + } + } + } + } + + public override TaggedString GetExplanation() + { + return "AlertLowFertilinDesc".Translate() + ":\n" + this.targetLabels.ToLineList(" - "); + } + + public override AlertReport GetReport() + { + return AlertReport.CulpritsAre(this.Targets); + } + + // Token: 0x04004B5C RID: 19292 + private List targets = new List(); + + // Token: 0x04004B5D RID: 19293 + private List targetLabels = new List(); + } +} diff --git a/Source/Genes/Life_Force/GeneGizmo_ResourceLifeForce.cs b/Source/Genes/Life_Force/GeneGizmo_ResourceLifeForce.cs new file mode 100644 index 0000000..f2b0055 --- /dev/null +++ b/Source/Genes/Life_Force/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) + { + this.draggableBar = true; + } + + public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms) + { + return base.GizmoOnGUI(topLeft, maxWidth, parms); + } + + protected override string GetTooltip() + { + + this.tmpDrainGenes.Clear(); + string text = string.Format("{0}: {1} / {2}\n", this.gene.ResourceLabel.CapitalizeFirst().Colorize(ColoredText.TipSectionTitleColor), this.gene.ValueForDisplay, this.gene.MaxForDisplay); + if (this.gene.pawn.IsColonistPlayerControlled || this.gene.pawn.IsPrisonerOfColony) + { + if (this.gene.targetValue <= 0f) + { + text += "NeverSeekFertilin"; + } + else + { + text = text + ("SeekFertilinBelow" + ": ") + this.gene.PostProcessValue(this.gene.targetValue); + } + } + if (!this.drainGenes.NullOrEmpty()) + { + 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/Genes/Life_Force/Gene_LifeForce.cs b/Source/Genes/Life_Force/Gene_LifeForce.cs new file mode 100644 index 0000000..c5cfa12 --- /dev/null +++ b/Source/Genes/Life_Force/Gene_LifeForce.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using Verse; +using RimWorld; +using rjw; + +namespace RJW_Genes +{ + public class Gene_LifeForce : Gene_Resource, IGeneResourceDrain + { + //Gene should only be active if sex is allowed for this pawn + public override bool Active + { + get + { + if (this.Overridden) + { + return false; + } + Pawn pawn = this.pawn; + + return ((pawn != null) ? pawn.ageTracker : null) == null || + ((float)this.pawn.ageTracker.AgeBiologicalYears >= this.def.minAgeActive && this.pawn.ageTracker.AgeBiologicalYears >= (RJWSettings.AllowYouthSex ? 13f : 18f)); + } + } + + 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; + } + foreach (Gizmo gizmo2 in GeneResourceDrainUtility.GetResourceDrainGizmos(this)) + { + yield return gizmo2; + } + yield break; + } + + //Depending on how low the value is it will increase sexdrive and if it reaches zero it will create a mental break which will make the pawn rape others. + //Not using base.Tick() as it is used to start mental breaks, but we have another way to do it. + public override void Tick() + { + //base.Tick(); + if (this.CanOffset && this.Resource != null) + { + GeneUtility.OffsetLifeForce(this, -this.ResourceLossPerDay / 60000f); + //this.Resource.Value -= this.ResourceLossPerDay / 60000; + if (this.Resource.Value <= 0 && this.pawn.IsHashIntervalTick(300)) + { + if (ModsConfig.BiotechActive && this.def.mentalBreakDef != null && + this.pawn.Spawned && !this.pawn.InMentalState && !this.pawn.Downed && + this.def.mentalBreakDef.Worker.BreakCanOccur(this.pawn)) + { + this.def.mentalBreakDef.Worker.TryStart(this.pawn, "MentalStateReason_Gene".Translate() + ": " + this.LabelCap, false); + } + } + } + } + + public bool StoredCumAllowed = true; + public Gene_Resource Resource + { + get + { + return this; + } + } + public Pawn Pawn + { + get + { + return this.pawn; + } + } + public bool CanOffset + { + get + { + return this.pawn.Spawned && this.Active; + } + } + + public float ResourceLossPerDay + { + get + { + return this.def.resourceLossPerDay; + } + } + + public string DisplayLabel + { + get + { + return this.def.resourceLabel; + } + } + + public override float InitialResourceMax + { + get + { + return 1f; + } + } + + public override float MinLevelForAlert + { + get + { + return 0.2f; + } + } + public override float MaxLevelOffset + { + get + { + return base.MaxLevelOffset; + } + } + protected override Color BarColor + { + get + { + return Color.grey; + } + } + protected override Color BarHighlightColor + { + get + { + return Color.white; + } + } + } +} diff --git a/Source/Genes/Life_Force/Gene_LifeForceDrain.cs b/Source/Genes/Life_Force/Gene_LifeForceDrain.cs new file mode 100644 index 0000000..335e257 --- /dev/null +++ b/Source/Genes/Life_Force/Gene_LifeForceDrain.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using Verse; +using RimWorld; + +namespace RJW_Genes +{ + public class Gene_LifeForceDrain : Gene, IGeneResourceDrain + { + public Gene_Resource Resource + { + get + { + if (this.cachedLifeForceGene == null || !this.cachedLifeForceGene.Active) + { + this.cachedLifeForceGene = this.pawn.genes.GetFirstGeneOfType(); + } + return this.cachedLifeForceGene; + } + } + + public bool CanOffset + { + get + { + return this.Active && this.Resource != null && this.Resource.Active; + } + } + + public float ResourceLossPerDay + { + get + { + return this.def.resourceLossPerDay; + } + } + + public Pawn Pawn + { + get + { + return this.pawn; + } + } + + public string DisplayLabel + { + get + { + return this.Label + " (" + "Gene".Translate() + ")"; + } + } + + public override void Tick() + { + base.Tick(); + if (this.CanOffset && this.Resource != null) + { + GeneUtility.OffsetLifeForce(this, -this.ResourceLossPerDay / 60000); + } + } + + public override IEnumerable GetGizmos() + { + foreach (Gizmo gizmo in GeneResourceDrainUtility.GetResourceDrainGizmos(this)) + { + yield return gizmo; + } + IEnumerator enumerator = null; + yield break; + yield break; + } + + [Unsaved(false)] + private Gene_LifeForce cachedLifeForceGene; + + private const float MinAgeForDrain = 3f; + } +} diff --git a/Source/Genes/Life_Force/HediffWithComps_tank.cs b/Source/Genes/Life_Force/HediffWithComps_tank.cs new file mode 100644 index 0000000..7dcea63 --- /dev/null +++ b/Source/Genes/Life_Force/HediffWithComps_tank.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RimWorld; +using Verse; +namespace RJW_Genes +{ + internal class HediffWithComps_tank : HediffWithComps + { + public override string LabelInBrackets + { + get + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append(base.LabelInBrackets); + stringBuilder.Append(this.Severity.ToStringPercent()); + return stringBuilder.ToString(); + } + } + } +} diff --git a/Source/Genes/Life_Force/IngestionOutcomeDoer_LifeForceOffset.cs b/Source/Genes/Life_Force/IngestionOutcomeDoer_LifeForceOffset.cs new file mode 100644 index 0000000..65e458e --- /dev/null +++ b/Source/Genes/Life_Force/IngestionOutcomeDoer_LifeForceOffset.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RimWorld; +using Verse; + +namespace RJW_Genes +{ + public class IngestionOutcomeDoer_LifeForceOffset : IngestionOutcomeDoer + { + protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) + { + if (GeneUtility.HasLifeForce(pawn)) + { + float num = ingested.stackCount * this.FertilinPerUnit / 100; + GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(pawn), num); + } + } + public float FertilinPerUnit = 1f; + } +} 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_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..6399e43 --- /dev/null +++ b/Source/Genes/Life_Force/JobDrivers/JobDriver_SexOnSpotReceiver.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RimWorld; +using Verse; +using Verse.AI; +using rjw; +using rjw.Modules.Interactions.Enums; +using rjw.Modules.Interactions.Helpers; +using rjw.Modules.Interactions.Objects; +using rjw.Modules.Interactions.Contexts; +using rjw.Modules.Interactions.Implementation; + +namespace RJW_Genes +{ + //Modified JobDriver_SexBaseRecieverLoved from rjw + public class JobDriver_SexOnSpotReciever : JobDriver_SexBaseReciever + { + protected override IEnumerable MakeNewToils() + { + base.setup_ticks(); + this.parteners.Add(base.Partner); + if (this.pawn.relations.OpinionOf(base.Partner) < 0) + { + this.ticks_between_hearts += 50; + } + else if (this.pawn.relations.OpinionOf(base.Partner) > 60) + { + this.ticks_between_hearts -= 25; + } + this.FailOnDespawnedOrNull(this.iTarget); + this.FailOn(() => !base.Partner.health.capacities.CanBeAwake); + this.FailOn(() => this.pawn.Drafted); + this.FailOn(() => base.Partner.Drafted); + yield return Toils_Reserve.Reserve(this.iTarget, 1, 0, null); + Toil toil2 = this.MakeSexToil(); + toil2.handlingFacing = false; + yield return toil2; + yield break; + } + + // Token: 0x06000420 RID: 1056 RVA: 0x00024190 File Offset: 0x00022390 + private Toil MakeSexToil() + { + Toil toil = new Toil(); + toil.defaultCompleteMode = ToilCompleteMode.Never; + toil.socialMode = RandomSocialMode.Off; + toil.handlingFacing = true; + toil.tickAction = delegate () + { + if (this.pawn.IsHashIntervalTick(this.ticks_between_hearts)) + { + base.ThrowMetaIconF(this.pawn.Position, this.pawn.Map, FleckDefOf.Heart); + } + }; + toil.AddEndCondition(delegate + { + if (this.parteners.Count <= 0) + { + return JobCondition.Succeeded; + } + return JobCondition.Ongoing; + }); + toil.AddFinishAction(delegate + { + if (xxx.is_human(this.pawn)) + { + this.pawn.Drawer.renderer.graphics.ResolveApparelGraphics(); + } + GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(this.pawn); + Hediff submitting = this.pawn.health.hediffSet.GetFirstHediffOfDef(xxx.submitting); + if (submitting != null) + { + this.pawn.health.RemoveHediff(submitting); + this.pawn.stances.stunner.StunFor(60, this.pawn, true, true); + } + }); + toil.socialMode = RandomSocialMode.Off; + return toil; + } + } +} diff --git a/Source/Genes/Life_Force/JobGiver_GetLifeForce.cs b/Source/Genes/Life_Force/JobGiver_GetLifeForce.cs new file mode 100644 index 0000000..b39d9cb --- /dev/null +++ b/Source/Genes/Life_Force/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("LustLicentia.RJWLabs") && gene_lifeforce.StoredCumAllowed) + { + Thing gatheredCum = this.GetStoredCum(pawn); + if (gatheredCum == null) + { + return null; + } + IngestionOutcomeDoer_LifeForceOffset ingestionOutcomeDoer = (IngestionOutcomeDoer_LifeForceOffset)gatheredCum.def.ingestible.outcomeDoers.First((IngestionOutcomeDoer x) => x is IngestionOutcomeDoer_LifeForceOffset); + if (ingestionOutcomeDoer == null) + { + return null; + } + int num = Mathf.RoundToInt(((gene_lifeforce.targetValue - gene_lifeforce.Value) * 100 + 10) / ingestionOutcomeDoer.FertilinPerUnit); + if (gatheredCum != null && num > 0) + { + Job job = JobMaker.MakeJob(RimWorld.JobDefOf.Ingest, gatheredCum); + job.count = Mathf.Min(gatheredCum.stackCount, num); + job.ingestTotalCount = true; + return job; + } + } + return null; + } + + //From JobGiver_GetHemogen, dont know exactly what this influences + public override float GetPriority(Pawn pawn) + { + if (!ModsConfig.BiotechActive) + { + return 0f; + } + Pawn_GeneTracker genes = pawn.genes; + if (((genes != null) ? genes.GetFirstGeneOfType() : 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/JobGiver_LifeForce_RandomRape.cs b/Source/Genes/Life_Force/JobGiver_LifeForce_RandomRape.cs new file mode 100644 index 0000000..f710c62 --- /dev/null +++ b/Source/Genes/Life_Force/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/LifeForceMentalBreakWorker.cs b/Source/Genes/Life_Force/LifeForceMentalBreakWorker.cs new file mode 100644 index 0000000..36b47b0 --- /dev/null +++ b/Source/Genes/Life_Force/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/LifeForceMentalState.cs b/Source/Genes/Life_Force/LifeForceMentalState.cs new file mode 100644 index 0000000..9c22f4e --- /dev/null +++ b/Source/Genes/Life_Force/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/LifeForceMentalStateWorker.cs b/Source/Genes/Life_Force/LifeForceMentalStateWorker.cs new file mode 100644 index 0000000..eaeaf89 --- /dev/null +++ b/Source/Genes/Life_Force/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/Patch_LifeForce.cs b/Source/Genes/Life_Force/Patch_LifeForce.cs new file mode 100644 index 0000000..f4eb817 --- /dev/null +++ b/Source/Genes/Life_Force/Patch_LifeForce.cs @@ -0,0 +1,180 @@ +using HarmonyLib; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RimWorld; +using Verse; + +namespace RJW_Genes +{ + + [HarmonyPatch(typeof(SexUtility), nameof(SexUtility.SatisfyPersonal))] + public static class Patch_LifeForce + { + public static void Postfix(SexProps props) + { + // ShortCuts: Exit Early if Pawn or Partner are null (can happen with Animals or Masturbation) + if (props.pawn == null || !props.hasPartner()) + return; + + // Exit if pawn has fertilin themself, it won't give any if it has lifeforce themself. + if (GeneUtility.HasLifeForce(props.pawn)) + { + return; + } + + //Summary// + //We use the positions of the pawn (dom or sub) and based on that which interactions will transfer fertilin + //By checking isreceiver we know if the succubus is the dom or the sub and if the situation is reverse we also swap the function we use + // + float absorb_factor = 0f; + if (GeneUtility.HasLifeForce(props.partner)) + { + Pawn succubus = props.partner; + + if (!props.isRevese) + { + if (props.isReceiver) + { + // Scenario Dom Succubus, normal + absorb_factor = BaseDom(props, succubus); + } + else + { + // Scenario Sub Succubus, normal + absorb_factor = BaseSub(props, succubus); + } + } + else + { + if (props.isReceiver) + { + // Scenario Dom Succubus, Reverse + absorb_factor = BaseSub(props, succubus); + } + else + { + // Scenario Sub Succubus, Reverse + absorb_factor = BaseDom(props, succubus); + } + } + + //If we remove this check fertelin is always lost, but the succubus doesn't always gain any + if (absorb_factor != 0f) + { + AbsorbFertilin(props, absorb_factor); + } + + if (GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_drainer) && !props.pawn.health.hediffSet.HasHediff(HediffDefOf.Succubus_Drained)) + { + props.pawn.health.AddHediff(HediffDefOf.Succubus_Drained); + GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(succubus), 0.25f); + } + } + } + public static void AbsorbFertilin(SexProps props, float absorb_factor = 1f) + { + Pawn_GeneTracker genes = props.partner.genes; + Gene_LifeForce gene = genes.GetFirstGeneOfType(); + Hediff fertilin_lost = props.pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Fertilin_Lost); + //Around quarter get ejected everytime pawn cums + float multiplier = Rand.Range(0.10f, 0.40f); + + + //Create a new ferilin_lost hediff or reduce multiplier + if (fertilin_lost == null) + { + Hediff new_fertilin_lost = HediffMaker.MakeHediff(HediffDefOf.Fertilin_Lost, props.pawn); + props.pawn.health.AddHediff(new_fertilin_lost); + new_fertilin_lost.Severity = multiplier; + } + else + { + multiplier *= 1 - fertilin_lost.Severity; + fertilin_lost.Severity += multiplier; + } + //More in the tank means more to give + if (props.pawn.Has(Quirk.Messy)) + { + multiplier *= 2; + } + //Currently taking the sum of all penises, maybe I should just consider one at random + float valuechange = CumUtility.GetTotalFluidAmount(props.pawn) / 100 * absorb_factor * multiplier; + GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(props.partner), valuechange); + //gene.Resource.Value += CumUtility.GetTotalFluidAmount(props.pawn) / 100 * absorb_factor * multiplier; + } + + + public static float BaseDom(SexProps props, Pawn succubus) + { + float absorb_factor = 0f; + if (props.sexType == xxx.rjwSextype.Sixtynine) + { + absorb_factor += 1f; + + } + else if (props.sexType == xxx.rjwSextype.Vaginal) + { + //with insertion absorbtion or vaginal cum absorbtion + //absorb_factor += 1f; + } + else if (props.sexType == xxx.rjwSextype.DoublePenetration) + { + if (GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_vaginal_absorber)) + { + //with insertion absorbtion? + //absorb_factor += 0.5f; + } + if (GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_anal_absorber)) + { + //with insertion absorbtion? + //absorb_factor += 0.5f; + } + } + else if (props.sexType == xxx.rjwSextype.Scissoring) + { + //with vaginal cum absorption && vaginal absorbtion + //absorb_factor += 1f; + } + return absorb_factor; + } + + public static float BaseSub(SexProps props, Pawn succubus) + { + float absorb_factor = 0f; + if (props.sexType == xxx.rjwSextype.Oral || props.sexType == xxx.rjwSextype.Fellatio || props.sexType == xxx.rjwSextype.Sixtynine) + { + absorb_factor += 1f; + + } + else if (props.sexType == xxx.rjwSextype.Vaginal && GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_vaginal_absorber)) + { + absorb_factor += 1f; + } + else if (props.sexType == xxx.rjwSextype.Anal && GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_anal_absorber)) + { + absorb_factor += 1f; + } + else if (props.sexType == xxx.rjwSextype.DoublePenetration) + { + if (GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_vaginal_absorber)) + { + absorb_factor += 0.5f; + } + if (GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_anal_absorber)) + { + absorb_factor += 0.5f; + } + } + else if (props.sexType == xxx.rjwSextype.Scissoring || props.sexType == xxx.rjwSextype.Cunnilingus) + { + //with vaginal cum absorbtion + //absorb_factor += 1f; + } + return absorb_factor; + } + } +} diff --git a/Source/Genes/Life_Force/Patch_SexTicks_ChangePsyfocus.cs b/Source/Genes/Life_Force/Patch_SexTicks_ChangePsyfocus.cs new file mode 100644 index 0000000..dd3444b --- /dev/null +++ b/Source/Genes/Life_Force/Patch_SexTicks_ChangePsyfocus.cs @@ -0,0 +1,57 @@ +using HarmonyLib; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RimWorld; +using Verse; + +namespace RJW_Genes +{ + + //[HarmonyPatch(typeof(JobDriver_Sex), nameof(JobDriver_Sex.ChangePsyfocus))] + public static class Patch_SexTicks_ChangePsyfocus + { + //Using ChangePsyfocus as it is something that fires every 60 ticks + public static void Postfix(ref JobDriver_Sex __instance, ref Pawn pawn, ref Thing target) + { + if (__instance.Sexprops.sexType == xxx.rjwSextype.Cunnilingus) + { + if (target != null) + { + Pawn pawn2 = target as Pawn; + if (pawn2 != null) + { + //We need who the pawn on top is and if reverse we need to make the sub the pawn on top + if (__instance.Sexprops.isRevese) + { + + DrinkCumflation(pawn2, pawn); + } + else + { + // + DrinkCumflation(pawn, pawn2); + return; + } + } + } + + } + } + + public static void DrinkCumflation(Pawn dom, Pawn sub) + { + if (GeneUtility.HasLifeForce(sub) && dom.health.hediffSet.HasHediff(HediffDef.Named("Cumflation"))) + { + Hediff cumflation = dom.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("Cumflation")); + Gene_LifeForce gene_LifeForce = sub.genes.GetFirstGeneOfType(); + cumflation.Severity -= 0.1f; + gene_LifeForce.Resource.Value += 0.05f; + } + } + //Maybe I can store gene and hediff so I dont need to look them up every time + } +} diff --git a/Source/Genes/Life_Force/ThinkNode_ConditionalCritcalLifeForce.cs b/Source/Genes/Life_Force/ThinkNode_ConditionalCritcalLifeForce.cs new file mode 100644 index 0000000..dbb3f6b --- /dev/null +++ b/Source/Genes/Life_Force/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/ThinkNode_ConditionalLowLifeForce.cs b/Source/Genes/Life_Force/ThinkNode_ConditionalLowLifeForce.cs new file mode 100644 index 0000000..0e71ce7 --- /dev/null +++ b/Source/Genes/Life_Force/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/Special/Gene_Aphrodisiac_Pheromones_.cs b/Source/Genes/Special/Gene_Aphrodisiac_Pheromones_.cs index 267f625..d9f4341 100644 --- a/Source/Genes/Special/Gene_Aphrodisiac_Pheromones_.cs +++ b/Source/Genes/Special/Gene_Aphrodisiac_Pheromones_.cs @@ -12,23 +12,31 @@ namespace RJW_Genes { public class Gene_Aphrodisiac_Pheromones : Gene { + + //Summary one every one check for all pawns nearby and in line of sight and add/renew a hediff which increases sexdrive for six hours. public override void Tick() { base.Tick(); if (this.pawn.IsHashIntervalTick(2500)) { - foreach (Pawn pawn in this.AffectedPawns(this.pawn.Position, this.pawn.Map)) - { - this.InduceAphrodisiac(pawn); - } + //Only spread pheromones if sexdrive above 1 + float sexfrequency = this.pawn.GetStatValue(StatDef.Named("SexFrequency")); + if(sexfrequency > 1f) + { + foreach (Pawn pawn in this.AffectedPawns(this.pawn.Position, this.pawn.Map)) + { + this.InduceAphrodisiac(pawn, sexfrequency); + } + } } } + //Creatus an IEnumerable of all pawns which are closeby and in lineofsight, self and other pawns with aphrodisiac pheromones gene are skipped. private IEnumerable AffectedPawns(IntVec3 pos, Map map) { foreach (Pawn pawn in map.mapPawns.AllPawns) { - if (pos.DistanceTo(pawn.Position) < 5) + if (this.pawn != null && pawn != this.pawn && pos.DistanceTo(pawn.Position) < 5 && GenSight.LineOfSight(pos, pawn.Position, pawn.Map) && !GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_aphrodisiac_pheromones)) { yield return pawn; } @@ -37,17 +45,36 @@ namespace RJW_Genes yield break; } - private void InduceAphrodisiac(Pawn pawn) + //Applies er renews a hediff which increases sexdrive for 6 hours + private void InduceAphrodisiac(Pawn pawn, float sexfrequency) { Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Aphrodisiac_Pheromone); + if (hediff != null) { hediff.Severity = 1f; } else { - pawn.health.AddHediff(HediffDefOf.Aphrodisiac_Pheromone); + Hediff aphrodisiac = HediffMaker.MakeHediff(HediffDefOf.Aphrodisiac_Pheromone, pawn); + foreach (StatModifier stat in aphrodisiac.CurStage.statFactors) + { + //Log.Message(pawn.Name.ToString()); + //Log.Message(stat.stat.defName); + //Log.Message(stat.value.ToString()); + if (stat.stat.defName == "SexFrequency") + { + stat.value = ModifySexfrequency(pawn, sexfrequency); + pawn.health.AddHediff(aphrodisiac); + } + } } } + + //Function to modify aphrodisiac strength, currently has no effect, but it's an easy hook for other modders. + public float ModifySexfrequency(Pawn pawn, float sexfrequency) + { + return sexfrequency; + } } } diff --git a/Source/HarmonyInit.cs b/Source/HarmonyInit.cs index 35ffb2e..8c5f3d6 100644 --- a/Source/HarmonyInit.cs +++ b/Source/HarmonyInit.cs @@ -27,6 +27,8 @@ namespace RJW_Genes // Gene: Generous Donor [Postfix Patch] harmony.Patch(AccessTools.Method(typeof(LicentiaLabs.CumflationHelper), nameof(LicentiaLabs.CumflationHelper.TransferNutrition)), postfix: new HarmonyMethod(typeof(Patch_TransferNutrition), nameof(Patch_TransferNutrition.Postfix))); + harmony.Patch(AccessTools.Method(typeof(rjw.JobDriver_Sex), nameof(rjw.JobDriver_Sex.ChangePsyfocus)), + postfix: new HarmonyMethod(typeof(Patch_SexTicks_ChangePsyfocus), nameof(Patch_SexTicks_ChangePsyfocus.Postfix))); } }))(); } diff --git a/Source/HediffDefOf.cs b/Source/HediffDefOf.cs index 9e70ad2..b0425ec 100644 --- a/Source/HediffDefOf.cs +++ b/Source/HediffDefOf.cs @@ -12,5 +12,7 @@ namespace RJW_Genes public static class HediffDefOf { public static readonly HediffDef Aphrodisiac_Pheromone; + public static readonly HediffDef Fertilin_Lost; + public static readonly HediffDef Succubus_Drained; } } diff --git a/Source/Interactions/CompAbility_SexInteractionRequirements.cs b/Source/Interactions/CompAbility_SexInteractionRequirements.cs new file mode 100644 index 0000000..f3b9c26 --- /dev/null +++ b/Source/Interactions/CompAbility_SexInteractionRequirements.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 CompAbility_SexInteractionRequirements : AbilityComp + { + public CompProperties_SexInteractionRequirements Props + { + get + { + return (CompProperties_SexInteractionRequirements)this.props; + } + } + + + } +} diff --git a/Source/Interactions/CompProperties_SexInteractionRequirements.cs b/Source/Interactions/CompProperties_SexInteractionRequirements.cs new file mode 100644 index 0000000..3756d7b --- /dev/null +++ b/Source/Interactions/CompProperties_SexInteractionRequirements.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; +using rjw; +using rjw.Modules.Interactions.Defs.DefFragment; +using rjw.Modules.Interactions.Enums; + +namespace RJW_Genes +{ + public class CompProperties_SexInteractionRequirements : AbilityCompProperties + { + public CompProperties_SexInteractionRequirements() + { + this.compClass = typeof(CompAbility_SexInteractionRequirements); + } + + public List tags = new List(); + public InteractionRequirement dominantRequirement; + public InteractionRequirement submissiveRequirement; + } +} diff --git a/Source/Interactions/CustomSexInteraction_Helper.cs b/Source/Interactions/CustomSexInteraction_Helper.cs new file mode 100644 index 0000000..4e69462 --- /dev/null +++ b/Source/Interactions/CustomSexInteraction_Helper.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; +using rjw; +using rjw.Modules.Interactions.Objects; +using rjw.Modules.Interactions.Helpers; +using rjw.Modules.Interactions.Enums; +using rjw.Modules.Interactions.Implementation; +using rjw.Modules.Interactions.Defs.DefFragment; +namespace RJW_Genes +{ + public class CustomSexInteraction_Helper + { + public static List GenerateInteractionDefList(Pawn pawn, Pawn pawn2, CompProperties_SexInteractionRequirements sexpropsreq) + { + List tags = new List(); + if (pawn2.IsAnimal()) + { + tags.Add(InteractionTag.Animal); + + } + else + { + tags = sexpropsreq.tags; + } + + InteractionRequirement dominantRequirement = sexpropsreq.dominantRequirement; + InteractionRequirement submissiveRequirement = sexpropsreq.submissiveRequirement; + List list = new List(); + //List a = from interaction in sexinteractions + //where InteractionHelper.GetWithExtension(interaction).DominantHasFamily(dominantRequirement.families.) + // select interaction; + + //should use where select but dont fully understand that, so I am using this. + foreach (InteractionDef interactionDef in SexUtility.SexInterractions) + { + //Use rjw function to check if the interaction would be valid + if (!LewdInteractionValidatorService.Instance.IsValid(interactionDef, pawn, pawn2)) + { + continue; + } + InteractionWithExtension withExtension = InteractionHelper.GetWithExtension(interactionDef); + bool add_interaction = false; + //only add interactions which have a correct tag + foreach (InteractionTag tag in tags) + { + if (withExtension.HasInteractionTag(tag)) + { + add_interaction = true; + break; + } + } + //In case of failure go to next interaction + if (!add_interaction) + { + continue; + } + //goes to next interaction if it doesn't have the required genitals + if (dominantRequirement != null) + { + foreach (GenitalFamily genitalFamily in dominantRequirement.families) + { + if (!withExtension.DominantHasFamily(genitalFamily)) + { + add_interaction = false; + break; + + } + } + if (!add_interaction) + { + continue; + } + foreach (GenitalTag tag in dominantRequirement.tags) + { + if (!withExtension.DominantHasTag(tag)) + { + add_interaction = false; + break; + + } + } + } + //goes to next interaction if it doesn't have the required genitals + if (submissiveRequirement != null) + { + foreach (GenitalFamily genitalFamily in submissiveRequirement.families) + { + if (!withExtension.SubmissiveHasFamily(genitalFamily)) + { + add_interaction = false; + break; + + } + } + if (!add_interaction) + { + continue; + } + foreach (GenitalTag tag in submissiveRequirement.tags) + { + if (!withExtension.SubmissiveHasTag(tag)) + { + add_interaction = false; + break; + + } + + } + } + if (add_interaction) + { + list.Add(interactionDef); + } + + } + return list; + } + + //Generates a valid interaction for the requirements and assigns sexprops based on that + public static SexProps GenerateSexProps(Pawn pawn, Pawn pawn2, CompProperties_SexInteractionRequirements sexpropsreq) + { + List interactionlist = GenerateInteractionDefList(pawn, pawn2, sexpropsreq); + if (!interactionlist.Any()) + { + return null; + } + InteractionDef dictionaryKey = interactionlist.RandomElement(); + bool rape = InteractionHelper.GetWithExtension(dictionaryKey).HasInteractionTag(InteractionTag.Rape); + SexProps sexProps = new SexProps(); + sexProps.pawn = pawn; + sexProps.partner = pawn2; + sexProps.sexType = SexUtility.rjwSextypeGet(dictionaryKey); + sexProps.isRape = rape; + sexProps.isRapist = rape; + sexProps.canBeGuilty = false; + sexProps.dictionaryKey = dictionaryKey; + sexProps.rulePack = SexUtility.SexRulePackGet(dictionaryKey); + return sexProps; + } + } +} diff --git a/Source/Interactions/DomSuccubusTailCustomRequirementHandler.cs b/Source/Interactions/DomSuccubusTailCustomRequirementHandler.cs new file mode 100644 index 0000000..cfa3ebf --- /dev/null +++ b/Source/Interactions/DomSuccubusTailCustomRequirementHandler.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; +using rjw.Modules.Interactions; +using rjw.Modules.Interactions.Internals.Implementation; +using rjw.Modules.Interactions.Objects; +using rjw; +using rjw.Modules.Interactions.Enums; + +//Modefied code based of RJW-AI code at https://gitgud.io/Ed86/rjw-ia/-/tree/master/ +namespace RJW_Genes +{ + [StaticConstructorOnStartup] + public class DomSuccubusTailCustomRequirementHandler : ICustomRequirementHandler + { + public string HandlerKey + { + get + { + return "DomSuccubusTailCustomRequirementHandler"; + } + } + + + static DomSuccubusTailCustomRequirementHandler() + { + Register(); + } + public static void Register() + { + InteractionRequirementService.CustomRequirementHandlers.Add(new DomSuccubusTailCustomRequirementHandler()); + if (Prefs.DevMode) + { + Log.Message("DomSuccubusTailCustomRequirementHandler registered: "); + } + } + + public bool FufillRequirements(InteractionWithExtension interaction, InteractionPawn dominant, InteractionPawn submissive) + { + if (GeneUtility.HasGeneNullCheck(dominant.Pawn, GeneDefOf.rjw_genes_succubus_tail)) + { + return true; + } + return false; + } + //public static readonly StringListDef filter = DefDatabase.GetNamed("DomSuccubusTailFilter"); + } +} diff --git a/Source/Interactions/GenesPartKindUsageRule.cs b/Source/Interactions/GenesPartKindUsageRule.cs new file mode 100644 index 0000000..6c0f53c --- /dev/null +++ b/Source/Interactions/GenesPartKindUsageRule.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using rjw; +using rjw.Modules.Interactions.Contexts; +using rjw.Modules.Interactions.Enums; +using rjw.Modules.Interactions.Rules.PartKindUsageRules; +using rjw.Modules.Shared; +using Verse; + +namespace RJW_Genes.Interactions +{ + //Summary// + //Set custom preferences for pawn. Gets integrated to rjw by AddtoIPartPreferenceRule in First + //Depending on the level of lifeforce increase the chance for using the mouth. + public class GenesPartKindUsageRule : IPartPreferenceRule + { + public IEnumerable> ModifiersForDominant(InteractionContext context) + { + Pawn pawn = context.Internals.Dominant.Pawn; + if (GeneUtility.HasCriticalLifeForce(pawn)) + { + yield return new Weighted(50f, LewdablePartKind.Mouth); + } + else if (GeneUtility.HasLowLifeForce(pawn)) + { + yield return new Weighted(10f, LewdablePartKind.Mouth); + } + else if (GeneUtility.HasLifeForce(pawn)) + { + yield return new Weighted(2f, LewdablePartKind.Mouth); + } + yield break; + } + + public IEnumerable> ModifiersForSubmissive(InteractionContext context) + { + Pawn pawn = context.Internals.Submissive.Pawn; + if (GeneUtility.HasCriticalLifeForce(pawn)) + { + yield return new Weighted(50f, LewdablePartKind.Mouth); + } + else if (GeneUtility.HasLowLifeForce(pawn)) + { + yield return new Weighted(10f, LewdablePartKind.Mouth); + } + else if (GeneUtility.HasLifeForce(pawn)) + { + yield return new Weighted(2f, LewdablePartKind.Mouth); + } + yield break; + } + } +} diff --git a/Source/Interactions/SubSuccubusTailCustomRequirementHandler - Copy.cs b/Source/Interactions/SubSuccubusTailCustomRequirementHandler - Copy.cs new file mode 100644 index 0000000..5824aa5 --- /dev/null +++ b/Source/Interactions/SubSuccubusTailCustomRequirementHandler - Copy.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; +using rjw.Modules.Interactions; +using rjw.Modules.Interactions.Internals.Implementation; +using rjw.Modules.Interactions.Objects; +using rjw; +using rjw.Modules.Interactions.Enums; + +//Modefied code based of RJW-AI code at https://gitgud.io/Ed86/rjw-ia/-/tree/master/ +namespace RJW_Genes +{ + [StaticConstructorOnStartup] + public class SubSuccubusTailCustomRequirementHandler : ICustomRequirementHandler + { + public string HandlerKey + { + get + { + return "SubSuccubusTailCustomRequirementHandler"; + } + } + + + static SubSuccubusTailCustomRequirementHandler() + { + Register(); + } + public static void Register() + { + InteractionRequirementService.CustomRequirementHandlers.Add(new SubSuccubusTailCustomRequirementHandler()); + if (Prefs.DevMode) + { + Log.Message("SubSuccubusTailCustomRequirementHandler registered: "); + } + } + + public bool FufillRequirements(InteractionWithExtension interaction, InteractionPawn dominant, InteractionPawn submissive) + { + if (GeneUtility.HasGeneNullCheck(submissive.Pawn, GeneDefOf.rjw_genes_succubus_tail)) + { + return true; + } + return false; + } + //public static readonly StringListDef filter = DefDatabase.GetNamed("SubSuccubusTailFilter"); + } +} diff --git a/Source/JobDefOf.cs b/Source/JobDefOf.cs new file mode 100644 index 0000000..8bae1fa --- /dev/null +++ b/Source/JobDefOf.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 +{ + [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; + } +} diff --git a/Source/Rjw-Genes.csproj b/Source/Rjw-Genes.csproj index 9473ed9..df23439 100644 --- a/Source/Rjw-Genes.csproj +++ b/Source/Rjw-Genes.csproj @@ -27,14 +27,14 @@ False - ..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll + ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\Assembly-CSharp.dll ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\Mods\licentia-labs-master\Assemblies\LicentiaLabs.dll False - ..\..\rjw\1.4\Assemblies\RJW.dll + ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\Mods\rjw-master\1.4\Assemblies\RJW.dll @@ -49,11 +49,11 @@ - ..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll + ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.dll False - ..\..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll + ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll ..\..\..\RimWorldWin64_Data\Managed\UnityEngine.IMGUIModule.dll @@ -117,19 +117,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/ThoughtDefOf.cs b/Source/ThoughtDefOf.cs new file mode 100644 index 0000000..02a4aac --- /dev/null +++ b/Source/ThoughtDefOf.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RimWorld; +using Verse; +namespace RJW_Genes +{ + [DefOf] + public static class ThoughtDefOf + { + public static readonly ThoughtDef rjw_genes_cock_eaten; + public static readonly ThoughtDef rjw_genes_seduced; + public static readonly ThoughtDef rjw_critical_fertilin; + } +}