Add custom settings to various parts of ORK Framework with your own classes.
Custom settings are an easy way to add your own settings to the editor and functionality to the game. There are globally available settings (see global custom settings below) and as settings bound to separate instances of content (e.g. combatants or items, see custom settings below).
Global Custom Settings #
Global custom settings are available, as the name suggests, globally – i.e. from everywhere and at all times. They are set up in Base/Control > Global Custom Settings.
Each global custom setting will create it’s own in-game instance and will be saved with save games. When enabling Clear New Game, starting a new game will automatically create a new, clean instance when starting a new game (e.g. to remove any changes made to the instance by a previous game.
Using #
You can call custom functionality via the Use function of it’s implementation (see details in the scripting information below). The Use function can start different functionality based on the passed on parameters, e.g. via the info string parameter.
The function can be used without scripting by built-in functionality in schematics (Use Global Custom Settings node), menu screens (Use Global Custom Settings button type in Button List menu parts), abilities, items, status effects, battle menus, research items and body parts (Use Global Custom Settings status change type).
Beside using this, you can also implement custom nodes to call functionality (other than the Use function) of your global custom settings classes.
Scripting #
To add your own global custom settings, you need to write a custom class extending from BaseGlobalCustomSettingsType class.
The class has to implement the CreateInstance function, which returns in instance class implementing the IGlobalCustomSettingsInstance interface. Additionally, the class has to add the EditorSettingsInfo attribute to add editor information for the type selection dropdown of the global custom settings.
The instance class is used for keeping track of any in-game changes as well as saving and loading the data of the instance with save games.
Accessing #
Global custom settings can be accessed via ORK.GlobalCustomSettings, either getting a setting by it’s index in the editor or by using it’s GUID.
Via index:
int index = 0; GlobalCustomSettings settings = ORK.GlobalCustomSettings.Get(index);
Via GUID:
string guid = "YOUR_GUID"; GlobalCustomSettings settings = ORK.GlobalCustomSettings.Get(guid);
You can access the in-game instance via the GlobalCustomSettings class by using the Instance property.
E.g. to cast it to a specific setting’s instance instead of the IGlobalCustomSettingsInstance interface:
DebugGlobalCustomSettingsType.Instance instance = ORK.GlobalCustomSettings.Get(index).Instance as DebugGlobalCustomSettingsType.Instance; if(instance != null) { // your code }
Casting it to your specific class instance allows you to access other functionality beside the functions provided by the interface.
Initialization and Unloading #
Global custom settings instances don’t require a specific function for initializing it’s content – if you need to handle some custom setup, call this in the constructor of your instance class.
However, the instance requires the Unload function, which will be called when an old instance is replaced by a new instance (e.g. when loading a save game or starting a new game with creating a new instance). This function can be used to handle things to clean up an old instance, e.g. to remove event hooks.
Debug Class Example #
Below you can see the an example implementation of the Debug global custom settings type.
This class outputs a text to the console and increases a counter by 1 each time it’s used. The counter is saved with save games.
using UnityEngine; using GamingIsLove.Makinom; using System.Collections.Generic; namespace GamingIsLove.ORKFramework { [EditorSettingInfo("Debug", "Test implementation, outputs information on user and target to the console.\n" + "Each call to the 'Use' function will increase a counter, which can also be output to the console.")] public class DebugGlobalCustomSettingsType : BaseGlobalCustomSettingsType { [EditorHelp("Debug Type", "Select the debug type will be used:\n" + "- Log: Printed to 'Debug.Log'.\n" + "- Warning: Printed to 'Debug.LogWarning'.\n" + "- Error: Printed to 'Debug.LogError'.", "")] [EditorFoldout("Debug Settings", "")] public DebugType type = DebugType.Log; [EditorSeparator] public VariableOrigin<GameObjectSelection> variable = new VariableOrigin<GameObjectSelection>(); [EditorHelp("Text", "The text that will be printed to the Unity console.", "")] [EditorEndFoldout] [EditorSeparator] [EditorTitleLabel("Console Output")] [EditorLabel("<user> = user information, <target> = target information\n" + "<count> = use counter, <info> = info text")] public TextContent text = new TextContent("<user>:<target>:<count>:<info>"); public DebugGlobalCustomSettingsType() { } public override IGlobalCustomSettingsInstance CreateInstance() { return new Instance(this); } /* ============================================================================ Instance class ============================================================================ */ public class Instance : IGlobalCustomSettingsInstance { protected DebugGlobalCustomSettingsType settings; protected int count = 0; public Instance(DebugGlobalCustomSettingsType settings) { this.settings = settings; } public virtual void Unload() { } public virtual void Use(object user, object target, string info, VariableHandler variables, SelectedDataHandler selectedData) { this.count++; UIText content = new UIText(this.settings.text, null, null, this.settings.variable.GetFirstHandler(new DataCall(user, target, variables, selectedData))); content.Replace("<count>", ORK.TextDisplaySettings.numberFormatting.intNumberFormat.FormatInt(this.count)); content.Replace("<user>", user is IContent ? ((IContent)user).GetName() : "" + user); content.Replace("<target>", target is IContent ? ((IContent)target).GetName() : "" + target); content.Replace("<info>", info); if(DebugType.Log == this.settings.type) { Debug.Log(content.Text); } else if(DebugType.Warning == this.settings.type) { Debug.LogWarning(content.Text); } else if(DebugType.Error == this.settings.type) { Debug.LogError(content.Text); } } public virtual DataObject SaveGame() { DataObject data = new DataObject(); data.Set("count", this.count); return data; } public virtual void LoadGame(DataObject data) { if(data != null) { data.Get("count", ref this.count); } } } } }
Custom Settings #
Custom settings can be added to combatants, classes, items, equipment, abilities and status effects.
Each instance of those contents will have their own instances of the added custom settings, e.g. each combatant has it’s own custom settings instances, each status effect added to a combatant has it’s own instances of it’s added custom settings.
The data of those instances are saved with the save data of the content they belong to, e.g. with a combatant, an item or equipment.
Using #
Using the correct custom settings of a content can depend on a settings key set up to identify it. Otherwise, the use is similar to global custom settings, i.e. you call the instance’s Use function.
The function can be used in schematics via the Use Custom Settings node and call it call it for content stored in selected data. Abilities, items and status effects can use the Use Custom Settings status change type to call their own instance’s Use function.
Beside using this, you can also implement custom nodes to call functionality (other than the Use function) of your custom settings classes.
Scripting #
To add your own custom settings, you need to write a custom class extending from BaseCustomSettingsType class.
The class has to implement the CreateInstance function, which returns in instance class implementing the ICustomSettingsInstance interface. Additionally, the class has to add the EditorSettingsInfo attribute to add editor information for the type selection dropdown of the custom settings.
The instance class is used for keeping track of any in-game changes as well as saving and loading the data of the instance with save games.
Accessing #
Since custom settings are bound to instances of content like combatants or items, they’re also accessed via those instances. Basically, everything implementing the ICustomSettings interface can give access to the instance of a custom setting added to it.
This is currently available in the following classes representing an instance of a content:
- abilities via the AbilityShortcut class
- classes via the ClassShortcut class
- combatants via the Combatant class
- equipment via the EquipShortcut class
- items via the ItemShortcut class
- status effects via the StatusEffect class
The ICustomSettings interface provides 2 functions to interact with the custom settings instance.
The UseCustomSettings function calls the Use function of the instance for a provided settings key, e.g. on an item (ItemShortcut class):
item.UseCustomSettings("key", user, target, "info", variables, selectedData);
The user and target parameters can be anything, e.g. a combatant, while the info string provides the context for the call. You can use it to call different functionality in your custom settings instance. Passing on variables or selected data is optional, e.g. pass on null if you don’t need them.
The GetCustomSettingsInstance function returns the instance of custom settings for a provided key, e.g. on a combatant (Combatant class):
DebugCustomSettingsType.Instance instance = combatant.GetCustomSettingsInstance("debug") as DebugCustomSettingsType.Instance;
The above example also casts the instance to a specific class implementation. If the returned instance doesn’t match the cast class type, the instance will be null.
Initialization #
Custom settings provide two initialization functions, the Init function for initialization of a new instance and the InitLoad function when initializing an instance before loading data from a save game. Both pass on the source they belong to, e.g. the instance of the combatant or item they’re bound to.
Debug Class Example #
Below you can see the an example implementation of the Debug custom settings type.
This class outputs a text to the console and increases a counter by 1 each time it’s used. The counter is saved with save games.
using UnityEngine; using GamingIsLove.Makinom; using System.Collections.Generic; namespace GamingIsLove.ORKFramework { [EditorSettingInfo("Debug", "Test implementation, outputs information on the instance, user and target to the console.\n" + "Each call to the 'Use' function will increase a counter, which can also be output to the console.")] public class DebugCustomSettingsType : BaseCustomSettingsType { [EditorHelp("Debug Type", "Select the debug type will be used:\n" + "- Log: Printed to 'Debug.Log'.\n" + "- Warning: Printed to 'Debug.LogWarning'.\n" + "- Error: Printed to 'Debug.LogError'.", "")] public DebugType type = DebugType.Log; [EditorSeparator] public VariableOrigin<GameObjectSelection> variable = new VariableOrigin<GameObjectSelection>(); [EditorHelp("Text", "The text that will be printed to the Unity console.", "")] [EditorSeparator] [EditorTitleLabel("Console Output")] [EditorLabel("<count> = use counter, <content> = content information (e.g. item)\n" + "<user> = user information, <target> = target information\n" + "<info> = info text")] public TextContent text = new TextContent("<content>:<user>:<target>:<count>:<info>"); public DebugCustomSettingsType() { } public override string ToString() { return "Debug"; } public override ICustomSettingsInstance CreateInstance() { return new Instance(this); } /* ============================================================================ Instance class ============================================================================ */ public class Instance : ICustomSettingsInstance { protected DebugCustomSettingsType settings; protected int count = 0; public Instance(DebugCustomSettingsType settings) { this.settings = settings; } public virtual void Init(object source) { } public virtual void InitLoad(object source) { } public virtual void Use(object source, object user, object target, string info, VariableHandler variables, SelectedDataHandler selectedData) { this.count++; UIText content = new UIText(this.settings.text, null, null, this.settings.variable.GetFirstHandler(new DataCall(user, target, variables, selectedData))); content.Replace("<count>", ORK.TextDisplaySettings.numberFormatting.intNumberFormat.FormatInt(this.count)); content.Replace("<content>", source is IContent ? ((IContent)source).GetName() : "" + source); content.Replace("<user>", user is IContent ? ((IContent)user).GetName() : "" + user); content.Replace("<target>", target is IContent ? ((IContent)target).GetName() : "" + target); content.Replace("<info>", info); if(DebugType.Log == this.settings.type) { Debug.Log(content.Text); } else if(DebugType.Warning == this.settings.type) { Debug.LogWarning(content.Text); } else if(DebugType.Error == this.settings.type) { Debug.LogError(content.Text); } } public virtual DataObject SaveGame() { DataObject data = new DataObject(); data.Set("count", this.count); return data; } public virtual void LoadGame(DataObject data) { if(data != null) { data.Get("count", ref this.count); } } } } }