Skip to content

Instantly share code, notes, and snippets.

@Silverfeelin
Last active May 23, 2021 22:34
Show Gist options
  • Save Silverfeelin/741fc94df3e93d988a7bf7aa9d6239b9 to your computer and use it in GitHub Desktop.
Save Silverfeelin/741fc94df3e93d988a7bf7aa9d6239b9 to your computer and use it in GitHub Desktop.
Bindings using Mutators in A Hat in Time

Bindings using Mutators

Creating custom key bindings for A Hat in Time

This guide demonstrates how you can use the Mutator class UDK offers to implement custom key bindings. I personally don't know if there is a better way to accomplish this, and I do know this isn't how you're normally supposed to use mutators. Either way, let us begin to create a custom key binding.

This guide does not cover how to create a mod, where to put files, how to compile and other similar tasks. If you do not know this information yet, please refer to different guides first (I.e. Your First Skin Mod).

1. Creating the Mutator

Creating a mutator class is as simple as extending Mutator. Since we'll be reacting to custom mutate commands, we'll also need the Mutate function. You can copy the below function as a base.

Keep in mind that your Mutate function should always call Super.Mutate(...), as seen in the example.

MyMutator.uc:

class MyMutator extends Mutator;

function Mutate(string MutateString, PlayerController Sender)
{
  Super.Mutate(MutateString, Sender);
}

2. Handling Custom Messages

The Mutate function will be called whenever the command mutate ..... is called. What comes after mutate is passed as the MutateString parameter.

A switch allows us to respond only to messages we care about.

class MyMutator extends Mutator;

function Mutate(string MutateString, PlayerController Sender)
{
  switch(Locs(MutateString))
  {
    case "mymessage":
      MyFunction();
      break;
  }

  Super.Mutate(MutateString, Sender);
}

function MyFunction()
{
  `broadcast("My function executed.");
}

As the above code makes use of Locs (lowercase), the mutate command can be entered case-insensitive.

3. Enabling the Mutator

This is where we deviate from actual mutators. As AHiT doesn't have a mutator selection menu, we have to improvise.

Keep in mind that the GameMod classes can be used to accomplish a lot of the things mutators can do. This is why we're only looking at mutators for bindable actions (using the Mutate function)!

3.1 GameMod Class

To enable the mutator in-game, we'll be adding the mutator from our GameMod. So first, let's create a GameMod class.

MyMutatorMod.uc:

class MyMutatorMod extends GameMod
	config(Mods);

var MyMutator mutator;

event OnModLoaded() {}
event OnModUnloaded() {}

3.2 Adding the Mutator

Now, we have to add the mutator to the world info, allowing the Mutate function to be called. This also differs from the normal implementation, because normally the code adds a mutator from a string (mutator class name), but that makes it more difficult to destroy the mutator when the mod is unloaded.

MyMutatorMod.uc:

class MyMutatorMod extends GameMod
	config(Mods);

var MyMutator mutator;

event OnModLoaded()
{
  local WorldInfo wi;
  wi = class'WorldInfo'.static.GetWorldInfo();

  mutator = Spawn(class'MyMutator');

  if (wi.Game.BaseMutator == None)
    wi.Game.BaseMutator = mutator;
  else
    wi.Game.BaseMutator.AddMutator(mutator);
}

event OnModUnloaded()
{
  mutator.Destroy();
}

4. Key Bindings

Note: In this example we're assigning a binding to a key without checking for any previous bindings. This may make other actions inaccessible, since users can not bind actions in-game yet! Please don't use commonly used keys (I.e. WASD).

At this point you should have a working mutator, that is loaded and unloaded by the GameMod class. You can test if your Mutate function works by using mutate in the console (I.e. mutate MyMessage).

The last step is to bind a key to your message. We can do this in the GameMod class as well.

Note the difference between '' and "". The function SetBind expects a Name for the key, and a string for the command. There's a slight difference between these two types, but to keep it simple: Use '' for names and "" for strings.

You also need to put your key in a variable, you can not put 'NumPadOne' directly in the SetBind function. This has to do with the function expecting an out parameter for.. reasons.

MyMutatorMod.uc:

class MyMutatorMod extends GameMod
	config(Mods);

var MyMutator mutator;

event OnModLoaded()
{
  local WorldInfo wi;
  local Hat_PlayerController pc;
  local Name npOne;

  wi = class'WorldInfo'.static.GetWorldInfo();
  pc = Hat_PlayerController(GetALocalPlayerController());
  npOne = 'NumPadOne';

  // Set Mutator
  mutator = Spawn(class'MyMutator');

  if (wi.Game.BaseMutator == None)
    wi.Game.BaseMutator = mutator;
  else
    wi.Game.BaseMutator.AddMutator(mutator);

  // Set binding
  pc.PlayerInput.SetBind(npOne, "mutate MyMessage");
}

event OnModUnloaded()
{
  mutator.Destroy();
}

5. The Result

The sample code will log a message whenever you hit NumPadOne (assuming you have NumLock on). If your bindings don't work, try disabling and enabling the mod, see if your code differs from the sample code, and see if the binding is not overridden by another mod or the game itself.

You should be able to find the key binding in \HatinTime\HatinTimeGame\Config\HatinTimeInput.ini:

Bindings=(Name="NumPadOne",Command="mutate MyMessage",Control=False,Shift=False,Alt=False,bIgnoreCtrl=False,bIgnoreShift=False,bIgnoreAlt=False)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment