Skip to content

Modules

Fran Kelava edited this page Oct 14, 2026 · 34 revisions

A module is a class deriving from FhModule. They are the basic unit of functionality and organization in Fahrenheit mods.

Mods, unless purely file-based, consist of anywhere from one to an unlimited number of modules. They allow you to split the combined functionality of your mods into smaller, legible, reusable pieces.

Modules may retrieve instances of each other at runtime and interact with each other.

Beyond being organizational scopes, modules possess the following properties:

  • Each gets its own global and local state.
  • Each gets its own log file.
  • Each gets to specify the games it supports.

Basic requirements

A valid module has only two basic requirements.

  • It must have exactly one, public, parameterless constructor.
  • It must implement the init method. See Initialization.

For example:

// A perfectly valid, minimal module that does nothing.
[FhLoad(FhGameId.FFX | FhGameId.FFX2 | FhGameId.FFX2LM)]
public sealed class ExampleModule : FhModule {
    public override bool init(FhModContext mod_context, FileStream global_state_file) {
        return true;
    }
}

Loading and initialization

For a module to be loaded, apply the FhLoad attribute specifying which games it supports. For example:

// Will be loaded in all three games.
[FhLoad(FhGameId.FFX | FhGameId.FFX2 | FhGameId.FFX2LM)]
public sealed class ModuleThatDoesThings : FhModule { }

// Will be loaded only in FF X.
[FhLoad(FhGameId.FFX)]
public sealed class ModuleThatAlsoDoesThings : FhModule { }

If the appropriate game is launched, Fahrenheit will instantiate the module.

Communicating with other modules

To retrieve an instance of another module at runtime safely, use a FhModuleHandle<T>. For example:

FhModuleHandle<ModuleThatDoesThings>     h_one = new(this);
FhModuleHandle<ModuleThatAlsoDoesThings> h_two = new(this);

if (h_one.try_get_module(out ModuleThatDoesThings?     m_imgui) && 
    h_two.try_get_module(out ModuleThatAlsoDoesThings? m_resload)) 
{
    // If the call succeeds, you may store the returned
    // modules and use them as you see fit.
}

Important

Always use handles to refer to other modules. They allow you to deal with their potential absence gracefully.

Never construct your own instances of modules.

From Fahrenheit's perspective, such modules do not exist, thus none of their callbacks execute.

Clone this wiki locally