Llyme / RW_CustomPawnGeneration

RimWorld mod. Allows you to change how pawns are generated.
0 stars 2 forks source link

100% Male nerfs colony generation when HAR is installed #14

Open mycroftjr opened 5 days ago

mycroftjr commented 5 days ago

With HAR installed, override Gender Frequency -> 100% Male causes so many pawn generations to exceed 120 tries and fail that most colonies don't get to populate onto the map (~20 goes down to 4).

(The specific failure is usually Generated pawn with disabled requiredWorkTags and it usually happens when trying to generate a Tribal_Chief?)

This is independent of any of the mod's other settings (Remove Parent Gender Restrictions, Override Forced Gender, body types, etc).

Also, the config wording should probably be clearer that with body type filtering enabled, the Xs are not allowed and the checkmarks are.

Sibling issue on HAR: https://github.com/erdelf/AlienRaces/issues/111

Llyme commented 5 days ago

I'll look into it. Though with the addition of Biotech, I do recommend just using genes to restrict a race to being a male/female-only race, like this one https://steamcommunity.com/sharedfiles/filedetails/?id=3249501807

Llyme commented 5 days ago

I just released an update that puts a hard limit on how many times a pawn's gender is re-rolled. Sadly, I don't think I can forcibly set the pawn's gender if another mod is also doing the same thing. The best I can do is to give the other mod priority over mine.

erdelf commented 5 days ago

Depends how you want to do it I suppose. Either you let me override, or you set the forced gender in the request.

mycroftjr commented 4 days ago

Depends how you want to do it I suppose. Either you let me override, or you set the forced gender in the request.

I assume that since 100% female works while 100% male doesn't, you're currently setting forced gender female somewhere? I wasn't able to find anything that looked like that in HAR's code, though... Where is it, and where would I set the forced gender?

mycroftjr commented 4 days ago

I just released an update that puts a hard limit on how many times a pawn's gender is re-rolled. Sadly, I don't think I can forcibly set the pawn's gender if another mod is also doing the same thing. The best I can do is to give the other mod priority over mine.

Any chance of that being a config option instead of hardcoded?

erdelf commented 4 days ago

Depends how you want to do it I suppose. Either you let me override, or you set the forced gender in the request.

I assume that since 100% female works while 100% male doesn't, you're currently setting forced gender female somewhere? I wasn't able to find anything that looked like that in HAR's code, though... Where is it, and where would I set the forced gender?

I don't set the forced gender no, I change it directly. I would assume you have a race that might just be 100% female or so? There are a few floating around.

mycroftjr commented 4 days ago

I would assume you have a race that might just be 100% female or so? There are a few floating around.

