[Solved] Can't find why wild animals always spawn as adult

Started by K4nna, October 06, 2021, 11:31:44 AM

Previous topic - Next topic

K4nna

Hello,
I want to be able to meet baby and juvenile wild animals when I enter on a new map, or as animals entering on my map.
As I found no mod for that, I want to see if I can do it.
First, I found it seems I can't do it with only xml, my last hint from xml is GenStep_Animals.

Even if I don't know C#, I search to understand how wild animal generation works, to see if I would be able to patch it if I learn to mod with C#.
So I opened files with dnSpy, found WildAnimalSpawner, saw they seems to be spawn with:

GenSpawn.Spawn(PawnGenerator.GeneratePawn(pawnKindDef, null), loc2, this.map, WipeMode.Vanish);

who send me to PawnGenerationRequest who give me:

public PawnGenerationRequest(PawnKindDef kind, Faction faction = null, PawnGenerationContext context = PawnGenerationContext.NonPlayer, int tile = -1, bool forceGenerateNewPawn = false, bool newborn = false, bool allowDead = false, bool allowDowned = false, bool canGeneratePawnRelations = true, bool mustBeCapableOfViolence = false, float colonistRelationChanceFactor = 1f, bool forceAddFreeWarmLayerIfNeeded = false, bool allowGay = true, bool allowFood = true, bool allowAddictions = true, bool inhabitant = false, bool certainlyBeenInCryptosleep = false, bool forceRedressWorldPawnIfFormerColonist = false, bool worldPawnFactionDoesntMatter = false, float biocodeWeaponChance = 0f, float biocodeApparelChance = 0f, Pawn extraPawnForExtraRelationChance = null, float relationWithExtraPawnChanceFactor = 1f, Predicate<Pawn> validatorPreGear = null, Predicate<Pawn> validatorPostGear = null, IEnumerable<TraitDef> forcedTraits = null, IEnumerable<TraitDef> prohibitedTraits = null, float? minChanceToRedressWorldPawn = null, float? fixedBiologicalAge = null, float? fixedChronologicalAge = null, Gender? fixedGender = null, float? fixedMelanin = null, string fixedLastName = null, string fixedBirthName = null, RoyalTitleDef fixedTitle = null, Ideo fixedIdeo = null, bool forceNoIdeo = false, bool forceNoBackstory = false, bool forbidAnyTitle = false)

Here I see newborn, who could make spawn as a newborn baby, not really what I want, and fixedBiologicalAge = null, but I don't think it's what I search for.
So I reach a dead end without find why wild animals always spawn as adult.
I don't search in the right place? any idea please?

RawCode

search for line that assign age to new animals, inject here, problem solved.

you can try to trick vanilla with XML defs with overlapping age stages, overlapping age expectation, negative age expectation and similar tricky values, but you must know how exactly game process them in order to actually use (if this is possible in current version at all).

K4nna

#2
Thanks, so by looking again and searching age, I found that I took a bad way. What I search for is in PawnGenerator.
So by following the things, I have PawnGenerator.GenerateRandomAge(pawn, request); who sent me here:

private static void GenerateRandomAge(Pawn pawn, PawnGenerationRequest request)
{
if (request.FixedBiologicalAge != null && request.FixedChronologicalAge != null)
{
float? fixedBiologicalAge = request.FixedBiologicalAge;
float? fixedChronologicalAge = request.FixedChronologicalAge;
if (fixedBiologicalAge.GetValueOrDefault() > fixedChronologicalAge.GetValueOrDefault() & (fixedBiologicalAge != null & fixedChronologicalAge != null))
{
Log.Warning(string.Concat(new object[]
{
"Tried to generate age for pawn ",
pawn,
", but pawn generation request demands biological age (",
request.FixedBiologicalAge,
") to be greater than chronological age (",
request.FixedChronologicalAge,
")."
}));
}
}
if (request.Newborn)
{
pawn.ageTracker.AgeBiologicalTicks = 0L;
}
else if (request.FixedBiologicalAge != null)
{
pawn.ageTracker.AgeBiologicalTicks = (long)(request.FixedBiologicalAge.Value * 3600000f);
}
else
{
int num = 0;
float num2;
for (;;)
{
if (pawn.RaceProps.ageGenerationCurve != null)
{
num2 = (float)Mathf.RoundToInt(Rand.ByCurve(pawn.RaceProps.ageGenerationCurve));
}
else if (pawn.RaceProps.IsMechanoid)
{
num2 = Rand.Range(0f, 2500f);
}
else
{
num2 = Rand.ByCurve(PawnGenerator.DefaultAgeGenerationCurve) * pawn.RaceProps.lifeExpectancy;
}
num++;
if (num > 300)
{
break;
}
if (num2 <= (float)pawn.kindDef.maxGenerationAge && num2 >= (float)pawn.kindDef.minGenerationAge)
{
goto IL_1A4;
}
}
Log.Error("Tried 300 times to generate age for " + pawn);
IL_1A4:
pawn.ageTracker.AgeBiologicalTicks = (long)(num2 * 3600000f) + (long)Rand.Range(0, 3600000);
}


This thing generate age for all pawns, not only animal. And, it's maths... I'm not sure which part make animals always spawn adult, maybe (float)pawn.kindDef.minGenerationAge, but I only find it in PawnKindDef like this: public int minGenerationAge; , nothing more :s

If I could try it easily, I would try to quit the loop this way:

if (num2 <= (float)pawn.kindDef.maxGenerationAge && num2 > 0)

But I would have to make this exit only for animals.

Or I could define minGenerationAge with XML?

_____________________________
_____________________________

Awesome! I can do my mod only by using XML now that I understood how it's works :D
Without your answer I would have give up or tried in C# then Give up ^^'

So I only have to define minGenerationAge and ageGenerationCurve for animals that I want to meet younger, and it's works!