AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting (https://forums.alliedmods.net/forumdisplay.php?f=107)
-   -   Timer Issue (https://forums.alliedmods.net/showthread.php?t=313122)

Lubricant Jam 12-29-2018 02:55

Timer Issue
 
Hey,

This is my first time creating my own plugins so please bare with me on this, I'm learning as I go from the usual tinkering and adaptation.

I am trying to create a simple timer which allows one person to complete the map, then slays them and after 30 seconds slays the rest of the server. It works perfectly for the first round, however any rounds after that the countdown starts at the beginning of every round after that and they continue to stack on top of each other.

Code:

public Action Event_RoundStart(Handle event, const char[] name, bool dontBroadcast)
{
        EndZoneTimer = INVALID_HANDLE;
        g_iCompleted = 0;
        g_iCountdown = 30;
        EndZoneTimer = CreateTimer(1.0, EndZoneCheck, INVALID_HANDLE, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
}

public Action EndZoneCheck(Handle timer, int userid)
{
    for (int client = 1; client <= MaxClients; ++client)
    {
                if (IsClientInGame(client) && coursetimer_InEndZone(client) && IsPlayerAlive(client))
                {
                        if (g_iCompleted == 0) {
                                EmitSoundToAll("training/countdown.wav", client, SNDCHAN_VOICE, SNDLEVEL_RAIDSIREN);
                                PrintToChatAll("[SM] \x07%N \x02has reached the end!", client);
                                PrintToChatAll("[SM] \x0330 seconds remaining to complete the map.");
                                ForcePlayerSuicide(client);
                                CountdownTimer = CreateTimer(1.0, Timer_Countdown, GetClientUserId(client), TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
                                g_iCompleted++;
                        }
                }
        }
}

public Action Timer_Countdown(Handle timer, int userid)
{
        int client = GetClientOfUserId(userid);

        if (g_iCountdown > 0 && IsClientInGame(client))
        {
                if ((g_iCountdown == 20) || (g_iCountdown == 10) || (g_iCountdown == 5) || (g_iCountdown < 4))
                        if (g_iCountdown == 1)
                        {
                                CountdownTimer = INVALID_HANDLE;
                                PrintToChatAll("[SM] \x03%d second remaining to complete the map.", g_iCountdown);
                                for (int i = 1; i <= MaxClients; ++i)
                                {
                                        if(IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) > 1)
                                        {
                                                ForcePlayerSuicide(i);
                                        }
                                }
                        }
                        else PrintToChatAll("[SM] \x03%d seconds remaining to complete the map.", g_iCountdown);

                g_iCountdown--;
        }
}

Any help is greatly appreciated.

backwards 12-29-2018 04:37

Re: Timer Issue
 
You aren't killing the original timer, you are just changing a pointer to it to now be a pointer to your newly created timer. You want to check if the handle is a valid timer first (for the very first instance loop where it will be invalid) and then before you reassign EndZoneTimer variable you want to use the KillTimer function.

PHP Code:

Handle EndZoneTimer INVALID_HANDLE;

public 
Action Event_RoundStart(Handle event, const char[] namebool dontBroadcast)
{
    if(
EndZoneTimer != INVALID_HANDLE)
    {
        
KillTimer(EndZoneTimertrue);
        
EndZoneTimer INVALID_HANDLE;    
    }

    
g_iCompleted 0;
    
g_iCountdown 30;
    
EndZoneTimer CreateTimer(1.0EndZoneCheckINVALID_HANDLETIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);



XiLuo 12-29-2018 04:42

Re: Timer Issue
 
TIMER_FLAG_NO_MAPCHANGE flag is that will not allow timer pass next map.And the flag TIMER_REPEAT for timer if you not kill it until the next map will kill
So to avoid timer repeat more,you can try this code
PHP Code:

public Action Event_RoundStart(Handle event, const char[] namebool dontBroadcast)
{
    
g_iCompleted 0;
    
g_iCountdown 30;
    
//if last round the timer is not over , we kill it and create new
    
if(EndZoneTimer != INVALID_HANDLE)
    {
        
KillTimer(EndZoneTimer);
        
EndZoneTimer INVALID_HANDLE;
    }
    
    
EndZoneTimer CreateTimer(1.0EndZoneCheckINVALID_HANDLETIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
}

public 
Action EndZoneCheck(Handle timerint userid)
{
    for (
int client 1client <= MaxClients; ++client)
    {
        if (
IsClientInGame(client) && coursetimer_InEndZone(client) && IsPlayerAlive(client))
        {
            if (
g_iCompleted == 0) {
                
EmitSoundToAll("training/countdown.wav"clientSNDCHAN_VOICESNDLEVEL_RAIDSIREN);
                
PrintToChatAll("[SM] \x07%N \x02has reached the end!"client);
                
PrintToChatAll("[SM] \x0330 seconds remaining to complete the map.");
                
ForcePlayerSuicide(client);
                if(
CountdownTimer!=INVALID_HANDLE)
                {
                    
KillTimer(CountdownTimer);
                    
CountdownTimer INVALID_HANDLE;
                }
                
CountdownTimer CreateTimer(1.0Timer_CountdownGetClientUserId(client), TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
                
g_iCompleted++;
                
//It's time to kill this timer and set it INVALID_HANDLE
                
KillTimer(timer);//KillTimer(EndZoneTimer);
                
EndZoneTimer INVALID_HANDLE;
            }
        }
    }
}

public 
Action Timer_Countdown(Handle timerint userid)
{
    
int client GetClientOfUserId(userid);

    if (
g_iCountdown && IsClientInGame(client))
    {
        if ((
g_iCountdown == 20) || (g_iCountdown == 10) || (g_iCountdown == 5) || (g_iCountdown 4))
            if (
g_iCountdown == 1)
            {
                
PrintToChatAll("[SM] \x03%d second remaining to complete the map."g_iCountdown);
                for (
int i 1<= MaxClients; ++i)
                {
                    if(
IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) > 1)
                    {
                        
ForcePlayerSuicide(i);
                    }
                }
                
// round over we must kill this timer now
                
KillTimer(timer);//KillTimer(CountdownTimer);
                
CountdownTimer INVALID_HANDLE;
            }
            else 
PrintToChatAll("[SM] \x03%d seconds remaining to complete the map."g_iCountdown);

        
g_iCountdown--;
    }


if there's something wrong please correct me,thanks.
Excuse my poor English,thanks again.

Lubricant Jam 12-29-2018 04:44

Re: Timer Issue
 
Quote:

Originally Posted by 1337norway (Post 2631547)
You aren't killing the original timer, you are just changing a pointer to it to now be a pointer to your newly created timer. You want to check if the handle is a valid timer first (for the very first instance loop where it will be invalid) and then before you reassign EndZoneTimer variable you want to use the KillTimer function.

PHP Code:

Handle EndZoneTimer INVALID_HANDLE;

public 
Action Event_RoundStart(Handle event, const char[] namebool dontBroadcast)
{
    if(
EndZoneTimer != INVALID_HANDLE)
    {
        
KillTimer(EndZoneTimertrue);
        
EndZoneTimer INVALID_HANDLE;    
    }

    
g_iCompleted 0;
    
g_iCountdown 30;
    
EndZoneTimer CreateTimer(1.0EndZoneCheckINVALID_HANDLETIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);



See I tried that initially and I've just put it back in exactly how you've said however the timer is still running on the next round.

backwards 12-29-2018 04:48

Re: Timer Issue
 
It's because RoundStart event happens after the freeze time. So during that freeze state the timer continues to count and kill players. You want to hook the event roundend and kill the timer there. Unless you still want players to be killed before the round restarts as there's a delay after round end event.

If the game type is csgo there's a few more events added you can use to kill the timer where you want:
round_prestart
round_poststart
round_start
round_end
round_officially_ended <- this is the one you probably want.

Find the list here

XiLuo 12-29-2018 04:52

Re: Timer Issue
 
I think your both EndZoneTimer and CountdownTimer should be killed on finish

Lubricant Jam 12-29-2018 05:10

Re: Timer Issue
 
Code:

public void OnPluginStart()
{
        HookEvent("round_end", Event_RoundEnd);
}

public Action Event_RoundEnd(Handle event, const char[] name, bool dontBroadcast)
{
        EndZoneTimer = INVALID_HANDLE;

        if(EndZoneTimer != INVALID_HANDLE)
        {
                KillTimer(EndZoneTimer);
                EndZoneTimer = INVALID_HANDLE;
        }
}

Still no luck, should I be using EventHookMode_Pre?

XiLuo 12-29-2018 05:20

Re: Timer Issue
 
Quote:

Originally Posted by Lubricant Jam (Post 2631555)
Code:

public void OnPluginStart()
{
        HookEvent("round_end", Event_RoundEnd);
}

public Action Event_RoundEnd(Handle event, const char[] name, bool dontBroadcast)
{
        EndZoneTimer = INVALID_HANDLE;

        if(EndZoneTimer != INVALID_HANDLE)
        {
                KillTimer(EndZoneTimer);
                EndZoneTimer = INVALID_HANDLE;
        }
}

Still no luck, should I be using EventHookMode_Pre?

It doesn't make sense,should be
PHP Code:

public Action Event_RoundEnd(Handle event, const char[] namebool dontBroadcast)
{
    if(
EndZoneTimer != INVALID_HANDLE
    { 
        
KillTimer(EndZoneTimer); 
        
EndZoneTimer INVALID_HANDLE
    }


And I think your CountdownTimer also should be initialized

Lubricant Jam 12-29-2018 05:25

Re: Timer Issue
 
Quote:

Originally Posted by XiLuo (Post 2631557)
It doesn't make sense,should be
PHP Code:

public Action Event_RoundEnd(Handle event, const char[] namebool dontBroadcast)
{
    if(
EndZoneTimer != INVALID_HANDLE
    { 
        
KillTimer(EndZoneTimer); 
        
EndZoneTimer INVALID_HANDLE
    }


And I think your CountdownTimer also should be initialized

I'm wondering if me ending the round as a draw plays a part to that or does that not matter as long as the round ends? The reason I end it as a draw is to allow unlimited rounds and let the time change the map as well as I need ignore win conditions on.

backwards 12-29-2018 05:38

Re: Timer Issue
 
It shouldn't matter if you end it as a draw, should just be an event argument you can grab on the end round event. You should debug all the code to make sure the functions are being called. Just by adding PrintToChatAll messages at the events of say round_end. just to confirm everything else is running as it should. A lot of times it's minor issues overlooked and not even the code you think it is.


All times are GMT -4. The time now is 02:14.

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