107 lines
4.5 KiB
C#
107 lines
4.5 KiB
C#
|
|
|
|
using RimWorld;
|
|
using RimWorld.Planet;
|
|
using rjw;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Verse;
|
|
|
|
namespace RJW_Menstruation
|
|
{
|
|
public class CompProperties_Pheromones : HediffCompProperties
|
|
{
|
|
public float daysToMaxSeverity;
|
|
public float range;
|
|
|
|
public CompProperties_Pheromones()
|
|
{
|
|
compClass = typeof(HediffComp_Pheromones);
|
|
}
|
|
}
|
|
|
|
public class HediffComp_Pheromones : HediffComp
|
|
{
|
|
public CompProperties_Pheromones Props => (CompProperties_Pheromones)props;
|
|
public const int emitInterval = GenTicks.TickRareInterval;
|
|
public const float emitRatio = (float)emitInterval / GenDate.TicksPerDay;
|
|
|
|
public override void CompPostTick(ref float severityAdjustment)
|
|
{
|
|
try
|
|
{
|
|
if (!Configurations.EnablePheromones) return;
|
|
if (!Pawn.RaceProps.Humanlike && (!Configurations.EnableAnimalCycle || Configurations.AnimalPheromoneEffect <= 0.0f)) return;
|
|
if (!Pawn.IsHashIntervalTick(emitInterval)) return;
|
|
if (!Pawn.SpawnedOrAnyParentSpawned) return;
|
|
|
|
foreach (Pawn pawn in AffectedPawns())
|
|
ApplyEffectToPawn(pawn);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error($"Error when trying to emit pheromones from pawn {Pawn}: {ex}");
|
|
}
|
|
}
|
|
|
|
protected IEnumerable<Pawn> AffectedPawns()
|
|
{
|
|
if(Pawn.GetCaravan() is Caravan caravan)
|
|
foreach (Pawn p in caravan.PawnsListForReading.Where(p => p != Pawn)) yield return p;
|
|
Map mapHeld = Pawn.MapHeld;
|
|
if (mapHeld == null) yield break;
|
|
foreach (Pawn pawn in mapHeld.mapPawns.AllPawnsSpawned)
|
|
{
|
|
if (pawn == Pawn) continue;
|
|
if (!pawn.RaceProps.Humanlike) continue;
|
|
if (Pawn.PositionHeld.InHorDistOf(pawn.PositionHeld, Props.range) && Pawn.GetRoom() == pawn.GetRoom())
|
|
yield return pawn;
|
|
}
|
|
}
|
|
|
|
protected float GetEffectOnPawn(Pawn target)
|
|
{
|
|
if (target.Suspended || target.Dead) return 0.0f;
|
|
if (target.needs?.TryGetNeed(VariousDefOf.SexNeed) == null) return 0.0f;
|
|
if (!xxx.can_do_loving(target)) return 0.0f;
|
|
if (target.story?.traits.HasTrait(TraitDefOf.Asexual) ?? true) return 0.0f;
|
|
float penisEffect;
|
|
if (Genital_Helper.has_penis_fertile(target)) penisEffect = 1.0f;
|
|
else if (target.gender == Gender.Male) penisEffect = 0.25f;
|
|
else return 0.0f;
|
|
|
|
BodyDef body = target.RaceProps.body;
|
|
if (!PawnCapacityUtility.BodyCanEverDoCapacity(body, PawnCapacityDefOf.Breathing)) return 0.0f;
|
|
HediffSet hediffs = target.health.hediffSet;
|
|
float breathingEffect = PawnCapacityUtility.CalculateCapacityLevel(hediffs, PawnCapacityDefOf.Breathing);
|
|
float noseEffect = 1.0f;
|
|
List<BodyPartRecord> noses = body.GetPartsWithDef(BodyPartDefOf.Nose);
|
|
if (noses.Any()) // if the body doesn't have a nose but still breathes, then let it be affected
|
|
noseEffect = noses.Average(nose => PawnCapacityUtility.CalculatePartEfficiency(hediffs, nose));
|
|
|
|
return penisEffect * breathingEffect * noseEffect;
|
|
}
|
|
|
|
protected void ApplyEffectToPawn(Pawn target)
|
|
{
|
|
float intensity = GetEffectOnPawn(target);
|
|
if (intensity <= 0.0f) return;
|
|
Hediff pheromones = target.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_AffectedByPheromones);
|
|
float decay = VariousDefOf.Hediff_AffectedByPheromones.CompProps<HediffCompProperties_SeverityPerDay>().severityPerDay;
|
|
float raiseSeverityPerDay = intensity / Props.daysToMaxSeverity - decay; // Desired increase plus enough to overcome pheromone decay
|
|
if (!Pawn.RaceProps.Humanlike) raiseSeverityPerDay *= Configurations.AnimalPheromoneEffect;
|
|
float amountToApply = emitRatio * raiseSeverityPerDay;
|
|
if (pheromones != null)
|
|
pheromones.Severity += amountToApply;
|
|
else
|
|
{
|
|
pheromones = HediffMaker.MakeHediff(VariousDefOf.Hediff_AffectedByPheromones, target);
|
|
pheromones.Severity = amountToApply;
|
|
target.health.AddHediff(pheromones);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|