AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Snippets and Tutorials (https://forums.alliedmods.net/forumdisplay.php?f=112)
-   -   [TUT/Snippet] Doing timed stuff without CreateTimers (https://forums.alliedmods.net/showthread.php?t=257587)

Chdata 02-04-2015 23:57

[TUT/Snippet] Doing timed stuff without CreateTimers
 
hi i like frog

I feel like something similar may have been posted before or something, but here's a thing I set up for myself.

As opposed to using CreateTimer() to run code in the future, there are various scenarios where you could just use a single float to do things such as, preventing code from executing until a certain amount of time has passed.

For example, all of the "m_flNext..." variables Source uses work this way. TF2 has m_flNextPrimaryAttack. This is set to a time in seconds, which is compared to the GameTime, which can be retrieved in SM via GetGameTime().

m_flNextPrimaryAttack prevents a player from attacking with +attack until the GameTime has reached or passed whatever time is stored in m_flNextPrimaryAttack.

If m_flNextPrimaryAttack is 60.0, the GameTime must reach 60 seconds before the player can attack. If at this 60 second mark you then set m_fl to 95.0, the player has to wait another 35 seconds before attacking again.

One might use that netprop by setting its value to GetGameTime()+flTime.

It's a fairly simple comparison, and it has a lot of applications. So I made a simple enum to easily track these.

For our version, we'll use GetEngineTime(). GetGameTime() resets to 0.0 when the map changes, whereas the Engine Time will keep increasing forever from the point the server started up. (Seriously, the previous sentence isn't documented anywhere where you'll find it soon).

Stocks:
Spoiler


And here's an example of where I use it.
Note: This code is actually from Advanced Weaponiser which I imported to another plugin.
Spoiler

Another example:
Spoiler

And lastly:
Spoiler

All you need to do to add a new / separate "timer" is add another entry into one of the enums above. Simple.

The m_flNext naming convention doesn't matter and isn't meant to be meaningful.
I just did that cause there's no other place I'm going to name variables like that and it gives a similar feel to the netprops in Source.

You can also use this in things like OnGameFrame() or OnThink to have times faster than 100 milliseconds (0.1 seconds), depending on what you want to do. Of course then it's still restricted to however fast OnGameFrame/OnThinkHooks fire.

Powerlord 02-10-2015 11:06

Re: [TUT/Snippet] Doing timed stuff without CreateTimers
 
Quote:

Originally Posted by Chdata (Post 2258573)
As opposed to using CreateTimer() to run code in the future, there are various scenarios where you could just use a single float to do things such as, preventing code from executing until a certain amount of time has passed.

For example, all of the "m_flNext..." variables Source uses work this way. TF2 has m_flNextPrimaryAttack. This is set to a time in seconds, which is compared to the GameTime, which can be retrieved in SM via GetGameTime().

This seems like a lot of work for what is essentially OnGameFrame on the game server side.

KyleS 02-10-2015 23:42

Re: [TUT/Snippet] Doing timed stuff without CreateTimers
 
If you need GameFrame synchronization, use RequestFrame.

Chdata 02-11-2015 09:12

Re: [TUT/Snippet] Doing timed stuff without CreateTimers
 
I do.

As for what Powerlord said... wot? I don't know how you're getting OnGameFrame out of that. You only need to set the next attack once, rather than multiple frames, depending on what you're doing.

For example, VSH sets your next attack to 2 seconds after you get a backstab, instead of the normal 0.6s fire rate of the knife.

And when you climb walls as a sniper it does more or less the same thing... but the plugin doesn't use OnGameFrame at all. (It does use a think hook for something else now though).

PHP Code:

stock SetNextAttack(iWeaponFloat:flSecs 0.0) {
    if (
iWeapon <= MaxClients || !IsValidEntity(iWeapon))  return;
    new 
Float:flNext GetGameTime() + flSecs;
    
SetEntPropFloat(iWeaponProp_Send"m_flNextPrimaryAttack"flNext);
    
SetEntPropFloat(iWeaponProp_Send"m_flNextSecondaryAttack"flNext);


Simple 5 line function.

If you want to delay every attack you'd just use TF2Items/TF2Attributes and use the fire rate penalty attribute.

Powerlord 02-11-2015 17:07

Re: [TUT/Snippet] Doing timed stuff without CreateTimers
 
Quote:

Originally Posted by Chdata (Post 2261087)
I do.

As for what Powerlord said... wot? I don't know how you're getting OnGameFrame out of that. You only need to set the next attack once, rather than multiple frames, depending on what you're doing.

For example, VSH sets your next attack to 2 seconds after you get a backstab, instead of the normal 0.6s fire rate of the knife.

And when you climb walls as a sniper it does more or less the same thing... but the plugin doesn't use OnGameFrame at all. (It does use a think hook for something else now though).

PHP Code:

stock SetNextAttack(iWeaponFloat:flSecs 0.0) {
    if (
iWeapon <= MaxClients || !IsValidEntity(iWeapon))  return;
    new 
Float:flNext GetGameTime() + flSecs;
    
SetEntPropFloat(iWeaponProp_Send"m_flNextPrimaryAttack"flNext);
    
SetEntPropFloat(iWeaponProp_Send"m_flNextSecondaryAttack"flNext);


Simple 5 line function.

If you want to delay every attack you'd just use TF2Items/TF2Attributes and use the fire rate penalty attribute.

I'm getting OnGameFrame out of that because Think hooks are called from eiface.h's GameFrame.

lingzhidiyu 02-11-2015 21:04

Re: [TUT/Snippet] Doing timed stuff without CreateTimers
 
I want know how much performance cost in this code.

PHP Code:

PreThink(client)
{
    if (!
AllowThis1[client])
    {
        return;
    }
    if (!
AllowThis2[client])
    {
        return;
    }
        
//and more bool...........



Chdata 02-11-2015 21:46

Re: [TUT/Snippet] Doing timed stuff without CreateTimers
 
Quote:

Originally Posted by lingzhidiyu (Post 2261350)
I want know how much performance cost in this code.

PHP Code:

PreThink(client)
{
    if (!
AllowThis1[client])
    {
        return;
    }
    if (!
AllowThis2[client])
    {
        return;
    }
        
//and more bool...........



https://forums.alliedmods.net/showpo...09&postcount=3

Comparatively a couple of bools shouldn't be bad. Unless you have like hundreds of bools. I try to use switch cases... according to Psychonic or Asherkin they don't calculate every comparison for every switch or something, just jump to whichever case.

Powerlord 02-12-2015 16:08

Re: [TUT/Snippet] Doing timed stuff without CreateTimers
 
Quote:

Originally Posted by Chdata (Post 2261360)
https://forums.alliedmods.net/showpo...09&postcount=3

Comparatively a couple of bools shouldn't be bad. Unless you have like hundreds of bools. I try to use switch cases... according to Psychonic or Asherkin they don't calculate every comparison for every switch or something, just jump to whichever case.

It's pretty common for a compiler to generate a jump table for a switch instead of treating it like an if / else if / else block.

Chdata 02-12-2015 17:54

Re: [TUT/Snippet] Doing timed stuff without CreateTimers
 
I love pointer tables

Code:

LDA !RamAdress  ;switch (!RamAdress)
PHX
ASL A
TAX
REP #$20
LDA Pointers,x
STA $0A
SEP #$20
PLX
JMP ($000A)

Pointers:
dw Action0
dw Action1
dw Action2
dw Action3
dw Action4
dw Action5

Action0:  ;case 0
RTS
Action1:  ;case 1
RTS
Action2:
RTS
Action3:
RTS
Action4:
RTS
Action5:
RTS


asherkin 02-13-2015 08:00

Re: [TUT/Snippet] Doing timed stuff without CreateTimers
 
All this is doing is re-implementing CreateTimer in SourcePawn rather than C++.


All times are GMT -4. The time now is 10:42.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.