User:Seasonedcabbages/Sandbox

From RimWorld Wiki
Jump to navigation Jump to search

Draft for general pawn creation mechanics as inferred from looking at the game in the debugger

About[edit]

The game generates every pawn from the same place, specifying what kind of pawn it is looking for in the pawn generation request. This page will follow the generation of the starting colonist as an example.

This page was written against game version 1.6.4871

Gender[edit]

Gender is a flat 50% chance if the request didn't ask for a specific gender. (!example)

Biological Age[edit]

Biological age is tracked by the game in ticks, however the request may specify an age in years and it is converted here.

If generating a newborn is requested, age is set to 0.

For other age groups each race group has its own defined age generation curve. For instance the humanlike generation curve for biotech:

Age Curve for humanlikes

The years 12.5-13 are excluded to avoid spawning pawns very close to reaching adulthood. The range of 14-14.001 is excluded only due to how the xml age generation curve definition works

Races without a defined generation curve use the default age generation curve which is then multiplied by the defined life expectancy of the pawn:

Default age curve

The age request can be further modified to specify minumum age, maximum age and desired developmental stages. in this case the generated age gets thrown out until an allowed one is generated or until 300 tries are reached.

Our colonist has a request for the developmental stage of Adult. Developmental stages are defined in a pawn's RaceProps. Adult is the last life stage of the colonist starting at 18 and so our generated pawn will be at least 18 while using the humanlike curve, throwing away any wrong results.

Chronological age[edit]

Chronological age is defined in the request for the kind of pawn to generate and goes off of the curve defined there if available. Otherwise, the following algorithm is used:

  1. Set chronological age to 0 if:
    1. Pawn does not have a cryosleep backstory
    2. Pawn has a cryptosleep backstory with a chance and does not pass the check as defined in the racedef
  2. Otherwise if cryptosleep backstory set or cryptosleep check passed:
    1. at a 5% chance choose years randomly in a range from 1000 to: Current ingame year - 2026 - pawn's biological age
    2. at a 25% chance pick a random amount of years from 1000 to 100
    3. at a 70% chance pick a random amount of years from 0 to 100
  3. If chronological age is lower than biological, set chronological age to be the same as biological age

The starting colonist does not have a set chronological age curve and has a set cryptosleep backstory chance of 100% and as such will always use the algorithm from step 2.

Needs[edit]

All needs initially get set to 50% of their maximum values, except for newborns which are created with a hunger of 18.75% (halfway between hungry and ravenously hungry) and a rest of 21% (halfway between drowsy and tired)

Xenotype[edit]

If biotech is available the following checks are run:

  1. If forced xenotype is requested, set it
  2. If custom xenotype is requested, try the Force Baseliner Chance and return Baseliner if successful
  3. If list of allowed xenotypes is provided, pick one
  4. Assemble a list of viable xenotypes for this pawn, respecting kind and faction restrictions
    1. If request specified ability for violence, remove xenotypes incapable
  5. Look up and assign weights to valid xenotypes on their rarity
  6. Attempt to select a valid xenotype randomly based on weights
  7. If no xenotype selected yet, select baseliner
  8. If the requested pawn does not belong to a faction and got generated as baseliner and request didn't contain a forced or custom xenotype, adjust the pawn xenotype:
    1. Collect all xenotypes including custom ones
    2. Assign weights to all xenotypes, base xenotypes get a weight as defined for "Factionless generation weight", custom xenotypes get a weight of 2 (most base xenotypes get a weight of 1, baseliner gets 40)
    3. Pick a random xenotype and assign it

Our colonist has a forced xenotype of Baseliner.

applicable call stack @skill generation:

