This is a short guide for users and modders on the mod system. The game does not support modding on MacOSX at this time, though further down there is an experimental setup that may work. [color=yellow][center]For Users[/center] Only install the mods you know are safe. The Strive team is not responsible for any damage caused by third party mods.[/color] The default mod folder varies by operating system, but can be located using the "Open Mod Folder" button found in the Mods menu. Beside it is a button containing the current mod folder location, which can be clicked to bring up a prompt to change the location. [color=yellow]How to install mods:[/color] 1. Download and put the mods in the mod folder. If a mod is compressed or archived(e.g., ZIP or RAR), then extract the contents. 2. Start the game and open the Mods menu. 3. Click on mods to select the ones to use and set their install order. 4. Click "Apply", and wait until completion popup appears. 5a. If no errors are reported, click Exit Game and restart the game after it's closed. 5b. If errors are reported, click Confirm and either reset the mods or apply a different set or order of mods before closing Strive. 6. If game fails to load, reinstall the game and try a different set or order of mods. [color=yellow]How to update mods:[/color] 1. Delete old version of the mods from the mod folder. 2. Download and put new version of the mods in the mod folder. If a mod is compressed or archived(e.g., ZIP or RAR), then extract the contents. 3. Start the game and open the Mods menu. 4. If any mods have changed folder name, click on those mods to select them and set their install order. 5. Click "Apply", and wait until completion popup appears. 6a. If no errors are reported, click Exit Game and restart the game after it's closed. 6b. If errors are reported, click Confirm and either reset the mods or apply a different set or order of mods before closing Strive. 7. If game fails to load, reinstall the game and try a different set or order of mods. [color=yellow]How to disable mods:[/color] 1. Start the game and open the Mods menu. 1. Unselect mods you no longer wish to use. 2. Click "Reset" to disable all mods OR deselect the mods you wish to remove and click "Apply". Wait until completion popup appears. 3a. If no errors are reported, click Exit Game and restart the game after it's closed. 3b. If errors are reported, reinstall the game. [color=yellow]Common installation problems:[/color] 1. Check if the mod has any install instructions. Verify that you have the most recent, or appropriate, version of the mod and that it is compatible with your version of Strive. 2. The game is very specific about where it searches for the file paths of mods, and even a small deviation can cause the mod to have no effect. Each mod's folder is treated as the relative path equivalent to Strive's "file" folder(e.g., '.../mods/MOD_NAME/scripts' is equivalent to '.../STRIVE_FOLDER/files/scripts'). This fact can be used to compare files and folders in a mod for correctness. Also, renaming folders can break any mod that stores gameplay files in that folder. 3. When "Apply" or "Reset" are clicked, the game reverts script files to the files found in the "backup" folder. Only the currently selected mods will be active after "Apply", thus mods cannot be added by spreading them across multiple installs. 4. Having more than one mod change the same file can result in conflicts by overwriting the same code multiple times or changing the line numbers for other mods. Sometimes this can be resolved by flipping their install order. Sometimes they will require manually changing the code. The script files(.gd) are plain text files and can be edited with any decent text editor(e.g., Notepad++, or Sublime Text 3). [color=yellow][center]Experimental Setup for Modding on MacOSX[/center][/color] [color=yellow]This setup may not work for everyone, please have a backup of your game files before attempting.[/color] This guide is an adaptation of the post "How to make mods work on Mac OSX(without wine)" by RK76Manishog on the itch.io forum. You will need both the Mac version and a Windows version of the game. During this setup you may find that some folders are hidden, to show them press Command-Shift-Period. Open the Windows version. There is a hidden folder called ".import", it is important that it be visible. Delete the Strive.exe and icon.png.import files. Keep this folder open as it will be used again. Open the Mac version, right click on Strive For Power.app and click "Show Package Contents". Now, go into /Contents/Resources. You should see Strive For Power.pck and icon.icns. Delete the .pck file as you don't need it anymore. Move everything inside the Windows folder into /Contents/Resources. After that, run Strive For Power.app and see if it works, if it does, then you're done! If not, then make sure to re-read every step, and if it still doesn't work then seek help on itch.io or Discord. The default location to put mods on Mac is Users/YOUR_USER_NAME/Library/Application Support/Strive/mods. Sometimes you might find out that some mods don't work, not all hope is lost if you experience this. Go into your mods folder and right click the files inside of the specific mod. Then click "Get Info" and look in "Sharing & Permissions" which should be at the bottom. Make sure that you turn every file to "Read & Write", including the folder itself. [color=yellow]To install portrait packs:[/color] Open the folder /Users/YOUR_USER_NAME/Library/Application Support/Strive, you should see the folders called "bodies" and "portraits", if not then you will need to make those two folders. Once you download a portrait pack, simply place the files in their respective folders. [color=yellow]Common setup problems:[/color] 1. If the mod system has errors when creating files and folders, try relocating the Strive program folder to the desktop or another location with less restricted permissions. 2. If you started a progress before switching to this setup, then you will need to edit the save file to Find and Replace all instances of ".gdc" with ".gd". [color=yellow][center]For Modders[/center][/color] The mod system does not provide any GUI for easier modding yet, its main objective is to provide simple mod management for users and support for multiple mods. Mods are stored in the mod folder, which has a default path of 'user://mods', where 'user://' is a relative path that depends on your system. The Mods menu provides the "Open Mod Folder" button that will ask your OS to display the mod folder, and button containing the current mod folder path, which can be clicked to bring up a prompt to change the path. The folder can have the file 'LoadOrder.ini', which tracks the install order and active mods. Each folder will be counted as a separate mod and displayed in the user's mod list. The each mod's folder should have a file named info.txt (if not found, one will be generated at '.../mods/MOD_NAME/info.txt'), which will hold a description of the mod to be shown in the Mods menu. On startup, if the backup folder does not already exist, the game automatically creates a backup copy of its script files(.gd) and scene files(.scn, .tscn) and stores them in 'res://backup', where 'res://' is a relative path that depends on where Strive executes from. A new backup can easily be created by deleting or renaming the backup folder and starting the game. Note, the mod system reverts script files to the files found in the "backup" folder, and it can erase any changes you have made to the game's script files. [color=yellow]Basic modding:[/color] Let's imagine you want to edit the script 'mainmenu.gd', which has a path of 'res://files/scripts/mainmenu.gd'. Create a folder in the game's mod folder with your mod's name. Add folder 'scripts' to it, and inside this add a copy of mainmenu.gd. The path of it will be 'user://mods/YOUR_MOD_FOLDER/scripts/mainmenu.gd'. Then you can edit anything you wish in your mod's copy and have those changes applied by the mod system. However, this is only optimal if you want to work with the entire script or just make your old changes into a mod. However, if each mod simply replaces the file, then they cannot coexist within the file. So the mod system provides tools for editing scripts with higher precision and efficiency. [color=yellow]How to edit existing script files (without entirely overwriting them):[/color] Find the code you want to change and identify the file-scoped definition that contains it. The definition will begin with a keyword('class', 'func', 'signal', 'var', 'onready var', 'const', 'enum') as the first text on a line(i.e., no tabs). Copy the entire definition into your mod file with the same name and path as the file you want to edit. Edit the contents of the copied definition to what you want it to be. The definition will be completely overwritten with the one provided by your file, and other parts of the file will be left untouched. Alternatively, if your mod provides a definition that does not match any already in the file, a new definition will be added to the end of the file. Example: Original file, 'res://files/example.gd': -------------------- var a = 10 func b(): print(10) -------------------- Your mod file, 'user://mods/YOUR_MOD_FOLDER/example.gd': -------------------- var a = 5 class c: var d = 4 func b(): print(1) print(2) -------------------- Resulting file, 'res://files/example.gd': -------------------- var a = 5 func b(): print(1) print(2) class c: var d = 4 -------------------- This is the cornerstone of the mod system: overwrite original file but only the parts you want to. However, in some cases you might want to edit just part of a definition(i.e. it is very long, or other modders might also access it). In such cases, you can add a special tag '' as the line above the definition. This will not overwrite whole definition with new code, but instead only add code at line X of a definition's contents. If X is 0, it will be added at the start; if x is -1, it will be added to the end. Example: Original file, 'res://files/example.gd': -------------------- func a(): print(10) class b: var c = 5 var d = 10 -------------------- Your mod file, 'user://mods/YOUR_MOD_FOLDER/example.gd': -------------------- func a(): print(1) print(2) class b: var e = 0 -------------------- Resulting file, 'res://files/example.gd': -------------------- func a(): print(1) print(2) print(10) class b: var c = 5 var e = 0 var d = 10 -------------------- The other tag available for easier modifications is ''. When added before the definition, it will ignore the contents of the provided definition and only remove the lines from X to Y in the original definition. X is the first line, and Y is the last line. It can be helpful to leave a note explaining what you intend to remove. Example: Original file, 'res://files/example.gd': -------------------- func a(): print(1) print(2) print(10) class b: var c = 5 var e = 0 var d = 10 -------------------- Your mod file, 'user://mods/YOUR_MOD_FOLDER/example.gd': -------------------- func a(): #literally anything class b: #removes variables c and e -------------------- Resulting file, 'res://files/example.gd': -------------------- func a(): print(1) print(10) class b: var d = 10 -------------------- Keep in mind that any changes to the code can make it difficult for other mods to nearby code and may result in unexpected behavior. The system will attempt to track the shifts in line numbers to maintain the intended line modifications, but it will not resolve conflicts between mods. [color=yellow]File patching:[/color] As of version 0.5.26, the system supports patching as well as modding. All files, even non-script files, in the folder 'user://mods/YOUR_MOD_FOLDER/patch/' will be copied into the game folder using the relative path similar to mod files. Please note, unlike mods the files will be copied to 'res://' not 'res://files', so files can be added to 'res://.import/'. The patch files will be applied before the mod files are applied. If original game files will be replaced by patch files, then backups will be created for those game files. This means that patch files are fully reversible in the same way as mod files. Example: Your mod file, 'user://mods/YOUR_MOD_FOLDER/patch/example.gd': -------------------- func a(): #literally anything class b: #literally anything -------------------- Resulting new file, 'res://example.gd': -------------------- func a(): #literally anything class b: #literally anything -------------------- [color=yellow]Custom files:[/color] You can use any files, images, and other data not included in the game, by giving them names or paths within the mod folder that do not match any existing game files. It is recommended that you place these within a custom named folder within the mod folder to avoid potentially modding a patch file from another mod. However, for it to be called from other scripts you will need a path. For the path you should use globals.modfolder as reference to user's mod folder. Example: var new_custom_script = load(globals.modfolder + "/YOUR_MOD_FOLDER/custom_mod_files/NEW_CUSTOM_SCRIPT.gd") var new_custom_image = load(globals.modfolder + "/YOUR_MOD_FOLDER/custom_mod_files/NEW_CUSTOM_IMAGE.png") [color=yellow]File tagging:[/color] As of version 0.5.26, the system has tags that can be used to indicate whether a script file is a mod file or a custom file. These tags primarily benefit the users by increasing the usefulness of the completion popup report after applying mods. Example: ###### ###### [color=yellow][center]Detailed Mechanics[/center][/color] This section is intended for those who want to know more technical details for writing mods. If your mod does not behave the way you expected, then this may help clarify why. [color=yellow]How definitions are matched:[/color] Definitions are identified by using regular expressions, regexs for short, which use strings to define search patterns and report any text that matches the given patterns. These patterns are composed of sub-pattern groups that each report the text that they matched. Every group is automatically assigned a numeric index starting at 0 and some groups are given names, but for this guide they will be given names for the part of the syntax that they match. These groups are: entire match, leading comments, header, and body. The mod file and the original file both use the same regexs, which results in some odd modding syntax. Definitions are matched between the two files according to only the header groups, even a single difference will result in them not matching. [color=yellow]Types of changes:[/color] There are two categories of changes a mod file can make: tagged and untagged. Tags are lines such as '' and '' that are provided before definitions. Untagged changes allow definitions to be added or replaced. The groups used to apply changes depend on which tag, if any, is present. The AddTo tag adds the text found by the body group of a modded definition. The RemoveFrom tag only cares about the header of a modded definition. Untagged changes use the entire match group to add or replace a definition. [color=yellow]Line numbers for tags:[/color] Getting the right line numbers for tags is often a process of trial and error, so here are some tips to help. Make sure to use a text editor that will tell you the line numbers as this makes the process a lot simpler. For adding code at a line or removing a line, you get the index by subtracting the line number of the beginning of the definition from the line number you wish to edit and subtracting 1 from the difference. So i [color=yellow]Leading comments:[/color] Any line beginning with '#' is considered a comment, or non-code notes, by Godot scripts. The regex for every definition has a leading comments group, though only untagged changes will make use of them. The group will include any number of comment lines immediately before the header, so long as the '#' is at the start of the line and no line between the comment and the header is not included. Examples: -------------------- #not included [color=green]#included #included[/color] var a = 1 #not included #not included [color=green]#included[/color] var b = 2 -------------------- [color=yellow]Syntax of classes and functions:[/color] Example header groups: -------------------- class NAME func NAME static func NAME -------------------- Note, the rest of the line is not apart of the header or body groups; it can be anything as far as the mod system is concerned. Classes and functions use the same regex pattern for their body group. It is essentially defined as including all the lines that start with a tab until the last line that starts with a tab. There are exceptions to include empty lines or comment lines even if they don't start with a tab. Basically, it will try to match until the next file-scoped definition, then back-track to the last line starting with a tab. Examples: -------------------- func HEADER(): [color=green]var included = 1 #included included = 2 #included[/color] #not included, leading comment for variable var notIncluded = 3 -------------------- [color=yellow]Syntax of variables and their variants:[/color] Example header groups: -------------------- var NAME onready var NAME const NAME enum NAME -------------------- All these definitions use the same regex pattern for their body groups. There are two versions: multiple lines and single line. The multiple line version starts with a '=' followed by either '{' or '['. The following lines can contain anything, until a matching '}' or ']' not followed by a ',' is at the start of a line (note, the entire line will be included). Be careful that the first line does not contain any '}' or ']', not even in a comment, or it will be incorrectly treated as the single line version. When using the AddTo tag, you will need to use the full syntax for it to be matched by the regex. Only the contents of the outer-most pair of '{}' or '[]' will be included in the body group; the rest is removed. Example: -------------------- var poem[color=green] = [ { 'roses' : 'red', 'violets' : 'blue' }, ] #comment can be here due to regex shortcut[/color] -------------------- The single line version will include anything on a single line, except the start of the multiple line version. [color=yellow]Syntax of signals:[/color] This syntax is unique as it does not have a body group. Example header group: -------------------- signal NAME -------------------- [color=yellow]If you still have questions:[/color] The fastest way to get answers is the Strive4Power Discord, which is the second link on the main screen. Otherwise, try posting to a relevant thread or starting a new thread in Strive's itch.io community forum, which is the third link on the main screen. There is a link to the wiki as well, but that tends to be out of date. Or, if you are feeling brave, try opening 'res://files/scripts/mods/modpanel.gd' with a text editor and find out how the mod system works.