diff --git a/Common/Assemblies/Rjw-Genes.dll b/Common/Assemblies/Rjw-Genes.dll index c35489b..dedcafe 100644 Binary files a/Common/Assemblies/Rjw-Genes.dll and b/Common/Assemblies/Rjw-Genes.dll differ diff --git a/Common/Defs/DutyDefs/Duties_Succubus.xml b/Common/Defs/DutyDefs/Duties_Succubus.xml new file mode 100644 index 0000000..ce43ed8 --- /dev/null +++ b/Common/Defs/DutyDefs/Duties_Succubus.xml @@ -0,0 +1,57 @@ + + + + rjw_genes_flirt + + + +
  • + SatisfyingNeeds + +
  • + +
  • +
  • +
  • +
  • +
  • + +
  • + +
  • +
    + + + + + +
  • + +
  • + +
  • + +
  • + 0.05 + +
  • + +
  • + + +
  • + + + + + + + +
  • + 5 +
  • + +
    +
    +
    + diff --git a/Common/Defs/HediffDefs/Hediffs_Genes.xml b/Common/Defs/HediffDefs/Hediffs_Succubus.xml similarity index 100% rename from Common/Defs/HediffDefs/Hediffs_Genes.xml rename to Common/Defs/HediffDefs/Hediffs_Succubus.xml diff --git a/Common/Languages/English/Keyed/Lifeforce.xml b/Common/Languages/English/Keyed/Lifeforce.xml index 23d3f75..65b022f 100644 --- a/Common/Languages/English/Keyed/Lifeforce.xml +++ b/Common/Languages/English/Keyed/Lifeforce.xml @@ -7,4 +7,9 @@ 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 a41e259..3431a12 100644 --- a/Source/GeneDefOf.cs +++ b/Source/GeneDefOf.cs @@ -1,6 +1,6 @@ using RimWorld; using Verse; - +using Verse.AI; namespace RJW_Genes { [DefOf] @@ -92,6 +92,7 @@ namespace RJW_Genes public static readonly XenotypeDef rjw_genes_succubus; - + //Other Defs + public static readonly DutyDef rjw_genes_flirt; } } diff --git a/Source/Genes/Life_Force/IncidentWorker_SuccubusDreamVisit.cs b/Source/Genes/Life_Force/IncidentWorker_SuccubusDreamVisit.cs index 2548370..4855d7f 100644 --- a/Source/Genes/Life_Force/IncidentWorker_SuccubusDreamVisit.cs +++ b/Source/Genes/Life_Force/IncidentWorker_SuccubusDreamVisit.cs @@ -4,6 +4,8 @@ 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 @@ -55,7 +57,20 @@ namespace RJW_Genes 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; @@ -64,7 +79,7 @@ namespace RJW_Genes //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; } @@ -84,5 +99,10 @@ namespace RJW_Genes { 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/LordJob_SuccubusVisit.cs b/Source/Genes/Life_Force/LordJob_SuccubusVisit.cs new file mode 100644 index 0000000..afe2630 --- /dev/null +++ b/Source/Genes/Life_Force/LordJob_SuccubusVisit.cs @@ -0,0 +1,87 @@ +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(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); + } + public Pawn target; + private int? durationTicks; + public StateGraph exitSubgraph; + + } +} 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/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..c5a6665 --- /dev/null +++ b/Source/Genes/Life_Force/ThinkNode_NewFlirtTarget.cs @@ -0,0 +1,36 @@ +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) + { + Pawn new_target = ValidTargets(pawn, pawn.Map).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/Rjw-Genes.csproj b/Source/Rjw-Genes.csproj index c6cc0f6..27399f6 100644 --- a/Source/Rjw-Genes.csproj +++ b/Source/Rjw-Genes.csproj @@ -133,10 +133,14 @@ + + + +