Friday Night Funkin' Cookbook
Friday Night Funkin' CookbookExpertScripted Modules

Scripted Modules

Reading time: 2 minutes

Most articles about scripting will cover basic functionality of overriding already existing methods. However, there is a need for completely custom functionality instead. This is where Modules step in.

A module is a class which runs very similarly to global scripts in other game engines. They are basically mini-states that run parallel to the original state.

You can use these modules to create entirely custom functionality, examples include:

  • Custom HUDs
  • Custom Menu's (Mod Menu, Pause Menu, Main Menu, etc)
  • Retroactively affect gameplay (Creating chances of sprites appearing on screen, and adding your own version of ghost tapping. Among other things)

Creating a Module

import funkin.modding.module.Module;

class KE_QOL extends Module
{
    public function new()
    {
        // This registers a NAME for the module, which might be needed later!
        super("KE-QOL");
    }

    public override function onScriptEvent(event:ScriptEvent)
    {
        // ...
    }

    public override function onStateChangeBegin(event:StateChangeScriptEvent)
    {
        // ...
    }

    public override function onNoteIncoming(event:NoteScriptEvent)
    {
        // ...
    }

    public override function onSongStart(event:ScriptEvent)
    {
        // ...
    }

    public override function onSongLoaded(event:SongLoadScriptEvent)
    {
        // ...
    }
}

Modules have all the events most scripts have, but the difference is. You also have access to state change events, every script event, losing/gaining focus, and sub-state changes.

Modules also have a priority system for compatibility with other mods, in your construction method, new(), you can set the priority property (which defaults to 1000). 1 is processed before anything else.

You can view a detailed list of script events and their callbacks in here

Scoped Modules

Sometimes when creating a module you might require a more specialized approach: Onlying firing events when you are in a certain state. A scoped module is the right tool.

To initalize this module you must assign the state property in the constructor, like so:

import funkin.ui.mainmenu.MainMenuState;

class ScopedModule_MainMenuState extends Module {
    public function new():Void {
        // Name: ScopedModule_MainmenuState
        // Priority: 1
        // Scoped state: MainMenuState
        super("ScopedModule_MainmenuState", 1, {
            state: MainMenuState
        });
    }

    public override function onStateChangeEnd(event:StateChangeScriptEvent):Void {
        super.onStateChangeEnd(event);

        // At the end of the state change event *INTO* the state (MainMenuState)

        trace("We've entered the Main Menu State!");
    }
}

Contributors:
Kade-gtihub
Kolo
Cameron Taylor
anysad
Last modified:
Created:
Category:  Expert
Tags: