Raised This Month: $51 Target: $400
 12% 

New Round / Player Spawn / Round Start / Round End - do Not mess it


  
 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
Author Message
VEN
Veteran Member
Join Date: Jan 2005
Old 07-28-2006 , 09:31   New Round / Player Spawn / Round Start / Round End - do Not mess it
Reply With Quote #1

Intro

I posting this because i saw so numerous mistakes/questions at this area of srcipting. This is the one of the common problems amongst the coders and even not only beginners! New Round / Player Spawn / Round Start / Round End is a different things so read the below explanations and do not mess them.

Usual call order of the events is listed below:
  1. New Round
  2. Player Spawn
  3. Round Start
  4. Round End

1. New Round

The "New Round" is happen at the "Freeze Time" start. The "Freeze Time" is a time in Counter-Strike when all players are "freezed" which means that they can't walk and do a primary attacks.

In the past years the most common way that was used to determine this event was the use of the "RoundTime" event with a "Time" message argument check, but there was a certain issues which makes this metod inefficient:
  • this event is specified, i.e. is sent to every player, so if there are no players no a server then it's not possible to detect the "New Round" with this method;
  • this event is also can be the same for the "Round Start" because the value of the "mp_freezetime" server CVar can be equal to the value of the "Time" argument of the "RoundTime" message, so it is not accurate enough.
