Skip to content

improved script classes + module docs #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions src/21-scripted-classes/21-00-scripted-classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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.

Expand Down
1 change: 0 additions & 1 deletion src/30-scripted-modules/30-01-TODO.md

This file was deleted.

69 changes: 69 additions & 0 deletions src/30-scripted-modules/30-01-custom-modules.md
Original file line number Diff line number Diff line change
@@ -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.
33 changes: 0 additions & 33 deletions src/30-scripted-modules/30-99-custom-modules.temp

This file was deleted.

5 changes: 3 additions & 2 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

---
Expand Down