This happens with 0 mods installed other than Harmony, all the DLC, HAR, and Custom Pawn Generator, so unless HAR includes any races (which it doesn't afaik), no.

mycroftjr commented 4 days ago

Setting forced gender doesn't seem to change much. For context, the error usually looks like this:

Pawn generation error: Generated pawn with disabled requiredWorkTags. Too many tries (120), returning null. Generation request: kindDef=Tribal_ChiefRanged, context=NonPlayer, faction=League of Nefososs, tile=-1,
 forceGenerateNewPawn=False, allowedDevelopmentalStages=Adult, allowDead=False, allowDowned=False, canGeneratePawnRelations=True, mustBeCapableOfViolence=False, colonistRelationChanceFactor=1,
 forceAddFreeWarmLayerIfNeeded=False, allowGay=True, prohibitedTraits=, allowFood=True, allowAddictions=True, inhabitant=False, certainlyBeenInCryptosleep=False, biocodeWeaponChance=0, validatorPreGear=, validatorPostGear=,
 fixedBiologicalAge=, fixedChronologicalAge=, fixedGender=, fixedLastName=, fixedBirthName=

and happens when generating a Tribal leader

erdelf commented 4 days ago

You did not set a forced gender in that one.. as it specifically mentions at the bottom. I was also talking to Llyme so that he could adjust it in the mod if desired.

mycroftjr commented 4 days ago

You did not set a forced gender in that one.. as it specifically mentions at the bottom. I was also talking to Llyme so that he could adjust it in the mod if desired.

Sorry, I should have been clearer. I'm a programmer, but forced gender seems completely unrelated to the error, which is ultimately where the pawn generation gives up regardless of my attempts at fixes and Llyme's fix from last night. I can't figure out how Custom Pawn Generation's Gender Frequency slider + HAR is causing Tribal leaders to have work tags that they need be disabled???

EDIT: in fact, I got it to set forceGender=Male in a Priority.First Prefix of PawnGenerator.GeneratePawn and it didn't really change the error:

Pawn generation error: Generated pawn with disabled requiredWorkTags. Too many tries (120), returning null. Generation request: kindDef=Tribal_ChiefRanged, context=NonPlayer, faction=Sezcoaz Sprintship, tile=-1,
 forceGenerateNewPawn=False, allowedDevelopmentalStages=Adult, allowDead=False, allowDowned=False, canGeneratePawnRelations=True, mustBeCapableOfViolence=False, colonistRelationChanceFactor=1,
 forceAddFreeWarmLayerIfNeeded=False, allowGay=True, prohibitedTraits=, allowFood=True, allowAddictions=True, inhabitant=False, certainlyBeenInCryptosleep=False, biocodeWeaponChance=0, validatorPreGear=, validatorPostGear=,
 fixedBiologicalAge=, fixedChronologicalAge=, fixedGender=Male, fixedLastName=, fixedBirthName=
UnityEngine.StackTraceUtility:ExtractStackTrace ()
Verse.Log:Error (string)
Verse.PawnGenerator:GenerateNewPawnInternal (Verse.PawnGenerationRequest&)
Verse.PawnGenerator:GenerateOrRedressPawnInternal (Verse.PawnGenerationRequest)
(wrapper dynamic-method) MonoMod.Utils.DynamicMethodDefinition:Verse.PawnGenerator.GeneratePawn_Patch4 (Verse.PawnGenerationRequest)
RimWorld.Faction:TryGenerateNewLeader ()
RimWorld.FactionGenerator:NewGeneratedFaction (RimWorld.FactionGeneratorParms)
RimWorld.FactionGenerator:CreateFactionAndAddToManager (RimWorld.FactionDef)
RimWorld.FactionGenerator:AddFactionToManager (RimWorld.FactionDef)
RimWorld.FactionGenerator:GenerateFactionsIntoWorld (System.Collections.Generic.List`1<RimWorld.FactionDef>)
RimWorld.Planet.WorldGenStep_Factions:GenerateFresh (string)
RimWorld.Planet.WorldGenerator:GenerateWorld (single,string,RimWorld.Planet.OverallRainfall,RimWorld.Planet.OverallTemperature,RimWorld.Planet.OverallPopulation,System.Collections.Generic.List`1<RimWorld.FactionDef>,single)
RimWorld.Page_CreateWorldParams:<CanDoNext>b__19_0 ()
Verse.LongEventHandler:RunEventFromAnotherThread (System.Action)
Verse.LongEventHandler/<>c:<UpdateCurrentAsynchronousEvent>b__28_0 ()
System.Threading.ThreadHelper:ThreadStart_Context (object)
System.Threading.ExecutionContext:RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool)
System.Threading.ExecutionContext:Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool)
System.Threading.ExecutionContext:Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object)
System.Threading.ThreadHelper:ThreadStart ()

I also sometimes get a different error instead:

