Merge pull request #14 from Shabakur/dev

More Fertilin stuff
This commit is contained in:
vegapnk 2023-01-20 08:27:14 +01:00 committed by GitHub
commit 2380db1ce6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 1025 additions and 168 deletions

Binary file not shown.

View File

@ -30,7 +30,7 @@
<li Class="RJW_Genes.CompProperties_AbilityLifeForceCost">
<fertilinCost>0.2</fertilinCost>
</li>
<li Class="RJW_Genes.CompProperties_AbilityPussyHeal"> <!-- namespace needs to be changed when copied to another mod-->
<li Class="RJW_Genes.CompProperties_AbilityPussyHeal">
<tendQualityRange>0.4~0.8</tendQualityRange>
</li>
<li Class="RJW_Genes.CompProperties_SexInteractionRequirements">

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<DutyDef>
<defName>rjw_genes_flirt</defName>
<thinkNode Class="ThinkNode_Priority">
<subNodes>
<!-- first fulfill needs -->
<li Class="ThinkNode_Tagger">
<tagToGive>SatisfyingNeeds</tagToGive>
<subNodes>
<li Class="ThinkNode_PrioritySorter">
<subNodes>
<li Class="JobGiver_GetFood"/>
<li Class="JobGiver_GetRest"/>
<li Class="JobGiver_SatisfyChemicalNeed"/>
<li Class="JobGiver_SatifyChemicalDependency" MayRequire="Ludeon.RimWorld.Biotech" />
</subNodes>
</li>
</subNodes>
</li>
<!-- switch target randomly or when target is unreachable/sleeping (similar to insults) -->
<li Class="RJW_Genes.ThinkNode_ConditionalCannotInteract">
<subNodes>
<li Class="RJW_Genes.ThinkNode_NewFlirtTarget" />
</subNodes>
</li>
<li Class="ThinkNode_ConditionalRandom">
<chance>0.05</chance>
<subNodes>
<li Class="RJW_Genes.ThinkNode_NewFlirtTarget" />
</subNodes>
</li>
<!--Go to target pawn-->
<li Class="JobGiver_AIFollowEscortee" />
<li Class="rjw.ThinkNode_ConditionalSexChecks">
<subNodes>
<!--If sexneed is low do rape or masturbate (like a nymph)-->
<li Class="rjw.ThinkNode_ConditionalFrustrated">
<subNodes>
<li Class="rjw.JobGiver_ViolateCorpse" />
<li Class="rjw.JobGiver_RandomRape" />
<li Class="rjw.JobGiver_Masturbate"/>
</subNodes>
</li>
<!--Will sometimes try and hookup with target pawn-->
<li Class="ThinkNode_ConditionalRandom">
<chance>0.1</chance>
<subNodes>
<li Class="RJW_Genes.JobGiver_TryQuickieWith" />
</subNodes>
</li>
</subNodes>
</li>
<!--Flirt with target pawn and try hookup with them, increases sexneed in target pawn, maybe flirt has custom text-->
<li Class="RJW_Genes.JobGiver_Flirt" />
<li Class="JobGiver_WanderNearDutyLocation">
<wanderRadius>5</wanderRadius>
</li>
</subNodes>
</thinkNode>
</DutyDef>
</Defs>

View File

