Raised This Month: $ Target: $400
 0% 

Most accurate way to make a stopwatch/timer?


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
MALON
Member
Join Date: Jan 2008
Old 08-21-2008 , 13:22   Most accurate way to make a stopwatch/timer?
Reply With Quote #1

What's the most accurate method to make a stopwatch/timer? I am looking to update my KZ plugin.

For example, make a set_task and increment something every .1 seconds and have the results of that be your time?

Or maybe do a start = get_gametime() then a finish = (get_gametime() - start)? (keep in mind i will have to use a set_task to keep a live display of a player's running time)


Additional question: Do timerbugs affect plugins or only map timers for KZ maps? If you don't know what a timerbug is, here's it's definition from xtreme-jumps:

"The KZ Timer isnt 100% exact, there are time shifts of 0,1-1 seconds on small maps (under 2 min) and shifts about 2-3 seconds on bigger maps (under 5 minutes) and time shifts up to 6 seconds on really big maps (5-15 minutes).
A timerbug occurs with a probability of 90% if the server is running longer than 60 minutes: The timer will show a better time than you actually achieved. (about 5-15 seconds better).
The probablity that a timerbug will occur if your server is running for less than 60 minutes is 0,0%."

Thanks,

--MALON
MALON is offline
Alka
AMX Mod X Plugin Approver
Join Date: Dec 2006
Location: malloc(null)
Old 08-21-2008 , 13:44   Re: Most accurate way to make a stopwatch/timer?
Reply With Quote #2

I think the accurate methode to make a KZ plugin is with get_gametime() for start/finish. For live timer display you don't need a task, just make get_gametime() - start and show it as a float. I think that timerbug is occuring when server works on low FPS, but dunno shure.
Alka is offline
MALON
Member
Join Date: Jan 2008
Old 08-21-2008 , 13:52   Re: Most accurate way to make a stopwatch/timer?
Reply With Quote #3

Thank you for the reply, but I didn't quite follow how I won't need a set_task to use the get_gametime() method of a stopwatch.

The goal is to have a HUD display that shows in real time what their elapsed time is since hitting the start button during the run, which of course would need to be updated at least once a second. I'm not understanding how to get away with updating it without a set_task.

Sorry,

--MALON
MALON is offline
Alka
AMX Mod X Plugin Approver
Join Date: Dec 2006
Location: malloc(null)
Old 08-21-2008 , 13:55   Re: Most accurate way to make a stopwatch/timer?
Reply With Quote #4

Oh, in this case have a look on this tutorial -> http://forums.alliedmods.net/showthr...highlight=task

All you have to do is to make an ent, hook the Think forward, check for that ent, and set its next_think to 0.1 for best results.
Alka is offline
MALON
Member
Join Date: Jan 2008
Old 08-21-2008 , 15:07   Re: Most accurate way to make a stopwatch/timer?
Reply With Quote #5

PHP Code:
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>


new g_Classname[] = "roflmao"
new Float:timer[33]
new 
bool:start[33] = false

public plugin_init()
{
    
register_plugin("ROFL","1.0","Hawk552")
    
    new 
Ent engfunc(EngFunc_CreateNamedEntity,engfunc(EngFunc_AllocString,"info_target"))
    
set_pev(Ent,pev_classname,g_Classname)
    
set_pev(Ent,pev_nextthink,1.0)
    
register_clcmd("say /reset""reset")
    
register_clcmd("say /starttimer""starter")
    
    
register_forward(FM_Think,"ForwardThink")
}

public 
ForwardThink(Ent)
{
    static 
Classname[33]
    
pev(Ent,pev_classname,Classname,32)
    
    if(!
equal(Classname,g_Classname))
        return 
FMRES_IGNORED
    
    
for(new 033i++){
        if(
start[i]){
            
client_print(iprint_chat"%f"timer[i])
            
timer[i]++
        }
    }
    
set_pev(Ent,pev_nextthink,1.0)
    
    return 
FMRES_IGNORED
}

public 
starter(id)
{
    if(!
start[id])
    
start[id] = true;
else
    
start[id] = false;
}

public 
reset(id)
{
    
timer[id] = 0.0;


So I made what I thought would be a 1 second counter, but it's far from it. I must not be understanding how to use the think forwards properly.

Any help would be awesome.

Thanks for you help so far, Alka. You've really put me on the right track at least.

--MALON
MALON is offline
MALON
Member
Join Date: Jan 2008
Old 08-21-2008 , 15:29   Re: Most accurate way to make a stopwatch/timer?
Reply With Quote #6

Actually, come to realize, I think it's a bad idea to use prethink to calculate a timer, because then the timer is based off of the client's FPS. Please correct me if I'm wrong. I think that doing a get_gametime() method might be best.

Thanks,

--MALON
MALON is offline
Alka
AMX Mod X Plugin Approver
Join Date: Dec 2006
Location: malloc(null)
Old 08-21-2008 , 15:47   Re: Most accurate way to make a stopwatch/timer?
Reply With Quote #7

No. That is not based on player FPS, that is a ent think on server side, not player...and yes get_gametime() is the best solution.

I maked this plugin for test.Show actual time elipsed since you typed /start . Also you can stop and reset timer with /reset command.Try it and tell me if is good.
Attached Files
File Type: sma Get Plugin or Get Source (timer_test.sma - 805 views - 1.6 KB)
Alka is offline
danielkza
AMX Mod X Plugin Approver
Join Date: May 2007
Location: São Paulo - Brasil
Old 08-21-2008 , 16:33   Re: Most accurate way to make a stopwatch/timer?
Reply With Quote #8

Part of the code from the KZ Plugin i was working on:
PHP Code:
new iTimerHUDSync
new Float:fPlayerTimer[33]
new 
iTimerSetCount[33]

new 
iPlayerCP_Count[33]

public 
fwButtonUse(buttonplayertypeFloat:value)
{
    if( !
get_pcvar_num(cvTimerOn) )
        return 
HAM_IGNORED

    
new szTarget[32]
    
pev(buttonpev_targetszTarget31)

    
// Check if this button is the timer's end/start. Look for the words "counter","clock" and "timer"
    // If they are found,check if it's the start or the end timer
    
if( containi(szTarget"counter") != -|| containi(szTarget"clock") != -|| containi(szTarget"timer") != -)
    {
        if( 
containi(szTarget"start") != -|| containi(szTarget"on") != -)
            
TimerStart(player)
        else if( 
containi(szTarget"stop") != -|| containi(szTarget"off") != -)
            
TimerEnd(player)
    }
    else
    {
        new 
szTargetName[32]
        
pev(buttonpev_targetnameszTargetName31)

        if( 
containi(szTargetName"counter") != -|| containi(szTargetName"clock") != -|| containi(szTargetName"timer") != -)
        {
            if( 
containi(szTargetName"start") != -|| containi(szTargetName"on") != -)
                
TimerStart(player)
            else if( 
containi(szTargetName"stop") != -|| containi(szTargetName"off") != -)
                
TimerEnd(player)
        }
    }

    return 
HAM_IGNORED
}


public 
fwTimerThink(ent)
{
    if( 
get_pcvar_num(cvTimerOn) )
    {
        new 
Float:fNow get_gametime()
        static 
Float:fTime
        
        
new iHoursiMinutesiSeconds

        
for (new id 1id iMaxPlayersid++)
        {
            if( !
fPlayerTimer[id] || !is_user_alive(id))
                continue

            
// Subtracting the current time with the one stored we get the elapsed time
            
fTime fNow fPlayerTimer[id]

            
iSeconds floatround(fTimefloatround_floor)
            
iHours iSeconds 3600
            iMinutes 
= (iSeconds 60) - (iHours 60)
            
iSeconds iSeconds 60

            
if( iSeconds == 60)
            {
                
iSeconds 0
                iMinutes
++
            }

            if( 
iMinutes == 60)
            {
                
iMinutes 0
                iHours
++
            }

            
set_hudmessage(0100200TIMER_XTIMER_Y)

            
ShowSyncHudMsg(idiTimerHUDSync"%d:%02d:%02d:%02d"iHoursiMinutesiSecondsfloatround(floatfract(fTime) * 100floatround_floor) )
        }

        
set_pev(entpev_nextthinkfNow TIMER_INTERVAL)
    }
}


TimerInit()
{
    
// Timer already initialized,return
    
if( fm_find_ent(iMaxPlayers"env_kz_timer") )
        return 
false

    
// Initialize HudSyncObj
    
iTimerHUDSync CreateHudSyncObj()

    
// Create entity
    
new ent engfunc(EngFunc_CreateNamedEntityengfunc(EngFunc_AllocString"info_target") )
    if( !
pev_valid(ent) )
        return 
false

    
// Set appropriate classname
    
set_pev(entpev_classname"env_kz_timer")

    
// Manually call the timer function,it will set up the next think
    
fwTimerThink(ent)
    
// Register it's think function
    
RegisterHamFromEntity(Ham_Thinkent"fwTimerThink")

    
// Spawn the entity
    
dllfunc(DLLFunc_Spawnent)

    return 
true
}


TimerStart(id)
{
    if(!
get_pcvar_num(cvTimerOn) || !is_user_alive(id))
        return

    new 
iLimit get_pcvar_num(cvTimerLimit)

    
// Player has no timer, or he's within the allowed reset limit
    
if( !fPlayerTimer[id] || (!iLimit || iTimerSetCount[id] < iLimit) )
    {
        
// Store the timer's start time
        
fPlayerTimer[id] = get_gametime()

        
// First one,initialize everything
        
if( !iTimerHUDSync)
            
TimerInit()

        
// Increase the timer set count
        
iTimerSetCount[id]++
    }
    else
    {
        
client_print(idprint_chat"[KZ] Timer failed - you reached the limit of %d starts"iLimit)
    }
}


TimerEnd(id)
{
    if(!
fPlayerTimer[id] || !is_user_alive(id))
        return

    
// Get current time
    
new Float:fTime get_gametime()

    
fTime -= fPlayerTimer[id]

    
// Format the time to a user-friendly display
    
new iSeconds floatround(fTimefloatround_floor)
    new 
iHours iSeconds 3600
    
new iMinutes = (iSeconds 60) - (iHours 60)
    
iSeconds iSeconds 60

    
if( iSeconds == 60)
    {
        
iSeconds 0
        iMinutes
++
    }

    if( 
iMinutes == 60)
    {
        
iMinutes 0
        iHours
++
    }

    
// Get user name
    
new szUserName[32]
    
get_user_name(idszUserName31)

    
client_print(0print_chat"[KZ] %s finished the map in %d:%02d:%02d:%02d, with %d checkpoints. Congratulations!"szUserNameiHoursiMinutesiSecondsfloatround(floatfract(fTime) * 100), iPlayerCP_Count[id])
    if(
iPlayerCP_Count[id] <= get_pcvar_num(cvHookCPs))
    {
        
client_print(id,print_chat,"[KZ] You were granted with the hook! Bind a key to +hook to use it!")
        
iPlayerHook_On[id] = true
    
}
    
    
// Reset user vars
    
fPlayerTimer[id] = 0.0
    iTimerSetCount
[id] = 0
    ClearSyncHud
(idiTimerHUDSync)

    
CheckPointReset(id)
}
// ---------------------------------------------------------- // 
danielkza is offline
Orangutanz
Veteran Member
Join Date: Apr 2006
Old 08-22-2008 , 11:47   Re: Most accurate way to make a stopwatch/timer?
Reply With Quote #9

Your current methods should work fine.

Under no circumstance should you use set_task for this kind of project. AMXX team broke this native a very long time ago when they didn't know what they were doing, it is still broke now funny enough
Orangutanz is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 03:12.


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