The reason you need to return values from HandleEvent() is to tell the engine that you have processed the key event.
You should NOT be implementing anything using the default HandleKeyPress() style system that the 'pause menu' uses in the menu.gsl script. A number of people have suggested implementing game-input doing this on the forums, but it is a bad idea and not recommended at all. The HandleKeyPress() system is for system-wide override's (for like the pause menu etc) but not for gameplay code input handling.
The way that event handling / keypresses works works is basically like this:
1) you define Actions in the input.cfg file. Actions are essentially what the keypress is supposed to do - things like 'MoveForward', 'Crouch', 'Jump' - basically the 'end result' of what the keypress should be interpreted as.
2) you assign KeyMappings to the actions (again, in the input.cfg file). Actions can have multiple KeyMap assignments, so you can define MoveForward as both the 'Up Arrow' and the 'W' key for example.
3) you create a player for your game. Any object in a player's inventory that has a controller script associated with it receives input events, which can either be processed by the object's controller or ignored.
In the HandleEvent() function, there are multiple types of events that get sent.
Input is one of them (triggers are the other big one - ie EnterProximity / ExitProximity events)
So a simple version of the HandleEvent function, is like so:
bool HandleEvent( Object@ object, const String& in event, GameEventParams@ params)
{
if (event == "Input")
{
Print(params.stringValue);
// we handled the event, so return true to let the engine know
return true;
}
// didn't handle the event, return false so other scripts can see if they want to
return false;
}
If you add that statement:
Print( params.stringValue);
to the top of your HandleEvent function (inside the event == "Input' section), you will see output of all the events that are received by the controller.
Note that the above script snippet basically tells you all of the actions that you have defined in the input.cfg file, but not what they are set to. That's what the params.floatValue variable is for:
bool HandleEvent( Object@ object, const String& in event, GameEventParams@ params)
{
if (event == "Input")
{
Print( "Input Action: " + params.stringValue + " value set to: " + params.floatValue);
// we handled the event, so return true to let the engine know
return true;
}
// didn't handle the event, return false so other scripts can see if they want to
return false;
}
In this chunk of script, you will see that your script is receiving all of the actions, and that they are all set to 0.0 by default. If you start pressing keys (that are mapped to the actions), you will see that the states change as keys are pressed.
Basically every action you have defined is sent to the controller script, in whatever state that it is - so if you have an action defined called 'Crouch', the controller script receives that action every time the HandleEvent() function is called - if it's not being pressed, it will be set to 0, if it IS being pressed, it will be greater than 0.
Input events are floats, which allows for analog input devices (gamepads / joysticks), where a button can be 'sort of' pressed ;}
Now that we can see all of the actions that a controller is receiving, then it becomes obvious that we need to start narrowing them down and actually 'catching' some of the events ourselves.
For example, if we have an Action called 'Forward' defined, we add a small section of script to 'catch' that event and process it, like so:
bool HandleEvent( Object@ object, const String& in event, GameEventParams@ params)
{
if (event == "Input")
{
if (params.stringValue == "Forward")
{
// set a variable that remembers what forward was set to
forwardPressed = params.floatValue;
// return true to tell the engine that we handled this event
return true;
}
}
// ignore all of the other events, so let other scripts handle them if they want
return false;
}
Basically using this kind of system, each controller can 'trap' events that they want to handle, and if they ignore them, then the events get sent to the other objects in the player's inventory (or other players) to let them handle the events if desired.
So using the default FPS Template as an example, there are 3 levels of controller that are active usually:
1) the player itself
2) the player object
3) inventory items in the player's inventory (ie weapons etc)
If you look at the weapon script, you'll see that the weapon actually handles the firing of the gun, not the player. This way you can have any number of objects in a player's inventory, and they can each handle their own input events and in essence be very 'self-contained' in how they behave in the game.