HScript Basics - SlightlySimple/FNF-Restructure-Engine GitHub Wiki

Restructure Engine comes with HScript support, allowing you to run code from outside the game to affect it. All scripts have the file extension ".hscript"

Script Types

In-Game

  • Global scripts, which are run on every song, are stored in the "data/autorun" folder.
  • Song-specific scripts are stored in the folder where the song's charts are. A song will attempt to load every script in this folder. Note that scripts in subfolders of a song's charts folder will not be loaded, which may be useful if you want to manually load them with other scripts.
  • Song group scripts are stored in the folder where the song's charts folder is, if that folder isn't the "data/songs" folder itself. For example, if the charts are in "data/songs/week1/fresh," these scripts would be inside "data/songs/week1"
  • Scripts for characters, stages, noteskins, events, and note types are stored in the folder where the respective element's JSON file is, and have the same name as the element.
  • Scripts can also manually load other script files.

In menus

Menu scripts are stored in "data/states," except for week-specific scripts which are stored in the folder with the week's JSON file, and have the same name.

Script Functions

  • create() is run right after the game and it's scripts are initialized.
  • update(elapsed) is run at the start of the game's update function, with elapsed being the time (in seconds) since the function was last run.
  • updatePost(elapsed) is run at the end of the game's update function.
  • beatHit() is run on every beat. You can use game.curBeat to get the current beat.
  • stepHit() is run on every step. You can use game.curStep to get the current step.
  • startCountdown() is run when the countdown is started.
  • countdownTick() is run on every tick of the countdown. You can use game.countdownProgress to get the current tick.
  • playSong() is run when the song starts.
  • endSong() is run when the song ends.
  • onNoteSpawned(newNote) is run every time a note is spawned, with newNote being the note in question.
  • onSustainSpawned(newSustain, newNote) is run every time a sustain note is spawned, with newSustain being the note in question and newNote being the note it's connected to.
  • noteHit(note) is run when a note was hit, whether it was hit by the player or the opponent. note is the note in question.
  • sustainHit(note) is run on every tick a sustain note is being hit, whether it's being hit by the player or the opponent. note is the note in question.
  • noteMissed(note) is run when a note was missed. note is the note in question.
  • sustainMissed(note) is run when a sustain note was missed. note is the note in question.
  • noNoteHit(hitNote) is run when a note key was pressed, but no note was hit. hitNote is the column associated with the key that was pressed.
  • noteSplash(note, newSplash) is run when a note splash is spawned. note is the note that was hit, and newSplash is the spawned note splash.
  • onEvent(event) is run when an event is triggered, ONLY on the script connected to that event. event is the event in question.
  • onAnyEvent(event) is run when an event is triggered, on every script. event is the event in question.
  • onCustomEvent(type, event) is run when the "custom" event is triggered, on every script. type is the type of the event, and event is the event in question.

Common variables and functions

  • PlayState is used to access anything in the PlayState class, while game is used to access the current instance of that class.
  • game.player1 is the player character (boyfriend,) game.player2 is the opponent (dad,) and game.gf is the girlfriend.
  • game.allCharacters is an array that stores all characters, and can be used when there are more than three characters to access the additional ones. For example, if you added a second opponent as a fourth character, you would use game.allCharacters[3]
  • game.stage is the current stage and all it's associated data, with game.stage.pieces being a map of the sprites that make up the stage. Note that in a stage script, you can use stage and stage.pieces instead. For example, to access the floor of the default stage, you would use game.stage.pieces["stagefront"]
  • game.songName is the current song name as it's displayed in all UI elements.
  • PlayState.songId is the filename of the current song. PlayState.songIdShort is the filename of the current song, without any preceding folders if there are any.
  • PlayState.inStoryMode is whether or not the player is in story mode. PlayState.storyProgress is which song of the week the player is on.
  • PlayState.firstPlay is whether or not the song has actually started since initially loading. This is used for cutscenes, to prevent them from playing again when a player dies or restarts the current song.
  • game.canStartCountdown is used to control whether the countdown can start. game.canEndSong is used to control whether the post-song events can happen. Both of these are used for cutscenes, and neither of them will prevent the startCountdown and endSong functions from triggering in scripts.
  • game.startCountdown() and game.endSong() can be used to manually start the countdown or end the song after a cutscene.
  • game.endingSong says whether the song has attempted to end at least once, even if game.canEndSong was false. It can be used in functions that trigger both before the start and at the end of a song, to determine which is currently happening.