@ -27,7 +27,6 @@
<li><symbol>fert</symbol></li>
</prefixSymbols>
</symbolPack>
<mentalBreakDef>rjw_genes_lifeforce_randomrape</mentalBreakDef>
<resourceLossPerDay>0.05</resourceLossPerDay>
<biostatCpx>1</biostatCpx>
<biostatMet>1</biostatMet>
@ -50,7 +49,7 @@
</GeneDef>
<GeneDef>
<defName>rjw_genes_pussyhealer</defName>
<defName>rjw_genes_pussyhealing</defName>
<label>Pussy Healer</label>
<labelShortAdj>pussyhealer</labelShortAdj>
<description>Carriers of this gene are able use vaginal sex to tend to other's wounds.</description>
@ -152,10 +151,21 @@
</symbolPack>
</GeneDef>
<GeneDef>
<defName>rjw_genes_cum_eater</defName>
<label>Cum eater</label>
<description>Carriers of this gene are able to absorb fertilin through eating cum.</description>
<iconPath>Things/Mote/Heart</iconPath>
<prerequisite>rjw_genes_lifeforce</prerequisite>
<displayOrderInCategory>1</displayOrderInCategory>
<displayCategory>rjw_genes_fertilin</displayCategory>
<biostatCpx>1</biostatCpx>
</GeneDef>
<GeneDef>
<defName>rjw_genes_vaginal_absorber</defName>
<label>Vaginal Fertilin Absorber</label>
<description>Carriers of this gene are able to absorb fertilin through their vagina.</description>
<description>Carriers of this gene are able to absorb the fertilin inside sperm through their vagina.</description>
<iconPath>Things/Mote/Heart</iconPath>
<prerequisite>rjw_genes_lifeforce</prerequisite>
<displayOrderInCategory>2</displayOrderInCategory>
@ -166,7 +176,7 @@
<GeneDef>
<defName>rjw_genes_anal_absorber</defName>
<label>Anal Fertilin Absorber</label>
<description>Carriers of this gene are able to absorb fertilin through their anus.</description>
<description>Carriers of this gene are able to absorb the fertilin inside sperm through their anus.</description>
<iconPath>Things/Mote/Heart</iconPath>
<prerequisite>rjw_genes_lifeforce</prerequisite>
<displayOrderInCategory>3</displayOrderInCategory>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<HediffDef>
<defName>Aphrodisiac_Pheromone</defName>
<defName>rjw_genes_aphrodisiac_pheromone</defName>
<hediffClass>HediffWithComps</hediffClass>
<label>induced libido</label>
<description>Aphrodisiac pheromone effects.</description>
<description>sex drive increasing due to smelling aphrodisiac pheromones.</description>
<defaultLabelColor>(1,0,0.5)</defaultLabelColor>
<maxSeverity>1.0</maxSeverity>
<comps>
@ -16,15 +16,15 @@
<li>
<becomeVisible>true</becomeVisible>
<statFactors>
<SexFrequency>2</SexFrequency>
<SexFrequency>2</SexFrequency> <!--This is a lie, it gets changed when applied -->
</statFactors>
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>Fertilin_Lost</defName>
<hediffClass>RJW_Genes.HediffWithComps_tank</hediffClass>
<defName>rjw_genes_fertilin_lost</defName>
<hediffClass>Hediff_HemogenCraving</hediffClass>
<label>lost fertilin</label>
<description>Percentage of fertilin lost.</description>
<defaultLabelColor>(1,1,1)</defaultLabelColor>
@ -42,7 +42,7 @@
</HediffDef>
<HediffDef>
<defName>Succubus_Drained</defName>
<defName>rjw_genes_succubus_drained</defName>
<hediffClass>HediffWithComps</hediffClass>
<label>Drained</label>
<description>The vitality of this pawn has been drained.</description>
@ -86,4 +86,54 @@
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>rjw_genes_fertilin_craving</defName>
<label>fertilin craving</label>
<hediffClass>Hediff_HemogenCraving</hediffClass>
<description>weakened due to running out of fertilin.</description>
<defaultLabelColor>(1,0,0.5)</defaultLabelColor>
<maxSeverity>1.0</maxSeverity>
<initialSeverity>0.01</initialSeverity>
<stages>
<li>
<label>minor</label>
<painOffset>0.05</painOffset>
<capMods>
<li>
<capacity>Consciousness</capacity>
<setMax>0.9</setMax>
</li>
</capMods>
</li>
<li>
<label>moderate</label>
<minSeverity>0.35</minSeverity>
<painOffset>0.1</painOffset>
<capMods>
<li>
<capacity>Consciousness</capacity>
<setMax>0.8</setMax>
</li>
</capMods>
</li>
<li>
<label>major</label>
<minSeverity>0.7</minSeverity>
<painOffset>0.15</painOffset>
<capMods>
<li>
<capacity>Consciousness</capacity>
<setMax>0.5</setMax>
</li>
</capMods>
</li>
</stages>
<comps>
<li Class="RJW_Genes.HediffCompProperties_SeverityFromFertilin">
<severityPerHourEmpty>0.05</severityPerHourEmpty>
<severityPerHourHemogen>-0.1</severityPerHourHemogen>
</li>
</comps>
</HediffDef>
</Defs>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<IncidentDef>
<defName>SuccubusDreamVisit</defName>
<label>dirty dreams</label>
<category>Misc</category>
<targetTags>
<li>Map_PlayerHome</li>
</targetTags>
<workerClass>RJW_Genes.IncidentWorker_SuccubusDreamVisit</workerClass>
<baseChance>1.0</baseChance>
<minRefireDays>10</minRefireDays>
<pointsScaleable>false</pointsScaleable>
</IncidentDef>
</Defs>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<!--Chitchat reduced copy-->
<InteractionDef>
<defName>rjw_genes_flirt</defName>
<label>flirt</label>
<symbol>Things/Mote/SpeechSymbols/Chitchat</symbol>
<logRulesInitiator>
<rulesStrings>
<li>r_logentry->[INITIATOR_nameDef] and [RECIPIENT_nameDef] [talkedabout] [TalkTopicLight].</li>
<li>r_logentry->[INITIATOR_nameDef] [talkedabout] [TalkTopicLight] with [RECIPIENT_nameDef].</li>
<li>r_logentry(p=0.8)->[INITIATOR_nameDef] [commentedabout] [TalkTopicLight] to [RECIPIENT_nameDef].</li>
<li>talkedabout(p=4)->chatted about</li>
<li>talkedabout->shared a word about</li>
<li>talkedabout->spoke about</li>
<li>talkedabout->gabbed about</li>
<li>talkedabout->talked about</li>
<li>talkedabout->joked about</li>
<li>talkedabout->quipped about</li>
<li>commentedabout->said something about</li>
<li>commentedabout->said a word about</li>
<li>commentedabout->made a comment about</li>
<li>commentedabout->commented about</li>
<li>commentedabout->told a joke about</li>
</rulesStrings>
</logRulesInitiator>
</InteractionDef>
</Defs>

View File

@ -22,4 +22,11 @@
<casualInterruptible>false</casualInterruptible>
<playerInterruptible>false</playerInterruptible>
</JobDef>
<JobDef>
<defName>rjw_genes_flirt</defName>
<driverClass>RJW_Genes.JobDriver_Flirt</driverClass>
<reportString>Seduced.</reportString>
<casualInterruptible>false</casualInterruptible>
</JobDef>
</Defs>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<PawnKindDef>
<defName>rjw_genes_succubus</defName>
<label>succubus</label>
<combatPower>50</combatPower>
<race>Human</race>
<xenotypeSet>
<xenotypeChances>
<rjw_genes_succubus>999</rjw_genes_succubus>
</xenotypeChances>
</xenotypeSet>
<acceptArrestChanceFactor>0.5</acceptArrestChanceFactor>
<useFactionXenotypes>false</useFactionXenotypes>
<minGenerationAge>18</minGenerationAge>
<maxGenerationAge>27</maxGenerationAge>
<itemQuality>Poor</itemQuality>
<backstoryCryptosleepCommonality>0.0</backstoryCryptosleepCommonality>
<isFighter>false</isFighter>
<gearHealthRange>
<min>0.3</min>
<max>0.9</max>
</gearHealthRange>
<apparelIgnoreSeasons>true</apparelIgnoreSeasons>
<apparelTags>
<li>Tribal</li>
</apparelTags>
<apparelMoney>
<min>0</min>
<max>0</max>
</apparelMoney>
<apparelAllowHeadgearChance>0</apparelAllowHeadgearChance>
<techHediffsMoney>
<min>0</min>
<max>0</max>
</techHediffsMoney>
<techHediffsTags>
<li>Poor</li>
</techHediffsTags>
<techHediffsChance>0.0</techHediffsChance>
<initialWillRange>2~4</initialWillRange>
<initialResistanceRange>28~44</initialResistanceRange>
</PawnKindDef>
</Defs>

View File

@ -32,13 +32,25 @@
</ThoughtDef>
<ThoughtDef>
<defName>rjw_critical_fertilin</defName>
<stages>
<li>
<label>low on fertilin</label>
<description>I'm almost out of fertilin. I'm scared of losing control.</description>
<baseMoodEffect>-10</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<defName>rjw_genes_critical_fertilin</defName>
<workerClass>ThoughtWorker_Hediff</workerClass>
<hediff>rjw_genes_fertilin_craving</hediff>
<stages>
<li>
<label>fertilin craving</label>
<description>My bones ache. I really need fertilin.</description>
<baseMoodEffect>-10</baseMoodEffect>
</li>
<li>
<label>fertilin craving</label>
<description>This hurts bad and I can't stop thinking about sex. I would do anything for some cum.</description>
<baseMoodEffect>-15</baseMoodEffect>
</li>
<li>
<label>fertilin craving</label>
<description>Can't think. Sex. Sex. Must. Have. Cum.</description>
<baseMoodEffect>-20</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
</Defs>

View File

@ -4,7 +4,7 @@
<XenotypeDef>
<defName>rjw_genes_succubus</defName>
<label>Succubus</label>
<description>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. </description>
<description>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.</description>
<descriptionShort>Succubi are beautiful and extremely hungry Xenohumans. They strive on having sex and extracting their victims life-force through this. </descriptionShort>
<iconPath>UI/Icons/Xenotypes/Sanguophage</iconPath>
<soundDefOnImplant>PawnBecameSanguophage</soundDefOnImplant>
@ -13,6 +13,7 @@
<combatPowerFactor>1</combatPowerFactor>
<displayPriority>-1000</displayPriority>
<factionlessGenerationWeight>0.005</factionlessGenerationWeight>
<inheritable>true</inheritable>
<doubleXenotypeChances>
<Pigskin>0.02</Pigskin>
<Impid>0.02</Impid>
@ -30,12 +31,10 @@
<li>rjw_genes_vaginal_absorber</li>
<li>rjw_genes_anal_absorber</li>
<li>rjw_genes_drainer</li>
<li>rjw_genes_pussyhealer</li>
<li>rjw_genes_paralysingkiss</li>
<li>rjw_genes_seduce</li>
<li>rjw_genes_elasticity</li>
<li>rjw_genes_succubus_wings</li>
<li>rjw_genes_succubus_tail</li>
<li>rjw_genes_aphrodisiac_pheromones</li>

View File

@ -3,8 +3,13 @@
<!-- Fertilin strings -->
<AbilityDisabledNoFertilinGene>Pawn doesn't have required fertilin gene.</AbilityDisabledNoFertilinGene>
<AbilityDisabledNoFertilin>Not enough fertilin to cast.</AbilityDisabledNoFertilin>
<MentalBreakNoFertilin>This happened because of low fertilin.</MentalBreakNoFertilin>
<AlertLowFertilin>Low fertilin</AlertLowFertilin>
<AlertLowFertilinDesc>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</AlertLowFertilinDesc>
<!--Succubus Events-->
<SuccubusLeaving>The succubus has fed enough on your colonists and will now leave.</SuccubusLeaving>
</LanguageData>

View File

