succubi are back

This commit is contained in:
Jaaldabaoth 2024-05-26 23:41:32 +02:00
parent 701168f642
commit 0617ea4995
124 changed files with 3894 additions and 12 deletions

View file

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using Verse.AI;
using RimWorld;
namespace RJW_Genes
{
public class JobGiver_Flirt : ThinkNode_JobGiver
{
// Token: 0x0600405A RID: 16474 RVA: 0x0017271C File Offset: 0x0017091C
protected override Job TryGiveJob(Pawn pawn)
{
Pawn target = pawn.mindState.duty.focus.Pawn;
if (pawn.CanReach(target, PathEndMode.InteractionCell, Danger.Deadly) && !target.jobs.curDriver.asleep)
{
return JobMaker.MakeJob(JobDefOf.rjw_genes_flirt, target);
}
return null;
}
}
}

View file

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

View file

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

View file

@ -0,0 +1,175 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using rjw;
using RJWSexperience;
using RimWorld;
using Verse;
using Verse.AI;
using Verse.AI.Group;
using UnityEngine;
namespace RJW_Genes
{
public class JobGiver_TryQuickieWith : ThinkNode_JobGiver
{
protected override Job TryGiveJob(Pawn pawn)
{
Pawn target = pawn.mindState.duty.focus.Pawn;
Pawn_JobTracker jobs = target.jobs;
string pawn_name = xxx.get_pawnname(pawn);
string target_name = xxx.get_pawnname(target);
//can reserve eachother
if (pawn.CanReserveAndReach(target, PathEndMode.InteractionCell, Danger.Some) && target.CanReserve(pawn, 1, 0, null, false))
{
//Dont interrupt player
if (!(((jobs != null) ? jobs.curJob : null) != null && jobs.curJob.playerForced))
{
float willingness = TargetWillingness(pawn, target);
if (Rand.Chance(willingness))
{
Job newJob =JobMaker.MakeJob(xxx.quick_sex, target);
return newJob;
}
else
{
if (RJWSettings.DebugLogJoinInBed) //change this when we have our own settigns
{
ModLog.Message(string.Format("{0} was not interested in having sex with {1}: ({2} chance)", pawn_name, target_name, willingness));
}
}
}
else
{
if (RJWSettings.DebugLogJoinInBed) //change this when we have our own settigns
{
//ModLog.Message(string.Format(" find_pawn_to_fuck({0}): lover has important job ({1}), skipping", pawn_name, target.jobs.curJob.def));
}
}
}
else
{
if (RJWSettings.DebugLogJoinInBed) //change this when we have our own settigns
{
ModLog.Message(" (" + pawn_name + "): cannot reach or reserve " + target_name);
}
}
return null;
}
public static float TargetWillingness(Pawn pawn, Pawn target)
{
string pawn_name = xxx.get_pawnname(pawn);
float willingness = SexAppraiser.would_fuck(target,pawn);
bool nymph = xxx.is_nympho(target);
bool loverelation = LovePartnerRelationUtility.LovePartnerRelationExists(pawn, target);
if (nymph || loverelation)
{
willingness *= 2;
}
if (xxx.HasNonPolyPartner(pawn, false) && !loverelation)
{
if (RJWHookupSettings.NymphosCanCheat && nymph && xxx.is_frustrated(pawn))
{
if (RJWSettings.DebugLogJoinInBed)
{
ModLog.Message(" find_partner(" + pawn_name + "): I'm a nympho and I'm so frustrated that I'm going to cheat");
}
}
else
{
if (!pawn.health.hediffSet.HasHediff(HediffDef.Named("AlcoholHigh"), false))
{
if (RJWSettings.DebugLogJoinInBed)
{
ModLog.Message(" find_partner(" + pawn_name + "): I interested in banging but that's cheating");
}
//Succubus has a small chance to seduce even if target is in relationship
willingness *= 0.1f;
}
else
{
if (RJWSettings.DebugLogJoinInBed)
{
ModLog.Message(" find_partner(" + pawn_name + "): I want to bang and im too drunk to care if its cheating");
}
//No change
}
}
}
return willingness;
}
public static float JoinChance(Pawn pawn ,Pawn target)
{
float chance = 0.1f;
//Sex satisfaction, how good the target is at sex
chance *= xxx.get_sex_satisfaction(target);
//Succubus mood
if (pawn.needs != null && pawn.needs.mood != null)
{
chance *= pawn.needs.mood.CurLevelPercentage + 0.5f;
}
//Size of genitals
bool size_matters = true; //To be placed in modsettings
if (size_matters)
{
//The larger the penis to greater the chance
if (RelationsUtility.AttractedToGender(pawn, Gender.Male))
{
chance *= GetGenitalSize(target, true) + 0.5f;
}
//The tighter the vagine the greater the chance, a size above 1 is considered as 1
if (RelationsUtility.AttractedToGender(pawn, Gender.Female))
{
chance *= 1f - Mathf.Min(GetGenitalSize(target, false),1f) + 0.5f;
}
}
//Sex ability from sexperience
if (ModsConfig.IsActive("rjw.sexperience"))
{
chance *= RJWSexperience.PawnExtensions.GetSexStat(pawn);
}
return Mathf.Max(chance,0f);
}
//Gets the size of the largest penis or the tightest vagina
public static float GetGenitalSize(Pawn pawn, bool penis_else_vagina)
{
List<Hediff> genitals = rjw.PawnExtensions.GetGenitalsList(pawn);
if(!genitals.NullOrEmpty())
{
if (penis_else_vagina)
{
List<Hediff> penises = genitals.Where(genital => Genital_Helper.is_penis(genital)).ToList();
{
if (!penises.NullOrEmpty())
{
return penises.Max(genital => genital.Severity);
}
}
}
else
{
List<Hediff> vaginas = genitals.Where(genital => Genital_Helper.is_vagina(genital)).ToList();
{
if (!vaginas.NullOrEmpty())
{
return vaginas.Min(genital => genital.Severity);
}
}
}
}
return 0f;
}
}
}