Hooks: Difference between revisions

From Heroes of Hammerwatch Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 124: Line 124:


<div style="font-weight:bold;line-height:1.6;">How does the game know the hooks?</div>
<div style="font-weight:bold;line-height:1.6;">How does the game know the hooks?</div>
In specific parts of the game a 'Hook' call is added which automatically looks up the hook that matches and executes it at that point in the code.
At a specific point in the core game code, a line similar to the following is executed: Hooks::Call("NameOfHook", argument1, argument2, ...);
Every hook call in the game code itself is defined as <code>Hooks::Call("NameOfHook", arguments1, arguments2)</code>


Hooks usually have 1 or even multiple arguments, these must match if you want to use the hook.
This function automatically looks up and executes any custom functions (Hooks) that have been registered with the matching name.
To give an example, let's take a look at <code>Hooks::Call("BaseGameModeConstructor", @this);</code> inside BaseGameMode class (BaseGameMode.as).
Every hook is defined by its name (the first string argument in Hooks::Call) and its required arguments.
For us to use this hook we must use the name <code>BaseGameModeConstructor</code>, with the argument <code>@this</code>. In this case <code>@this</code> refers to the class itself. The class this is in is <code>BaseGameMode</code>.
This means that the argument is the class <code>BaseGameMode</code>.


So we know the name and the argument to use this hook, to use it we use this:
Crucially: For a custom hook function to execute, its name and arguments must exactly match the definition in the core game's Hooks::Call.
  namespace MyTestMod // Be sure to always put it inside a namespace, conflicts or other things may occur if you don't
 
Example using the BaseGameModeConstructor Hook, let's look at the core game call for this example:
{| class="wikitable"
|+ Caption text
|-
! Component !! Description
|-
| Hooks::Call("BaseGameModeConstructor", @this); || the complete line inside BaseGameMode.as
|-
| BaseGameModeConstructor || This is the '''Hook Name''' you must use.
|-
| @this|| This is the Required Argument.
|}
 
'''@this''' refers to the instance of the class the hook is called from, which in this case is the BaseGameMode class itself.
To use this hook in a mod, you must create a function that matches the name and accepts a BaseGameMode object as its argument.
Your custom hook function must be placed inside a namespace and be decorated with the [Hook] attribute.
  namespace MyTestMod // Always use a namespace to prevent conflicts!
  {
  {
    // This is executed when the game comes along to Hooks::Call("BaseGameModeConstructor", @this);
    // The [Hook] attribute tells the game that this is a custom hook function.
    [Hook] // [Hook] means for the game that this is an hook we use, if you don't put this on top of the hook we are using, the game doesn't recognize it.
    // Without it, the function will not be recognized or executed.
    void BaseGameModeConstructor(BaseGameMode@ baseGameMode){ // void BaseGameModeConstructoris the name from Hooks::Call("BaseGameModeConstructor"... the argument @this refers to the BaseGameMode as we found.
    [Hook]
        print("Hello World"); // Prints hello world in the console
    void BaseGameModeConstructor(BaseGameMode@ baseGameMode) // Matches name and argument type!
    }
    {  
        // This code will run every time the BaseGameMode constructor executes
        // Hooks::Call("BaseGameModeConstructor", @this);
        print("Hello World from MyTestMod!");  
    }
  }
  }


If the arguments do not match in the hook, it will either not execute or returns an error in the console
Important Note on Arguments: If the arguments in your custom hook function do not match the arguments in the core game's Hooks::Call, the hook will either fail to execute silently or return an error in the console. Argument matching is mandatory.
</div></div>
 
 
'''Can you create Hooks yourself?'''
 
You should be able to yes, especially if you overwrite the base game files you can put hooks everywhere, although this is HIGHLY discouraged.
 
These files need to be updated every game update, although there have been talking about a community based hooks to make use of hooks in places we want them, there never have been made plans.

Revision as of 18:28, 15 December 2025

ATTENTION: it's possible a hook won't work, due to the parameters not matching, if you find one, report it to the modders channel or the hoh2 wiki discussion.

Hooks are script functions that are called at specific moments. This way, you can insert code into the game.

They are specified in script files and tagged with the Hook specifier. They also must be placed within a namespace to avoid ambiguity between multiple mods.

The following is an example of such a file:

namespace MyTestMod
{
   [Hook]
   void BaseGameModeConstructor(BaseGameMode@ baseGameMode){
       print("Hello World");
   }
}

GetGeneratedAttributes

void GetGeneratedAttributes(PlayerStatsDetail@ stats, array<string>@ strArray, array<string>@ icons, bool isHandHeld)

PlayerDamagedActor

void PlayerDamagedActor(Player@ player, Actor@ actor, DamageInfo di)

PlayerDamageActor

void PlayerDamageActor(PlayerBase@ playerBase, Actor@ actor, DamageInfo@ damageInfo, Skills::Skill@ skill)

PlayerDamageActorNoWeapon

void PlayerDamageActorNoWeapon(PlayerBase@ playerBase, Actor@ actor, DamageInfo@ damageInfo)