Int32 Verse.PawnGenerator:FinalLevelOfSkill (Pawn, SkillDef, PawnGenerationRequest)+0x80 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\Verse\PawnGenerator.cs:[1564:9-1564:35] C#

	Void Verse.PawnGenerator:GenerateSkills (Pawn, PawnGenerationRequest)+0x19 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\Verse\PawnGenerator.cs:[1453:7-1453:73]	C#
	Pawn Verse.PawnGenerator:TryGenerateNewPawnInternal (PawnGenerationRequest, String, Boolean, Boolean)+0x470 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\Verse\PawnGenerator.cs:[627:9-627:52]	C#
	Pawn Verse.PawnGenerator:GenerateNewPawnInternal (PawnGenerationRequest)+0xa2 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\Verse\PawnGenerator.cs:[543:7-543:135]	C#
	Pawn Verse.PawnGenerator:GenerateOrRedressPawnInternal (PawnGenerationRequest)+0x142 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\Verse\PawnGenerator.cs:[247:7-247:66]	C#
	Pawn Verse.PawnGenerator:GeneratePawn (PawnGenerationRequest)+0x8 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\Verse\PawnGenerator.cs:[184:7-184:86]	C#
	Pawn Verse.StartingPawnUtility:NewGeneratedStartingPawn (Int32)+0x15 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\Verse\StartingPawnUtility.cs:[309:7-309:49]	C#
	Void Verse.StartingPawnUtility:AddNewPawn (Int32)+0x1 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\Verse\StartingPawnUtility.cs:[422:5-422:68]	C#
	Void RimWorld.ScenPart_ConfigPage_ConfigureStartingPawns:GenerateStartingPawns ()+0xc at D:\SteamLibrary\steamapps\common\Assembly-CSharp\RimWorld\ScenPart_ConfigPage_ConfigureStartingPawns.cs:[69:9-69:41]	C#
	Void RimWorld.ScenPart_ConfigPage_ConfigureStartingPawnsBase:PostIdeoChosen ()+0x165 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\RimWorld\ScenPart_ConfigPage_ConfigureStartingPawnsBase.cs:[44:5-44:33]	C#
	Void RimWorld.ScenPart_ConfigPage_ConfigureStartingPawns:PostIdeoChosen ()+0x21 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\RimWorld\ScenPart_ConfigPage_ConfigureStartingPawns.cs:[79:5-79:26]	C#
	Void RimWorld.Scenario:PostIdeoChosen ()+0x14 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\RimWorld\Scenario.cs:[267:34-267:47]	C#
	Void RimWorld.Page_ChooseIdeoPreset:DoClassic ()+0x60 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\RimWorld\Page_ChooseIdeoPreset.cs:[457:5-457:35]	C#
	Void RimWorld.Page_ChooseIdeoPreset:DoNext ()+0x36 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\RimWorld\Page_ChooseIdeoPreset.cs:[531:9-531:25]	C#
	Void RimWorld.Page:DoBottomButtons (Rect, String, String, Action, Boolean, Boolean)+0xfd at D:\SteamLibrary\steamapps\common\Assembly-CSharp\RimWorld\Page.cs:[72:9-72:22]	C#
	Void RimWorld.Page_ChooseIdeoPreset:DoWindowContents (Rect)+0x3be at D:\SteamLibrary\steamapps\common\Assembly-CSharp\RimWorld\Page_ChooseIdeoPreset.cs:[166:5-166:33]	C#
	Void Verse.Window:InnerWindowOnGUI (Int32)+0x1a6 at D:\SteamLibrary\steamapps\common\Assembly-CSharp\Verse\Window.cs:[192:7-192:44]	C#
	Void UnityEngine.GUI:CallWindowDelegate (WindowFunction, Int32, Int32, GUISkin, Int32, Single, Single, GUIStyle)+0x7f at :-1	C#

raw skill generation:

  • step 1: newborns are assigned a skill of 0 for every skill
  • step 2: get the inital num based on:
  • step 2.1: skills usually defined in backstory gets the PawnGenerator.LevelRandomCurve randomby (!which skills are that)
  • step 2.2: skills not defined like that get a randfloat (0,4)
  • step 3: apply any backstory skill gains at a random factor of (1,1.4)
  • step 4: apply trait skill gains (constant factor) (!these are probably also negatives)
  • step 5: multiply the num randomly on a range from 1 to Age Range
  • step 5.1: Age range is AgeskillMaxFactorCurve * AgeSkillFactor, both at the points of biological age
  • step 6: apply LevelFinalAdjustmentCurve
  • step 7: apply modifiers from type of pawn (xenotypes etxc.)0
  • step 8: if any skills are higher or lower than allowed by kind of pawn, pick randomly in that range (!probably didnt get this step right, read up more on kindDef)
  • step 9: Round then clamp to (0,20)

Passions continue on in GenerateSkills:

  • step 1: number of passions points is set as 5 + random gaussian between -4 and +4.
  • major passions cost 1.5 points, minor passions cost 1 point.
  • step 2: randomly pick between new minor and major passion counts (equal chance) until points are depleted.
  • step 3: if a trait requires a passion, it is selected now. major passions get picked first, minor passions are assigned even if not available
  • step 4: then do biotech kid stuff (!complete)
  • step 5: order other skills in descending order, try to assign passion if one is available and if skill doesn't either conflict with a trait or there's a gene that disables the passion

passions may be depleted at any step during this process which means no more passions will be generated. If somehow passions are left over at the end of the process they go unused