Difference between revisions of "Classmaps"

From Heroes of Hammerwatch wiki
Jump to: navigation, search
(Created page with "Classmaps can be used by mods to hook into class instantiation from scripts and engine by dynamically changing the type of the class that is being instantiated. This means tha...")
 
 
Line 30: Line 30:
 
     // function here:
 
     // function here:
 
     //
 
     //
     //  Player::Damage(dmg, pos, dir);
+
     //  return Player::Damage(dmg, pos, dir);
 
   
 
   
 
     return 0;
 
     return 0;

Latest revision as of 14:41, 15 March 2019

Classmaps can be used by mods to hook into class instantiation from scripts and engine by dynamically changing the type of the class that is being instantiated. This means that certain classes can be inherited from with your own code, potentially having to avoid overwriting a file.

Definitions for classmaps exist within info.xml, and range from 3 different types of mappings:

  • Behaviors: Classes that are used as behaviors on units, such as Player, CompositeActorBehavior, Pickup, etc.
  • Gamemodes: Classes that are gamemodes, such as RandomLevel, Town, BossLevel, etc.
  • Scripts: Classes instantiated in scripts via InstantiateClass, such as modifiers, actions, effects, movements, skills, upgrades, shops, interfaces, etc.

You define a mapping by providing 2 class names, a "from" name and a "to" name. For example, to map the Player class to your own MyPlayer class, you would put this in your info.xml file:

<dict name="classmaps">
  <array name="behaviors">
    <array><string>Player</string><string>MyPlayer</string></array>
  </array>
</dict>

We use the behaviors mapping here because Player is a unit behavior. Typically, when you make class mappings, you'll want to inherit from the original class in order to change or add code. For example, in the above example of the custom player class, we can make the player never take any damage by overriding the Damage function:

class MyPlayer : Player
{
  MyPlayer(UnitPtr unit, SValue& params)
  {
    super(unit, params);
  }

  int Damage(DamageInfo dmg, vec2 pos, vec2 dir) override
  {
    // Just return 0! If we did want to do damage and just
    // wanted to use this as a hook, we could call the base
    // function here:
    //
    //   return Player::Damage(dmg, pos, dir);

    return 0;
  }
}

Note that the constructor there is required (as well as the super call inside of it) in order for the class to properly be instantiated.