PlayerDamage

void PlayerDamage(Player@ player, DamageInfo di)

PlayerDamageTaken

void PlayerDamageTaken(Player@ player, DamageInfo di)

PlayerInitialize

void PlayerInitialize(PlayerBase@ playerBase)

PlayerRefreshScene

void PlayerRefreshScene(PlayerBase@ playerBase)

PlayerRecordConstructor

void PlayerRecordConstructor(PlayerRecord@ record)

PickedCharacter

void PickedCharacter(PlayerRecord@ record)

CreateCharacter

void CreateCharacter(PlayerRecord@ record)

PlayerRecordSave

void PlayerRecordSave(PlayerRecord@ record, SValueBuilder &builder)

PlayerRecordLoad

void PlayerRecordLoad(PlayerRecord@ record, SValue@ data)

PlayerRecordRefreshModifiers

void PlayerRecordRefreshModifiers(PlayerRecord@ record)

LevelupCharacter

void LevelupCharacter(PlayerRecord@ record)

GameModeStart

void GameModeStart(AGameplayGameMode@ aGameplayGameMode, SValue@ save)

GameModePostStart

void GameModePostStart(AGameplayGameMode@ aGameplayGameMode)

GameModePreRenderFrame

void GameModePreRenderFrame(AGameplayGameMode@ aGameplayGameMode, int idt)

GameModeRenderFrame

void GameModeRenderFrame(AGameplayGameMode@ aGameplayGameMode, int idt, SpriteBatch& sb)

GameModeSpawnPlayer

void GameModeSpawnPlayer(AGameplayGameMode@ aGameplayGameMode, PlayerRecord@ record)

GameModeSpawnPlayerCorpse

void GameModeSpawnPlayerCorpse(AGameplayGameMode@ aGameplayGameMode, PlayerRecord@ record)

BaseGameModeConstructor

void BaseGameModeConstructor(BaseGameMode@ baseGameMode)

GameModeUpdatePaused

void GameModeUpdatePaused(BaseGameMode@ baseGameMode, int ms, GameInput& gameInput, MenuInput& menuInput)

GameModeUpdate

void GameModeUpdate(BaseGameMode@ baseGameMode, int ms, GameInput& gameInput, MenuInput& menuInput)

LoadWidgetProducers

void LoadWidgetProducers(GUIBuilder@ builder)

HUDConstructor

void HUDConstructor(HUD@ hud, GUIBuilder@ b)

TownRecordConstructor

void TownRecordConstructor(TownRecord@ townRecord)

TownRecordSave

void TownRecordSave(TownRecord@ townRecord, SValueBuilder& builder)

TownRecordLoad

void TownRecordLoad(TownRecord@ townRecord, SValue@ save)

TownRecordSpawnTown

void TownRecordSpawnTown(TownRecord@ townRecord)

TownRecordRefreshHeroTitles

void TownRecordRefreshHeroTitles(TownRecord@ townRecord)

TownRecordRefreshDonationTitles

void TownRecordRefreshDonationTitles(TownRecord@ townRecord)







How does the game know the hooks?

At a specific point in the core game code, a line similar to the following is executed: Hooks::Call("NameOfHook", argument1, argument2, ...);

This function automatically looks up and executes any custom functions (Hooks) that have been registered with the matching name. Every hook is defined by its name (the first string argument in Hooks::Call) and its required arguments.

Crucially: For a custom hook function to execute, its name and arguments must exactly match the definition in the core game's Hooks::Call.

Example using the BaseGameModeConstructor Hook, let's look at the core game call for this example:

Caption text
Component Description
Hooks::Call("BaseGameModeConstructor", @this); the complete line inside BaseGameMode.as
BaseGameModeConstructor This is the Hook Name you must use.
@this This is the Required Argument.

@this refers to the instance of the class the hook is called from, which in this case is the BaseGameMode class itself. To use this hook in a mod, you must create a function that matches the name and accepts a BaseGameMode object as its argument. Your custom hook function must be placed inside a namespace and be decorated with the [Hook] attribute.

namespace MyTestMod // Always use a namespace to prevent conflicts!
{
    // The [Hook] attribute tells the game that this is a custom hook function.
    // Without it, the function will not be recognized or executed.
    [Hook]
    void BaseGameModeConstructor(BaseGameMode@ baseGameMode) // Matches name and argument type!
    { 
        // This code will run every time the BaseGameMode constructor executes
        // Hooks::Call("BaseGameModeConstructor", @this);
        print("Hello World from MyTestMod!"); 
    }
}

Important Note on Arguments: If the arguments in your custom hook function do not match the arguments in the core game's Hooks::Call, the hook will either fail to execute silently or return an error in the console. Argument matching is mandatory.


Can you create Hooks yourself?

You should be able to yes, especially if you overwrite the base game files you can put hooks everywhere, although this is HIGHLY discouraged.

These files need to be updated every game update, although there have been talking about a community based hooks to make use of hooks in places we want them, there never have been made plans.