Of course i haven't like that method so i had to think of something more efficient. So some months ago after a little research i've discovered the new method which does not have the issues that is listed above:
PHP Code:
register_event("HLTV""event_new_round""a""1=0""2=0"
Notice the two conditions.

Note that this event is not called for very first round, i.e. on map start. If you need to catch that moment as well then in the most cases it's enough to use the plugin_init() or plugin_cfg() forward functions.

Also i was amazed at how many mistakes was made even by the "expirienced" coders in try to detect the "New Round"! The most common mistake was:
PHP Code:
register_event("ResetHUD""newRound""b"
which is completely incorrect. The "ResetHUD" is a specified event which is called under many circumstances for every player. So sometimes you can get more than even one hundred such "newRound" function calls per a single round!


2. Player Spawn

I think no need to explain what the "Player Spawn" is. But many of the coders still do not know how to detect this event correctly.

If you are using AMX Mod X v1.8 or higher, or if you have the "Ham Sandwich" module installed the most simple and efficient way of the "Player Spawn" detection is a hook of the "Spawn" function itself:
PHP Code:
RegisterHam(Ham_Spawn"player""fwHamPlayerSpawnPost"1
The last parameter means that the registered function will be called right after player spawn (post variant of the hook) and not right before player spawn (pre variant of the hook). At least for Counter-Strike it's also necessary to skip registered function call for a dead players. This call is happen when a player enters a server. The most common example is shown below:
PHP Code:
#include <amxmodx>
#include <hamsandwich>
 
public plugin_init() {
        
RegisterHam(Ham_Spawn"player""fwHamPlayerSpawnPost"1)
}
 
public 
fwHamPlayerSpawnPost(iPlayer) {
        if (
is_user_alive(iPlayer)) {
                
// player spawned
        
}

If the above method isn't suitable for you for some reasons, it's possible to use the different more "famous" method of the "ResetHUD" event hook that doesn't require an additional module but is more complex.

You should note that the use of that method may even lead to a server crash. It could happen because the plugin actions is performed on a player in the middle of his spawn process. The example of such "dangerous" action is a call of the strip_user_weapons() fun module's function.

Many of plugin writers does know that the "ResetHUD" event is called on a player spawn but not all of them does know that this event is also called when a player is enter a server (at least in Counter-Strike), on "fullupdate" client command execution, demo recording and round restart attempt (on Counter-Strike's "sv_restartround" / "sv_restart" CVar change for alive players). So to use the "ResetHUD" to detect the "Player Spawn" we will need to filter out all that actions.

The moment when a player is joined a server can be filtered out by registering the "ResetHUD" event with a "e" flag which means that the registered function will be called on alive players. Note that sometimes that "e" flag will also allow a calls of the registered function on a dead players as well (this is a bug of the AMX Mod X core that has been fixed in version 1.80). So it's recommended to do the "alive" check inside of the registered function itself.

The execution of the "fullupdate" client command and the start of a demo recording can be filtered out by blocking the command:
PHP Code:
// ...
register_clcmd("fullupdate""clcmd_fullupdate")
// ...
 
public clcmd_fullupdate() {
    
// stops the command but allows to "catch" it by any other running plugin
    
return PLUGIN_HANDLED_MAIN

Though that method is simple it's recommended to not block the "fullupdate" command since it is used (automatically) on a client side on demo recording to properly update the HUD display and pass a proper data to a demo file on a beginning of a record process. Instead of "fullupdate" command block it's enough to just skip a call of the registered (to the "ResetHUD" event) function at the time when that command is issued on a client side.

As for round restart attempt, probably some of you does think that it's not necessary to filter this event out because it's always called right before "New Round". This is incorrect - not always, it's possible to set "sv_restartround" / "sv_restart" CVar value for example to 60 so new round will be delayed for one full minute! Therefore to filter this out as well on round restart attempt for every alive player we will have to skip the call of the registered to the "ResetHUD" event function.

The result code that is able to detect the "Player Spawn" is shown below:
PHP Code:
#include <amxmodx>
#include <fakemeta>
 
#define MAX_CLIENTS 32
 
new bool:g_bPlayerNonSpawnEvent[MAX_CLIENTS 1]
 
new 
g_iFwFmClientCommandPost
 
public plugin_init() {
        
register_event("ResetHUD""fwEvResetHUD""b")
        
register_event("TextMsg""fwEvGameWillRestartIn""a""2=#Game_will_restart_in")
        
register_clcmd("fullupdate""fwCmdClFullupdate")
}
 
public 
fwEvResetHUD(iPlayerId) {
        if (!
is_user_alive(iPlayerId))
                return
 
        if (
g_bPlayerNonSpawnEvent[iPlayerId]) {
                
g_bPlayerNonSpawnEvent[iPlayerId] = false
                
return
        }
 
        
fwPlayerSpawn(iPlayerId)
}
 
public 
fwEvGameWillRestartIn() {
        static 
iPlayers[32], iPlayersNumi
        get_players
(iPlayersiPlayersNum"a")
        for (
0iPlayersNum; ++i)
                
g_bPlayerNonSpawnEvent[iPlayers[i]] = true
}
 
public 
fwCmdClFullupdate(iPlayerId) {
        
g_bPlayerNonSpawnEvent[iPlayerId] = true
        
static const szFwFmClientCommandPost[] = "fwFmClientCommandPost"
        
g_iFwFmClientCommandPost register_forward(FM_ClientCommandszFwFmClientCommandPost1)
        return 
PLUGIN_CONTINUE
}
 
public 
fwFmClientCommandPost(iPlayerId) {
        
unregister_forward(FM_ClientCommandg_iFwFmClientCommandPost1)
        
g_bPlayerNonSpawnEvent[iPlayerId] = false
        
return FMRES_HANDLED
}
 
public 
fwPlayerSpawn(iPlayerId) {
        
// player spawned


3. Round Start

The "Round Start" is happen at the "Freeze Time" end.

Many of the coders does think that the "Round Start" and "New Round" is the same event and doing a things that is related to the "New Round" in "Round Start" but this is incorrect. Some of the coders especially in the past have used the "RoundTime" event to detect the "Round Start", but again this is inefficient method (the details can be found in the "New Round" section of the article).

The correct method that can be used to detect the "Round Start" is shown below:
PHP Code:
register_logevent("logevent_round_start"2"1=Round_Start"

4. Round End

The "Round End" is happen right at the moment when one of the teams is completed objectives: all players in the opposite team is killed, all hostages is rescued, time of the round is up, etc.

Some of the coders does think that the "Round End" and "New Round" is the same event and doing a things that is related to the "New Round" in the "Round End" but this is incorrect.

The correct method that can be used to detect the "Round End" is shown below:
PHP Code:
register_logevent("logevent_round_end"2"1=Round_End"

Still confused?

Still confused and don't really sure which from the above events should be used in your plugin? Review the below examples that may help you to understand the things better.
  • The "New Round" event can be used to move a spawn point entities or to play a music for a players if a freeze time is too long.
  • The "Player Spawn" can be used to alter a player's properties like start health, weapons, etc.
  • The "Round Start" can be used to create your own "buytime" for a plugins that provide a purchasable items or when you want to create a surprise item.
  • The "Round End" can be used to protect a players with a godmode until the "New Round" or to create a quick minigame until the "New Round".

Last edited by VEN; 03-22-2008 at 09:23.
VEN is offline
 



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 06:59.


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