Evolving Genes - KonradHeinser/EBSGFramework GitHub Wiki
This gene class allows you to make genes that get replaced/removed when certain conditions are met, with a check occurring once per hour. It requires a specific class and the EBSGExtension, though any gene stuff in this framework which references the HediffAdder class in its description or examples are also available:
<geneClass>EBSGFramework.Gene_EvolvingGene</geneClass>
<modExtensions>
<li Class="EBSGFramework.EBSGExtension">
</li>
</modExtensions>
These are the options available in the extension tied specifically to this class:
-
maxEvolutions : Default (1) : The number of times that this can trigger. If set to -1, then this gene can trigger any number of times
-
recoverEvolutions : Default (True) : If the result is another evolving gene, then anything that removes that child will result in this gene regaining a charge. If something removes this gene, then the result will not recreate the gene, meaning no extra evolutions will occur
-
keepEvolvingGene : Default (False) : When maxEvolutions runs out, if this remains False then this gene is removed. If this is set to True, then the gene is kept until something else comes along to remove it
-
checkEvolutionsPostAdd : Default (False) : Determines if the gene should check its conditions immediately after being added. This can often act strange when initially creating pawns due to the order that things are added to pawns during initial generation. There are a few instances where this can be set to True, namely if you aren't worried about misfires, the gene is generally added to a pawn mid-game, or the only conditions used are validAges and chancePerCheck
- This strangeness includes hediffs being treated as missing due to the adding order, skills being treated as though they were level 0, and gene checks can frequently fail to check things properly depending on the order the game decides to add them in
-
geneticEvolutions : The list of items that contains the conditions and results. Each li may contain the following:
- result : The GeneDef to replace this gene with. If left empty, then this gene is removed if the conditions are met, regardless of how many maxEvolutions are left. This is the last thing the gene will do
- skipIfCarrierHasResult : Default (False) : If the carrier already has the result, this option will be skipped. Doesn't do anything if the result is empty
- inheritable : Default (Same) : Determines if the result should be a Xeno or Endo gene. The options are Same, Xeno, and Endo, with Same copying the inheritability of the evolving gene
- dontRemove : Default (False) : When True, result will no longer cause the gene to be removed when left empty, with maxEvolutions still being able to remove the gene as normal. This only has use when maxEvolutions is above 1 and the gene needs to stick around
- xenotypes : A weighted list that uses xenotype defNames as the node name and the weight as the value. This is the first thing the gene will do, so any genes added/removed will happen after this. For those familiar with Alter Xenotype, the xenotype changing functions similar to that
- setXenotype : Default (True) : While true, most old genes are removed when using xenotypes, with the only exceptions being hair and skin color endogenes. When false, only genes that are incompatible with genes from the new xenotype are removed, creating a type of hybrid that still uses the new xenotype's name
- chancePerCheck : Default (1) : The chance of the evolution actually having a chance to occur each hour. If this chance fails, then this evolution is skipped, and the gene checks the next one on the list
- ignoreChanceDuringPostAdd : Default (False) : If checkEvolutionsPostAdd is set to True, then this determines if that initial check will use the chancePerCheck
- message : The message to send on evolution if the pawn is a colonist, colony slave, or colony prisoner as long as said pawn is on a map or in a caravan. {0} is the short version of the pawn's name, {1} is a capitalized version of the result's label, and {2} is the result's label
- messageType : Default (NeutralEvent) : The MessageTypeDef to use for message
- hasAnyOfHediff : Special list of hediffs that uses the HediffDef's defName for the name, and a range of severities for the value. The pawn must have at least one of the listed hediffs with severities in the range
- hasAllOfHediff : Special list of hediffs that uses the HediffDef's defName for the name, and a range of severities for the value. The pawn must have all of the listed hediffs with severities in the range
- hasNoneOfHediff : Special list of hediffs that uses the HediffDef's defName for the name, and a range of severities for the value. The pawn must have none of the listed hediffs with severities in the range
- hasAnyOfGene : List of GeneDefs that the pawn must have at least one of
- removeFirstGene : Removes the first gene that the pawn has from hasAnyOfGene when evolving. It will attempt to go in the same order as hasAnyOfGene when picking the gene to remove
- hasAllOfGene : List of GeneDefs that the pawn must have all of
- removeAllHasAllGene : Default (False) : Remove all of the genes in hasAllOfGene when evolving
- hasNoneOfGene : List of GeneDefs that the pawn must have none of
- addHasNoneCount : Default (0) : Adds genes from hasNoneOfGene when evolving, allowing you to provide multiple genes or a random gene. If set to -1, it will add all of the genes, and if set to a number above 0 it will add that many randomly selected from the list (i.e. if there are 2 genes in hasNoneOfGene and this is set to 1, 1 of them will be picked at random to add)
- validAges : Range of ages that the evolution apply for. If your goal is solely to remove the gene at a certain age, it is recommended to use Remove at Age instead
- skillRequirements : Special list of skills that use the SkillDef's defName for the name, and a range of skill levels for the value. If no value is entered (i.e. ), then the condition is met as long as the skill is not disabled. Aptitude is not included in the level, so other genes won't affect this
- complexSkillRequirements : A list of special lists that use the SkillDef's defName for the name, and a range of skill levels for the value. Each li acts similar to skillRequirements where all of skills in the li must be within the range. If any of the li's have all of their skills met, then the pawn will be considered to have met this condition
- overrideKeep : Default (False) : Causes the main gene to do the reverse the results of keepEvolvingGene when maxEvolutions runs out if this is the last result picked. Mostly intended for use when maxEvolutions is set to 1 as other values can act strangely. If result is left empty, then this doesn't do anything
This example can evolve in 4 different ways. If the pawn's shooting or melee passes 10, then combat evolution is replaced with the related shooting/melee gene. If the pawn has at least 80% bloodloss when the check occurs, then this gene replaces itself with the wound healing gene. If the pawn suffers from any level of malnutrition, then there is a 5% chance per hour that the gene will be removed.
The first 3 are set up to check languages files for the message, though if you just copy this gene over your message will just be the text in the message nodes because your language files probably don't have those:
<GeneDef>
<defName>CombatEvolution</defName>
<label>combat evolution</label>
<description>Carriers of this gene can become specialized in melee or shooting with enough practice. In certain cases, this may evolve in unexpected ways.</description>
<geneClass>EBSGFramework.Gene_EvolvingGene</geneClass>
<biostatMet>-3</biostatMet>
<modExtensions>
<li Class="EBSGFramework.EBSGExtension">
<geneticEvolutions>
<li>
<result>AptitudeRemarkable_Shooting</result>
<message>EvolutionCombat</message>
<skillRequirements>
<Shooting>10~20</Shooting>
</skillRequirements>
</li>
<li>
<result>AptitudeRemarkable_Melee</result>
<message>EvolutionCombat</message>
<skillRequirements>
<Melee>10~20</Melee>
</skillRequirements>
</li>
<li>
<result>WoundHealing_SuperFast</result>
<message>EvolutionHealing</message>
<hasAnyOfHediff>
<BloodLoss>0.8~1</BloodLoss>
</hasAnyOfHediff>
</li>
<li>
<chancePerCheck>0.05</chancePerCheck>
<message>Gene lost to counter malnutrition</message>
<messageType>NegativeHealthEvent</messageType>
<hasAnyOfHediff>
<Malnutrition />
</hasAnyOfHediff>
</li>
</geneticEvolutions>
</li>
</modExtensions>
</GeneDef>
This is a simplistic example of how the charges can be used to make a limited version of ever changing genes based on pawn skills. The only gene that will be removed automatically and cause combat evolution to regain a charge is blocked evolution, because the other three genes listed aren't evolving genes. Blocked evolution is added when either shooting or melee are level 5 or lower:
<GeneDef>
<defName>CombatEvolution</defName>
<label>combat evolution</label>
<description>Carriers of this gene can become specialized in melee or shooting with enough practice. In certain cases, this may evolve in unexpected ways.</description>
<geneClass>EBSGFramework.Gene_EvolvingGene</geneClass>
<biostatMet>-3</biostatMet>
<modExtensions>
<li Class="EBSGFramework.EBSGExtension">
<keepEvolvingGene>True</keepEvolvingGene>
<maxEvolutions>2</maxEvolutions>
<geneticEvolutions>
<li>
<result>BlockedEvolution</result>
<complexSkillRequirements>
<li> <!--Condition met if shooting or melee are below 5-->
<Shooting>0~4</Shooting>
</li>
<li>
<Melee>0~4</Melee>
</li>
</complexSkillRequirements>
</li>
<li>
<result>AptitudeRemarkable_Shooting</result>
<message>EvolutionCombat</message>
<skillRequirements>
<Shooting>10~20</Shooting>
</skillRequirements>
</li>
<li>
<result>AptitudeRemarkable_Melee</result>
<message>EvolutionCombat</message>
<skillRequirements>
<Melee>10~20</Melee>
</skillRequirements>
</li>
<li>
<result>WoundHealing_SuperFast</result>
<message>EvolutionHealing</message>
<hasAnyOfHediff>
<BloodLoss>0.8~1</BloodLoss>
</hasAnyOfHediff>
</li>
<li>
<chancePerCheck>0.05</chancePerCheck>
<message>Gene lost to counter malnutrition</message>
<messageType>NegativeHealthEvent</messageType>
<hasAnyOfHediff>
<Malnutrition />
</hasAnyOfHediff>
</li>
</geneticEvolutions>
</li>
</modExtensions>
</GeneDef>
<GeneDef>
<defName>BlockedEvolution</defName>
<label>blocked evolution</label>
<description>This pawn can only evolve once because their melee and shooting are too low. If both skills are raised above 5, then the pawn will be able to evolve a second time.</description>
<geneClass>EBSGFramework.Gene_EvolvingGene</geneClass>
<biostatMet>1</biostatMet>
<modExtensions>
<li Class="EBSGFramework.EBSGExtension">
<geneticEvolutions>
<li>
<skillRequirements> <!--Both shooting and melee must be above 5-->
<Shooting>5</Shooting>
<Melee>5</Melee>
</skillRequirements>
</li>
</geneticEvolutions>
</li>
</modExtensions>
</GeneDef>