Skip to content

Commit

Permalink
Merge pull request #17 from SpontanCombust:dev
Browse files Browse the repository at this point in the history
0.6.0
  • Loading branch information
SpontanCombust authored Sep 14, 2023
2 parents 20d3964 + a7a3b3d commit 0b86bd9
Show file tree
Hide file tree
Showing 38 changed files with 1,418 additions and 1,150 deletions.
19 changes: 3 additions & 16 deletions .github/workflows/update-doc-and-samples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,21 @@ jobs:
- name: Parse doc example
run: >
cargo run --release --
-f="../doc/mod-menu.xml"
"../doc/mod-menu.xml"
-o="../doc/mod-menu.ws"
-p="MOD" -p="mod_"
-m="MyModSettings"
-v="1.23"
--option-parsing-mode=enums
working-directory: settings-parser
- name: Parse DifficultyMod sample
run: >
cargo run --release --
-f="../samples/DifficultyMod/bin/config/r4game/user_config_matrix/pc/SampleDifficultyMod.xml"
"../samples/DifficultyMod/bin/config/r4game/user_config_matrix/pc/SampleDifficultyMod.xml"
-o="../samples/DifficultyMod/Mods/modSampleDifficultyMod/content/scripts/local/difficulty_mod_base.ws"
-m="ModDifficultySettingsBase"
-p="DM"
--default-preset-keyword="DEFAULT"
-v="1.1"
--no-getter
working-directory: settings-parser
- name: Parse MonsterOfTheWeek sample
run: >
cargo run --release --
-f="../samples/MonsterOfTheWeek/bin/config/r4game/user_config_matrix/pc/SampleMonsterOfTheWeek.xml"
"../samples/MonsterOfTheWeek/bin/config/r4game/user_config_matrix/pc/SampleMonsterOfTheWeek.xml"
-o="../samples/MonsterOfTheWeek/Mods/modSampleMonsterOfTheWeek/content/scripts/local/monster_of_the_week_settings.ws"
-m="MonsterOfTheWeekSettings"
-p="MOTW"
-p="motw"
-v="1.0"
--option-parsing-mode=enums
working-directory: settings-parser
- name: CLI specification
run: |
Expand Down
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@ Framework for modding Witcher 3 that simplifies the pipeline of using mod settin
## Overview
Witcher 3 allows for creating custom mod menus which provide an interface between the mod developer and the end user to further customize their experience. The way settings are accessed in game's scripts is not complicated, but can often result in very boilerplaty code and situations when settings can be fetched improperly simply due to some typo. This framework is trying to midigate that.

First part of this framwork is the menu xml parser. It turns the mod menu xml into WitcherScript code which mirrors the structure of customisable variables in the xml and assures on compile time that the developer uses their variables properly - no way for typos or bad type cast.
Framework provides xml parser program. It generates WitcherScript code which mirrors the structure of customisable variables in the xml and assures on compile time that the developer uses their variables properly - no way for typos, bad type cast or other headaches.

Second part of this framework is WitcherScript code that updates generated by parser settings class and even notifies you about it.

## Instructions for mod users

1. Check for [framework version](#framework-version-support) you need
2. Go to the [releases page](https://github.com/SpontanCombust/tw3-settings-framework/releases)
3. Download `TW3_Mod_Settings_Framework_modSettingsFramework.zip` from the newest version or version specified by the developer
3. Download `TW3_Mod_Settings_Framework_modSettingsFramework.zip` dependency from the newest version or version specified by the developer
4. Install it like any other Witcher 3 mod by dropping what's inside into your `Mods` folder
5. Use Script Merger to solve any conflicts

Expand All @@ -44,12 +43,13 @@ Second part of this framework is WitcherScript code that updates generated by pa
3. Download `TW3_Mod_Settings_Framework_Parser.zip` and unpack it anywhere. Use the `settings_parser.exe` program with the menu xml of your mod

```shell
./settings_parser -f ../../doc/mod-menu.xml -m MyModSettings -v 1.23 --omit-prefix=MOD
./settings_parser "../../doc/mod-menu.xml"
Group MODtab2 at line 40, column 6 has no vars and will be ignored.
Successfully parsed ../../doc/mod-menu.xml into ../../doc/mod-menu.ws
```
Parser at minimum takes a path to the menu xml file (`-f` flag) and a name you wish your settings class to have (`-m` flag).
To see all the possible options that can be used with the parser use the `--help` (shorhand `-h`) option or check the latest [parser CLI specification](doc/cli_specification.md).
Parser can generate WitcherScript by the means of simply drag-and-dropping the XML file onto exe. It is however recommended to use it with some kind of command line prompt to see any warnings or errors it might return. To see all the possible options that can be used with the parser use the `--help` (shorhand `-h`) option or check the latest [parser CLI specification](doc/cli_specification.md).

Since version v0.6 most of the data parser needs is retrieved directly from the XML based on custom attributes. List of these attributes can be found in [xml specification](doc/xml_specification.md).

[Example mod xml](doc/mod-menu.xml)

Expand Down Expand Up @@ -100,14 +100,20 @@ The most common usage of this would be overriding `ReadSettings()` method to run
## Remarks

### Framework version support:
- 0.4+ for game version 4.04
- 0.4.0 - 0.6.0 for game version 4.04
- 0.3.0 - 0.3.1 for game version 4.03
- 0.1.0 - 0.2.0 for game version 1.32 (requires [Community Patch - Base](https://www.nexusmods.com/witcher3/mods/3652))

### Migrating from version v0.5 to v0.6 and beyond (for developers)
Script files generated by pre-v0.6 version parsers and therefore mods using them are not compatible with the current version of `modSettingsFramework` and can't be mixed.
If you're a mod creator, please reparse you XMLs for this version.
Also, most of the data that previously had to be passed into the CLI now has to be put directly in the XML. Therefore the process of parsing said file has been changed to some degree. Check [details](doc/details.md) and [xml specification](doc/xml_specification.md) for more information about that.

## Documentation
[Further reading](doc/details.md)

[XML specification](doc/xml_specification.md)

[WitcherScript class specification](doc/class_specification.md)

[Parser CLI specification](doc/cli_specification.md)
Expand Down
43 changes: 31 additions & 12 deletions doc/class_specification.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,51 @@
# Class specification


## [ISettingsGroup](../modSettingsFramework/content/scripts/local/settings_group.ws)
Abstract base class which is an analogue to settings groups in XML. Child classes generated by the parser store settings variables.
## [`CSettingsMasterRegistry`](../modSettingsFramework/content/scripts/local/settings_master_registry.ws)
Class that contains all settings master objects and updates them when necessary.

### Public member constants
- `id: name` - value of the id attribute for the group in the XML.
- `defaultPresetIndex: int` - value of the default preset used by the given group. By default it's 0. To see how to instruct the CLI to deduce default presets refer to [CLI specification](cli_specification.md).
- `FRAMEWORK_VERSION: name` - version of the framework

### Public member functions
- `Init(parent_: ISettingsMaster) : void` - used internally.
- `Reset(presetIndex: int) : void` - applies a preset with given id. Automatically updates settings class to reflect this.
- `ResetToDefault() : void` - calls Reset() with defaultPresetIndex.
- `AddSettings(settingsMaster : ISettingsMaster, id : name): void` - adds a settings master object to the registry and initialises it. The 'id' parameter is used to identify said object later.
- `GetSettings(id : name) : ISettingsMaster` - returns stored settings master object or NULL if it can't find any with this id.
- `RemoveSettings(id : name) : void` - removes settings master object from the registry.
- `ReadAllSettings() : void` - reads settings values from user config into stored settings master objects.


## [`ISettingsMaster`](../modSettingsFramework/content/scripts/local/settings_master.ws)
Abstract base class for the settings class generated by the parser. The child class generated by the parser stores instances of classes extending ISettingsGroup. The class generated by the parser can be extended further to provide custom reactionary behaviour for its methods.

### Public member constants
- `modVersion: string` - arbitrary version string that can be passed during parsing.
- `id: name` - arbitrary identifier of the settings master object. Used by the registry to differentiate between them.

### Public member functions
- `Init() : void` - initializes settings groups, reads data from config and optionally resets this data to default if your mod has just been installed.
- `ReadSettings() : void` - reads the data from game's configuration into your settings object.
- `WriteSettings() : void` - writes the data from your settings object into game's configuration.
- `ValidateSettings(): void` - checks all fields in the settings object and corrects their values so they adhere to the limits set in the XML, e.g. if the value of a variable corresponding to a slider config is within the correct range.
- `ResetSettingsToDefault() : void` - applies default presets to all groups.
- `ReadSettings() : void` - calls Read() on all group objects.
- `WriteSettings() : void` - calls Write() on all group objects and saves data to disk.
- `ValidateSettings(): void` - calls Validate() on all group objects.
- `ResetSettingsToDefault() : void` - applies default presets to all groups and saves data to disk.
- `ShouldResetSettingsToDefaultOnInit() : bool` - a condition telling the class whether it should use ResetSettingsToDefault on Init. By default it checks whether GetVarValue() for a random (in reality the first one) var from the xml returns "".
- `ReadSettingValue(config: CInGameConfigWrapper, groupId: name, varId: name) : string` - method used by ReadSettings to retrieve values from game config. By default it used CInGameConfigWrapper directly.
- `WriteSettingValue(config: CInGameConfigWrapper, groupId: name, varId: name, value: string) : void` - method used by WriteSettings to write values into game config. By default it used CInGameConfigWrapper directly.
- `ResetSettingValues(config: CInGameConfigWrapper, groupId: name, presetIndex: int) : void` - method used by ISettingsGroup's Reset method to apply a preset. By default it used CInGameConfigWrapper directly.


## [ISettingsGroup](../modSettingsFramework/content/scripts/local/settings_group.ws)
Abstract base class which is an analogue to settings groups in XML. Child classes generated by the parser store settings variables.

### Public member constants
- `id: name` - value of the id attribute for the group in the XML.
- `defaultPresetIndex: int` - value of the default preset used by the given group. By default it's 0. To see how to instruct the parser deduce default presets refer to [XML specification](./xml_specification.md).

### Public member functions
- `Init(parent_: ISettingsMaster) : void` - used internally.
- `ValidateSettings() : void` - checks all fields and corrects their values so they adhere to the limits set in the XML, e.g. if the value of a variable corresponding to a slider config is within the correct range.
- `ReadSettings(optional config: CInGameConfigWrapper) : void` - reads the data from game's configuration.
- `WriteSettings(shouldSave: bool, optional config: CInGameConfigWrapper) : void` - writes the data into game's configuration. If 'shouldSave' is true saved the data to disk.
- `ResetSettings(presetIndex: int, shouldSave: bool, optional config: CInGameConfigWrapper) : void` - applies a preset with given id. Automatically updates settings class to reflect this. If 'shouldSave' is true saved the data to disk.
- `ResetSettingsToDefault() : void` - calls Reset() with defaultPresetIndex.
- `EnumValueMappingConfigToUnified(vId: name, val: int) : int` - returns integer value of the unified enum type for options var index in user config. If the config value is not valid for given option, should return -1. More about unified enums in [details](./details.md).
- `EnumValueMappingUnifiedToConfig(vId: name, val: int) : int` - returns the options var index in user config for integer value of unified enum. If the unified value is not valid for given option, should return -1. More about unified enums in [details](./details.md).
- `EnumValueMappingValidateUnified(vId: name, val: int) : int` - If integer value for given enum variable is correct returns said value. Otherwise returns the smallest valid value. More about unified enums in [details](./details.md).
53 changes: 8 additions & 45 deletions doc/cli_specification.md
Original file line number Diff line number Diff line change
@@ -1,58 +1,21 @@
```
TW3 Settings Framework Parser 0.5.0
TW3 Settings Framework Parser 0.6.0
Parses a mod menu XML file and outputs witcher script code representing settings of this menu
USAGE:
settings_parser [OPTIONS] --file <XML_FILE_PATH> --master <SETTINGS_MASTER_NAME>
settings_parser [OPTIONS] <XML_FILE_PATH>
OPTIONS:
-f, --file <XML_FILE_PATH>
Path to the menu xml file. (REQUIRED)
-m, --master <SETTINGS_MASTER_NAME>
Name to use for the settings master class. (REQUIRED)
-v, --mod-version <MOD_VERSION>
Version of the mod in format. Format is arbitrary, but preferably a real number
[default: 1.0]
ARGS:
<XML_FILE_PATH> Path to the menu xml file. (REQUIRED)
OPTIONS:
-o, --output <OUTPUT_WS_FILE_PATH>
Path of the WitcherScipt output file, by default it's made from the menu xml file name
in the same directory
-p, --omit-prefix <OMIT_PREFIX>
Prefix to omit from groups and vars when generating code. Case sensitive. Possible
multiple cases
--default-preset-keyword <DEFAULT_PRESET_KEYWORD>
Keyword used in default presets' display_name. Used to deduce IDs of default presets for
config groups so they can be used in ResetToDefault() methods. If won't find default
preset or any preset at that will use 0 as the preset ID. Case insensitive [default:
default]
--option-parsing-mode <OPTION_PARSING_MODE>
Controls how OPTION type vars are parsed into WitcherScript
- ints:
Treats options vars as regular ints instead of creating custom enum types for them.
This essentially means the behaviour from before v0.5.
- enums:
Parses options vars into enums. Then tries to find vars that have the same set of
displayName attributes in option node
and assigns them one common type.
Requires that displayNames of all option nodes contain some prefix that determines their
relation.
If two option arrays contain the same set of possible values they are considered to have
the same enum type.
- enums-strict:
Parses options vars into enums with an exception that having mutliple option arrays
designated by the same prefix
but having different sets of values is disallowed. This prevents possible user mistakes
from happening. [default: enums] [possible values: ints, enums, enums-strict]
--no-var-validation
Disables the generation of code for value correction. After reading from or before
writing to user config values will no longer be checked if they adhere to the XML, e.g.
if slider value is in a specified range
--strict-enums
Causes the parser to throw an error if it will find occurances options that would
generate unified enum type. More about unified enums in `doc/details.md`
--no-getter
Prevents the settings object getter convenience function from being generated
Expand Down
Loading

0 comments on commit 0b86bd9

Please sign in to comment.