mirror of
https://github.com/vegapnk/RJW-Genes.git
synced 2024-08-15 00:23:31 +00:00
Merge Cumeater and follow up changes
This commit is contained in:
commit
7220accf4a
38 changed files with 1022 additions and 162 deletions
|
@ -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<Gene_GenitaliaResizingGene> GetGenitaliaResizingGenes(Pawn pawn)
|
||||
{
|
||||
var ResizingGenes = new List<Gene_GenitaliaResizingGene>();
|
||||
|
@ -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); }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -60,17 +60,6 @@ namespace RJW_Genes
|
|||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<Gizmo> GetGizmos()
|
||||
{
|
||||
foreach (Gizmo gizmo in GeneResourceDrainUtility.GetResourceDrainGizmos(this))
|
||||
{
|
||||
yield return gizmo;
|
||||
}
|
||||
IEnumerator<Gizmo> enumerator = null;
|
||||
yield break;
|
||||
yield break;
|
||||
}
|
||||
|
||||
[Unsaved(false)]
|
||||
private Gene_LifeForce cachedLifeForceGene;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
65
Source/Genes/Life_Force/HediffComp_SeverityFromFertilin.cs
Normal file
65
Source/Genes/Life_Force/HediffComp_SeverityFromFertilin.cs
Normal file
|
@ -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<Gene_LifeForce>() : null) == null;
|
||||
}
|
||||
}
|
||||
private Gene_LifeForce LifeForce
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.cachedLifeForceGene == null)
|
||||
{
|
||||
this.cachedLifeForceGene = base.Pawn.genes.GetFirstGeneOfType<Gene_LifeForce>();
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
108
Source/Genes/Life_Force/IncidentWorker_SuccubusDreamVisit.cs
Normal file
108
Source/Genes/Life_Force/IncidentWorker_SuccubusDreamVisit.cs
Normal file
|
@ -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<Pawn> list = new List<Pawn> {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<NamedArgument>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerable<Pawn> 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
56
Source/Genes/Life_Force/JobDrivers/JobDriver_Flirt.cs
Normal file
56
Source/Genes/Life_Force/JobDrivers/JobDriver_Flirt.cs
Normal file
|
@ -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<Toil> 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>();
|
||||
need_Sex.CurLevel += -0.01f;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private const TargetIndex TargetInd = TargetIndex.A;
|
||||
}
|
||||
}
|
||||
|
24
Source/Genes/Life_Force/JobGiver_Flirt.cs
Normal file
24
Source/Genes/Life_Force/JobGiver_Flirt.cs
Normal 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))
|
||||
{
|
||||
return JobMaker.MakeJob(JobDefOf.rjw_genes_flirt, target);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
99
Source/Genes/Life_Force/JobGiver_TryQuickieWith.cs
Normal file
99
Source/Genes/Life_Force/JobGiver_TryQuickieWith.cs
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
90
Source/Genes/Life_Force/LordJob_SuccubusVisit.cs
Normal file
90
Source/Genes/Life_Force/LordJob_SuccubusVisit.cs
Normal file
|
@ -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<Gizmo> GetPawnGizmos(Pawn p)
|
||||
{
|
||||
return base.GetPawnGizmos(p);
|
||||
}
|
||||
|
||||
public override void ExposeData()
|
||||
{
|
||||
Scribe_Values.Look<int?>(ref this.durationTicks, "durationTicks", null, false);
|
||||
Scribe_References.Look<Pawn>(ref this.target, "target", false);
|
||||
}
|
||||
public Pawn target;
|
||||
private int? durationTicks;
|
||||
}
|
||||
}
|
34
Source/Genes/Life_Force/LordToil_Flirt.cs
Normal file
34
Source/Genes/Life_Force/LordToil_Flirt.cs
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<Gene_LifeForce>();
|
||||
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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<Gene_LifeForce>();
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using HarmonyLib;
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace RJW_Genes
|
||||
{
|
||||
/// <summary>
|
||||
/// 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".
|
||||
/// </summary>
|
||||
[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<GeneDef> 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<GeneDef> absorption_genes_list = new List<GeneDef> { GeneDefOf.rjw_genes_drainer, GeneDefOf.rjw_genes_cum_eater
|
||||
, GeneDefOf.rjw_genes_vaginal_absorber, GeneDefOf.rjw_genes_anal_absorber };
|
||||
List<GeneDef> absorption_genes_parents = new List<GeneDef>();
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
37
Source/Genes/Life_Force/ThinkNode_NewFlirtTarget.cs
Normal file
37
Source/Genes/Life_Force/ThinkNode_NewFlirtTarget.cs
Normal file
|
@ -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<Pawn> 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<Pawn> 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<Pawn> enumerator = null;
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<Pawn> AffectedPawns(IntVec3 pos, Map map)
|
||||
{
|
||||
foreach (Pawn pawn in map.mapPawns.AllPawns)
|
||||
{
|
||||
if (this.pawn != null && pawn != this.pawn && pos.DistanceTo(pawn.Position) < 5 && GenSight.LineOfSight(pos, pawn.Position, pawn.Map) && !GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_aphrodisiac_pheromones))
|
||||
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<Pawn> 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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue