-
Open the project using Unity 2019.4.26f1
- Unity console will show many compiler errors, but don't panic!
- Click Modification Tools -> Setup project menu entry and choose Pathfinder: Wrath of the Righteous installation folder in the dialog that will appear
- If Unity shows you API Update Required dialog click No Thanks
- Close and reopen project
- Click Modification Tools -> Setup render pipeline menu entry
- Project is now ready
-
Setup your modification (take a look at Assets/Modifications/ExampleModification for examples)
- Create a folder for your modification in Assets/Modifications
- Create Modification scriptable object in this folder (right click on folder -> Create -> Modification)
- Specify Unique Name in Modification scriptable object
- Create Scripts folder and your-modification-name.Scripts.asmdef file inside it (right click on folder -> Create -> Assembly Definition)
- Create Content, Blueprints and Localization folders as needed
-
Create your modification
-
Build your modification (use Modification Tools -> Build menu entry)
-
Test your modification
- Copy Build/your-modification-name folder to user-folder/AppData/LocalLow/Owlcat Games/Pathfinder Wrath Of The Righteous/Modifications
- Add your modification to user-folder/AppData/LocalLow/Owlcat Games/Pathfinder Wrath Of The Righteous/OwlcatModificationManagerSettings.json
{ "EnabledModifications": ["your-modification-name"] // use name from the manifest(!), not folder name }
- Before patch 1.1.1 there was a typo in filename used to store settings: OwlcatModificationManangerSettings.json. This is now corrected, please use the correct filename (the game will still find file under the old name).
- Run Pathfinder: Wrath of the Righteous
-
Publish build results from Build folder
- TODO
All content of your modification must be placed in folder with Modification scriptable object or it's subfolders.
All of your scripts must be placed in assemblies (in folder with *.asmdef files or it's subfolders). Never put your scripts (except Editor scripts) in other places.
All of your content (assets, prefabs, scenes, sprites, etc) must be placed in your-modification-name/Content folder.
Blueprints are JSON files which represent serialized version of static game data (classes inherited from SimpleBlueprint).
-
Blueprints must have file extension *.jbp and must be situated in your-modification-name/Blueprints folder.
- example: Examples/Basics/Blueprints/TestBuff.jbp
// *.jbp file format { "AssetId": "unity-file-guid-from-meta", // "42ea8fe3618449a5b09561d8207c50ab" for example "Data": { "$type": "type-id, type-name", // "618a7e0d54149064ab3ffa5d9057362c, BlueprintBuff" for example // type-specific data } }
- if you specify AssetId of an existing blueprint (built-in or from another modification) then the existing blueprint will be replaced
-
For access to metadata of all built-in blueprints use this method
// read data from <WotR-installation-path>/Bundles/cheatdata.json // returns object {Entries: [{Name, Guid, TypeFullName}]} BlueprintList Kingmaker.Cheats.Utilities.GetAllBlueprints();
-
You can write patches for existing blueprints: to do so, create a *.patch JSON file in your-modification-name/Blueprints folder. Instead of creating a new blueprint, these files will modify existing ones by changing only fields that are specified in the patch and retaining everything else as-is.
-
Example 1: Examples/Basics/Blueprints/ChargeAbility.patch
-
Example 2: Examples/Basics/Blueprints/InvisibilityBuff.patch
-
Connection between the existing blueprint and the patch must be specified in BlueprintPatches scriptable object (right click in folder -> Create -> Blueprints' Patches)
- example: Examples/Basics/BlueprintPatches.asset
-
OLD: Newtonsoft.Json's Populate is used for patching (_#ArrayMergeSettings and _#Entries isn't supported)
-
NEW (game version 1.1.1): Newtonsoft.Json's Merge is used for patching
// *.patch file format: change icon in BlueprintBuff and disable first component { "_#ArrayMergeSettings": "Merge", // "Union"/"Concat"/"Replace" "m_Icon": {"guid": "b937cb64288636b4c8fd4ba7bea337ea", "fileid": 21300000}, "Components": [ { "m_Flags": 1 } ] }
OR
{ "_#Entries": [ { "_#ArrayMergeSettings": "Merge", // "Union"/"Concat"/"Replace" "m_Icon": {"guid": "b937cb64288636b4c8fd4ba7bea337ea", "fileid": 21300000}, "Components": [ { "m_Flags": 1 } ] } ] }
-
You can add localized strings to the game or replace existing strings. Create enGB|ruRU|deDE|frFR|zhCN|esES.json file(s) in your-modification-name/Localization folder.
-
example: Examples/Basics/Localizations/enGB.json
-
You shouldn't copy enGB locale with different names if creating only enGB strings: enGB locale will be used if modification doesn't contains required locale.
-
The files should be in UTF-8 format (no fancy regional encodings, please!)
// localization file fromat
{
"strings": [
{
"Key": "guid", // "15edb451-dc5b-4def-807c-a451743eb3a6" for example
"Value": "whatever-you-want"
}
]
}
You can mark static method with OwlcatModificationEnterPoint attribute and the game will invoke this method with corresponding OwlcatModification parameter once on game start. Only one entry point per assembly is allowed.
- example: Examples/Basics/Scripts/ModificationRoot.cs (ModificationRoot.Initialize method)
[OwlcatModificationEnterPoint]
public static void EnterPoint(OwlcatModification modification)
{
...
}
Use OwlcatModification.OnGUI for inserting GUI to the game. It will be accessible from modifications' window (ctrl+M to open). GUI should be implemented with IMGUI (root layout is vertical).
- example: Examples/Basics/Scripts/ModificationRoot.cs (ModificationRoot.Initialize method)
Harmony lib is included in the game and you can use it for patching code at runtime.
-
example: Examples/Basics/Scripts/ModificationRoot.cs (ModificationRoot.Initialize method) and Examples/Basics/Scripts/Tests/HarmonyPatch.cs
OwlcatModification modification = ...;
modification.OnGUI = () => GUILayout.Label("Hello world!");
-
You can save/load global modification's data or settings with methods OwlcatModification.LoadData and OwlcatModification.SaveData. Unity Serializer will be used for saving this data.
- Example: Examples/Basics/Scripts/ModificationRoot.cs (ModificationRoot.TestData method)
[Serialzable] public class ModificationData { public int IntValue; } ... OwlcatModification modification = ...; var data = modification.LoadData<ModificationData>(); data.IntValue = 42; modification.SaveData(data);
-
You can save/load per-save modification's data or settings by adding EntityPartKeyValueStorage to Game.Instance.Player.
- Example: Examples/Basics/Scripts/Tests/PerSaveDataTest.cs
var data = Game.Instance.Player.Ensure<EntityPartKeyValueStorage>().GetStorage("storage-name"); data["IntValue"] = 42.ToString();
You can subscribe to game events with EventBus.Subscribe or raise your own event using EventBus.RaiseEvent.
-
Example (subscribe): Examples/Basics/Scripts/ModificationRoot.cs (ModificationRoot.Initialize method)
-
Raise your own event:
interface IModificationEvent : IGlobalSubscriber { void HandleModificationEvent(int intValue); } ... EventBus.RaiseEvent<IModificationEvent>(h => h.HandleModificationEvent(42))
- IBeforeRulebookEventTriggerHandler and IAfterRulebookEventTriggerHandler exists specifically for modifications. These events are raised before OnEventAboutToTrigger and OnEventDidTigger correspondingly.
- Use RulebookEvent.SetCustomData and RulebookEvent.TryGetCustomData to store and read your custom RulebookEvent data.
OwlcatModification.LoadResourceCallbacks is invoked every time when a resource (asset, prefab or blueprint) is loaded.
A Controller is a class that implements a particular set of game mechanics. It must implementi IController interface.
Game Modes (objects of class GameMode) are logical groupings of Controllers which all must be active at the same time. Only one Game Mode can be active at any moment. Each frame the game calls Tick method for every Controller in active Game Mode. You can add your own logic to Pathfinder's main loop or extend/replace existing logic using OwlcatModificationGameModeHelper.
- Example (subscribe): Examples/Basics/Scripts/Tests/ControllersTest.cs
Default Unity shaders doesn't work in Pathfinder. Use shaders from Owlcat namespace in your materials. If you don't know what you need it's probably Owlcat/Lit shader.
You can create scenes for modifications but there is a couple limitations:
-
if you want to use Owlcat's MonoBehaviours (i.e. UnitSpawner) you must inherit from it and use child class defined in your assembly
-
place an object with component OwlcatModificationMaterialsInSceneFixer in every scene which contains Renderers
-
Copy guid and file id as json string: right-click-on-asset -> Modification Tools -> Copy guid and file id
-
Copy blueprint's guid: right-click-on-blueprint -> Modification Tools -> Copy blueprint's guid
-
Create blueprint: right-click-in-folder -> Modification Tools -> Create Blueprint
-
Find blueprint's type: Modification Tools -> Blueprints' Types
Work in progress. Please note that users will be able to change order of mods in the manager. We're planning to provide the ability to specify a list of dependencies for your modification, but it will only work as a hint: the user will be responsible for arranging a correct order of mods in the end.
- Command line argument -start_from=area-name/area-preset-name allows you to start game from the specified area without loading main menu.
- Cheat reload_modifications_data allows you to reload content, blueprints and localizations. All instantiated objects (prefab instances, for example) stays unchanged.