Flexible Settings - KonradHeinser/EBSGFramework GitHub Wiki

At the moment, this is relegated to being an "unofficial" addition to the framework for two reasons.

  1. There are other mods that allow you to do this, like VEF (as far as I know) and XML extensions (assuming it's still being maintained)
  2. I have no clue how well any of this stuff plays with other mods, and given the first reason I didn't see much reason to risk encountering those issues

The stuff still exists on the Steam version, so as long as you are willing to do a whole lot of testing for the weird and niche issues, and don't want to use VEF, XML Extensions, or your own C# for your settings, feel free to use this. If you don't want to use this stuff, you don't need to worry about this creating a useless constant overhead as the first thing this checks is whether or not someone has even added settings to the list.


Intro

This framework has a section in its mod page labeled "others' mods" where other modders can add settings of their own. The settings themselves are handled by special defs, while the actions of those settings are handled by at least one xml patch operation. If you are only planning on using the settings part of this framework, it is strongly recommended that you use a load folders to avoid creating a hard requirement.

The first step for adding settings to the list is making a category similar to this:

    <EBSGFramework.SettingCategoryDef>
        <defName>InsertDefNameHere</defName>
        <label>labeling labeled labels</label>
    </EBSGFramework.SettingCategoryDef>

These categories are only used for showing players the settings. The list of categories is put into a drop down that always puts the categories in alphabetical order.


The Settings

The settings themselves are handled in a def that looks similar to this:

    <EBSGFramework.SettingDef>
        <defName>FancyDefName</defName>
        <label>labeling</label>
        <description>Descriptions are optional.</description>
        <category>InsertDefNameHere</category>
        <type>None</type>
    </EBSGFramework.SettingDef>

Outside of the optional description, the basic def stuff works like normal. These are the options that are specific to the SettingDef:

  • category : This is the SettingCategoryDef the setting is linked to. If this is not filled in, then the game will yell at you on launch
  • type : The setting type you want to use. While None is technically an option, you will get yelled at by the game for obvious reasons. The actual options are:
    • Toggle : A basic active/inactive switch
    • Slider : A slider that the user drags to the desired value. For instances where precision is desired, a numeric input would probably be better, especially if the range is exceptionally wide. The current value of the setting is put in parenthesis (###) after your label
    • SliderInt : A variation of the Slider that only uses whole numbers
    • Dropdown : A dropdown menu with options you specify
    • Numeric : A text box that the player can put numbers inside of
    • NumericInt : A variation of numeric that only accepts whole numbers
  • defaultToggle : Default (False) : When using the Toggle type, this determines what it's initially set to for first time users
  • defaultValue : Default (0) : The default for every other type. Dropdowns are zero based, meaning 0 represents the first item on the list, 1 the second, etc
  • validRange : For sliders and numbers, this range dictates the minimum and maximum values
  • positionInCategory : Default (0) : Determines where in the category to put the item, with higher numbers pushing the item further down the list. If multiple items have the same position (or none are specified), the code will generally keep them in the same order that the defs were initially loaded

Patching

Similar to how all settings use the same def that acts differently based on the type, there is only one patch type that will change its action based on what setting type it is checking.

    <Operation Class="EBSGFramework.PatchOperationFlexibleSetting">
        <setting>FancyDefName</setting>
    </Operation>

If the setting is a Toggle, there are only two options available. The general concept of this patch is similar to a PatchOperationConditional, but instead of checking an xpath it checks the setting:

  • active : A patch operation that triggers when the setting is active
  • inactive : A patch operation that triggers when the setting is inactive

If the setting is a Dropdown, everything resides within a single tag similar to how PatchOperationSequence is set up:

  • operations : The list of operations that correspond with the related drop down option in the setting. If the option should do nothing, then all you need to put in that spot is a <li />. If you put fewer operations than there are options, than options later in the list will all do nothing

The remaining ones are all ultimately just ways of getting numbers from the player, and all use the same options. There are two ways these numbers can be used:

Togglish:

  • range : If you add this to the operation, then the setting in question must be in the range you put. If you only put a single number, then the setting must be at or above the value you enter
  • invertRange : Default (True) : While True, the results of whether or not the setting is in the range is flipped
  • active : Patch Operation to trigger when the range check passes
  • inactive : Patch Operation to trigger when the range check fails

Just a number:

  • xpath : The xpath to look at for the action. If this doesn't lead to a number, you will have problems
  • action : Default (Replace) : What to actually do with the setting and the target's number. The options are Replace, Multiple, Divide, and Offset
  • offset : Default (0) : An offset added to the setting value before the patch does the action
  • factor : Default (1) : A factor to multiply the setting value by before the patch does the action and after the offset is applied

Examples

Due to the nature of this page, the examples are different from normal. The only common point is the category I used, which was this:

    <EBSGFramework.SettingCategoryDef>
        <defName>EBSGExampleSettings</defName>
        <label>EBSG Framework examples</label>
    </EBSGFramework.SettingCategoryDef>

Toggle Example

This toggle starts as true, but if it's set to false then its moved to the bottom of the category the next time the game is started up:

    <EBSGFramework.SettingDef>
        <defName>EBSGBool</defName>
        <label>bool</label>
        <description>This is a bool setting.</description>
        <defaultToggle>True</defaultToggle>
        <type>Toggle</type>
        <category>EBSGExampleSettings</category>
    </EBSGFramework.SettingDef>
    <Operation Class="EBSGFramework.PatchOperationFlexibleSetting">
        <setting>EBSGBool</setting>
        <inactive Class="PatchOperationAdd">
            <xpath>Defs/EBSGFramework.SettingDef[defName="EBSGBool"]</xpath>
            <value>
                <positionInCategory>1</positionInCategory>
            </value>
        </inactive>
    </Operation>

Slider Example

This slider moves the location of the archite genes section from its default of 1000 to wherever the user wants to put it:

    <EBSGFramework.SettingDef>
        <defName>EBSGSlider</defName>
        <label>slider</label>
        <category>EBSGExampleSettings</category>
        <type>Slider</type>
        <defaultValue>1000</defaultValue>
        <validRange>0.01~10000</validRange>
    </EBSGFramework.SettingDef>
    <Operation Class="EBSGFramework.PatchOperationFlexibleSetting">
        <setting>EBSGSlider</setting>
        <xpath>Defs/GeneCategoryDef[defName="Archite"]/displayPriorityInXenotype</xpath>
    </Operation>

SliderInt Example

This slider example messes with the information of the naked speed gene in three potential ways

  1. The first patch replaces the metabolic efficiency with the value of the setting
  2. The second patch makes the effects linearly scale with the metabolic efficiency (the factor of 0.5 is due to the vanilla stats being based on a metabolic efficiency of 2 instead of 1)
  3. The third patch checks to see if the metabolic efficiency was set to be below 0, at which point the label is changed to represent the fact that speed is penalized when naked and boosted when clothed (boosted far more than balance would allow. Normally the minimum would be set to 0 to counter that)
    <EBSGFramework.SettingDef>
        <defName>EBSGSliderInt</defName>
        <label>slidering</label>
        <category>EBSGExampleSettings</category>
        <type>SliderInt</type>
        <defaultValue>2</defaultValue>
        <validRange>-9~9</validRange>
    </EBSGFramework.SettingDef>
    <Operation Class="EBSGFramework.PatchOperationFlexibleSetting">
        <setting>EBSGSliderInt</setting>
        <xpath>Defs/GeneDef[defName="NakedSpeed"]/biostatMet</xpath>
    </Operation>

    <Operation Class="EBSGFramework.PatchOperationFlexibleSetting">
        <setting>EBSGSliderInt</setting>
        <action>Multiply</action>
        <xpath>Defs/GeneDef[defName="NakedSpeed"]/conditionalStatAffecters/li/statOffsets/MoveSpeed</xpath>
        <factor>0.5</factor>
    </Operation>

    <Operation Class="EBSGFramework.PatchOperationFlexibleSetting">
        <setting>EBSGSliderInt</setting>
        <range>0</range>
        <invertRange>True</invertRange>
        <active Class="PatchOperationReplace">
            <xpath>Defs/GeneDef[defName="NakedSpeed"]/label</xpath>
            <value>
                <label>clothed speed</label>
            </value>
        </active>
    </Operation>

Dropdown Example

This drop down has two options that normally do nothing (the first and third options), and a middle one that changes the label. Because the default is set to 1, the label also defaults to what the patch says to make it:

    <EBSGFramework.SettingDef>
        <defName>EBSGDropDown</defName>
        <label>dropdown</label>
        <type>Dropdown</type>
        <defaultValue>1</defaultValue>
        <dropLabels>
            <li>Zero</li>
            <li>One</li>
            <li>Two</li>
        </dropLabels>
        <category>EBSGExampleSettings</category>
    </EBSGFramework.SettingDef>
    <Operation Class="EBSGFramework.PatchOperationFlexibleSetting">
        <setting>EBSGDropDown</setting>
        <operations>
            <li />
            <li Class="PatchOperationReplace">
                <xpath>Defs/EBSGFramework.SettingDef[defName="EBSGDropDown"]/label</xpath>
                <value>
                    <label>It is I, ME!</label>
                </value>
            </li>
        </operations>
    </Operation>


Numeric Example

This numeric setting does the same thing as the slider example, just with a number input to type stuff into instead of the slider

    <EBSGFramework.SettingDef>
        <defName>EBSGNumeric</defName>
        <label>numbers!!!</label>
        <category>EBSGExampleSettings</category>
        <type>Numeric</type>
        <defaultValue>1000</defaultValue>
        <validRange>0.01~10000</validRange>
    </EBSGFramework.SettingDef>
    <Operation Class="EBSGFramework.PatchOperationFlexibleSetting">
        <setting>EBSGNumeric</setting>
        <xpath>Defs/GeneCategoryDef[defName="Archite"]/displayPriorityInXenotype</xpath>
    </Operation>

NumericInt Example

Similar to numeric, this is just a typing version of the slider int example:

    <EBSGFramework.SettingDef>
        <defName>EBSGNumericInt</defName>
        <label>whole numbers</label>
        <category>EBSGExampleSettings</category>
        <type>NumericInt</type>
        <defaultValue>2</defaultValue>
        <validRange>-9~9</validRange>
    </EBSGFramework.SettingDef>
    <Operation Class="EBSGFramework.PatchOperationFlexibleSetting">
        <setting>EBSGNumericInt</setting>
        <xpath>Defs/GeneDef[defName="NakedSpeed"]/biostatMet</xpath>
    </Operation>

    <Operation Class="EBSGFramework.PatchOperationFlexibleSetting">
        <setting>EBSGNumericInt</setting>
        <action>Multiply</action>
        <xpath>Defs/GeneDef[defName="NakedSpeed"]/conditionalStatAffecters/li/statOffsets/MoveSpeed</xpath>
        <factor>0.5</factor>
    </Operation>

    <Operation Class="EBSGFramework.PatchOperationFlexibleSetting">
        <setting>EBSGNumericInt</setting>
        <range>0</range>
        <invertRange>True</invertRange>
        <active Class="PatchOperationReplace">
            <xpath>Defs/GeneDef[defName="NakedSpeed"]/label</xpath>
            <value>
                <label>naked slowness</label>
            </value>
        </active>
    </Operation>
⚠️ **GitHub.com Fallback** ⚠️