Detecting Keypress / Action

Discussions about Coding and Scripting
1337GameDev
Skilled
Posts: 198
Joined: Thu Apr 16, 2020 3:23 pm
Personal rank: GameDev

Detecting Keypress / Action

Post by 1337GameDev »

I am wanting to detect a key press / a bound action being triggered -- most notable the "use" action.

I do see "some" mentions of hints in TrainingDM.uc on the following lines:

[Line 15]

Code: Select all

var string KeyAlias[255];
[Line 114]

Code: Select all

function LoadKeyBindings(PlayerPawn P)
{
	local int i;
	local string k;

	for (i=0; i<255; i++)
	{
		k = P.ConsoleCommand( "KEYNAME "$i );
		KeyAlias[i] = P.ConsoleCommand( "KEYBINDING "$k );
	}
}
[Line 252]

Code: Select all

function DMTutEvent4()
{
	local int i;
	local string Message;
	local string ForwardKey, BackKey, LeftStrafeKey, RightStrafeKey;

	for (i=0; i<255; i++)
	{
		if (KeyAlias[i] ~= "MoveForward")
		{
			if (ForwardKey != "")
				ForwardKey = ForwardKey$","@class'UMenuCustomizeClientWindow'.default.LocalizedKeyName[i];
			else
				ForwardKey = class'UMenuCustomizeClientWindow'.default.LocalizedKeyName[i];
		}
		if (KeyAlias[i] ~= "MoveBackward")
		{
			if (BackKey != "")
				BackKey = BackKey$","@class'UMenuCustomizeClientWindow'.default.LocalizedKeyName[i];
			else
				BackKey = class'UMenuCustomizeClientWindow'.default.LocalizedKeyName[i];
		}
		if (KeyAlias[i] ~= "StrafeLeft")
		{
			if (LeftStrafeKey != "")
				LeftStrafeKey = LeftStrafeKey$","@class'UMenuCustomizeClientWindow'.default.LocalizedKeyName[i];
			else
				LeftStrafeKey = class'UMenuCustomizeClientWindow'.default.LocalizedKeyName[i];
		}
		if (KeyAlias[i] ~= "StrafeRight")
		{
			if (RightStrafeKey != "")
				RightStrafeKey = RightStrafeKey$","@class'UMenuCustomizeClientWindow'.default.LocalizedKeyName[i];
			else
				RightStrafeKey = class'UMenuCustomizeClientWindow'.default.LocalizedKeyName[i];
		}
	}

	TutorialSound(DM[4]);
	Message = TutMessage4Parts[0]@"["$ForwardKey$"]"@TutMessage4Parts[1]@"["$BackKey$"]"@TutMessage4Parts[2]@"["$LeftStrafeKey$"]"@TutMessage4Parts[3]@"["$RightStrafeKey$"]"$TutMessage4Parts[4];
	TournamentConsole(Trainee.Player.Console).AddMessage(Message);
	SoundIndex++;
}
I'm unsure if this is correct for what I want, or how this is to be used. It seems fragile and not entirely clear what's going on. I have sene in other threads about detecting a PlayerPawn's keypress, and needing to add a Console subclass or keyevent alias in a config (which will inevitably fail ant anti-cheat).

I'm unsure of the exact way to do what I want.
User avatar
ExpEM
Adept
Posts: 298
Joined: Wed Nov 09, 2016 1:48 am

Re: Detecting Keypress / Action

Post by ExpEM »

As no one has responded I'll see what I can do to help.
First off, by 'Use Action' I'm guessing you are referring to the 'grab' key.
Second, the code you have posted here is used to get the human readable names of the keys to display in the tutorial text.

So, what is it you want to do?
You can probably do it with a Mutator. See the code for Relics, specifically, the TossRelic button as an example.

If you really want to get complex and over ride an existing button then you will most likely have to create a custom PlayerPawn which is a whole other hurdle.
Signature goes here.
1337GameDev
Skilled
Posts: 198
Joined: Thu Apr 16, 2020 3:23 pm
Personal rank: GameDev