Error while generating pawn. Rethrowing. Exception: System.NullReferenceException: Object reference not set to an instance of an object
[Ref 54A9A622]
 at RimWorld.PawnRelationWorker_Sibling.ResolveMyName (Verse.PawnGenerationRequest& request, Verse.Pawn generated) [0x00044] in <f0ac5eb9b52e4cc396c70fc9a4ee15e5>:0 
 at RimWorld.PawnRelationWorker_Sibling.CreateRelation (Verse.Pawn generated, Verse.Pawn other, Verse.PawnGenerationRequest& request) [0x001c3] in <f0ac5eb9b52e4cc396c70fc9a4ee15e5>:0 
 at Verse.PawnGenerator.GeneratePawnRelations (Verse.Pawn pawn, Verse.PawnGenerationRequest& request) [0x00197] in <f0ac5eb9b52e4cc396c70fc9a4ee15e5>:0 
     - PREFIX rimworld.erdelf.alien_race.main: Boolean AlienRace.HarmonyPatches:GeneratePawnRelationsPrefix(Pawn pawn, PawnGenerationRequest& request)
     - PREFIX com.rimworld.mod.nyan.custom_pawn_generation: Void RW_CustomPawnGeneration.Patch_PawnGenerator_GeneratePawnRelations:Prefix(Pawn pawn, PawnGenerationRequest& request)
     - POSTFIX com.rimworld.mod.nyan.custom_pawn_generation: Void RW_CustomPawnGeneration.Patch_PawnGenerator_GeneratePawnRelations:Postfix(Pawn pawn, PawnGenerationRequest& request)
 at AlienRace.HarmonyPatches.GenerateTraitsPostfix (Verse.Pawn pawn, Verse.PawnGenerationRequest request) [0x00017] in <a85659a3d060459285306e05bfed23d7>:0 
 at Verse.PawnGenerator.GenerateTraits (Verse.Pawn pawn, Verse.PawnGenerationRequest request) [0x005e5] in <f0ac5eb9b52e4cc396c70fc9a4ee15e5>:0 
     - PREFIX rimworld.erdelf.alien_race.main: Void AlienRace.HarmonyPatches:GenerateTraitsPrefix(Pawn pawn)
     - PREFIX com.rimworld.mod.nyan.custom_pawn_generation: Void RW_CustomPawnGeneration.Patch_PawnGenerator_GenerateTraits:Prefix(Pawn pawn, PawnGenerationRequest request)
     - POSTFIX rimworld.erdelf.alien_race.main: Void AlienRace.HarmonyPatches:GenerateTraitsPostfix(Pawn pawn, PawnGenerationRequest request)
     - POSTFIX com.rimworld.mod.nyan.custom_pawn_generation: Void RW_CustomPawnGeneration.Patch_PawnGenerator_GenerateTraits:Postfix(Pawn pawn, PawnGenerationRequest request)
 at Verse.PawnGenerator.TryGenerateNewPawnInternal (Verse.PawnGenerationRequest& request, System.String& error, System.Boolean ignoreScenarioRequirements, System.Boolean ignoreValidator) [0x004a1] in <f0ac5eb9b52e4cc396c70fc9a4ee15e5>:0 
     - TRANSPILER rimworld.erdelf.alien_race.main: IEnumerable`1 AlienRace.HarmonyPatches:TryGenerateNewPawnInternalTranspiler(IEnumerable`1 instructions)
     - PREFIX rimworld.erdelf.alien_race.main: Void AlienRace.HarmonyPatches:TryGenerateNewPawnInternalPrefix(PawnGenerationRequest& request)
     - PREFIX com.rimworld.mod.nyan.custom_pawn_generation: Void RW_CustomPawnGeneration.Patch_PawnGenerator_TryGenerateNewPawnInternal:Prefix(PawnGenerationRequest& request)
     - POSTFIX com.rimworld.mod.nyan.custom_pawn_generation: Void RW_CustomPawnGeneration.Patch_PawnGenerator_TryGenerateNewPawnInternal:Postfix(PawnGenerationRequest request)
 at Verse.PawnGenerator.GenerateNewPawnInternal (Verse.PawnGenerationRequest& request) [0x00094] in <f0ac5eb9b52e4cc396c70fc9a4ee15e5>:0 
 at Verse.PawnGenerator.GenerateOrRedressPawnInternal (Verse.PawnGenerationRequest request) [0x00136] in <f0ac5eb9b52e4cc396c70fc9a4ee15e5>:0 
 at Verse.PawnGenerator.GeneratePawn (Verse.PawnGenerationRequest request) [0x00044] in <f0ac5eb9b52e4cc396c70fc9a4ee15e5>:0 
     - PREFIX com.rimworld.mod.nyan.custom_pawn_generation: Void RW_CustomPawnGeneration.Patch_PawnGenerator_GeneratePawn:Prefix(PawnGenerationRequest& request)
     - PREFIX rimworld.erdelf.alien_race.main: Void AlienRace.HarmonyPatches:GeneratePawnPrefix(PawnGenerationRequest& request)
     - POSTFIX rimworld.erdelf.alien_race.main: Void AlienRace.HarmonyPatches:GeneratePawnPostfix(Pawn __result)
     - POSTFIX com.rimworld.mod.nyan.custom_pawn_generation: Void RW_CustomPawnGeneration.Patch_PawnGenerator_GeneratePawn:Patch(Pawn __result, PawnGenerationRequest request)