@ -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;
@ -89,6 +90,10 @@ namespace RJW_Genes
public static readonly GeneDef rjw_genes_succubus_tail;
public static readonly GeneDef rjw_genes_succubus_wings;
// Others & Non-Genes
//Other Defs
public static readonly XenotypeDef rjw_genes_succubus;
public static readonly DutyDef rjw_genes_flirt;
public static readonly MentalBreakDef rjw_genes_lifeforce_randomrape;
}
}

View File

@ -28,16 +28,21 @@ 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)
{
//Mood debuff
}
else if (old_value > 0f && drain.Resource.Value <= 0f)
{
Pawn pawn = drain.Pawn;
//Do things
if (!drain.Pawn.health.hediffSet.HasHediff(HediffDefOf.rjw_genes_fertilin_craving))
{
drain.Pawn.health.AddHediff(HediffDefOf.rjw_genes_fertilin_craving);
}
}
}
@ -163,7 +168,7 @@ namespace RJW_Genes
{
return false;
}
return pawn.genes.HasGene(GeneDefOf.rjw_genes_pussyhealer);
return pawn.genes.HasGene(GeneDefOf.rjw_genes_pussyhealing);
}
public static bool IsUnbreakable(Pawn pawn)

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View 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;
}
}

View File

@ -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();
}
}
}
}

View 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);
}
}
}

View File

@ -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);

View 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;
}
}

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))
{
return JobMaker.MakeJob(JobDefOf.rjw_genes_flirt, target);
}
return null;
}
}
}

View File

@ -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)

View 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;
}
}
}

View 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;
}
}

View 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;
}
}

View File

@ -7,7 +7,6 @@ using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
namespace RJW_Genes
{
@ -65,29 +64,29 @@ 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.Succubus_Drained))
if (GeneUtility.HasGeneNullCheck(succubus, GeneDefOf.rjw_genes_drainer) && !props.pawn.health.hediffSet.HasHediff(HediffDefOf.rjw_genes_succubus_drained))
{
props.pawn.health.AddHediff(HediffDefOf.Succubus_Drained);
props.pawn.health.AddHediff(HediffDefOf.rjw_genes_succubus_drained);
GeneUtility.OffsetLifeForce(GeneUtility.GetLifeForceGene(succubus), 0.25f);
}
}
}
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>();
Hediff fertilin_lost = props.pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Fertilin_Lost);
Hediff fertilin_lost = props.pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.rjw_genes_fertilin_lost);
//Around quarter get ejected everytime pawn cums
float multiplier = Rand.Range(0.10f, 0.40f);
//Create a new ferilin_lost hediff or reduce multiplier
//Create a new ferilin_lost hediff or increase it
if (fertilin_lost == null)
{
Hediff new_fertilin_lost = HediffMaker.MakeHediff(HediffDefOf.Fertilin_Lost, props.pawn);
Hediff new_fertilin_lost = HediffMaker.MakeHediff(HediffDefOf.rjw_genes_fertilin_lost, props.pawn);
props.pawn.health.AddHediff(new_fertilin_lost);
new_fertilin_lost.Severity = multiplier;
}
@ -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))
{

View File

@ -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>();

View File

@ -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());
}
}
}
}
}
}

View File

@ -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);
}
}
}

View 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;
}
}
}

View File