Re: Detecting Keypress / Action

Post by 1337GameDev »

Hmm, I simply want to have a callback whenever the user presses the key that's bound to the "Use Action."

That code does make more sense now, I knew it was relevant somehow. How does the tutorial "hook" into these events when a user presses those?

I don't want to make a new playerpawn, just invoke a function whenever the player performs "Use action" regardless of what key they have bound to that.
User avatar
ExpEM
Adept
Posts: 298
Joined: Wed Nov 09, 2016 1:48 am

Re: Detecting Keypress / Action

Post by ExpEM »

I had a squiz at the code for TrainingDM and it doesn't actually check that one presses keys, it fakes it. E.G. to test if you jump it just checks that the players height has changed so you an fake it by running on a slope.
I'm still unsure exactly what you are referring to as the 'Use Action' as that isn't a key that exists in UT. The closest that comes to mind is either the 'Grab' key that is unused or the 'ActivateInventory' key which is only used in Unreal.

If you are wanting to make a new key and keybind then that makes things nice and easy, you can make a sub class of the UTExtraKeyBindings Object.
When a key is pressed it gets sent to a few actors in game (working off of memory from years ago here so forgive me if I'm wrong). The Actors that check for it are: GameType, PlayerPawn, Inventory?, Mutator and the Console object.
Sorry I don't remember what order they are called in...
You can use the MutateString function to check when the key is pressed.

If you want to intercept an existing key then again things get more difficult.

To help me help you, open your console, type "preferences" and a window will open, expand 'Advanced', expand 'Raw Key Bindings'. Then find the key that you use as the 'Action Key', if you could tell me what it says in the right hand column next to it then I'll know exactly what key you are talking about to advise you further.
Signature goes here.
1337GameDev
Skilled
Posts: 198
Joined: Thu Apr 16, 2020 3:23 pm
Personal rank: GameDev

Re: Detecting Keypress / Action

Post by 1337GameDev »

Ahhhh, you're correct. There is no "Use" that I thought existed...

Well, there seems to be a "Other / Misc" in "Preferences -> Controls" menu.
This has:
Use Holdable
Use Selected Item

Hmm, how would these be detected?

Do you have an example (eg: a filename+line number) of a piece of code that uses some kind of control detection?
I'll look in the chaos relics to see, but curious if you have an example of what you are talking about in terms of "MutateString."

Edit: Hmm, i find an example in Relic.uc - Line: 66
Would I care to detect a key directly, or just listen for these bindings to be safe and give player control over bindings?

I also found this:

Code: Select all

class ExtraRelicsBindings expands UTExtraKeyBindings;

defaultproperties
{
     SectionName="Relics"
     LabelList(0)="Toss Relic"
     AliasNames(0)="mutate tossrelic"
}
I'm assuming this is what generates the key binding option in the preferences menu. Is this correct? Can this be customized for any unique binding?
User avatar
sektor2111
Godlike
Posts: 6410
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Detecting Keypress / Action

Post by sektor2111 »

I must ask if this work worth efforts. User might have a key bound for such a command:
- exec rabbit
In which "rabbit" it's a name of a file having multiple commands called there. You cannot actually see what "rabbit" file does.

Also good luck with hunting keys when user will do a separate injection for a radar and having nothing bound on the keys.
It's why I did not answered anything but... in my opinion, except logging player's keys I don't think it worth wasting weeks here... If I well recall Kelly has such a small tool reporting key binds used by player. I don't think it's helpful as long as I read in a game chat-log: "it's time for remapping keys" - lol.
Dennis
Average
Posts: 72
Joined: Tue Jan 12, 2021 9:18 pm

Re: Detecting Keypress / Action

Post by Dennis »

<deleted>
Last edited by Dennis on Sun Feb 21, 2021 3:22 pm, edited 1 time in total.
Fraggers hangout place: http://fraggers.online/
User avatar
sektor2111
Godlike
Posts: 6410
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Detecting Keypress / Action

Post by sektor2111 »

Re-Read first line from his first post.
User avatar
ExpEM
Adept
Posts: 298
Joined: Wed Nov 09, 2016 1:48 am

Re: Detecting Keypress / Action

Post by ExpEM »

1337GameDev wrote: Sat Feb 20, 2021 7:56 am Well, there seems to be a "Other / Misc" in "Preferences -> Controls" menu.
This has:
Use Holdable
Use Selected Item
Hmm, I am missing these from my installation so I'm guessing they are from a mod. Any idea which one?
1337GameDev wrote: Sat Feb 20, 2021 7:56 am

Code: Select all

class ExtraRelicsBindings expands UTExtraKeyBindings;
defaultproperties
{
     SectionName="Relics"
     LabelList(0)="Toss Relic"
     AliasNames(0)="mutate tossrelic"
}
I'm assuming this is what generates the key binding option in the preferences menu. Is this correct? Can this be customized for any unique binding?
Your assumption is correct, this is the class that allows you to bind a custom key, in this case "Mutate tossrelic".

If you look at this code:

Code: Select all

relics.Relic
function Mutate(string MutateString, PlayerPawn Sender)
{
	local Inventory S;

	if (MutateString ~= "TossRelic")
	{
		S = Sender.FindInventoryType(RelicClass);
		if (S != None)
		{
			RelicInventory(S).DropInventory();
			Sender.DeleteInventory(S);
		}
	}

	if ( NextMutator != None )
		NextMutator.Mutate(MutateString, Sender);
}
This line is the hook:

Code: Select all

	if (MutateString ~= "TossRelic")
Now, this wont work for default keys. Only keys created from UTExtraKeyBindings which use the 'mutate' substring will be recognised by the mutate function.

/////////////////////////////////////////////////////////////////////////

Working on the assumption that 'Use Holdable' and 'Use Selected Item' are LableList[x] names from a subclass of UTExtraKeyBindings (aka from a mod) then we can really get somewhere.
ExpEM wrote: Sat Feb 20, 2021 5:04 am To help me help you, open your console, type "preferences" and a window will open, expand 'Advanced', expand 'Raw Key Bindings'. Then find the key that you use as the 'Action Key', if you could tell me what it says in the right hand column next to it then I'll know exactly what key you are talking about to advise you further.
Doing this from your console is an important step here, the preferences command and preferences menu are two different things.

You need to find the exact name of the key command you want to hook.
Under 'Raw Key Bindings' find the binding you are using, on the right hand side it will have the 'key command'.

Code: Select all

Example:
-Advanced
 +File System
 +Game Engine Settings
 +Key Aliases
 -Raw Key Bindings
  -[P] | TossRelic
Have a look under 'Key Aliases' while your doing that and look for the 'Key command' you just found.
Note: The 'Key command' may not have an associated Alias.

Code: Select all

Example:
-Advanced
 +File System
 +Game Engine Settings
 -Key Aliases
  -Aliases
   -[x] | (Command="mutate tossrelic", Alias=TossRelic)
    -Alias | TossRelic
    -Command | mutate tossrelic 
 +Raw Key Bindings
What we are hoping to see here is that my assumption is correct that the keys your listing are from a mod and will have "mutate" in the command string.
Because if that is the case all you have to do is write a simple mutator and using the mutate function listen for the Alias(s). (Re: relics.Relic code).

/////////////////////////////////////////////////////////////////////////

If my assumption is wrong then I need you to list what the 'Key command' is and if it has an Alias then list that too please.
That way we can track down what class we need to mess with to do what you want.
Signature goes here.
1337GameDev
Skilled
Posts: 198
Joined: Thu Apr 16, 2020 3:23 pm
Personal rank: GameDev

Re: Detecting Keypress / Action

Post by 1337GameDev »

Hmm, I see what you're talking about in the menu. I don't see a binding for the

Code: Select all

Use Holdable

Code: Select all

Use Selected Item
aliases or in raw key bindings....
I grepped for those words from the ROOT of the Ut99 install folder, and found no matches...

Odd....
Hmm.

But I do see Grab, bound to the "G" key, which could be a base command in UT99? Maybe the alias "InventoryActivate" for the command "ActivateItem"? Is this a base ut99 alias / command i could hook to? What would be matched against if I made my own Mutate method in a muator, for this "mutate string" comparison?

In the end, I would like my mutator to be code instantiated via a map's MyLevel actor package, to provide a unique experience.

Hmm, they wouldn't have a key alias if they just downloaded the map / joined a server.... Hmm....

Which is why I just wanted to detect a key, and just "assumed" it was "acceptable" even if it did something else for the user (to simply things). I could also use this tactic for detecting player actions around actors -- eg: pressing jump, so trigger something on the map, etc.

I did find the following key alias, but it doesn't seem to be bound:
InventoryActivate (Command: ActivateItem)
activateitem.png
activateitem.png (8.1 KiB) Viewed 705 times
User avatar
ExpEM
Adept
Posts: 298
Joined: Wed Nov 09, 2016 1:48 am

Re: Detecting Keypress / Action

Post by ExpEM »

1337GameDev wrote: Thu Feb 25, 2021 6:38 am But I do see Grab, bound to the "G" key, which could be a base command in UT99?
The grab functionality is implemented through the PlayerPawn class, while you could force your own PlayerPawn to be used I don't recommend it.
1337GameDev wrote: Thu Feb 25, 2021 6:38 am Maybe the alias "InventoryActivate" for the command "ActivateItem"? Is this a base ut99 alias / command i could hook to? What would be matched against if I made my own Mutate method in a muator, for this "mutate string" comparison?
InventoryActivate would be an excellent choice as you can hook it from a custom inventory actor, you can also hook into the jump key using inventory.
InventoryActivate is bound to 'Enter' by default. And shouldn't mess with default UT pickups.

So let us work with this as an idea.
-Inventory class hooking into jump and or InventoryActivate.
-Mutator class to give players said Inventory.
-Actor class to embed mutator into map.

In Inventory we have two functions to play with.
To hook jump:

Code: Select all

//
// Used to inform inventory when owner jumps.
//
function OwnerJumped()
{
	if( Inventory != None )
		Inventory.OwnerJumped();
}
And to hook InventoryActivate (Enter):

Code: Select all

//
// Toggle Activation of selected Item.
// 
function Activate()
{
	if( bActivatable )
	{
		if (Level.Game.LocalLog != None)
			Level.Game.LocalLog.LogItemActivate(Self, Pawn(Owner));
		if (Level.Game.WorldLog != None)
			Level.Game.WorldLog.LogItemActivate(Self, Pawn(Owner));

		if ( M_Activated != "" )
			Pawn(Owner).ClientMessage(ItemName$M_Activated);	
		GoToState('Activated');
	}
}
Playing around with either of these functions shouldn't be too hard, to hook InventoryActivate you may need your inventory to be the selected class which wouldn't be hard to force with some horribly hacky code.
I haven't looked into this much but I'll happily look into it if you get stuck.

////////////////////////////////////

Next, the mutator.
All you need is a simple class to add the inventory to players when they respawn.
Have a look at the code for the Stealth mutator for how to do this.

////////////////////////////////////

Last of all to embed a mutator is easy todo, this is code I have used in one of my maps.

Code: Select all

class AddImpactMut expands Actor;

Function BeginPlay()
{
	Local Mutator M;

	M = Spawn(Class'ImpactArena');
	Level.Game.BaseMutator.AddMutator(M);
	Destroy();
}
That is the entire class, nice and easy. Just pop it somewhere in your level and call your own mutator with it.
Signature goes here.
1337GameDev
Skilled
Posts: 198
Joined: Thu Apr 16, 2020 3:23 pm
Personal rank: GameDev

Re: Detecting Keypress / Action

Post by 1337GameDev »

ExpEM wrote: Fri Feb 26, 2021 11:38 pm
1337GameDev wrote: Thu Feb 25, 2021 6:38 am But I do see Grab, bound to the "G" key, which could be a base command in UT99?
The grab functionality is implemented through the PlayerPawn class, while you could force your own PlayerPawn to be used I don't recommend it.
1337GameDev wrote: Thu Feb 25, 2021 6:38 am Maybe the alias "InventoryActivate" for the command "ActivateItem"? Is this a base ut99 alias / command i could hook to? What would be matched against if I made my own Mutate method in a muator, for this "mutate string" comparison?
InventoryActivate would be an excellent choice as you can hook it from a custom inventory actor, you can also hook into the jump key using inventory.
InventoryActivate is bound to 'Enter' by default. And shouldn't mess with default UT pickups.

So let us work with this as an idea.
-Inventory class hooking into jump and or InventoryActivate.
-Mutator class to give players said Inventory.
-Actor class to embed mutator into map.

In Inventory we have two functions to play with.
To hook jump:

Code: Select all

//
// Used to inform inventory when owner jumps.
//
function OwnerJumped()
{
	if( Inventory != None )
		Inventory.OwnerJumped();
}
And to hook InventoryActivate (Enter):

Code: Select all

//
// Toggle Activation of selected Item.
// 
function Activate()
{
	if( bActivatable )
	{
		if (Level.Game.LocalLog != None)
			Level.Game.LocalLog.LogItemActivate(Self, Pawn(Owner));
		if (Level.Game.WorldLog != None)
			Level.Game.WorldLog.LogItemActivate(Self, Pawn(Owner));

		if ( M_Activated != "" )
			Pawn(Owner).ClientMessage(ItemName$M_Activated);	
		GoToState('Activated');
	}
}
Playing around with either of these functions shouldn't be too hard, to hook InventoryActivate you may need your inventory to be the selected class which wouldn't be hard to force with some horribly hacky code.
I haven't looked into this much but I'll happily look into it if you get stuck.

////////////////////////////////////

Next, the mutator.
All you need is a simple class to add the inventory to players when they respawn.
Have a look at the code for the Stealth mutator for how to do this.

////////////////////////////////////

Last of all to embed a mutator is easy todo, this is code I have used in one of my maps.

Code: Select all

class AddImpactMut expands Actor;

Function BeginPlay()
{
	Local Mutator M;

	M = Spawn(Class'ImpactArena');
	Level.Game.BaseMutator.AddMutator(M);
	Destroy();
}
That is the entire class, nice and easy. Just pop it somewhere in your level and call your own mutator with it.
Hmm, i like this idea and tried to implement it. In the game's preferences for controls, what is the command for activating the selected item?

Also, i am curious how to set an inventory item as selected for a given Pawn / PlayerPawn....

I see M_Selected, but is simply a localized name for an Inventory item it seems.
Hmm....

And is the proper way to ensure the Inventory item never is dropped, is to override the DropFrom and BecomePickup methods, and essentially make them empty?
User avatar
sektor2111
Godlike
Posts: 6410
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Detecting Keypress / Action

Post by sektor2111 »

Inventory is dropped when Pawn dies, unless you want to stack multiple copies each time when Pawn dies and respawns and then it will be needed a check for this inventory to not mess with it multiple times...
1337GameDev
Skilled
Posts: 198
Joined: Thu Apr 16, 2020 3:23 pm
Personal rank: GameDev

Re: Detecting Keypress / Action

Post by 1337GameDev »

sektor2111 wrote: Sat Mar 20, 2021 7:30 am Inventory is dropped when Pawn dies, unless you want to stack multiple copies each time when Pawn dies and respawns and then it will be needed a check for this inventory to not mess with it multiple times...
Yup, I use Pawn.FindInventoryOfType to check for an instance, before spawning and calling Pawn.AddInventory.

So dupes shouldn’t be an issue. I just want to stop the item from being dropped. Do I merely call destroy in these methods instead?

And what action in ut99 inputs will activate an item?
User avatar
sektor2111
Godlike
Posts: 6410
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Detecting Keypress / Action

Post by sektor2111 »

I would pay attention to not break Inventory chain - that's another linked list...

Key for activating an item goes somewhere in keys menu assignment - now, I don't know if I have bound something there because... usually I don't play games requiring this function...
Post Reply