UnityEngine.StackTraceUtility:ExtractStackTrace ()
Verse.Log:Error (string)
(wrapper dynamic-method) MonoMod.Utils.DynamicMethodDefinition:Verse.PawnGenerator.GeneratePawn_Patch4 (Verse.PawnGenerationRequest)
RimWorld.Faction:TryGenerateNewLeader ()
RimWorld.FactionGenerator:NewGeneratedFaction (RimWorld.FactionGeneratorParms)
RimWorld.FactionGenerator:CreateFactionAndAddToManager (RimWorld.FactionDef)
RimWorld.FactionGenerator:AddFactionToManager (RimWorld.FactionDef)
RimWorld.FactionGenerator:GenerateFactionsIntoWorld (System.Collections.Generic.List`1<RimWorld.FactionDef>)
RimWorld.Planet.WorldGenStep_Factions:GenerateFresh (string)
RimWorld.Planet.WorldGenerator:GenerateWorld (single,string,RimWorld.Planet.OverallRainfall,RimWorld.Planet.OverallTemperature,RimWorld.Planet.OverallPopulation,System.Collections.Generic.List`1<RimWorld.FactionDef>,single)
RimWorld.Page_CreateWorldParams:<CanDoNext>b__19_0 ()
Verse.LongEventHandler:RunEventFromAnotherThread (System.Action)
Verse.LongEventHandler/<>c:<UpdateCurrentAsynchronousEvent>b__28_0 ()
System.Threading.ThreadHelper:ThreadStart_Context (object)
System.Threading.ExecutionContext:RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool)
System.Threading.ExecutionContext:Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool)
System.Threading.ExecutionContext:Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object)
System.Threading.ThreadHelper:ThreadStart ()
Llyme commented 4 days ago

I released another update that sets the FixedGender whenever the gender gets changed by my mod (enabled by default; can be disabled.) There was also an option that I put in the mod a long time ago that prevents changing gender when FixedGender is not empty, though it had a poor description, so I updated it. Hopefully this resolves the issue. image image

mycroftjr commented 4 days ago

I released another update that sets the FixedGender whenever the gender gets changed by my mod (enabled by default; can be disabled.) There was also an option that I put in the mod a long time ago that prevents changing gender when FixedGender is not empty, though it had a poor description, so I updated it. Hopefully this resolves the issue.

No dice, error remains the same (Set Fixed Gender on, Override Forced Gender on OR off):

Pawn generation error: Generated pawn with disabled requiredWorkTags. Too many tries (120), returning null. Generation
request: kindDef=Tribal_ChiefMelee, context=NonPlayer, faction=Firehome of Cavga, tile=-1, forceGenerateNewPawn=False,
allowedDevelopmentalStages=Adult, allowDead=False, allowDowned=False, canGeneratePawnRelations=True,
mustBeCapableOfViolence=False, colonistRelationChanceFactor=1, forceAddFreeWarmLayerIfNeeded=False, allowGay=True,
prohibitedTraits=, allowFood=True, allowAddictions=True, inhabitant=False, certainlyBeenInCryptosleep=False,
biocodeWeaponChance=0, validatorPreGear=, validatorPostGear=, fixedBiologicalAge=, fixedChronologicalAge=,
fixedGender=, fixedLastName=, fixedBirthName=

fixedGender also seems to still not be set, but like I said, that didn't fix the issue in the first place (see my branch). The more I investigate, the less I understand what this has to do with gender and the more I become sure that this is a conflict specifically between HAR and Custom Pawn Generation.

The error is not present if I go with the gene route instead, even though I'd expect that to cause HAR the same amount of trouble...

Llyme commented 4 days ago

I assume the PawnGenerationRequest.FixedGender is in read-only. I'll release an update later that forcibly sets it.

