rjw_menstruation/1.4/source/RJW_Menstruation/RJW_Menstruation/Cum.cs

280 lines
8.4 KiB
C#

using RimWorld;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using Verse;
namespace RJW_Menstruation
{
public class Cum : IExposable
{
public Pawn pawn;
protected float volume; // ml
public float fertility = 1.0f;
public bool notcum = false; // for other fluids
public string notcumLabel = "";
protected bool useCustomColor = false;
protected float notcumthickness = 0;
protected float cumthickness = 1.0f;
protected Thing internalThing;
public float Volume
{
get
{
return volume;
}
}
public float FertVolume
{
get
{
return volume * fertility;
}
}
public float CumThickness
{
get
{
return cumthickness;
}
}
public float DecayResist
{
get
{
if (!notcum) return DNA.cumThickness;
else return notcumthickness;
}
set
{
notcumthickness = value;
}
}
protected Color customColor;
public PawnDNAModExtension DNA
{
get
{
if (DNAcache != null) return DNAcache;
try
{
DNAcache = pawn.def.GetModExtension<PawnDNAModExtension>();
}
catch (NullReferenceException)
{
DNAcache = ThingDefOf.Human.GetModExtension<PawnDNAModExtension>();
}
if (DNAcache == null)
{
DNAcache = ThingDefOf.Human.GetModExtension<PawnDNAModExtension>();
}
return DNAcache;
}
}
protected PawnDNAModExtension DNAcache = null;
public ThingDef FilthDef
{
get
{
if (filthDef == null) return VariousDefOf.CumFilth;
else return filthDef;
}
set
{
filthDef = value;
}
}
protected ThingDef filthDef = null;
public Color Color
{
get
{
if (!useCustomColor) return DNA.CumColor;
else return customColor;
}
set
{
useCustomColor = true;
customColor = value;
}
}
public Thing CumThing
{
get
{
if (internalThing == null)
{
internalThing = ThingMaker.MakeThing(VariousDefOf.CumFilth);
internalThing.stackCount = (int)volume;
}
internalThing.stackCount = (int)volume;
return internalThing;
}
}
public Cum() { }
public Cum(Pawn pawn)
{
this.pawn = pawn;
volume = 1.0f;
fertility = 1.0f;
}
/// <summary>
/// Not Cum
/// </summary>
/// <param name="pawn"></param>
/// <param name="volume"></param>
/// <param name="notcumlabel"></param>
/// <param name="decayresist"></param>
/// <param name="filthDef"></param>
public Cum(Pawn pawn, float volume, string notcumlabel, float decayresist = 0, ThingDef filthDef = null)
{
this.pawn = pawn;
this.volume = volume;
this.fertility = 0f;
this.notcum = true;
this.notcumLabel = notcumlabel;
this.notcumthickness = decayresist;
this.filthDef = filthDef;
}
public Cum(Pawn pawn, float volume, float fertility, ThingDef filthDef = null)
{
this.pawn = pawn;
this.volume = volume;
this.fertility = fertility;
this.filthDef = filthDef;
}
public virtual void ExposeData()
{
Scribe_References.Look(ref pawn, "pawn", true);
Scribe_Values.Look(ref volume, "volume", volume, true);
Scribe_Values.Look(ref fertility, "fertility", fertility, true);
Scribe_Values.Look(ref notcumthickness, "notcumthickness", 0);
Scribe_Values.Look(ref notcum, "notcum", false);
Scribe_Values.Look(ref notcumLabel, "notcumLabel", "");
Scribe_Values.Look(ref useCustomColor, "useCustomColor", false);
Scribe_Values.Look(ref customColor, "customColor", default);
Scribe_Defs.Look(ref filthDef, "filthDef");
}
public void MakeThinner(float speed)
{
cumthickness = cumthickness.LerpMultiple(DecayResist, 0.3f, speed);
}
public void MergeWithCum(float volumein, float fertility, ThingDef updatefilthDef = null)
{
if (updatefilthDef != null) filthDef = updatefilthDef;
volume += volumein;
this.fertility = (this.volume * this.fertility + volumein * fertility) / (this.volume + volumein);
cumthickness = Mathf.Lerp(cumthickness, 1.0f, volumein / volume);
}
public void MergeWithFluid(float volumein, float thickness, ThingDef updatefilthDef = null)
{
if (updatefilthDef != null) filthDef = updatefilthDef;
volume += volumein;
fertility = volume * fertility / (volume + volumein);
notcumthickness = Mathf.Lerp(notcumthickness, thickness, volumein / volume);
}
public bool ShouldRemove()
{
if ((notcum || FertVolume < 0.001f) && volume < 0.01f) return true;
return false;
}
public float DismishNatural(float leakfactor, HediffComp_Menstruation comp, float antisperm = 0.0f)
{
// comp is used for Hydrogen's RJW Muscle Injury
float totalleak = volume;
float decayPerInterval = 1 - Mathf.Pow(1 - Configurations.CumDecayRatio, comp.HoursBetweenSimulations);
float fertilityDecayPerInterval = 1 - Mathf.Pow(1 - Configurations.CumFertilityDecayRatio, comp.HoursBetweenSimulations);
antisperm *= comp.HoursBetweenSimulations;
volume *= Math.Max(0, 1 - decayPerInterval * (1 - DecayResist) * leakfactor);
fertility *= Math.Max(0, 1 - (fertilityDecayPerInterval * (1 - DecayResist) + antisperm));
CutMinor();
totalleak -= volume;
return totalleak;
}
public float DismishForce(float portion, float leakfactor = 1.0f)
{
float totalleak = volume;
volume *= Math.Max(0, 1 - (portion * (1 - DecayResist / 10)) * leakfactor);
CutMinor();
totalleak -= volume;
return totalleak;
}
public void CumEffects(Pawn pawn)
{
if (notcum || DNA?.ingestionOutcomeDoers == null || volume < 1.0f) return;
foreach (IngestionOutcomeDoer doer in DNA.ingestionOutcomeDoers)
doer.DoIngestionOutcome(pawn, CumThing);
}
protected void CutMinor()
{
if (volume < 0.01f) volume = 0f;
}
}
public class CumMixture : Cum
{
protected List<string> cums;
public bool ispurecum = true;
public List<string> Getingredients => cums;
public CumMixture()
{
notcum = true;
cums = new List<string>();
}
public CumMixture(Pawn pawn, float volume, List<string> cums, Color color, ThingDef mixtureDef, bool pure)
{
this.pawn = pawn;
this.volume = volume;
this.cums = cums;
this.customColor = color;
this.useCustomColor = true;
ispurecum = pure;
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Collections.Look(ref cums, "cumslabel", LookMode.Value, new object[0]);
}
public string GetIngredients()
{
StringBuilder res = new StringBuilder();
if (!cums.NullOrEmpty()) for (int i = 0; i < cums.Count; i++)
{
res.Append(cums[i]);
if (i < cums.Count - 1) res.Append(", ");
}
return res.ToString();
}
}
}