@ -13,11 +13,11 @@ 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
float sexfrequency = this.pawn.GetStatValue(StatDef.Named("SexFrequency"));
@ -31,12 +31,12 @@ namespace RJW_Genes
}
}
//Creatus an IEnumerable of all pawns which are closeby and in lineofsight, self and other pawns with aphrodisiac pheromones gene are skipped.
//Creatus 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;
}
@ -45,10 +45,10 @@ namespace RJW_Genes
yield break;
}
//Applies er renews a hediff which increases sexdrive for 6 hours
//Applies or renews a hediff which increases sexdrive for 1 hours
private void InduceAphrodisiac(Pawn pawn, float sexfrequency)
{
Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.Aphrodisiac_Pheromone);
Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.rjw_genes_aphrodisiac_pheromone);
if (hediff != null)
{
@ -56,12 +56,9 @@ namespace RJW_Genes
}
else
{
Hediff aphrodisiac = HediffMaker.MakeHediff(HediffDefOf.Aphrodisiac_Pheromone, pawn);
Hediff aphrodisiac = HediffMaker.MakeHediff(HediffDefOf.rjw_genes_aphrodisiac_pheromone, pawn);
foreach (StatModifier stat in aphrodisiac.CurStage.statFactors)
{
//Log.Message(pawn.Name.ToString());
//Log.Message(stat.stat.defName);
//Log.Message(stat.value.ToString());
if (stat.stat.defName == "SexFrequency")
{
stat.value = ModifySexfrequency(pawn, sexfrequency);

View File

@ -11,9 +11,10 @@ namespace RJW_Genes
[DefOf]
public static class HediffDefOf
{
public static readonly HediffDef Aphrodisiac_Pheromone;
public static readonly HediffDef Fertilin_Lost;
public static readonly HediffDef Succubus_Drained;
public static readonly HediffDef rjw_genes_aphrodisiac_pheromone;
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;
}
}

View File

@ -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<Weighted<LewdablePartKind>> ModifiersForDominant(InteractionContext context)
{
Pawn pawn = context.Internals.Dominant.Pawn;
if (GeneUtility.HasCriticalLifeForce(pawn))
Gene_LifeForce gene = pawn.genes.GetFirstGeneOfType<Gene_LifeForce>();
if (gene != null)
{
yield return new Weighted<LewdablePartKind>(50f, LewdablePartKind.Mouth);
}
else if (GeneUtility.HasLowLifeForce(pawn))
{
yield return new Weighted<LewdablePartKind>(10f, LewdablePartKind.Mouth);
}
else if (GeneUtility.HasLifeForce(pawn))
{
yield return new Weighted<LewdablePartKind>(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<LewdablePartKind>(weight, LewdablePartKind.Mouth);
yield return new Weighted<LewdablePartKind>(weight, LewdablePartKind.Beak);
}
if (pawn.genes.HasGene(GeneDefOf.rjw_genes_vaginal_absorber))
{
yield return new Weighted<LewdablePartKind>(weight, LewdablePartKind.Vagina);
}
if (pawn.genes.HasGene(GeneDefOf.rjw_genes_anal_absorber))
{
yield return new Weighted<LewdablePartKind>(weight, LewdablePartKind.Anus);
}
}
yield break;
}
public IEnumerable<Weighted<LewdablePartKind>> 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<Gene_LifeForce>();
if (gene != null)
{
yield return new Weighted<LewdablePartKind>(50f, LewdablePartKind.Mouth);
}
else if (GeneUtility.HasLowLifeForce(pawn))
{
yield return new Weighted<LewdablePartKind>(10f, LewdablePartKind.Mouth);
}
else if (GeneUtility.HasLifeForce(pawn))
{
yield return new Weighted<LewdablePartKind>(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<LewdablePartKind>(weight, LewdablePartKind.Mouth);
yield return new Weighted<LewdablePartKind>(weight, LewdablePartKind.Beak);
if (pawn.genes.HasGene(GeneDefOf.rjw_genes_vaginal_absorber))
{
yield return new Weighted<LewdablePartKind>(weight, LewdablePartKind.Vagina);
}
if (pawn.genes.HasGene(GeneDefOf.rjw_genes_anal_absorber))
{
yield return new Weighted<LewdablePartKind>(weight, LewdablePartKind.Anus);
}
}
yield break;
}

View File

@ -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;
}
}

View File

