diff --git a/Common/Assemblies/Rjw-Genes.dll b/Common/Assemblies/Rjw-Genes.dll index 4b6ffe9..0738b37 100644 Binary files a/Common/Assemblies/Rjw-Genes.dll and b/Common/Assemblies/Rjw-Genes.dll differ diff --git a/Common/Defs/AbilityDefs/Ability_PussyHeal.xml b/Common/Defs/AbilityDefs/Ability_PussyHeal.xml index 1887160..8f97b60 100644 --- a/Common/Defs/AbilityDefs/Ability_PussyHeal.xml +++ b/Common/Defs/AbilityDefs/Ability_PussyHeal.xml @@ -30,7 +30,7 @@
  • 0.2
  • -
  • +
  • 0.4~0.8
  • diff --git a/Common/Defs/DutyDefs/Duties_Succubus.xml b/Common/Defs/DutyDefs/Duties_Succubus.xml new file mode 100644 index 0000000..f441c6f --- /dev/null +++ b/Common/Defs/DutyDefs/Duties_Succubus.xml @@ -0,0 +1,69 @@ + + + + rjw_genes_flirt + + + +
  • + SatisfyingNeeds + +
  • + +
  • +
  • +
  • +
  • + +
  • + + + + +
  • + +
  • + +
  • + +
  • + 0.05 + +
  • + +
  • + + +
  • + +
  • + + +
  • + +
  • +
  • +
  • + +
  • + +
  • + 0.1 + +
  • + +
  • + + + + +
  • + +
  • + 5 +
  • + + + + + diff --git a/Common/Defs/Genes/GeneDefs_LifeForce.xml b/Common/Defs/Genes/GeneDefs_LifeForce.xml index b9b87c3..efa275e 100644 --- a/Common/Defs/Genes/GeneDefs_LifeForce.xml +++ b/Common/Defs/Genes/GeneDefs_LifeForce.xml @@ -27,7 +27,6 @@
  • fert
  • - rjw_genes_lifeforce_randomrape 0.05 1 1 @@ -50,7 +49,7 @@ - rjw_genes_pussyhealer + rjw_genes_pussyhealing pussyhealer Carriers of this gene are able use vaginal sex to tend to other's wounds. @@ -152,10 +151,21 @@ + + rjw_genes_cum_eater + + Carriers of this gene are able to absorb fertilin through eating cum. + Things/Mote/Heart + rjw_genes_lifeforce + 1 + rjw_genes_fertilin + 1 + + rjw_genes_vaginal_absorber - Carriers of this gene are able to absorb fertilin through their vagina. + Carriers of this gene are able to absorb the fertilin inside sperm through their vagina. Things/Mote/Heart rjw_genes_lifeforce 2 @@ -166,7 +176,7 @@ rjw_genes_anal_absorber - Carriers of this gene are able to absorb fertilin through their anus. + Carriers of this gene are able to absorb the fertilin inside sperm through their anus. Things/Mote/Heart rjw_genes_lifeforce 3 diff --git a/Common/Defs/HediffDefs/Hediffs_Genes.xml b/Common/Defs/HediffDefs/Hediffs_Succubus.xml similarity index 58% rename from Common/Defs/HediffDefs/Hediffs_Genes.xml rename to Common/Defs/HediffDefs/Hediffs_Succubus.xml index c25b9b3..cb01a23 100644 --- a/Common/Defs/HediffDefs/Hediffs_Genes.xml +++ b/Common/Defs/HediffDefs/Hediffs_Succubus.xml @@ -4,7 +4,7 @@ rjw_genes_aphrodisiac_pheromone HediffWithComps - Aphrodisiac pheromone effects. + sex drive increasing due to smelling aphrodisiac pheromones. (1,0,0.5) 1.0 @@ -16,7 +16,7 @@
  • true - 2 + 2
  • @@ -24,7 +24,7 @@ rjw_genes_fertilin_lost - RJW_Genes.HediffWithComps_tank + Hediff_HemogenCraving Percentage of fertilin lost. (1,1,1) @@ -86,4 +86,54 @@ + + + rjw_genes_fertilin_craving + + Hediff_HemogenCraving + weakened due to running out of fertilin. + (1,0,0.5) + 1.0 + 0.01 + +
  • + + 0.05 + +
  • + Consciousness + 0.9 +
  • + + +
  • + + 0.35 + 0.1 + +
  • + Consciousness + 0.8 +
  • + + +
  • + + 0.7 + 0.15 + +
  • + Consciousness + 0.5 +
  • + + +
    + +
  • + 0.05 + -0.1 +
  • +
    +
    \ No newline at end of file diff --git a/Common/Defs/IncidentsDefs/Incidents_Succubus.xml b/Common/Defs/IncidentsDefs/Incidents_Succubus.xml new file mode 100644 index 0000000..297aca5 --- /dev/null +++ b/Common/Defs/IncidentsDefs/Incidents_Succubus.xml @@ -0,0 +1,16 @@ + + + + + SuccubusDreamVisit + + Misc + +
  • Map_PlayerHome
  • +
    + RJW_Genes.IncidentWorker_SuccubusDreamVisit + 1.0 + 10 + false +
    +
    \ No newline at end of file diff --git a/Common/Defs/InteractionDef/Interactions_Flirt.xml b/Common/Defs/InteractionDef/Interactions_Flirt.xml new file mode 100644 index 0000000..27c5408 --- /dev/null +++ b/Common/Defs/InteractionDef/Interactions_Flirt.xml @@ -0,0 +1,33 @@ + + + + + + + rjw_genes_flirt + + Things/Mote/SpeechSymbols/Chitchat + + +
  • r_logentry->[INITIATOR_nameDef] and [RECIPIENT_nameDef] [talkedabout] [TalkTopicLight].
  • +
  • r_logentry->[INITIATOR_nameDef] [talkedabout] [TalkTopicLight] with [RECIPIENT_nameDef].
  • +
  • r_logentry(p=0.8)->[INITIATOR_nameDef] [commentedabout] [TalkTopicLight] to [RECIPIENT_nameDef].
  • + +
  • talkedabout(p=4)->chatted about
  • +
  • talkedabout->shared a word about
  • +
  • talkedabout->spoke about
  • +
  • talkedabout->gabbed about
  • +
  • talkedabout->talked about
  • +
  • talkedabout->joked about
  • +
  • talkedabout->quipped about
  • + +
  • commentedabout->said something about
  • +
  • commentedabout->said a word about
  • +
  • commentedabout->made a comment about
  • +
  • commentedabout->commented about
  • +
  • commentedabout->told a joke about
  • + +
    +
    +
    +
    diff --git a/Common/Defs/JobDefs/Jobs_LifeForce.xml b/Common/Defs/JobDefs/Jobs_LifeForce.xml index 6992ddd..3e35062 100644 --- a/Common/Defs/JobDefs/Jobs_LifeForce.xml +++ b/Common/Defs/JobDefs/Jobs_LifeForce.xml @@ -22,4 +22,11 @@ false false + + + rjw_genes_flirt + RJW_Genes.JobDriver_Flirt + Seduced. + false + \ No newline at end of file diff --git a/Common/Defs/PawnKindDefs/PawnKind_Succubus.xml b/Common/Defs/PawnKindDefs/PawnKind_Succubus.xml new file mode 100644 index 0000000..7ac7a42 --- /dev/null +++ b/Common/Defs/PawnKindDefs/PawnKind_Succubus.xml @@ -0,0 +1,45 @@ + + + + + rjw_genes_succubus + + 50 + Human + + + 999 + + + 0.5 + false + 18 + 27 + Poor + 0.0 + false + + 0.3 + 0.9 + + true + +
  • Tribal
  • +
    + + 0 + 0 + + 0 + + 0 + 0 + + +
  • Poor
  • +
    + 0.0 + 2~4 + 28~44 +
    +
    \ No newline at end of file diff --git a/Common/Defs/ThoughtDefs/Thoughts_LifeForce.xml b/Common/Defs/ThoughtDefs/Thoughts_LifeForce.xml index bca1f93..a43d67f 100644 --- a/Common/Defs/ThoughtDefs/Thoughts_LifeForce.xml +++ b/Common/Defs/ThoughtDefs/Thoughts_LifeForce.xml @@ -32,13 +32,25 @@ - rjw_critical_fertilin - -
  • - - I'm almost out of fertilin. I'm scared of losing control. - -10 -
  • -
    -
    + rjw_genes_critical_fertilin + ThoughtWorker_Hediff + rjw_genes_fertilin_craving + +
  • + + My bones ache. I really need fertilin. + -10 +
  • +
  • + + This hurts bad and I can't stop thinking about sex. I would do anything for some cum. + -15 +
  • +
  • + + Can't think. Sex. Sex. Must. Have. Cum. + -20 +
  • +
    + diff --git a/Common/Defs/Xenotypes/Succubus.xml b/Common/Defs/Xenotypes/Succubus.xml index 41f3ff7..b3967c6 100644 --- a/Common/Defs/Xenotypes/Succubus.xml +++ b/Common/Defs/Xenotypes/Succubus.xml @@ -5,7 +5,7 @@ rjw_genes_succubus Succubi are strongly enhanced xenohumans. Powered by archites, their abilities go far beyond normal genetic enhancements. These overnaturally beautiful creatures strive parasitically on the Fertilin found in semen. - Succubi are beautiful and extremely hungry Xenohumans. They strive on having sex and extracting their victims life-force through this. + Succubi are beautiful and extremely hungry Xenohumans. They strive on having sex and extracting their victims life-force through this. UI/Icons/Xenotypes/Sanguophage PawnBecameSanguophage 0.5 @@ -13,6 +13,7 @@ 1 -1000 0.005 + true 0.02 0.02 @@ -30,12 +31,10 @@
  • rjw_genes_vaginal_absorber
  • rjw_genes_anal_absorber
  • -
  • rjw_genes_drainer
  • - -
  • rjw_genes_pussyhealer
  • rjw_genes_paralysingkiss
  • rjw_genes_seduce
  • rjw_genes_elasticity
  • +
  • rjw_genes_succubus_wings
  • rjw_genes_succubus_tail
  • rjw_genes_aphrodisiac_pheromones
  • diff --git a/Common/Languages/English/Keyed/Lifeforce.xml b/Common/Languages/English/Keyed/Lifeforce.xml index 23d3f75..ddd1344 100644 --- a/Common/Languages/English/Keyed/Lifeforce.xml +++ b/Common/Languages/English/Keyed/Lifeforce.xml @@ -3,8 +3,13 @@ Pawn doesn't have required fertilin gene. Not enough fertilin to cast. - + This happened because of low fertilin. 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 + + + + The succubus has fed enough on your colonists and will now leave. + \ No newline at end of file diff --git a/Source/GeneDefOf.cs b/Source/GeneDefOf.cs index 64ddaa1..7637d57 100644 --- a/Source/GeneDefOf.cs +++ b/Source/GeneDefOf.cs @@ -1,6 +1,6 @@ using RimWorld; using Verse; - +using Verse.AI; namespace RJW_Genes { [DefOf] @@ -79,8 +79,9 @@ namespace RJW_Genes // LifeForce public static readonly GeneDef rjw_genes_lifeforce; + public static readonly GeneDef rjw_genes_pussyhealing; public static readonly GeneDef rjw_genes_lifeforce_drain; - public static readonly GeneDef rjw_genes_pussyhealer; + public static readonly GeneDef rjw_genes_cum_eater; public static readonly GeneDef rjw_genes_vaginal_absorber; public static readonly GeneDef rjw_genes_anal_absorber; public static readonly GeneDef rjw_genes_drainer; @@ -90,5 +91,12 @@ namespace RJW_Genes // Cosmetic public static readonly GeneDef rjw_genes_succubus_tail; public static readonly GeneDef rjw_genes_succubus_wings; - } + + //Other Defs + public static readonly XenotypeDef rjw_genes_succubus; + public static readonly DutyDef rjw_genes_flirt; + public static readonly MentalBreakDef rjw_genes_lifeforce_randomrape; + + } + } diff --git a/Source/Genes/GeneUtility.cs b/Source/Genes/GeneUtility.cs index 5ee1c09..9ec55c4 100644 --- a/Source/Genes/GeneUtility.cs +++ b/Source/Genes/GeneUtility.cs @@ -19,16 +19,22 @@ namespace RJW_Genes { float old_value = drain.Resource.Value; drain.Resource.Value += offset; - //PostOffSetLifeForce(drain, old_value); + PostOffSetLifeForce(drain, old_value); } public static void PostOffSetLifeForce(IGeneResourceDrain drain, float old_value) { if (old_value > 0.2f && drain.Resource.Value <= 0.2f) + { + //TODO: Mood debuff + } + else if (old_value > 0f && drain.Resource.Value <= 0f) { Pawn pawn = drain.Pawn; - - //TODO: Do things + if (!drain.Pawn.health.hediffSet.HasHediff(HediffDefOf.rjw_genes_fertilin_craving)) + { + drain.Pawn.health.AddHediff(HediffDefOf.rjw_genes_fertilin_craving); + } } } @@ -67,7 +73,6 @@ namespace RJW_Genes } return MaxEggSize; } - public static List GetGenitaliaResizingGenes(Pawn pawn) { var ResizingGenes = new List(); @@ -98,6 +103,7 @@ namespace RJW_Genes } return pawn.genes.HasGene(genedef); } + public static bool HasLifeForce(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_lifeforce); } public static bool IsMechbreeder(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_mechbreeder); } public static bool IsInsectIncubator(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_insectincubator); } @@ -107,7 +113,7 @@ namespace RJW_Genes public static bool IsElastic(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_elasticity); } public static bool IsCumflationImmune(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_cumflation_immunity); } public static bool IsGenerousDonor(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_generous_donor); } - public static bool IsPussyHealer(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_pussyhealer); } + public static bool IsPussyHealer(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_pussyhealing); } public static bool IsUnbreakable(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_unbreakable); } public static bool HasParalysingKiss(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_paralysingkiss); } public static bool HasSeduce(Pawn pawn) { return HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_seduce); } diff --git a/Source/Genes/Life_Force/Gene_LifeForce.cs b/Source/Genes/Life_Force/Gene_LifeForce.cs index 5bb73b6..8cac6b3 100644 --- a/Source/Genes/Life_Force/Gene_LifeForce.cs +++ b/Source/Genes/Life_Force/Gene_LifeForce.cs @@ -46,32 +46,19 @@ namespace RJW_Genes { 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. + //every tick it decreases fertilin value and everyday if fertilin is below alert minimum there a ~50 chance for mental break public override void Tick() { - //base.Tick(); + 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; diff --git a/Source/Genes/Life_Force/Gene_LifeForceDrain.cs b/Source/Genes/Life_Force/Gene_LifeForceDrain.cs index 335e257..c50dae5 100644 --- a/Source/Genes/Life_Force/Gene_LifeForceDrain.cs +++ b/Source/Genes/Life_Force/Gene_LifeForceDrain.cs @@ -60,17 +60,6 @@ namespace RJW_Genes } } - 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; diff --git a/Source/Genes/Life_Force/HediffCompProperties_SeverityFromFertilin.cs b/Source/Genes/Life_Force/HediffCompProperties_SeverityFromFertilin.cs new file mode 100644 index 0000000..558c3e0 --- /dev/null +++ b/Source/Genes/Life_Force/HediffCompProperties_SeverityFromFertilin.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; +namespace RJW_Genes +{ + public class HediffCompProperties_SeverityFromFertilin : HediffCompProperties + { + public HediffCompProperties_SeverityFromFertilin() + { + this.compClass = typeof(HediffComp_SeverityFromFertilin); + } + + // Token: 0x04001162 RID: 4450 + public float severityPerHourEmpty; + + // Token: 0x04001163 RID: 4451 + public float severityPerHourHemogen; + } +} diff --git a/Source/Genes/Life_Force/HediffComp_SeverityFromFertilin.cs b/Source/Genes/Life_Force/HediffComp_SeverityFromFertilin.cs new file mode 100644 index 0000000..d497d59 --- /dev/null +++ b/Source/Genes/Life_Force/HediffComp_SeverityFromFertilin.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using RimWorld; +namespace RJW_Genes +{ + public class HediffComp_SeverityFromFertilin : HediffComp + { + public HediffCompProperties_SeverityFromFertilin Props + { + get + { + return (HediffCompProperties_SeverityFromFertilin)this.props; + } + } + public override bool CompShouldRemove + { + get + { + Pawn_GeneTracker genes = base.Pawn.genes; + return ((genes != null) ? genes.GetFirstGeneOfType() : null) == null; + } + } + private Gene_LifeForce LifeForce + { + get + { + if (this.cachedLifeForceGene == null) + { + this.cachedLifeForceGene = base.Pawn.genes.GetFirstGeneOfType(); + } + return this.cachedLifeForceGene; + } + } + public override void CompPostTick(ref float severityAdjustment) + { + base.CompPostTick(ref severityAdjustment); + severityAdjustment += ((this.LifeForce.Value > 0f) ? this.Props.severityPerHourHemogen : this.Props.severityPerHourEmpty) / 2500f; + this.MentalBreak(); + } + + public void MentalBreak() + { + if (cachedLifeForceGene.Resource.Value <= cachedLifeForceGene.Resource.MinLevelForAlert && this.Pawn.IsHashIntervalTick(2500) && Rand.Chance(0.03f)) //~50% chance each day for mental break + { + if (this.Pawn.genes.HasGene(GeneDefOf.rjw_genes_cum_eater) + || this.Pawn.genes.HasGene(GeneDefOf.rjw_genes_vaginal_absorber) || this.Pawn.genes.HasGene(GeneDefOf.rjw_genes_anal_absorber) || this.Pawn.genes.HasGene(GeneDefOf.rjw_genes_drainer)) + { + MentalBreakDef randomrape = GeneDefOf.rjw_genes_lifeforce_randomrape; + if (ModsConfig.BiotechActive && + this.Pawn.Spawned && !this.Pawn.InMentalState && !this.Pawn.Downed && + randomrape.Worker.BreakCanOccur(this.Pawn)) + { + randomrape.Worker.TryStart(this.Pawn, "MentalBreakNoFertilin".Translate(), false); + } + } + } + } + + private Gene_LifeForce cachedLifeForceGene; + } +} diff --git a/Source/Genes/Life_Force/HediffWithComps_tank.cs b/Source/Genes/Life_Force/HediffWithComps_tank.cs deleted file mode 100644 index 7dcea63..0000000 --- a/Source/Genes/Life_Force/HediffWithComps_tank.cs +++ /dev/null @@ -1,23 +0,0 @@ -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/IncidentWorker_SuccubusDreamVisit.cs b/Source/Genes/Life_Force/IncidentWorker_SuccubusDreamVisit.cs new file mode 100644 index 0000000..82522fb --- /dev/null +++ b/Source/Genes/Life_Force/IncidentWorker_SuccubusDreamVisit.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; +using Verse.AI.Group; +using RimWorld; +using rjw; +namespace RJW_Genes +{ + public class IncidentWorker_SuccubusDreamVisit : IncidentWorker + { + //This incidint will only fire if there is a pawn asleep and sexneed is lower than 0.25 + protected override bool CanFireNowSub(IncidentParms parms) + { + if (!base.CanFireNowSub(parms)) + { + return false; + } + Map map = (Map)parms.target; + if (!map.mapTemperature.SeasonAcceptableFor(ThingDefOf.Human)) + { + return false; + } + foreach (Pawn pawn in map.mapPawns.FreeColonistsAndPrisonersSpawned) + { + if (pawn.jobs.curDriver.asleep && xxx.need_some_sex(pawn) > 1f) + { + return true; + } + } + return false; + + } + + protected override bool TryExecuteWorker(IncidentParms parms) + { + Map map = (Map)parms.target; + Pawn victim = ValidVictims(map).RandomElement(); + if (victim == null) + { + return false; + } + IntVec3 loc = victim.Position; + Faction faction; + if (!this.TryFindFormerFaction(out faction)) + { + return false; + } + + //Spawn succubus at pawn + Pawn succubus = PawnGenerator.GeneratePawn(new PawnGenerationRequest(PawnKindDef.Named("rjw_genes_succubus"), faction, PawnGenerationContext.NonPlayer, -1, + false, false, false, true, false, 1f, false, true, false, true, true, false, false, false, false, 0f, 0f, null, 1f, null, null, + null, null, null, null, null, null, null, null, null, null, false, false, false, false, null, null, null, null, null, 0f, + DevelopmentalStage.Adult, null, null, null, false)); + succubus.SetFaction(null, null); + GenSpawn.Spawn(succubus, loc, map, WipeMode.Vanish); + + //Set succubus behaviour + List list = new List {succubus}; + LordMaker.MakeNewLord(parms.faction, this.CreateLordJob(parms, succubus, victim), map, list); + + //Make succubus rape victim. + if (RJWSettings.rape_enabled) + { + succubus.pather.StopDead(); + succubus.jobs.StopAll(); + Job newJob = JobMaker.MakeJob(xxx.RapeRandom, victim); + succubus.jobs.StartJob(newJob, JobCondition.InterruptForced, null, false, true, null, null, false, false, null, false, true); + } + + //Broken for now + //Sends letter + //string value = succubus.DevelopmentalStage.Child() ? "FeralChild".Translate().ToString() : succubus.KindLabel; + //TaggedString value2 = succubus.DevelopmentalStage.Child() ? "Child".Translate() : "Person".Translate(); + //TaggedString baseLetterLabel = this.def.letterLabel.Formatted(value).CapitalizeFirst(); + //TaggedString baseLetterText = this.def.letterText.Formatted(succubus.NameShortColored, value2, succubus.Named("PAWN")).AdjustedFor(succubus, "PAWN", true).CapitalizeFirst(); + //PawnRelationUtility.TryAppendRelationsWithColonistsInfo(ref baseLetterText, ref baseLetterLabel, succubus); + //base.SendStandardLetter(baseLetterLabel, baseLetterText, this.def.letterDef, parms, succubus, Array.Empty()); + + return true; + } + + private IEnumerable ValidVictims(Map map) + { + foreach (Pawn pawn in map.mapPawns.FreeColonistsAndPrisonersSpawned) + { + if (pawn.jobs.curDriver.asleep && xxx.need_some_sex(pawn) > 1f) + { + yield return pawn; + } + } + yield break; + } + + private bool TryFindFormerFaction(out Faction formerFaction) + { + return Find.FactionManager.TryGetRandomNonColonyHumanlikeFaction(out formerFaction, false, true, TechLevel.Undefined, false); + } + + protected virtual LordJob_SuccubusVisit CreateLordJob(IncidentParms parms, Pawn succubus, Pawn target) + { + return new LordJob_SuccubusVisit(target); + } + } +} diff --git a/Source/Genes/Life_Force/IngestionOutcomeDoer_LifeForceOffset.cs b/Source/Genes/Life_Force/IngestionOutcomeDoer_LifeForceOffset.cs index 65e458e..f3e50f1 100644 --- a/Source/Genes/Life_Force/IngestionOutcomeDoer_LifeForceOffset.cs +++ b/Source/Genes/Life_Force/IngestionOutcomeDoer_LifeForceOffset.cs @@ -12,7 +12,7 @@ namespace RJW_Genes { protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) { - if (GeneUtility.HasLifeForce(pawn)) + if (GeneUtility.HasLifeForce(pawn) && GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_cum_eater)) { float num = ingested.stackCount * this.FertilinPerUnit / 100; GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(pawn), num); diff --git a/Source/Genes/Life_Force/JobDrivers/JobDriver_Flirt.cs b/Source/Genes/Life_Force/JobDrivers/JobDriver_Flirt.cs new file mode 100644 index 0000000..ad61bb0 --- /dev/null +++ b/Source/Genes/Life_Force/JobDrivers/JobDriver_Flirt.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; +using RimWorld; +using rjw; +namespace RJW_Genes +{ + public class JobDriver_Flirt : JobDriver + { + private Pawn Target + { + get + { + return (Pawn)((Thing)this.pawn.CurJob.GetTarget(TargetIndex.A)); + } + } + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + return true; + } + + //Some wait toils to induce delay + protected override IEnumerable MakeNewToils() + { + this.FailOnDespawnedOrNull(TargetIndex.A); + yield return Toils_Interpersonal.GotoInteractablePosition(TargetIndex.A); + yield return Toils_General.Wait(300, TargetIndex.A); + yield return Toils_Interpersonal.WaitToBeAbleToInteract(this.pawn); + Toil toil = Toils_Interpersonal.GotoInteractablePosition(TargetIndex.A); + toil.socialMode = RandomSocialMode.Off; + yield return toil; + yield return this.InteractToil(); + Toil toil1 = Toils_General.Wait(600, TargetIndex.A); + toil1.socialMode = RandomSocialMode.Off; + yield break; + } + private Toil InteractToil() + { + return Toils_General.Do(delegate + { + if (this.pawn.interactions.TryInteractWith(this.Target, ThoughtDefOf.rjw_genes_flirt)) + { + Need_Sex need_Sex = this.Target.needs.TryGetNeed(); + need_Sex.CurLevel += -0.01f; + } + }); + } + + private const TargetIndex TargetInd = TargetIndex.A; + } +} + diff --git a/Source/Genes/Life_Force/JobGiver_Flirt.cs b/Source/Genes/Life_Force/JobGiver_Flirt.cs new file mode 100644 index 0000000..ac08c6b --- /dev/null +++ b/Source/Genes/Life_Force/JobGiver_Flirt.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; +using RimWorld; +namespace RJW_Genes +{ + public class JobGiver_Flirt : ThinkNode_JobGiver + { + // Token: 0x0600405A RID: 16474 RVA: 0x0017271C File Offset: 0x0017091C + protected override Job TryGiveJob(Pawn pawn) + { + Pawn target = pawn.mindState.duty.focus.Pawn; + if (pawn.CanReach(target, PathEndMode.InteractionCell, Danger.Deadly)) + { + return JobMaker.MakeJob(JobDefOf.rjw_genes_flirt, target); + } + return null; + } + } +} diff --git a/Source/Genes/Life_Force/JobGiver_GetLifeForce.cs b/Source/Genes/Life_Force/JobGiver_GetLifeForce.cs index b39d9cb..3cb781b 100644 --- a/Source/Genes/Life_Force/JobGiver_GetLifeForce.cs +++ b/Source/Genes/Life_Force/JobGiver_GetLifeForce.cs @@ -27,7 +27,7 @@ namespace RJW_Genes } - if (ModsConfig.IsActive("LustLicentia.RJWLabs") && gene_lifeforce.StoredCumAllowed) + if (ModsConfig.IsActive("rjw.sexperience") && gene_lifeforce.StoredCumAllowed && genes.HasGene(GeneDefOf.rjw_genes_cum_eater)) { Thing gatheredCum = this.GetStoredCum(pawn); if (gatheredCum == null) diff --git a/Source/Genes/Life_Force/JobGiver_TryQuickieWith.cs b/Source/Genes/Life_Force/JobGiver_TryQuickieWith.cs new file mode 100644 index 0000000..854d906 --- /dev/null +++ b/Source/Genes/Life_Force/JobGiver_TryQuickieWith.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using rjw; +using RimWorld; +using Verse; +using Verse.AI; +namespace RJW_Genes +{ + public class JobGiver_TryQuickieWith : ThinkNode_JobGiver + { + protected override Job TryGiveJob(Pawn pawn) + { + Pawn target = pawn.mindState.duty.focus.Pawn; + Pawn_JobTracker jobs = target.jobs; + string pawn_name = xxx.get_pawnname(pawn); + string target_name = xxx.get_pawnname(target); + //can reserve eachother + if (pawn.CanReserveAndReach(target, PathEndMode.InteractionCell, Danger.Some) && target.CanReserve(pawn, 1, 0, null, false)) + { + //target is not busy + if (!(((jobs != null) ? jobs.curJob : null) != null && jobs.curJob.playerForced)) + { + float willingness = TargetWillingness(pawn, target); + if (Rand.Chance(willingness)) + { + return JobMaker.MakeJob(xxx.quick_sex, target); + } + else + { + if (RJWSettings.DebugLogJoinInBed) //change this when we have our own settigns + { + ModLog.Message(string.Format("{0} was not interested in having sex with {1}: ({2} chance)", pawn_name, target_name, willingness)); + } + } + } + else + { + if (RJWSettings.DebugLogJoinInBed) //change this when we have our own settigns + { + ModLog.Message(string.Format(" find_pawn_to_fuck({0}): lover has important job ({1}), skipping", pawn_name, target.jobs.curJob.def)); + } + } + } + else + { + if (RJWSettings.DebugLogJoinInBed) //change this when we have our own settigns + { + ModLog.Message(" (" + pawn_name + "): cannot reach or reserve " + target_name); + } + } + return null; + } + public static float TargetWillingness(Pawn pawn, Pawn target) + { + string pawn_name = xxx.get_pawnname(pawn); + float willingness = SexAppraiser.would_fuck(target,pawn); + bool nymph = xxx.is_nympho(target); + bool loverelation = LovePartnerRelationUtility.LovePartnerRelationExists(pawn, target); + if (nymph || loverelation) + { + willingness *= 2; + } + if (xxx.HasNonPolyPartner(pawn, false) && !loverelation) + { + if (RJWHookupSettings.NymphosCanCheat && nymph && xxx.is_frustrated(pawn)) + { + if (RJWSettings.DebugLogJoinInBed) + { + ModLog.Message(" find_partner(" + pawn_name + "): I'm a nympho and I'm so frustrated that I'm going to cheat"); + } + } + else + { + if (!pawn.health.hediffSet.HasHediff(HediffDef.Named("AlcoholHigh"), false)) + { + if (RJWSettings.DebugLogJoinInBed) + { + ModLog.Message(" find_partner(" + pawn_name + "): I interested in banging but that's cheating"); + } + //Succubus has a small chance to seduce even if target is in relationship, maybe setting like succubus can homewreck + willingness *= 0.1f; + } + else + { + if (RJWSettings.DebugLogJoinInBed) + { + ModLog.Message(" find_partner(" + pawn_name + "): I want to bang and im too drunk to care if its cheating"); + } + //No change + } + } + } + return willingness; + } + } +} diff --git a/Source/Genes/Life_Force/LordJob_SuccubusVisit.cs b/Source/Genes/Life_Force/LordJob_SuccubusVisit.cs new file mode 100644 index 0000000..8991fc5 --- /dev/null +++ b/Source/Genes/Life_Force/LordJob_SuccubusVisit.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; +using Verse.AI.Group; +using RimWorld; +namespace RJW_Genes +{ + //Based on LordJob_VisitColony + public class LordJob_SuccubusVisit : LordJob + { + public LordJob_SuccubusVisit() + { + + } + public LordJob_SuccubusVisit(Pawn target) + { + this.target = target; + } + + // + //Stategraph has lordtoils which say what a pawn should be doing + //Transitions say when active lordtoil for pawn should change + // + public override StateGraph CreateGraph() + { + StateGraph stateGraph = new StateGraph(); + + //Flirt + LordToil_Flirt lordToil_Flirt = new LordToil_Flirt(this.target, 7f); + stateGraph.AddToil(lordToil_Flirt); + stateGraph.StartingToil = lordToil_Flirt; + + //Leave + LordToil_ExitMapRandom lordToil_ExitMapRandom = new LordToil_ExitMapRandom(); + stateGraph.AddToil(lordToil_ExitMapRandom); + LordToil_ExitMapAndDefendSelf lordToil_ExitMapAndDefendSelf = new LordToil_ExitMapAndDefendSelf(); + stateGraph.AddToil(lordToil_ExitMapAndDefendSelf); + + //Leave after some time + Transition transition1 = new Transition(lordToil_Flirt, lordToil_ExitMapRandom, false, true); + int tickLimit; + if (this.durationTicks != null) + { + tickLimit = this.durationTicks.Value; + } + else + { + tickLimit = Rand.Range(60000, 180000); //~1-3 days + } + transition1.AddTrigger(new Trigger_TicksPassed(tickLimit)); + + transition1.AddPreAction(new TransitionAction_Message("SuccubusLeaving".Translate(), null, 1f)); + stateGraph.AddTransition(transition1); + + //If they become hostile + Transition transition3 = new Transition(lordToil_Flirt, lordToil_ExitMapAndDefendSelf, false, true); + transition3.AddSource(lordToil_ExitMapRandom); //Not sure what this does + transition3.AddTrigger(new Trigger_BecamePlayerEnemy()); + transition3.AddTrigger(new Trigger_PawnKilled()); + transition3.AddPostAction(new TransitionAction_EndAllJobs()); + stateGraph.AddTransition(transition3, false); + + Transition transition4 = new Transition(lordToil_ExitMapRandom, lordToil_ExitMapAndDefendSelf, false, true); + transition4.AddSource(lordToil_Flirt); //Not sure what this does + transition4.AddTrigger(new Trigger_PawnHarmed(1f, true, Faction.OfPlayer)); + stateGraph.AddTransition(transition4, false); + + return stateGraph; + } + + //add toggleable gizmo to allow playes to have colonists sex the succubus into joining your colony + //comfort pawn? cooldown? + public override IEnumerable GetPawnGizmos(Pawn p) + { + return base.GetPawnGizmos(p); + } + + public override void ExposeData() + { + Scribe_Values.Look(ref this.durationTicks, "durationTicks", null, false); + Scribe_References.Look(ref this.target, "target", false); + } + public Pawn target; + private int? durationTicks; + } +} diff --git a/Source/Genes/Life_Force/LordToil_Flirt.cs b/Source/Genes/Life_Force/LordToil_Flirt.cs new file mode 100644 index 0000000..0bd1e38 --- /dev/null +++ b/Source/Genes/Life_Force/LordToil_Flirt.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; +using Verse.AI.Group; +using RimWorld; +namespace RJW_Genes +{ + //Based on LordToil_EscortPawn + public class LordToil_Flirt : LordToil + { + public LordToil_Flirt(Pawn victim, float followRadius) + { + this.victim = victim; + this.followRadius = followRadius; + } + + + public override void UpdateAllDuties() + { + for (int i = 0; i < this.lord.ownedPawns.Count; i++) + { + PawnDuty duty = new PawnDuty(GeneDefOf.rjw_genes_flirt, this.victim, this.followRadius); + this.lord.ownedPawns[i].mindState.duty = duty; + } + } + + public Pawn victim; + public float followRadius; + } +} diff --git a/Source/Genes/Life_Force/Patch_LifeForce.cs b/Source/Genes/Life_Force/Patch_LifeForce.cs index 9dbda44..cc4da8e 100644 --- a/Source/Genes/Life_Force/Patch_LifeForce.cs +++ b/Source/Genes/Life_Force/Patch_LifeForce.cs @@ -7,7 +7,6 @@ using System.Text; using System.Threading.Tasks; using RimWorld; using Verse; - namespace RJW_Genes { @@ -65,7 +64,7 @@ namespace RJW_Genes //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); + TransferFertilin(props, absorb_factor); } if (GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_drainer) && !props.pawn.health.hediffSet.HasHediff(HediffDefOf.rjw_genes_succubus_drained)) @@ -75,7 +74,7 @@ namespace RJW_Genes } } } - public static void AbsorbFertilin(SexProps props, float absorb_factor = 1f) + public static void TransferFertilin(SexProps props, float absorb_percentage = 1f) { Pawn_GeneTracker genes = props.partner.genes; Gene_LifeForce gene = genes.GetFirstGeneOfType(); @@ -84,7 +83,7 @@ namespace RJW_Genes float multiplier = Rand.Range(0.10f, 0.40f); - //Create a new ferilin_lost hediff or reduce multiplier + //Create a new ferilin_lost hediff or increase it if (fertilin_lost == null) { Hediff new_fertilin_lost = HediffMaker.MakeHediff(HediffDefOf.rjw_genes_fertilin_lost, props.pawn); @@ -96,48 +95,37 @@ namespace RJW_Genes 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; - } + + multiplier *= absorb_percentage; //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; + float valuechange = TotalFertilinAmount(props, multiplier); GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(props.partner), valuechange); //gene.Resource.Value += CumUtility.GetTotalFluidAmount(props.pawn) / 100 * absorb_factor * multiplier; } + public static float TotalFertilinAmount(SexProps props, float multiplier) + { + float total_fluid = CumUtility.GetTotalFluidAmount(props.pawn) / 100; + + //More in the tank means more to give + if (props.pawn.Has(Quirk.Messy)) + { + total_fluid *= 2; + } + if (props.pawn.RaceProps.Animal) + { + total_fluid *= 0.1f; //Should make this settable in settings + } + + return total_fluid; + } public static float BaseDom(SexProps props, Pawn succubus) { float absorb_factor = 0f; - if (props.sexType == xxx.rjwSextype.Sixtynine) + if (props.sexType == xxx.rjwSextype.Sixtynine && GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_cum_eater)) { 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; } @@ -145,10 +133,10 @@ namespace RJW_Genes 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) + if ((props.sexType == xxx.rjwSextype.Oral || props.sexType == xxx.rjwSextype.Fellatio || props.sexType == xxx.rjwSextype.Sixtynine) + && GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_cum_eater)) { absorb_factor += 1f; - } else if (props.sexType == xxx.rjwSextype.Vaginal && GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_vaginal_absorber)) { diff --git a/Source/Genes/Life_Force/Patch_SexTicks_ChangePsyfocus.cs b/Source/Genes/Life_Force/Patch_SexTicks_ChangePsyfocus.cs index dd3444b..ea0d9d6 100644 --- a/Source/Genes/Life_Force/Patch_SexTicks_ChangePsyfocus.cs +++ b/Source/Genes/Life_Force/Patch_SexTicks_ChangePsyfocus.cs @@ -24,7 +24,7 @@ namespace RJW_Genes 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 + //We need to know who the pawn on top is and if reverse we need to make the sub the pawn on top if (__instance.Sexprops.isRevese) { @@ -44,7 +44,7 @@ namespace RJW_Genes public static void DrinkCumflation(Pawn dom, Pawn sub) { - if (GeneUtility.HasLifeForce(sub) && dom.health.hediffSet.HasHediff(HediffDef.Named("Cumflation"))) + if (GeneUtility.HasLifeForce(sub) && GeneUtility.HasGeneNullCheck(sub,GeneDefOf.rjw_genes_cum_eater)&& dom.health.hediffSet.HasHediff(HediffDef.Named("Cumflation"))) { Hediff cumflation = dom.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("Cumflation")); Gene_LifeForce gene_LifeForce = sub.genes.GetFirstGeneOfType(); diff --git a/Source/Genes/Life_Force/Patch_Vanilla_Inheritance_Fertilin.cs b/Source/Genes/Life_Force/Patch_Vanilla_Inheritance_Fertilin.cs new file mode 100644 index 0000000..94c427f --- /dev/null +++ b/Source/Genes/Life_Force/Patch_Vanilla_Inheritance_Fertilin.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using HarmonyLib; +using RimWorld; +using Verse; + +namespace RJW_Genes +{ + /// + /// This Patch is applied to add a absorption gene for fertilin if it has none, but it does have the fertilin gene + /// First tries to get one from the parents else chooses one of them at random + /// the genes are determined and "simply added". + /// + [HarmonyPatch(typeof(PregnancyUtility), "GetInheritedGeneSet", new Type[] + { + typeof(Pawn), + typeof(Pawn), + //typeof(bool) + } + )] + public static class PatchVanillaPregnancyFertilin + { + [HarmonyPostfix] + public static void InheritedGenes(Pawn father, Pawn mother, ref GeneSet __result) + { + //Also make a setting for this + if (__result.GenesListForReading.Contains(GeneDefOf.rjw_genes_lifeforce)) + { + List gene_list = __result.GenesListForReading; + + //If no absorption gene get one from the parents, else a random one + if(!(gene_list.Contains(GeneDefOf.rjw_genes_drainer) || gene_list.Contains(GeneDefOf.rjw_genes_cum_eater) + || gene_list.Contains(GeneDefOf.rjw_genes_vaginal_absorber) || gene_list.Contains(GeneDefOf.rjw_genes_anal_absorber))) + { + List absorption_genes_list = new List { GeneDefOf.rjw_genes_drainer, GeneDefOf.rjw_genes_cum_eater + , GeneDefOf.rjw_genes_vaginal_absorber, GeneDefOf.rjw_genes_anal_absorber }; + List absorption_genes_parents = new List(); + foreach (GeneDef geneDef in absorption_genes_list) + { + if(mother.genes != null && mother.genes.HasGene(geneDef)) + { + absorption_genes_parents.Add(geneDef); + } + if (father.genes != null && father.genes.HasGene(geneDef)) + { + absorption_genes_parents.Add(geneDef); + } + } + if (!absorption_genes_parents.NullOrEmpty()) + { + __result.AddGene(absorption_genes_parents.RandomElement()); + } + else + { + __result.AddGene(absorption_genes_list.RandomElement()); + } + } + } + } + } +} diff --git a/Source/Genes/Life_Force/ThinkNode_ConditionalCannotInteract.cs b/Source/Genes/Life_Force/ThinkNode_ConditionalCannotInteract.cs new file mode 100644 index 0000000..06e05b4 --- /dev/null +++ b/Source/Genes/Life_Force/ThinkNode_ConditionalCannotInteract.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; +namespace RJW_Genes +{ + public class ThinkNode_ConditionalCannotInteract : ThinkNode_Conditional + { + protected override bool Satisfied(Pawn pawn) + { + Pawn target = pawn.mindState.duty.focus.Pawn; + if (target == null) + { + return true; + } + return (target.jobs != null && target.jobs.curDriver.asleep) || !pawn.CanReach(target, PathEndMode.InteractionCell, Danger.Deadly); + } + } +} diff --git a/Source/Genes/Life_Force/ThinkNode_NewFlirtTarget.cs b/Source/Genes/Life_Force/ThinkNode_NewFlirtTarget.cs new file mode 100644 index 0000000..9dee5ad --- /dev/null +++ b/Source/Genes/Life_Force/ThinkNode_NewFlirtTarget.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; +using rjw; +namespace RJW_Genes +{ + public class ThinkNode_NewFlirtTarget : ThinkNode + { + public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams) + { + List validTargets = ValidTargets(pawn, pawn.Map).ToList(); + Pawn new_target = validTargets.NullOrEmpty() ? null : validTargets.RandomElement(); + if (new_target != null) + { + pawn.mindState.duty.focus = new_target; + } + return ThinkResult.NoJob; + } + + private IEnumerable ValidTargets(Pawn pawn, Map map) + { + foreach (Pawn pawn2 in map.mapPawns.FreeAdultColonistsSpawned) + { + if (pawn != null && pawn2 != null && pawn != pawn2 && !pawn2.jobs.curDriver.asleep && SexAppraiser.would_fuck(pawn, pawn2) > 0.1f) + { + yield return pawn2; + } + } + //IEnumerator enumerator = null; + yield break; + } + } +} diff --git a/Source/Genes/Special/Gene_Aphrodisiac_Pheromones.cs b/Source/Genes/Special/Gene_Aphrodisiac_Pheromones.cs index c400c17..46f25d2 100644 --- a/Source/Genes/Special/Gene_Aphrodisiac_Pheromones.cs +++ b/Source/Genes/Special/Gene_Aphrodisiac_Pheromones.cs @@ -1,10 +1,4 @@ -using HarmonyLib; -using rjw; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; using Verse; using RimWorld; @@ -13,13 +7,13 @@ 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. + // Summary: once every one hour check for all pawns nearby and in line of sight (same room) and add/renew a hediff which lasts for 1 hour. public override void Tick() { base.Tick(); - if (this.pawn.IsHashIntervalTick(2500)) + if (this.pawn.IsHashIntervalTick(2500) && this.pawn.Map != null) { - //Only spread pheromones if sexdrive above 1 + // Only spread pheromones if sexdrive above 1 float sexfrequency = this.pawn.GetStatValue(StatDef.Named("SexFrequency")); if(sexfrequency > 1f) { @@ -31,21 +25,23 @@ namespace RJW_Genes } } - //Creates an IEnumerable of all pawns which are closeby and in lineofsight, self and other pawns with aphrodisiac pheromones gene are skipped. + // Creates an IEnumerable of all pawns which are closeby and in lineofsight, self and other pawns with aphrodisiac pheromones gene are skipped (to prevent loops). private IEnumerable AffectedPawns(IntVec3 pos, Map map) { foreach (Pawn pawn in map.mapPawns.AllPawns) { - if (this.pawn != null && pawn != this.pawn && pos.DistanceTo(pawn.Position) < 5 && GenSight.LineOfSight(pos, pawn.Position, pawn.Map) && !GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_aphrodisiac_pheromones)) + if (pawn != null && this.pawn != null && pawn != this.pawn + && pos.DistanceTo(pawn.Position) < 5 && GenSight.LineOfSight(pos, pawn.Position, pawn.Map) + && !GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_aphrodisiac_pheromones)) { yield return pawn; } } - //IEnumerator enumerator = null; + yield break; } - //Applies or renews a hediff which increases sexdrive for 6 hours + // Applies or renews a hediff which increases sexdrive for 6 hours private void InduceAphrodisiac(Pawn pawn, float sexfrequency) { Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.rjw_genes_aphrodisiac_pheromone); @@ -68,7 +64,7 @@ namespace RJW_Genes } } - //Function to modify aphrodisiac strength, currently has no effect, but it's an easy hook for other modders. + // Function to modify aphrodisiac strength, currently has no effect, but provides an easy hook for other modders and patches. public float ModifySexfrequency(Pawn pawn, float sexfrequency) { return sexfrequency; diff --git a/Source/HediffDefOf.cs b/Source/HediffDefOf.cs index f0ba596..4d59a41 100644 --- a/Source/HediffDefOf.cs +++ b/Source/HediffDefOf.cs @@ -15,5 +15,6 @@ namespace RJW_Genes public static readonly HediffDef rjw_genes_fertilin_lost; public static readonly HediffDef rjw_genes_succubus_drained; public static readonly HediffDef rjw_genes_orgasm_rush_hediff; + public static readonly HediffDef rjw_genes_fertilin_craving; } } diff --git a/Source/Interactions/GenesPartKindUsageRule.cs b/Source/Interactions/GenesPartKindUsageRule.cs index 6c0f53c..1825550 100644 --- a/Source/Interactions/GenesPartKindUsageRule.cs +++ b/Source/Interactions/GenesPartKindUsageRule.cs @@ -10,42 +10,68 @@ using Verse; namespace RJW_Genes.Interactions { //Summary// - //Set custom preferences for pawn. Gets integrated to rjw by AddtoIPartPreferenceRule in First + //Set custom preferences for pawn. Gets integrated into rjw by AddtoIPartPreferenceRule in First //Depending on the level of lifeforce increase the chance for using the mouth. public class GenesPartKindUsageRule : IPartPreferenceRule { public IEnumerable> ModifiersForDominant(InteractionContext context) { Pawn pawn = context.Internals.Dominant.Pawn; - if (GeneUtility.HasCriticalLifeForce(pawn)) + Gene_LifeForce gene = pawn.genes.GetFirstGeneOfType(); + if (gene != null) { - 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); + float weight = 2f; + if (gene.Value < gene.MinLevelForAlert) + { + weight *= 10; + } + else if (gene.Value < gene.targetValue) + { + weight *= 2.5f; + } + if (pawn.genes.HasGene(GeneDefOf.rjw_genes_cum_eater)) + { + yield return new Weighted(weight, LewdablePartKind.Mouth); + yield return new Weighted(weight, LewdablePartKind.Beak); + } + + if (pawn.genes.HasGene(GeneDefOf.rjw_genes_vaginal_absorber)) + { + yield return new Weighted(weight, LewdablePartKind.Vagina); + } + if (pawn.genes.HasGene(GeneDefOf.rjw_genes_anal_absorber)) + { + yield return new Weighted(weight, LewdablePartKind.Anus); + } } yield break; } public IEnumerable> ModifiersForSubmissive(InteractionContext context) { - Pawn pawn = context.Internals.Submissive.Pawn; - if (GeneUtility.HasCriticalLifeForce(pawn)) + Pawn pawn = context.Internals.Dominant.Pawn; + Gene_LifeForce gene = pawn.genes.GetFirstGeneOfType(); + if (gene != null) { - 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); + float weight = 2f; + if (gene.Value < gene.MinLevelForAlert) + { + weight *= 10; + } + else if (gene.Value < gene.targetValue) + { + weight *= 2.5f; + } + yield return new Weighted(weight, LewdablePartKind.Mouth); + yield return new Weighted(weight, LewdablePartKind.Beak); + if (pawn.genes.HasGene(GeneDefOf.rjw_genes_vaginal_absorber)) + { + yield return new Weighted(weight, LewdablePartKind.Vagina); + } + if (pawn.genes.HasGene(GeneDefOf.rjw_genes_anal_absorber)) + { + yield return new Weighted(weight, LewdablePartKind.Anus); + } } yield break; } diff --git a/Source/JobDefOf.cs b/Source/JobDefOf.cs index 8bae1fa..b077aa3 100644 --- a/Source/JobDefOf.cs +++ b/Source/JobDefOf.cs @@ -14,5 +14,6 @@ namespace RJW_Genes public static readonly JobDef rjw_genes_lifeforce_seduced; public static readonly JobDef sex_on_spot; public static readonly JobDef sex_on_spot_reciever; + public static readonly JobDef rjw_genes_flirt; } } diff --git a/Source/Rjw-Genes.csproj b/Source/Rjw-Genes.csproj index 440dfae..f4ab208 100644 --- a/Source/Rjw-Genes.csproj +++ b/Source/Rjw-Genes.csproj @@ -28,6 +28,7 @@ ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\Assembly-CSharp.dll + False ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\Mods\licentia-labs-master\Assemblies\LicentiaLabs.dll @@ -35,6 +36,7 @@ ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\Mods\rjw-master\1.4\Assemblies\RJW.dll + False @@ -54,6 +56,7 @@ ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll + False ..\..\..\RimWorldWin64_Data\Managed\UnityEngine.IMGUIModule.dll @@ -125,14 +128,25 @@ + + + + + + + + + + + @@ -140,7 +154,6 @@ - diff --git a/Source/ThoughtDefOf.cs b/Source/ThoughtDefOf.cs index 02a4aac..aefcfa8 100644 --- a/Source/ThoughtDefOf.cs +++ b/Source/ThoughtDefOf.cs @@ -12,6 +12,8 @@ namespace RJW_Genes { public static readonly ThoughtDef rjw_genes_cock_eaten; public static readonly ThoughtDef rjw_genes_seduced; - public static readonly ThoughtDef rjw_critical_fertilin; + + //Others with same names but other defs than in genedefof + public static readonly InteractionDef rjw_genes_flirt; } }