| Home Page | Recent Changes | Preferences

Input Keys

So its time to create a class that requires the user to press a key? You've come to the right place. I'll walk you through the steps here.

Step 1: Setting up the Key Binding

This is the easiest step. Start by creating a new class, something like ExtraWordBindings (please replace Word with something descriptive, thanks!) and make it look something like this:

Class ExtraWordBindings extends UTExtraKeyBindings;

defaultproperties
{
     SectionName="YourSection" // Enter a descriptive section name here
     LabelList(0)="First Binding Caption" // Something Descriptive, Please.
     LabelList(1)="Second Binding Caption"
     AliasNames(0)="mutate Word" // Change Word to something that describes the action this key will do
     AliasNames(1)="mutate Word"
}

Compile the script and now you should have a working option in the "Controls" option panel.

Step 2: Creating the mutator to process your key input

Okay now you can use one mutator to parse all your key bindings, or one mutator for each binding. I like one mutator for each binding, because these mutators should be automatically added into the mutatorlist if the associated actor is present in the map. DO NOT CREATE AN INT ENTRY FOR THESE MUTATORS!

They should look something like this. (Once again, PLEASE replace "Word" with something DESCRIPTIVE!)

class WordKeyMut extends Mutator;

function AddMutator(Mutator M)
{
    if ( M.IsA('WordKeyMut') ) // This mutator's name!
    {
        return; //only allow one mutator
    }
    Super.AddMutator(M);
}

function Mutate(string MutateString, PlayerPawn Sender)
{
    local YourClass Other; // YourClass will be the name of the class that we
                               // will create in the next step - the actual actor 
                               // that this mutator is processing key input for.

    if (MutateString ~= "SomeString") // SomeString should be equal to an AliasName set in the class above,
                                          //without "mutate".  i.e., if your AliasName was "mutate Activate",
                                          //SomeString should be "Activate"
    {
        foreach AllActors(class'YourClass', Other)
        {
            if ( Other.IsA('YourClass') )
            {
                log("YourClass Detected");
                if ( Other.BooleanValue ) // Change BooleanValue to a descriptive variable name!
                                                          // It will be set in the class we will create in the next
                                                          // step, to see if the actor is actually in a state that
                                                          // it can be activated.
                {
                    log("YourClass Active");
                    Other.FunctionName( ); // Change FunctionName to something descriptive!
                                                               // It will be created in the next step as well,
                                                               // and it will contain everything we want to happen
                                                               //when the user presses a key.

                }
            }
        }

    }

    if ( NextMutator != None )
        NextMutator.Mutate(MutateString, Sender);
}

Step 3: Creating your actor!

Create your map actor as you otherwise would create any other map actor. How to create them is beyond the scope of this article. Once its created, you want to add the following near the beginning of the class:

function PreBeginPlay()
{
    Level.Game.BaseMutator.AddMutator(Spawn(class'Package.Mutator')); // Replace Package with your package name,
                                                                          // and Mutator with the name of the mutator
                                                                          // we created above.
    Super.PreBeginPlay();
}

Right at the very beginning, define a boolean variable called whatever you replaced "BooleanValue" with in the class above. You may also want another variable (as an Actor), to store who is allowed to actually activate the object.

Now you code a function with its name set to whatever you made "FunctionName", which will be what you want to happen when a player activates the object. You will also need to put in the code to set your boolean to true when someone is allowed to activate it.

Now you're set! Below is an example of what I've done, to create a trigger that requires the user to activate it before use.

My Working (we hope) Example!

Here is the trigger class, it works like any other trigger:

//=============================================================================
// UseTrigger:  Almost identical to Trigger except requires user to press
// activate to spawn the event.
// By Nick Bowler (Draconx), http://www.deadjunkie.com/~draconx/
//=============================================================================
class UseTrigger extends Trigger;

//-----------------------------------------------------------------------------

var bool Activatable;
var Actor ActivatedBy;
var Actor OtherBkp;

//=============================================================================

function PreBeginPlay()
{
    Level.Game.BaseMutator.AddMutator(Spawn(class'Package.ActivateMut'));
    Super.PreBeginPlay();
}

//
// Called when something touches the trigger.
//
function Touch( actor Other )
{
    if (Other.IsA('PlayerPawn'))
    {
        log("UseTrigger Activated");
        OtherBkp = Other;
        Activatable = true;
    }
}

function UsePressed( )
{

    log("UseTrigger Used");
    Super.Touch( OtherBkp);

}

//
// When something untouches the trigger.
//
function UnTouch( actor Other )
{
    if (Other.IsA('PlayerPawn'))
    {
        log("UseTrigger Deactivated");
        Activatable = false;
    }
}

defaultproperties
{
    Activatable=false
}

Here is the mutator which processes the key input:

//=============================================================================
// ActivateMut - Required for UseTrigger to function correctly.  Placing a
// UseTrigger in your map automatically adds this mutator, so it should not
// be added manually.
// By Nick Bowler (Draconx), http://www.deadjunkie.com/~draconx/
//=============================================================================
class ActivateMut extends Mutator;

function AddMutator(Mutator M)
{
    if ( M.IsA('ActivateMut') )
    {
        return; //only allow one mutator
    }
    Super.AddMutator(M);
}

function Mutate(string MutateString, PlayerPawn Sender)
{
    local UseTrigger Other;

    if (MutateString ~= "activate")
    {
        foreach AllActors(class'UseTrigger', Other)
        {
            if ( Other.IsA('UseTrigger') )
            {
                log("UseTrigger Detected");
                if ( Other.Activatable )
                {
                    log("UseTrigger Active");
                    Other.UsePressed( );

                }
            }
        }

    }

    if ( NextMutator != None )
        NextMutator.Mutate(MutateString, Sender);
}

And here is the class which adds to the keybindings:

class UseTriggerBindings extends UTExtraKeyBindings;

defaultproperties
{
     SectionName="Miscellaneous"
     LabelList(0)="Activate"
     AliasNames(0)="mutate activate"
}

And there you have it. I hope you found this tutorial useful!


Foxpaw: This is a clever workaround, but wouldn't exec functions/input variables be more elegant and easier, too?

Wormbo: Exec functions can only be executed by the player who is the owner of the actor and I don't see how input variables would work in this case.

Foxpaw: Don't mutators have full access to exec functions and input variables for the local viewport?

Wormbo: No, mutators are serverside. They only have a Mutate function which is called by the PlayerController's exec function Mutate which in turn is always replicated to the server.

Foxpaw: Oh. I thought mutators were loaded on both the client and the server and followed the normal replication rules.

Wormbo: They follow replication rules, that's why they aren't replicated at all unless you change RemoteRole, bAlwaysRelevant, etc.

ToJo: Does anyone know if there is a simplier way to do this in UT 2003?

Foxpaw: An interaction should work.


Category Tutorial

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Image Uploads

Random Page

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

Mapping Topics

Mapping Lessons

UnrealEd Interface

Questions&Answers

Scripting Topics

Scripting Lessons

Making Mods

Class Tree

Questions&Answers

Modeling Topics

Questions&Answers

Log In