@ -28,6 +28,7 @@
</Reference>
<Reference Include="Assembly-CSharp">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="LicentiaLabs">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\Mods\licentia-labs-master\Assemblies\LicentiaLabs.dll</HintPath>
@ -35,6 +36,7 @@
</Reference>
<Reference Include="RJW">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\Mods\rjw-master\1.4\Assemblies\RJW.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@ -54,6 +56,7 @@
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>..\..\..\RimWorldWin64_Data\Managed\UnityEngine.IMGUIModule.dll</HintPath>
@ -125,14 +128,25 @@
<Compile Include="Genes\Life_Force\Abilities\CompProperties_Seduce.cs" />
<Compile Include="Genes\Life_Force\Abilities\CompProperties_AbilityCockEater.cs" />
<Compile Include="Genes\Life_Force\Gene_LifeForceDrain.cs" />
<Compile Include="Genes\Life_Force\HediffCompProperties_SeverityFromFertilin.cs" />
<Compile Include="Genes\Life_Force\HediffComp_SeverityFromFertilin.cs" />
<Compile Include="Genes\Life_Force\IncidentWorker_SuccubusDreamVisit.cs" />
<Compile Include="Genes\Life_Force\IngestionOutcomeDoer_LifeForceOffset.cs" />
<Compile Include="Genes\Life_Force\JobGiver_TryQuickieWith.cs" />
<Compile Include="Genes\Life_Force\JobDrivers\JobDriver_Flirt.cs" />
<Compile Include="Genes\Life_Force\JobDrivers\JobDriver_SexOnSpotReceiver.cs" />
<Compile Include="Genes\Life_Force\JobDrivers\JobDriver_SexOnSpot.cs" />
<Compile Include="Genes\Life_Force\JobDrivers\JobDriver_Seduced.cs" />
<Compile Include="Genes\Life_Force\JobGiver_Flirt.cs" />
<Compile Include="Genes\Life_Force\LordJob_SuccubusVisit.cs" />
<Compile Include="Genes\Life_Force\LordToil_Flirt.cs" />
<Compile Include="Genes\Life_Force\Patch_SexTicks_ChangePsyfocus.cs" />
<Compile Include="Genes\Life_Force\Patch_Vanilla_Inheritance_Fertilin.cs" />
<Compile Include="Genes\Life_Force\ThinkNode_ConditionalCannotInteract.cs" />
<Compile Include="Genes\Life_Force\ThinkNode_ConditionalLowLifeForce.cs" />
<Compile Include="Genes\Life_Force\ThinkNode_ConditionalCritcalLifeForce.cs" />
<Compile Include="Genes\Life_Force\JobGiver_GetLifeForce.cs" />
<Compile Include="Genes\Life_Force\ThinkNode_NewFlirtTarget.cs" />
<Compile Include="Genes\Special\Patch_AgeDrain.cs" />
<Compile Include="Interactions\CompAbility_SexInteractionRequirements.cs" />
<Compile Include="Genes\Life_Force\Abilities\CompAbilityEffect_PussyHeal.cs" />
@ -140,7 +154,6 @@
<Compile Include="Interactions\CompProperties_SexInteractionRequirements.cs" />
<Compile Include="Genes\Life_Force\Abilities\CompProperties_AbilityPussyHeal.cs" />
<Compile Include="Genes\Life_Force\GeneGizmo_ResourceLifeForce.cs" />
<Compile Include="Genes\Life_Force\HediffWithComps_tank.cs" />
<Compile Include="Genes\Life_Force\JobDrivers\JobDriver_CastAbilityAfterSex.cs" />
<Compile Include="Genes\Life_Force\LifeForceMentalState.cs" />
<Compile Include="Genes\Life_Force\LifeForceMentalStateWorker.cs" />
@ -157,7 +170,7 @@
<Compile Include="HediffDefOf.cs" />
<Compile Include="Interactions\CustomSexInteraction_Helper.cs" />
<Compile Include="Interactions\GenesPartKindUsageRule.cs" />
<Compile Include="Interactions\SubSuccubusTailCustomRequirementHandler - Copy.cs" />
<Compile Include="Interactions\SubSuccubusTailCustomRequirementHandler.cs" />
<Compile Include="Interactions\DomSuccubusTailCustomRequirementHandler.cs" />
<Compile Include="JobDefOf.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View File

@ -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;
}
}