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
    • Hediffs will almost always be treated as missing, skills will always be 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 not added or left empty, then this gene is removed if the conditions are met, regardless of how many maxEvolutions are left
    • 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
    • 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
    • hasAllOfGene : List of GeneDefs that the pawn must have all of
    • hasNoneOfGene : List of GeneDefs that the pawn must have none of
    • 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>
⚠️ **GitHub.com Fallback** ⚠️