Skip to main content

Introduction to HScript

Friday Night Funkin’ uses HScript for mod scripting - a scripting language that looks and works like Haxe. Scripts can extend classes, react to events, and modify gameplay in real-time.
HScript syntax is nearly identical to Haxe. If you know Haxe, you already know HScript!

Script Types

There are three main types of scripts in FNF:

Modules

Global scripts that receive events from any game state

Scripted Classes

Scripts that extend base Flixel classes

State Scripts

Scripts attached to specific game states or objects

Creating a Module

Modules are the most powerful script type - they receive events globally across all game states.

Basic Module Structure

1

Create script file

In your mod folder, create a .hxc file:
2

Import the Module class

MyModule.hxc
3

Add event handlers

Override methods to handle events:

Module Constructor

The Module constructor takes these parameters:
Module.hx
  • moduleId - Unique identifier for your module
  • priority - Event priority (lower = earlier, default 1000)
  • params - Optional parameters (can restrict to specific state)
Use priority to control when your module receives events relative to others. Priority 1 runs before Priority 1000.

Module Properties

Available Events

Lifecycle Events

Gameplay Events

UI Events

Event Manipulation

Events can be cancelled or stopped:
Only cancelable events can be cancelled. Check event.cancelable before calling cancel().

Scripted Classes

Create custom classes that extend Flixel base classes:

Available Base Classes

From funkin/modding/base/:
  • ScriptedFlxBasic
  • ScriptedFlxObject
  • ScriptedFlxSprite
  • ScriptedFlxSpriteGroup
  • ScriptedFlxState
  • ScriptedFlxSubState
  • ScriptedFlxTypedGroup

Example: Custom Sprite

CustomSprite.hxc
Usage in another script:

Available Imports

The following classes are automatically imported:
You can use these directly without importing:

Manual Imports

For other classes, import them explicitly:

Script Event Interface

Scripts can implement the IScriptedClass interface:
Specialized interfaces add more events:
  • IPlayStateScriptedClass - All gameplay events
  • IStateChangingScriptedClass - State transition events
  • IFreeplayScriptedClass - Freeplay menu events
  • IBPMSyncedScriptedClass - Beat and step events
  • INoteScriptedClass - Note-related events

Practical Examples

Example 1: Score Multiplier

ScoreMultiplier.hxc

Example 2: Custom Countdown Sound

CustomCountdown.hxc

Example 3: Health Drain

HealthDrain.hxc

Example 4: Camera Flash on Beat

BeatFlash.hxc

Example 5: Chart Modifier

ChartRandomizer.hxc

ModStore - Persistent Data

Share data between scripts using ModStore:
Usage:

Security & Limitations

For security, certain classes are blacklisted or sandboxed:
Blacklisted (not accessible):
  • Sys - System commands
  • sys.* - File system access
  • cpp.Lib - Native libraries
  • polymod.* - Polymod internals
  • hscript.* - Script parser
Sandboxed (limited access):
  • FileUtil → FileUtilSandboxed
  • Reflect → ReflectUtil (safe subset)
  • Type → ReflectUtil (safe subset)
  • Newgrounds API (read-only)

Debugging Scripts

Use trace() to log debug information:
Traces appear in the game console (enable with F5 or compile flags).

Best Practices

  • Avoid heavy operations in onUpdate()
  • Cache expensive calculations
  • Use module active property to disable when not needed
  • Set appropriate priority to avoid redundant processing
  • Check for null before accessing properties
  • Validate event data before using
  • Use try-catch for risky operations
  • Test scripts thoroughly before distribution
  • One class per file
  • Use descriptive class and variable names
  • Comment complex logic
  • Break large scripts into smaller modules
  • Don’t assume specific class internals
  • Use public APIs when available
  • Test with multiple game versions
  • Document required API version

Next Steps

Polymod Deep Dive

Learn advanced asset manipulation and merging

Modding Overview

Return to the modding overview