mycroftjr commented 4 days ago

I assume the PawnGenerationRequest.FixedGender is in read-only. I'll release an update later that forcibly sets it.

I really don't think it is (I think you're just setting it too late)... either way, please download HAR and test it yourself :/

Llyme commented 4 days ago

I'll try it out after work.

Llyme commented 4 days ago

I don't know why but PawnGenerationRequest.FixedGender keeps getting reset to null after PawnGenerator.GenerateRandomAge... I tried setting the desired gender directly on PawnGenerationRequest.FixedGender, at the beginning of PawnGenerator.TryGenerateNewPawnInternal, but it gets reset anyway. I'll figure something out tomorrow since this is way too exhausting to do at night.

erdelf commented 4 days ago

a bit odd. You only have our mods loaded ?

While I have a prefix on the method, as you can see if fixedGender is set, it shouldn't really do much

        public static void GenerateRandomAgePrefix(Pawn pawn, PawnGenerationRequest request)
        {
            if (!request.FixedGender.HasValue && !pawn.kindDef.fixedGender.HasValue && pawn.RaceProps.hasGenders)
            {

relevant code

mycroftjr commented 3 days ago

I don't know why but PawnGenerationRequest.FixedGender keeps getting reset to null after PawnGenerator.GenerateRandomAge... I tried setting the desired gender directly on PawnGenerationRequest.FixedGender, at the beginning of PawnGenerator.TryGenerateNewPawnInternal, but it gets reset anyway. I'll figure something out tomorrow since this is way too exhausting to do at night.

Setting it first-thing in GeneratePawn as I do in my fork worked for me, FixedGender-wise

Llyme commented 3 days ago

I got tired of it and just prevented the error Generated pawn with disabled requiredWorkTags. from happening. It kinda works now. Not sure if this is safe. It only prevents the error if the pawn's gender was changed by the mod.

Llyme commented 3 days ago

It seems to be working well now. I added a warning error just so everyone's aware of my mod being aggressive. I'll also add an option to make it not aggressive. image

Llyme commented 3 days ago

I released the update. Hopefully the issue gets fixed this time. EDIT: Also, I removed the Set Fixed Gender option since it's permanently enabled now.

mycroftjr commented 2 days ago

It seems to be working well now. I added a warning error just so everyone's aware of my mod being aggressive. I'll also add an option to make it not aggressive.

Isn't it kind of bad for a leader to be generated with disabled WorkTags that they need?

Btw, is there some flowchart or something to see the full pawn generation flow? Because I'm unable to see how e.g. PawnGenerator.GenerateRandomAge is defined or called in 1.5 I found https://github.com/josh-m/RW-Decompile/blob/master/Verse/PawnGenerator.cs#L450 for 1.0... DERP I just had decompile off at the top of my C# settings in VS 2019...

Llyme commented 2 days ago

It's not necessarily game breaking, and I couldn't figure out what was causing the pawn from spawning with a disabled work tag. So far, I've only seen 1 pawn spawn with that problem so I think it's a fair trade, considering the alternative of losing more than half of their tribe.

mycroftjr commented 2 days ago

It's not necessarily game breaking, and I couldn't figure out what was causing the pawn from spawning with a disabled work tag. So far, I've only seen 1 pawn spawn with that problem so I think it's a fair trade, considering the alternative of losing more than half of their tribe.

Yeah, I suppose it is preferable instead of nerfing colony generation... I'm gonna keep looking into this until it's solved, though

mycroftjr commented 2 days ago

So, regardless of world seed, the error is always on a pawn named "Umbra 'Darklight' Nighthawk" who obtains the backstories AccursedChild88 and ShamanOfShadows47 in PawnBioAndNameGenerator.TryGiveSolidBioTo. The pawn needs the Violent work tag, but ends up with the following disabled: Violent, Firefighting, Cleaning, Hauling, Mining. (Source: https://github.com/mycroftjr/RW_CustomPawnGeneration/blob/requiredWorkTagsInvestigation/Hooks.cs#L251-L349)

Google shows that this is a Unique name + backstory in the base game (probably a donator), so the question is why the Leader pawn that needs Violent being allowed to assume this identity?

Most of those disables come from the accursed child background (https://imgur.com/we-get-he-is-child-of-darkness-DUDE1hB), but not the Violence, so that must be disabled by ShamanOfShadows47 (https://www.reddit.com/r/RimWorld/comments/5p1l2m/heystop_that/ shows that it is normal for him to be incapable of violence).

According to https://www.reddit.com/r/RimWorld/comments/at9gej/comment/eh12rgs , Darklight is usually a faction leader - so assuming he's always non-violent, does he usually get assigned to a Gentle tribe? No, surprisingly he can lead Savage tribes in vanilla (https://www.reddit.com/r/RimWorld/comments/okfm64/jesus_how_many_tribes_does_mr_edgy_man_mc_dark/) - or maybe vanilla behaviour has changed since then?

With HAR installed and 100% males, Darklight seems to be a faction leader basically 100% of the time (usually of a Savage tribe). Even 80% males usually sees him as a tribal leader. Without HAR installed, or using men-only genes in place of this mod, the likelihood of getting Darklight as a faction leader seems to drop dramatically, if not to 0 altogether... So the combination of HAR and this mod is either making him unable to be re-rolled for a leader roll, or making him much more likely?

Llyme commented 2 days ago

It sounds like a lot of work to get this pawn to get what it wants... If he gets generated in a way where he is supposed to be a child (still capable of violence,) but ends up spawning as an adult (obtaining shaman of shadows, making him incapable of violence,) which ends up re-rolling until 120x (the limit,) I think it's safe to say that it is generally impossible for me to deal with this unless I forcibly turn him into a teenager, and I don't really want to dive too deep into it.

mycroftjr commented 1 day ago

It sounds like a lot of work to get this pawn to get what it wants... If he gets generated in a way where he is supposed to be a child (still capable of violence,) but ends up spawning as an adult (obtaining shaman of shadows, making him incapable of violence,) which ends up re-rolling until 120x (the limit,) I think it's safe to say that it is generally impossible for me to deal with this unless I forcibly turn him into a teenager, and I don't really want to dive too deep into it.

Can't you just force the pawn to take a different bio if it wants to be violent?

Llyme commented 1 day ago

I could, but that would ruin the elaborate joke though. Isn't the pawn supposed to be the darkness guy?

mycroftjr commented 1 day ago

Bio meaning name AND backstory

Llyme commented 1 day ago

I'll try it out, though next week because I'm out of town right now.

mycroftjr commented 1 day ago

So with my updated fork code, I've narrowed down where things are actually going wrong. When PawnGenerator.TryGenerateNewPawnInternal sets error and returns null, it will be called again by GenerateNewPawnInternal - and normally, things like PawnBioAndNameGenerator.TryGiveSolidBioTo will give different results the 2nd time. But with HAR installed and any custom GenderFrequency setting in this mod... it just doesn't. When it gives Darklight, it will continue to do so until GenerateNewPawnInternal finally gives up.

With HAR installed and GenderFrequency turned off, the "boulder" world seed will actually roll Darklight at first for 2 different leader pawns, and in both cases roll a better identity for the pawn the 2nd time. Without HAR, the "transport company" seed is needed for TryGiveSolidBioTo to produce a bad result (and it's not with Darklight), but it properly corrects itself.

mycroftjr commented 1 day ago

Ok, with https://github.com/mycroftjr/RW_CustomPawnGeneration/blob/dontTakeThatBio/Hooks.cs#L341-L463 I can stop Darklight from being assigned as the bio in the first place... but I can't tell if my IsBioUseable postfix is actually changing the return value like it should be, since Darklight shouldn't be considered for the TryGetRandomUnusedSolidBioFor postfix if the IsBioUseable postfix returns false, but that's where I "catch the issue" in reality?

Basically, I'd like a Harmony code review to make sure I'm doing Harmony correctly lol

Also, this might still not be the "optimal" solution because I think it might change the behaviour of seeded worlds, but w/e

erdelf commented 1 day ago

Basically, I'd like a Harmony code review to make sure I'm doing Harmony correctly lol

you are setting it correctly

mycroftjr commented 18 hours ago

you are setting it correctly

So... why doesn't IsBioUseable work every time