From b0764220c6d71a467c4074e0027aad47c6a01c8e Mon Sep 17 00:00:00 2001 From: cyn0x8 Date: Tue, 25 Feb 2025 02:03:18 -0800 Subject: [PATCH] script stufff --- .../21-00-scripted-classes.md | 25 ++++++- src/30-scripted-modules/30-01-TODO.md | 1 - .../30-01-custom-modules.md | 69 +++++++++++++++++++ .../30-99-custom-modules.temp | 33 --------- src/SUMMARY.md | 5 +- 5 files changed, 95 insertions(+), 38 deletions(-) delete mode 100644 src/30-scripted-modules/30-01-TODO.md create mode 100644 src/30-scripted-modules/30-01-custom-modules.md delete mode 100644 src/30-scripted-modules/30-99-custom-modules.temp diff --git a/src/21-scripted-classes/21-00-scripted-classes.md b/src/21-scripted-classes/21-00-scripted-classes.md index a4364b2..5b0ad55 100644 --- a/src/21-scripted-classes/21-00-scripted-classes.md +++ b/src/21-scripted-classes/21-00-scripted-classes.md @@ -3,8 +3,11 @@ Funkin's implementation of HScript uses a system of scripted classes. To create a scripted class, create an `.hxc` file in your `mods/mymod/scripts/` folder, and, using Haxe syntax, create a new class which extends the base class for the type of object you are scripting, like so: ```haxe +// Package your scripts to help avoid conflicts with other mods! +package mymod.mysubpackage; + // Remember to import each class you want to reference in your script! -import funkin.play.song.Song; +import funkin.play.song.Song; // or use ScriptedSong, it doesn't matter // Choose a name for your scripted class that will be unique // Also specify the class you are extending, we choose Song here. @@ -18,6 +21,24 @@ class BallisticSong extends Song { } ``` +## File Structure and Packages + +A `.hxc` script file will run if and only if it's placed somewhere within the `scripts` folder of your mod root. To avoid conflicts with other mods, it's recommended to do 2 things: + +You should try to "package" all your scripts. For example, if you have a script `mymod/scripts/mymod/mysubpackage/MyScript.hxc`, you should have the first line of your script be: + +```haxe +package mymod.mysubpackage; +``` + +This creates a unique namespace for your script file so scripts from other mods don't override any classes in it. Also note that by doing this, you will also need to include the package name when initializing a script class instance, like: + +```haxe +var someVar:ScriptedFunkinSprite = ScriptedFunkinSprite.init("mymod.mysubpackage.MyScript"); +``` + +Also, try to also structure your script folders like you would for the source code a typical Haxe project. Script files are also kinda treated like mod assets, so if multiple mods have the same script filename at the same relative path, one is going to end up overriding the others. The folder structure should follow the same as your package structure, with some name unique to your mod at top-level. Though not *technically* necessary, it's good practice for stability and compatibility with other mods. + ## List of Scriptable Classes There is a predefined list of classes which the game has set up to be scriptable, and will automatically load and execute when relevant. More of these will be added in the future. @@ -43,7 +64,7 @@ There is a predefined list of classes which the game has set up to be scriptable - `funkin.play.cutscene.dialogue.Speaker` for providing unique behavior to custom speakers used in conversations. See [Dialogue Cutscenes](21-scripted-classes/21-05-dialogue-cutscenes.md) - `funkin.ui.freeplay.Album` for defining custom behavior for Freeplay Albums. See [WIP] -There is also `funkin.modding.module.Module` for custom scripted Modules, which are scripts which receive events everywhere, rather than only in a specific context. See [Scripted Modules](30-scripted-modules/30-00-scripted-modules.md) for more information on how these work. +There is also `funkin.modding.module.Module` for custom scripted Modules, which are singleton script classes which receive events everywhere, rather than only in a specific context. See [Scripted Modules](30-scripted-modules/30-00-scripted-modules.md) for more information on how these work. There are also scripted classes are also set up to be scriptable, but will only be useful if they're accessed from another script. Expect more of these to be added in the future. diff --git a/src/30-scripted-modules/30-01-TODO.md b/src/30-scripted-modules/30-01-TODO.md deleted file mode 100644 index 548b3c7..0000000 --- a/src/30-scripted-modules/30-01-TODO.md +++ /dev/null @@ -1 +0,0 @@ -# TODO: Write this part. \ No newline at end of file diff --git a/src/30-scripted-modules/30-01-custom-modules.md b/src/30-scripted-modules/30-01-custom-modules.md new file mode 100644 index 0000000..7027d0b --- /dev/null +++ b/src/30-scripted-modules/30-01-custom-modules.md @@ -0,0 +1,69 @@ +# Creating a Friday Night Funkin' Mod - Custom Modules + +This guide will walk you through the process of creating a functioning, fully compatible Friday Night Funkin' mod, using the game's official systems for loading custom content and scripts. Once your mod is complete, you will be able to place it in the `mods` folder in your game install and use its content in-game without overriding the base game content and still maintain compatibility with other mods. + +This entry goes over making custom script modules for your mod. + +## What are modules? + +Modules are singleton, "global" script classes that allow you to do... really anything! They can be used to inject something into a state, to modify parts of gameplay like the HUD, to add systems and helpers for mods to use, to add entirely new features to the game, whatever you want! Within the limits of Hscript and Polymod, of course. + +## How modules work + +Each module is initialized with a unique `id` string that is used to identify it, as well as a `priority` integer that collectively determine the order they are all loaded in, as well as the order their callbacks are called in. The greater the number, the later it's processed (alphabetical by ID if the priorities are the same). The number can be any integer, even negative, and defaults to 1000 if none provided. It's a very helpful feature to utilize in case any modules depend on another! + +`ModuleHandler` is the class that handles all module instances internally, but it's also to be used by scripts to get the module instances to interact with via `ModuleHandler.getModule(id:String):Module`. + +## Example + +In a script `mymod/scripts/mymod/mysubpackage/Example.hxc`: + +```haxe +package mymod.mysubpackage; + +import funkin.modding.module.Module; // or use ScriptedModule, it doesn't matter +import funkin.modding.module.ModuleHandler; + +class MyModule1 extends Module { + override public function new() { + super("mymod-MyModule1", 0); // <-- your module id and priority respectively + } + + override public function onCreate(event:ScriptEvent):Void { + trace("Hello from mymod-MyModule1!"); + } + + public var someVar:Int = 69; + + public function someFunction(someArg1:Float, someArg2:Bool = true):Void { + trace("someArg1: " + Std.string(someArg1)); + trace("someArg2: " + Std.string(someArg2)); + } +} + +class MyModule2 extends Module { + override public function new() { + super("mymod-MyModule2", 1); + } + + override public function onCreate(event:ScriptEvent):Void { + trace("Hello from mymod-MyModule2!"); + + var myModule1:Module = ModuleHandler.getModule("mymod-MyModule1"); + myModule1.scriptCall("someFunction", [myModule1.scriptGet("someVar")]); + } +} +``` + +The output from this example should show something like: + +``` +Hello from mymod-MyModule1! +Hello from mymod-MyModule2! +someArg1: 69 +someArg2: true +``` + +## Some advice + +Module IDs must be unique to avoid conflicts with other mods; therefore, it's recommended as a good practice to prefix your module IDs with with your mod name like `mymod-MyModule` or the package of the script like `mymod.mysubpackage.MyModule`. Just anything that'll make it unique! It'll be pretty wordy... but the tradeoff for stability is often worth it. diff --git a/src/30-scripted-modules/30-99-custom-modules.temp b/src/30-scripted-modules/30-99-custom-modules.temp deleted file mode 100644 index 9ee5158..0000000 --- a/src/30-scripted-modules/30-99-custom-modules.temp +++ /dev/null @@ -1,33 +0,0 @@ -# Creating a Friday Night Funkin' Mod - Custom Modules - -This guide will walk you through the process of creating a functioning, fully compatible Friday Night Funkin' mod, using the game's official systems for loading custom content and scripts. Once your mod is complete, you will be able to place it in the `mods` folder in your game install and use its content in-game without overriding the base game content and still maintain compatibility with other mods. - -This entry goes over making custom modules for your mod - -## what are modules? -modules are scripts that allow you to interact with the full game with only functions/callbacks, you can use them to alter ui elements in menus, and edit the game feild in the song without having to make a script for the stage/song/character - -## how modules work -modules are taken care of by the ModuleHandler in the game that takes every class that extends `funkin.modding.module.Module` and handles it by firing its callbacks - -## where to add the module file -first you need to make a scripts folder if you dont already have one in your mods folder. for where you should add your module file(s) in that folder it doesnt really matter, you can add them in folders to keep your files clean so the next part is optional, make a folder called `modules` in `yourmod/scripts/.`. and then make a file named `yourModule.hxc` in that folder, you dont have to make the first letter upperCase like hx files and offcourse change 'yourModule' to your modules name - -## how to make a module -to make a module you need some scripting knowledge so you can understand how it works, so in that file that you created make a class with the name of your module (make sure the first letter is uppercase) and make it extend `funkin.modding.module.Module` after that override the classes constructor and in the super call function add the classes name in a string - -``` -import funkin.modding.module.Module; - -class MyModule extends Module{ - override public function new() - { - super('MyModule'); // <-- your modules name here - } -} -``` - -## how to add callbacks to a module - ---add something here - diff --git a/src/SUMMARY.md b/src/SUMMARY.md index deda19c..be9b8b8 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -50,12 +50,13 @@ - [Using HScript](20-using-hscript/20-00-using-hscript.md) - [What is HScript?](20-using-hscript/20-01-what-is-hscript.md) -- [Scripted Classes](20-using-hscript/21-00-scripted-classes.md) +- [Scripted Classes](21-scripted-classes/21-00-scripted-classes.md) - [Scripted Songs](21-scripted-classes/21-01-scripted-songs.md) +- [Scripted Modules](30-scripted-modules/30-00-scripted-modules.md) + - [Custom Modules](30-scripted-modules/30-01-custom-modules.md) # HScript (Advanced) -- [WIP: Scripted Modules](30-scripted-modules/30-00-scripted-modules.md) - [WIP: Custom Shaders](31-custom-shaders/31-00-custom-shaders.md) ---