[.NET] [C#] [SHVDN] Modding Basics! What is OnTick? [Part 2]
Hello guys, its me and I'm back with another tutorial for you guys. I know its been a while, but well I was busy working with another guy in the development of Grand Theft Space but now I got some free time so I can write this tutorial!
Knowledge of the last tutorial
What we'll do in this part
What is OnTick?
How to use OnTick?
Why to use OnTick?
What is OnTick?
OnTick is basically an even that gets triggered at an interval you can set, if you don't it runs each frame. If you want to set an interval, this is how you do it:
Keep in mind that nearly everything time-related in SHVDN is in milliseconds, and this is no exception. Now, everything in the OnTick method runs each second.
Why to use OnTick?
OnTick is used for functions that have to be called each frame, like Game.DisableAllControlsThisFrame. It can also be used for functions like "Never Wanted" or other functions that require logic real-time.
How to use OnTick?
In our script, we'll be developing a simple Never Wanted feature. We have already coded a function to set our wanted levels to 0, but what about never worrying to get a star ever again?
To start, we should make a boolean that gets toggled when we press our key:
In our OnKeyDown event we can toggle our bool if the key pressed is L(Keep in mind you can change these keys, they're not meant to be only L or J):
And in our OnTick method we can check if the bool is true:
If it is, set our wanted level to 0!
That's it, that is how you use the event OnTick! In the next tutorial we'll see how we can create vehicles and manipulate them, and also look at vector math. Until then, bye.
Note:- Yes I know this was a relatively small tutorial but we need to cover the basics before we step into the good stuff. Don't worry, I have a lot in store for you, like Particle FX, Animations, (maybe..?) custom vehicles and heck, even how to show you how to make custom models using GIMS EVO!
@GTAVModder4Life since a few days i know i have to write the interval above tick, keydown and so on and now i know if i want something in a loop i do this with ontick but one thing is new THIS.keyDown. why you write it in front of KeyDown? has this any effect or is it like "public void" and you can just use it without "public"? what i am really happy about is to see the "Game.DisableAllControlsThisFrame" part. till now i have engaged only with vehicle natives. done a few other things but not really involved with that. but i wanted this function in a few of my scripts. so if i write "Game.DisableAllControlsThisFrame = !Game.DisableAllControlsThisFrame" you cant do anything ingame or lets say when i am in my menu the phone doesnt pop up when i move upward? also for my all lights on key the brakelights get on for a second but i want all lights permanently on, so i have to put this in onTick?
@TobsiCred lelele i remember i got stuck for like 2 hours cos I was used to python where time module counts everything in seconds
@TobsiCred putting "this." doesnt really do much difference here, I forgot to remove that part in the screenshot. But oh well
About Game.DisableAllControlsThisFrame it is a method and takes an index as a parameter. Now from testing people discovered this was 2, so the code would be Game.DisableAllControlsThisFrame(2);
And yes it wont let you do anything ingame.
About the lights you may require them in the ontick function, you know, test for a bit, see what works
@GTAVModder4Life perfect, everything works
You don't need to subscribe to both the KeyDown event and the KeyUp event. Decide for either one. I recommend the KeyUp event because it's more reliable on key combinations.
Don't attach an empty event handler method to an event. That makes absolutely no sense. I know you didn't do that in your examples here. I'm just saying because I have seen this several times in the code of other people.
The key filter is insufficient. It does not differentiate between L, Shift+L, Ctrl+L, Alt+L or any combination of these. A correct key filter looks like this:
if(e.KeyCode == Keys.L && !e.Alt && !e.Ctrl && !e.Shift)
Maybe you ask why it is important to query such bool properties for being false. The simple reason is that we only have a low amount of keys on the keyboard but a huge load of mods which need keyboard input. If one waits for L and the other for Shift+L and one or both have no proper key filtering you end up with a conflict!
For performance reasons one should only subscribe to the Tick event if actually needed.
Avoid accidental multiple subscriptions of the same event handler to the Tick event. This can easily happen, especially when the code grows bigger. Simply avoid this with the help of a bool field, like this:
private bool _onTickAttached;
private void SomeMethod(...)
Tick += OnTick;
_onTickAttached = true;
private void AnotherMethod()
Tick -= OnTick;
_onTickAttached = false;
You don't need to subscribe to both the KeyDown event and the KeyUp event.
That's not entirely true if you need to manage key-held states, which would be initiated by the KeyDown event. KeyUp is fine for press & release events but no good for detecting key-held, or simultaneous presses that don't have simultaneous releases.
KeyUp and KeyDown provide different functionality, which is why they are separate events. The biggest danger with KeyDown is that the key repeat can fire off multiple event triggers, which is why I personally use KeyUp... it can't repeat.
Shift, Control and Alt are also Modifiers and should be detected as such with
if(e.KeyCode == Keys.L && e.Modifiers == Keys.Shift)etc... They're not a key-press event in the strictest sense, they are more of a keyboard state.
@LeeC2202 About using both key events: of course you are right in that case. However I had those mods in mind which attach both events and one of them to an empty handler (relates to my point 2). I should have made this more clear. My bad.
About the keyboard state: Why is
e.Modifiers != Keys.Shiftbetter than
!e.Shift? In the MSDN library we can read the following remark: "To determine whether a specific modifier key was pressed, use the Control, Shift, and Alt properties. Modifier flags can be combined with bitwise OR.". So if I want to query a combination of Shift, Ctrl and/or Alt I'd need to filter the Modifiers property through a bitwise OR operation instead of simply querying KeyEventArgs.Shift and so on.
@Cyron43 If you use e.Shift, you are detecting that keypress at that moment in time, so if you press Shift slightly early, or late, it doesn't register in the event. Because modifiers are a state change, they register and stay active, as long as the key is held.
If you think of the way you normally treat the Shift key (or Control and Alt), you press and hold it, then press the secondary key.
Edit: If you wanted to test for someone pressing the Shift key as an action, then you would use e.Shift... or at least that's the way I have always handled it.
@LeeC2202 That makes sense. Thank you.
However, what you described is exactly the reason why I always use the KeyUp event as it recognizes the key combination at the time the user releases the keys. I can imagine that someone (hypothetically) releases the keys not simultaneously. What if he releases the Shift-key first? The KeyUp event would fire (right?) but wouldn't the Modifier-property return "None" (or whatever gets returned in that case)? I admit I have never used the Modifier-property in my profession but you gave me a reason to have a closer look at it.
@Cyron43 The modifier is generally a KeyDown related property. It is designed to be there before a keypress, so yeah, releasing Shift first would trigger the KeyUp event but in theory, you have already dealt with the Modifier + Keys combo in the KeyDown.
It probably all harks back to the days when mechanical typewriters actually made a physical change to the mechanism when the shift lever was pressed. So it quite literally modified the state of the typewriter.
@Cyron43 ...but in theory, you have already dealt with the Modifier + Keys combo in the KeyDown.
But I use the KeyUp event. So again, I see no benefit in using the Modifier property. I have never used it in all my years as a developer and all the key handlings I have programmed run like a charm.
@Cyron43 If it is of no benefit, I wouldn't worry about it. For those who need it, it will work, for those who don't, there are alternate solutions.
The modifiers are intended to be used with the KeyDown, so if you don't use that, it's nothing to worry about. You don't use it at all, I use it a lot, it's just the different ways people work and the different types of software they write.
I have done both app and game development for close to 36 years and in that time, I have had many instances where I need to press Shift then hold a key to do an action fast, or press Control then hold a key to do something slow. So because that relies on two keys being held, you never trigger a KeyUp event, so that event serves no purpose in that situation.
If I am solely doing a key-based app, that only registers key-presses, then I will only ever use KeyUp because it avoids repeats. It's all about being in the situation where a certain process is required and if you ever need a solution that requires keys being held, rather than pressed, you will then use KeyDown.