-Fix mods sometimes having a None variable as their state -Fix mods already in load order not updating to reflect if there's no loadable scripts -Fix mods without scripts being turned off when using DISABLEALLMODS file flag
13 KiB
--- MOD LOADER USAGE ---
If there's problems with installed mods - like if an enabled mod makes the game crash on startup - there's 3 file flags you can apply to work around it, checked only in the root of the mods folder. They will be any file starting with:
- "DISABLEALLMODS". This will force disable all currently installed mods, but will still load all their metadata. This doesn't change the saved states of your mods, so you can still enable/disable them while this flag is active.
- "NOLOADORDER". This will erase the load order/states and always load mods in folder alphabetical order, with mod states depending on the "Enable New Mods" option in the preferences menu.
- "NOMODS". This turns off mod loading entirely by making the game not find any metadata files to load. These file flags already exist in the mods folder, but renamed to not trigger in-game. Enable them by renaming the file to take off the first hyphen.
When ordering the mods in the mod menu, know that not all mod code will be loaded according to the order. Ren'Py has a feature called 'init' that will run code at certain mod-defined stages (priorities) of the engine starting up, so if one mod's init block is set to run at an earlier priority than another mod's, it doesn't matter what order it is in the mod loader, it will always load that init first. The only time when the order comes into effect is if two mod's init blocks run at the same priority, or aren't running in an init block.
--- MOD CREATION PRE-REQUSITES ---
Before modding, you may want to do either of these things:
-Download Snoot Game as a renpy project and launch through the SDK so you can have easy access to debugging and other QoL tools, including dev mode. (Download the repo in this link: https://git.cavemanon.xyz/Cavemanon/SnootGame) -Open script.rpy and put 'config.developer = True' somewhere in the 'init python' block to have access to renpy's dev mode.
Pick the latter option if you're lazy, since you don't seriously need to use the SDK for most things.
--- MOD CRREATION ---
When creating a mod, make a new folder within the 'mods' directory at the root of the game directory and name it whatever you want. Inside that folder, make a file called 'metadata.json', and follow the JSON file format to implement details about your mod. An example would be:
{
"ID": "234234u9SDjjasdhl23",
"Name": "Test Mod",
"Label": "test_mod_label",
"Version": "1.0",
"Authors": [ "Author1", "Author2", "Author3" ],
"Links": "Link1",
"Description": "This contains the description of my mod"
}
Make sure there isn't a comma at the end of the last entry in your JSON.
Below is all the possible entries you can put in, and explanations for what they do. Note that you don't need to put all of these in your metadata file, and infact the only hard requirement is the "ID" entry.
"ID" : The ID of your mod. Required to be able to load your mod at all, as it is used by the mod loader for mod orders and enabling/disabling. Make this as unique of a string as you can, like a hash. Smash your keyboard if you must. This is how the game knows to differentiate your mod from others (And can be used by other mods to find if a user has your mod installed, if they so choose).
"Name" : The name of your mod. If this doesn't exist, the game will assume the name of your mod folder.
"Label" : The label to jump to start your mod story. If this doesn't exist, the button this mod will appear as will do nothing when clicked. Useful if you're only modifying something relating to the base game.
"Version" : The version number of your mod.
"Authors" : The authors of your mod. This can be a list of strings or just a string. If it's just a string, it will display in the mod details pane with only "Author:" instead of "Authors:"
"Links" : The links to download your mod and/or advertisement. This can be a list of strings or just a string. If it's just a string, it will display in the mod details pane with only "Link:" instead of "Links:". In order for this to be useful, use the 'a' text tag to make these texts hyperlinks.
"Description" : The description of your mod.
"Mobile Description" : The description of your mod, but only appearing while playing Snoot on Android. If this doesn't exist, it will assume the contents of the description entry. Otherwise, you can copy your description text here and format it however you think it fits for Android.
"Display" : How your mod button appears if there's an icon image detected. This can be set to "name" - which only displays the mod name - "icon" - which only displays the icon, taking up the entire button - or "both" - which displays the name and icon together, with the icon miniaturized and to the side of the name. This defaults to "both" if it doesn't exist, and if an icon image is not present, it will fall back to "name" mode.
"Thumbnail Displayable" : What displayable to use for the thumbnail when the mod is enabled. If this doesn't exist, the game will use the thumbnail image found alongside your metadata file
"Icon Displayable" : What displayable to use for the icon when the mod is enabled. If this doesn't exist, the game will use the icon image found alongside your metadata file
"Screenshot Displayables" : What displayables to use for screenshots when the mod is enabled. This should be a list of strings. The game will choose each displayable in the list over images found alongside the metadata file sequentially, so if there's 5 screenshot images and 3 screenshot displayables, the last 2 will still display the screenshot images, and the first 3 will display the screenshot displayables. If there's more displayables than images, then the mod will appear to gain screenshots in the mod details pane when the mod is enabled. If you enter empty strings in the list ( "" ), the game will interpret that as a deliberate skipping over to load screenshot images instead of displayables, so if your list consists of '[ "", "my_displayable" ]' and there's any number of screenshot images found, the first screenshot will still show a screenshot image, and only the next one will show a displayable. If this entry doesn't exist, it will just use the screenshot images found alongside your metadata file.
In the same directory as your metadata file, there's image files you can put in the to make your mod more appealing. These can be any of Ren'Py's supported image file types, so the file extension here is just for demonstration:
-'thumbnail.png' will appear as a banner for your mod, at the top of the mod details pane
-'icon.png' will show a small image next your mod name or take up the entire button depending on what your "Display" entry is set to. NOTE: Putting in an image too big in dimensions will crash the game.
-'screenshot(number).png' will show screenshots at the bottom of the mod details pane. The '(number)' is a placeholder for a number that represents what order your screenshots appear in. For example, you can have 'screenshot1.png', 'screenshot2.png', and 'screenshot3.png' in your mod directory, and they will all appear in the mod details pane in order. These numbers don't need to be strictly sequential, they can be any number as long as they are integers, and the order will be derived from ASCII ordering.
As the game loads the metadata, it will also collect scripts for loading. When you make your mod scripts, ALL OF THEM NEED TO HAVE .rpym EXTENSIONS. This is important for being able to control mods with the mod loader, otherwise there would be mod conflicts galore. If you use .rpy extensions to make your mod scripts, they will work, but they will not be manageable by the mod loader. This means you should only use them for development, or if you're not using the mod loader anyway - such as adding a translation to the base game.
Additionally, Ren'Py will not load any files from the mods folder automatically, so any and all audio/image/video files need to be manually defined to be usable.
--- TRANSLATION ---
For disambiguation, a "language code" refers to the code Ren'Py uses to refer to languages program-wide, and can be found on the folder names in "game/tl", with "None" being the default language (Representing a fallback language, but usually meaning English. Internally, it's an actual None variable)
For translating mods, you should use the Ren'Py SDK to automatically generate translations from mod scripts. Make sure to use a language code that Snoot supports when you do so, so you don't accidentally create a new language. Put them into an organized directory in your mod and change them to use .rpym extensions so that translations don't activate unless your mod is as well (This prevents potential conflicts from other mods from interface/string translations).
For assets, the easiest way is to put them in the "tl" folder and have the same filepath to your mod asset as it is from the "game" folder to your asset, just like how the officially supported translations are. This will make your mod less portable, but at least there's no namespace or file conflicts for translating images. If you're deadset on making your mod portable, you'll have to make conditionals in your mod to swap out images depending on the language, which means other people translating your mod can't just add a file somewhere and be done with it, they will need to edit your mod scripts as well.
For translating metadata, you can translate the .json file by creating a new .json and naming it "metadata_(language code).json" (Ex: "metadata_es.json" for spanish). Fill out the .json how you would with the normal metadata file, but with your translated strings. The game will automatically pick this up and replace the strings (or add, if there's no 'None' variant of an entry) according to your language. Note that translating the ID or Label will do nothing, so you will always need a metadata.json file with at least an ID entry even if your mod isn't in english.
For the images found alongisde your metadata, you can do the same thing as your .json to replace them. Simply append your language code to your image filename like "thumbnail_es.png", "icon_es.png", etc.. For screenshots, the number in your filename will determine if any given translated image will replace another image, or add it inbetween images. So if you have "screenshot4.png", and you have "screenshot2_es.png" and "screenshot5_es.png", all screenshots will show up if your language is in spanish. If there's "screenshot4_es.png" in the directory, then it will replace "screenshot4.png". The final screenshot display will always take the english screenshots as a base before replacing the images with whatever translated images that exist.
--- TIPS ---
The Ren'Py documentation is your friend, but it is also a bitch-ass friend. It will sometimes be notoriously unhelpful, so consult other renpy dudes from the Ren'Py discord, your snoot communities, or youtube. This may also be of interest, as it will link to other documentation as well as many interesting libraries you can use: https://github.com/methanoliver/awesome-renpy
Link to Ren'Py documentation: https://www.renpy.org/doc/html/
When making the file structure for your mod, this is the ideal. Keep it nice and organized, preferably keeping the root of your mods folder clear of eveything but metadata related stuff:
In the root of the mods folder:
folder_of_your_mod_name
- metadata.json
- Your various image metadatas
-> asset_folder
- asset.png
-> script_folder
- script.rpym
-> etc. folders...
- etc. files...
To start your mod, just make it under the label you defined in your metadata file in a mod script. An example in a newly created "mymodscript.rpym":
label my_mod_label:
scene my_background
show my_sprite
"blah blah dialogue"
Textbox limitation: ~300 characters / four lines, the maximum in the vanilla game's script is around roughly ~278 and that only barely overflows to four lines, so <200 characters / three lines of text should be fine.
If a user has many mods installed, it would be annoying to need to keep track of which mods to enable or disable because of code conflicts, so make your variables/functions unique. Since Ren'Py's own scripting doesn't support namespaced stuff, a very simple way is to prefix all your variables/functions with a mod-unique name, similar to your mod ID. An example would be "mymodisfantastic2349234_function_or_variable". Kinda ugly, but manageable with Ctrl-F and string replacement if there's problems. If there must be code conflicts, let the user know in your mod description!