rjw_menstruation/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Pheromones.cs

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