mirror of
https://github.com/amevarashi/RJW-Sexperience.git
synced 2024-08-14 23:54:08 +00:00
Refactored RecordRandomizer
This commit is contained in:
parent
3c4060f8bd
commit
b99b74e27b
2 changed files with 130 additions and 90 deletions
|
@ -4,6 +4,7 @@ using Verse;
|
||||||
using RimWorld;
|
using RimWorld;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using RJWSexperience.Logs;
|
using RJWSexperience.Logs;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace RJWSexperience.SexHistory
|
namespace RJWSexperience.SexHistory
|
||||||
{
|
{
|
||||||
|
@ -17,31 +18,25 @@ namespace RJWSexperience.SexHistory
|
||||||
{
|
{
|
||||||
log.Message($"Randomize request for {pawn.NameShortColored}");
|
log.Message($"Randomize request for {pawn.NameShortColored}");
|
||||||
|
|
||||||
int avgsex = -500;
|
int avgSexPerYear = -500;
|
||||||
bool isvirgin = Rand.Chance(Settings.VirginRatio);
|
bool isVirgin = Rand.Chance(Settings.VirginRatio);
|
||||||
int totalsex = 0;
|
|
||||||
int totalbirth = 0;
|
|
||||||
|
|
||||||
if (isvirgin)
|
if (isVirgin)
|
||||||
log.Message("Rand.Chance rolled virgin");
|
log.Message("Rand.Chance rolled virgin");
|
||||||
|
|
||||||
if (pawn.story != null)
|
if (pawn.story == null)
|
||||||
{
|
{
|
||||||
int sexableage = 0;
|
log.Error("Tried to randomize records for a pawn without a story");
|
||||||
int minsexage = 0;
|
|
||||||
if (Settings.MinSexableFromLifestage)
|
|
||||||
{
|
|
||||||
LifeStageAge lifeStageAges = pawn.RaceProps.lifeStageAges.Find(x => x.def.reproductive);
|
|
||||||
if (lifeStageAges == null)
|
|
||||||
{
|
|
||||||
log.Message($"No reproductive life stage! {pawn.NameShortColored}'s randomization cancelled");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
minsexage = (int)lifeStageAges.minAge;
|
|
||||||
}
|
int sexLifeYears = 0;
|
||||||
else
|
int minsexage = GetMinSexAge(pawn, out string errorMessage);
|
||||||
|
|
||||||
|
if (minsexage < 0)
|
||||||
{
|
{
|
||||||
minsexage = (int)(pawn.RaceProps.lifeExpectancy * Settings.MinSexablePercent);
|
log.Error(errorMessage);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Message($"Min sex age is {minsexage}");
|
log.Message($"Min sex age is {minsexage}");
|
||||||
|
@ -51,103 +46,139 @@ namespace RJWSexperience.SexHistory
|
||||||
|
|
||||||
if (pawn.ageTracker.AgeBiologicalYears > minsexage)
|
if (pawn.ageTracker.AgeBiologicalYears > minsexage)
|
||||||
{
|
{
|
||||||
sexableage = pawn.ageTracker.AgeBiologicalYears - minsexage;
|
sexLifeYears = pawn.ageTracker.AgeBiologicalYears - minsexage;
|
||||||
avgsex = (int)(sexableage * Settings.SexPerYear * LustUtility.GetLustFactor(lust));
|
avgSexPerYear = (int)(sexLifeYears * Settings.SexPerYear * LustUtility.GetLustFactor(lust));
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Message($"Generating {sexableage} years of sex life");
|
log.Message($"Generating {sexLifeYears} years of sex life");
|
||||||
log.Message($"Average sex/year: {avgsex}");
|
log.Message($"Average sex/year: {avgSexPerYear}");
|
||||||
|
|
||||||
|
int totalSexCount = 0;
|
||||||
|
|
||||||
if (pawn.relations != null && pawn.gender == Gender.Female)
|
if (pawn.relations != null && pawn.gender == Gender.Female)
|
||||||
{
|
{
|
||||||
totalbirth += pawn.relations.ChildrenCount;
|
// Make sure pawn had at least as much sex as ChildrenCount
|
||||||
totalsex += totalbirth;
|
// TODO: make sure the sex is vaginal
|
||||||
pawn.records?.AddTo(xxx.CountOfSexWithHumanlikes, totalbirth);
|
// TODO: children may be not humanlike
|
||||||
pawn.records?.SetTo(xxx.CountOfBirthHuman, totalbirth);
|
totalSexCount += pawn.relations.ChildrenCount;
|
||||||
if (totalbirth > 0) isvirgin = false;
|
pawn.records.AddTo(xxx.CountOfSexWithHumanlikes, pawn.relations.ChildrenCount);
|
||||||
}
|
pawn.records.Set(xxx.CountOfBirthHuman, pawn.relations.ChildrenCount);
|
||||||
if (!isvirgin)
|
|
||||||
{
|
|
||||||
totalsex += GeneratePartnerTypeRecords(pawn, avgsex);
|
|
||||||
|
|
||||||
if (Settings.SlavesBeenRapedExp && pawn.IsSlave)
|
if (pawn.relations.ChildrenCount > 0)
|
||||||
|
isVirgin = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isVirgin)
|
||||||
{
|
{
|
||||||
totalsex += RandomizeRecord(pawn, xxx.CountOfBeenRapedByAnimals, Rand.Range(-50, 10), Rand.Range(0, 10) * sexableage);
|
Dictionary<RecordDef, int> generatedRecords = GeneratePartnerTypeRecords(pawn, avgSexPerYear, sexLifeYears);
|
||||||
totalsex += RandomizeRecord(pawn, xxx.CountOfBeenRapedByHumanlikes, 0, Rand.Range(0, 100) * sexableage);
|
|
||||||
|
foreach(KeyValuePair<RecordDef, int> record in generatedRecords)
|
||||||
|
{
|
||||||
|
pawn.records.Set(record.Key, record.Value);
|
||||||
|
totalSexCount += record.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (totalSexCount > 0)
|
||||||
|
pawn.records.AddTo(RsDefOf.Record.SexPartnerCount, Math.Max(1, Rand.Range(0, totalSexCount / 7)));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
pawn.records?.SetTo(xxx.CountOfSex, totalsex);
|
pawn.records.Set(xxx.CountOfSex, totalSexCount);
|
||||||
log.Message($"Splitting {totalsex} sex acts between sex types");
|
log.Message($"Splitting {totalSexCount} sex acts between sex types");
|
||||||
GenerateSextypeRecords(pawn, totalsex);
|
GenerateSextypeRecords(pawn, totalSexCount);
|
||||||
log.Message($"{pawn.NameShortColored} randomized");
|
log.Message($"{pawn.NameShortColored} randomized");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assign a new random value to the Lust record of the <paramref name="pawn"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pawn"></param>
|
||||||
|
/// <returns>Assigned value</returns>
|
||||||
public static float RandomizeLust(Pawn pawn)
|
public static float RandomizeLust(Pawn pawn)
|
||||||
{
|
{
|
||||||
float value = Utility.RandGaussianLike(Settings.AvgLust - Settings.MaxLustDeviation, Settings.AvgLust + Settings.MaxLustDeviation);
|
float value = Utility.RandGaussianLike(Settings.AvgLust - Settings.MaxLustDeviation, Settings.AvgLust + Settings.MaxLustDeviation);
|
||||||
float minValue;
|
|
||||||
|
|
||||||
if (xxx.is_nympho(pawn))
|
if (xxx.is_nympho(pawn))
|
||||||
minValue = 0;
|
value = Mathf.Clamp(value, 0, float.MaxValue);
|
||||||
else
|
|
||||||
minValue = float.MinValue;
|
|
||||||
|
|
||||||
value = Mathf.Clamp(value, minValue, float.MaxValue);
|
pawn.records.SetTo(RsDefOf.Record.Lust, value);
|
||||||
float recordvalue = pawn.records.GetValue(RsDefOf.Record.Lust);
|
|
||||||
pawn.records.AddTo(RsDefOf.Record.Lust, value - recordvalue);
|
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int RandomizeRecord(Pawn pawn, RecordDef record, int avg, int dist, int min = 0, int max = int.MaxValue)
|
/// <summary>
|
||||||
|
/// Get minimal biological age the pawn can begin sex life
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pawn"></param>
|
||||||
|
/// <param name="errorMessage">null if no error</param>
|
||||||
|
/// <returns>-1 means error. <paramref name="errorMessage"/> should be not null in that case</returns>
|
||||||
|
private static int GetMinSexAge(Pawn pawn, out string errorMessage)
|
||||||
{
|
{
|
||||||
int value = (int)Mathf.Clamp(Utility.RandGaussianLike(avg - dist, avg + dist), min, max);
|
errorMessage = null;
|
||||||
int recordvalue = pawn.records.GetAsInt(record);
|
|
||||||
pawn.records.AddTo(record, value - recordvalue);
|
|
||||||
|
|
||||||
return value;
|
if (!Settings.MinSexableFromLifestage)
|
||||||
|
{
|
||||||
|
// Legacy approach. Does not account for long-lived races with human-like aging curve
|
||||||
|
return (int)(pawn.RaceProps.lifeExpectancy * Settings.MinSexablePercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GeneratePartnerTypeRecords(Pawn pawn, int avgsex)
|
LifeStageAge lifeStageAges = pawn.RaceProps.lifeStageAges.Find(x => x.def.reproductive);
|
||||||
|
if (lifeStageAges == null)
|
||||||
{
|
{
|
||||||
|
errorMessage = $"No reproductive life stage! {pawn.NameShortColored}'s randomization cancelled";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (int)lifeStageAges.minAge;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int Randomize(int avg, int dist, int min = 0, int max = int.MaxValue) => (int)Mathf.Clamp(Utility.RandGaussianLike(avg - dist, avg + dist), min, max);
|
||||||
|
|
||||||
|
private static Dictionary<RecordDef, int> GeneratePartnerTypeRecords(Pawn pawn, int avgSexPerYear, int sexLifeYears)
|
||||||
|
{
|
||||||
|
Dictionary<RecordDef, int> generatedRecords = new Dictionary<RecordDef, int>();
|
||||||
int deviation = (int)Settings.MaxSexCountDeviation;
|
int deviation = (int)Settings.MaxSexCountDeviation;
|
||||||
int totalSexCount = 0;
|
|
||||||
|
|
||||||
if (xxx.is_rapist(pawn))
|
if (xxx.is_rapist(pawn))
|
||||||
{
|
{
|
||||||
if (xxx.is_zoophile(pawn))
|
if (xxx.is_zoophile(pawn))
|
||||||
{
|
{
|
||||||
if (pawn.Has(Quirk.ChitinLover)) totalSexCount += RandomizeRecord(pawn, xxx.CountOfRapedInsects, avgsex, deviation);
|
if (pawn.Has(Quirk.ChitinLover))
|
||||||
else totalSexCount += RandomizeRecord(pawn, xxx.CountOfRapedAnimals, avgsex, deviation);
|
generatedRecords.Add(xxx.CountOfRapedInsects, Randomize(avgSexPerYear, deviation));
|
||||||
|
else
|
||||||
|
generatedRecords.Add(xxx.CountOfRapedAnimals, Randomize(avgSexPerYear, deviation));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
totalSexCount += RandomizeRecord(pawn, xxx.CountOfRapedHumanlikes, avgsex, deviation);
|
generatedRecords.Add(xxx.CountOfRapedHumanlikes, Randomize(avgSexPerYear, deviation));
|
||||||
}
|
}
|
||||||
|
|
||||||
avgsex /= 8;
|
avgSexPerYear /= 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xxx.is_zoophile(pawn))
|
if (xxx.is_zoophile(pawn))
|
||||||
{
|
{
|
||||||
if (pawn.Has(Quirk.ChitinLover)) totalSexCount += RandomizeRecord(pawn, xxx.CountOfRapedInsects, avgsex, deviation);
|
if (pawn.Has(Quirk.ChitinLover))
|
||||||
else totalSexCount += RandomizeRecord(pawn, xxx.CountOfSexWithAnimals, avgsex, deviation);
|
generatedRecords.Add(xxx.CountOfRapedInsects, Randomize(avgSexPerYear, deviation));
|
||||||
avgsex /= 10;
|
else
|
||||||
|
generatedRecords.Add(xxx.CountOfSexWithAnimals, Randomize(avgSexPerYear, deviation));
|
||||||
|
|
||||||
|
avgSexPerYear /= 10;
|
||||||
}
|
}
|
||||||
else if (xxx.is_necrophiliac(pawn))
|
else if (xxx.is_necrophiliac(pawn))
|
||||||
{
|
{
|
||||||
totalSexCount += RandomizeRecord(pawn, xxx.CountOfSexWithCorpse, avgsex, deviation);
|
generatedRecords.Add(xxx.CountOfSexWithCorpse, Randomize(avgSexPerYear, deviation));
|
||||||
avgsex /= 4;
|
avgSexPerYear /= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
totalSexCount += RandomizeRecord(pawn, xxx.CountOfSexWithHumanlikes, avgsex, deviation);
|
generatedRecords.Add(xxx.CountOfSexWithHumanlikes, Randomize(avgSexPerYear, deviation));
|
||||||
|
|
||||||
if (totalSexCount > 0)
|
if (Settings.SlavesBeenRapedExp && pawn.IsSlave)
|
||||||
pawn.records.AddTo(RsDefOf.Record.SexPartnerCount, Math.Max(1, Rand.Range(0, totalSexCount / 7)));
|
{
|
||||||
|
generatedRecords.Add(xxx.CountOfBeenRapedByAnimals, Randomize(Rand.Range(-50, 10), Rand.Range(0, 10) * sexLifeYears));
|
||||||
|
generatedRecords.Add(xxx.CountOfBeenRapedByHumanlikes, Randomize(0, Rand.Range(0, 100) * sexLifeYears));
|
||||||
|
}
|
||||||
|
|
||||||
return totalSexCount;
|
return generatedRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateSextypeRecords(Pawn pawn, int totalsex)
|
private static void GenerateSextypeRecords(Pawn pawn, int totalsex)
|
||||||
|
@ -238,10 +269,7 @@ namespace RJWSexperience.SexHistory
|
||||||
if (xxx.is_homosexual(pawn))
|
if (xxx.is_homosexual(pawn))
|
||||||
return pawn.gender;
|
return pawn.gender;
|
||||||
|
|
||||||
if (pawn.gender == Gender.Male)
|
return pawn.gender.Opposite();
|
||||||
return Gender.Female;
|
|
||||||
else
|
|
||||||
return Gender.Male;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,24 @@ namespace RJWSexperience
|
||||||
return ((float)res).Denormalization(min, max);
|
return ((float)res).Denormalization(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set exact <paramref name="value"/> for the <paramref name="record"/>
|
||||||
|
/// </summary>
|
||||||
public static void SetTo(this Pawn_RecordsTracker records, RecordDef record, float value)
|
public static void SetTo(this Pawn_RecordsTracker records, RecordDef record, float value)
|
||||||
{
|
{
|
||||||
float recordval = records.GetValue(record);
|
float recordval = records.GetValue(record);
|
||||||
records.AddTo(record, value - recordval);
|
records.AddTo(record, value - recordval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set exact <paramref name="value"/> for the <paramref name="record"/>
|
||||||
|
/// </summary>
|
||||||
|
public static void Set(this Pawn_RecordsTracker records, RecordDef record, int value)
|
||||||
|
{
|
||||||
|
int currentValue = records.GetAsInt(record);
|
||||||
|
records.AddTo(record, value - currentValue);
|
||||||
|
}
|
||||||
|
|
||||||
public static float Normalization(this float num, float min, float max)
|
public static float Normalization(this float num, float min, float max)
|
||||||
{
|
{
|
||||||
return (num - min) / (max - min);
|
return (num - min) / (max - min);
|
||||||
|
|
Loading…
Reference in a new issue