Junior Member
|
04-16-2010
, 13:58
Create custom hud message for X seconds!
|
#1
|
Ever wanted to display a hud message with countdown effect to someone or all players connected to your server ?
- I started with a few global variables to cache the information which is required.
PHP Code:
static MaxPlayersNum /* Server Players Slots */
static CountdownTaskId /* Process Id */
static HudSyncObject /* Hud Synchronization Object */
static HudRandomColor[ 3 ] /* Random Color From Range (140 - 155) */
new _MessageB[ 33 ][ 64 ] /* Message Before */
new _MessageA[ 33 ][ 32 ] /* Message After */
new _TaskResult[ 33 ][ 64 ] /* Name of the function to be called after countdown */
new _TaskInstances[ 33 ] /* Only 1 countdown is allowed to player */
new Float:_Seconds[ 33 ] = 0.0 /* Juggling Seconds */
- You wonder now what would I do with something like that ? Ok. I tell you why:
- _Seconds is used to display a number and the most important thing, is that everytime it saves new value into variable with specified player id.
- _MessageB is used to display a custom text message before the time remaining;
- _MessageA is used to display a custom text message after the time remaining.
- _TaskResult is a new variable used to store a public name function and call it after countdown.
- _TaskInstances is a new variable used to block simultaneously task operations. For example: 2 countdowns at one time...
Code:
Time remaining: 20 seconds before server shutting down.
- "Time remaining:" = _MessageB
- "20" = _Seconds
- "seconds before server shutting down." = _MessageA
=> _MessageB Seconds _MessageA <=
- This is the first function I used in order to ensure proper working without flooding the server.
PHP Code:
/* Get all required information, prepare task! */
CreateHudCountdown
(
Player, /* Player Id */
const MessageB[ ], /* Message Before */
Seconds, /* How much longer countdown will be */
const MessageA[ ] = "seconds remaining", /* Alternative message, used after seconds */
Delay = 0, /* How much the task will wait before starting */
const Result[ ] = "" /* New parameter used to postpone the countdown task for a few seconds. */
)
{
/* Check the player id first, then begin, otherwise we will receive
AMXX errors about invalid target => VERY IMPORTANT!
*/
if( !( Player == 0 ) && !is_user_valid( Player ) )
{
return
}
/* Copy B & A messages to global variables for later use */
if( strlen( MessageB ) <= 0 )
{
/* Block continuing if message before doesn't have a specified string */
return
} else {
copy( _MessageB[Player], charsmax( _MessageB ), MessageB )
}
if( !( strlen( MessageA ) == 0 || !contain( MessageA, "seconds remaining" ) ) )
{
copy( _MessageA[Player], charsmax( _MessageA ), MessageA )
} else {
copy( _MessageA[Player], charsmax( _MessageA ), "seconds remaining" )
}
/* Copy seconds to global variable for later use */
_Seconds[Player] = floatmin( float( Seconds ), floatclamp( float( Seconds ), 5.0, 60.0 * 60.0 /* 1 Hour */ ) )
/* Start the task right now or delayed with all gathered information */
new _Time_Left[ 7 ]
formatex( _Time_Left, charsmax( _Time_Left ), "%d:%02d", ( get_timeleft( ) / 60 ), ( get_timeleft( ) % 60 ) )
new _New_Delay[ 6 ]
formatex( _New_Delay, charsmax( _New_Delay ), "%d:%02d", floatround( Delay / 60.0, floatround_floor ),
floatround( Delay - 60.0 * floatround( Delay / 60.0, floatround_floor ), floatround_floor ) )
/* Make sure that delay is not higher than game time left remaining */
if( !( str_to_num( _New_Delay ) >= str_to_num( _Time_Left ) ) )
{
/* Increase task instances to 1 */
_TaskInstances[ Player ] += 1
/* Store the result right now, then start the task */
if( strlen( Result ) > 0 )
{
copy( _TaskResult[ Player ], charsmax( _TaskResult ), Result )
}
/* Finally, start the task! */
set_task( floatmax( 0.1, float( Delay ) ), "MakeHudCountdown", CountdownTaskId + Player, "", 0, "", 0 )
}
}
- This is the second function which is used to show the message and recall the task to maintain the countdown until finishes.
PHP Code:
/* After all information gathered, this public will be used as a task for specified player */
public MakeHudCountdown( Player_TaskId )
{
/* Calculate the difference between player and task id */
new _Player = ( Player_TaskId - CountdownTaskId )
/* Don't continue if we have an unknown player */
if( !( _Player == 0 ) && !is_user_valid( _Player ) )
{
return
}
/* Check multiple instances every time when this function is called */
if( !( _TaskInstances[ _Player ] == 0 ) && _TaskInstances[ _Player ] > 1 )
{
return
}
/* Cache value for this global variable to avoid re-indexing */
new Seconds = _Seconds[ _Player ]
/* Seconds are valid, continue */
if( !( Seconds <= 0.0 ) )
{
/* Initialize all needed variables only for this function */
/* We will gonna need two type of variables */
/* First, those variables will be lost at every function call */
new
Float:_TimeOff, /* Delay between calling this task again */
Float:_FadeIN, /* Delay in milliseconds to appear the message */
Float:_FadeOUT, /* Delay in milliseconds to disappear the message */
_String[ 96 ] /* Final message created by B & A + seconds */
/* Second, those variables will remain in memory (just like a global variable) */
static
_Dot, /* Good for making an animation meaning a progress ... */
_Flick5Times /* Effect during startup countdown */
/* If seconds are 10, 9, 8, 7, etc..., call this function faster
and make a cool efect for countdown
*/
if( Seconds <= 10.0 )
{
_TimeOff = 0.1
_FadeIN = 0.1
_FadeOUT = 0.0
/* Format the string differently than the second.
If the seconds <= 10, then will be displayed the milliseconds below, too.
This progress is maded at a faster rate.
*/
formatex( _String, charsmax( _String ), "%s^n%.1f %s",
_MessageB[ _Player ], Seconds, _MessageA[ _Player ] )
}
/* If seconds are higher than 10, then call this function every 1 second */
else {
_TimeOff = 1.0
_FadeIN = Seconds >= 15 && _Flick5Times != 5 ? 0.5 : 1.0
_FadeOUT = Seconds >= 15 && _Flick5Times != 5 ? 0.5 : 1.0
/* Flicking will be always visible at startup for 5 seconds,
then it will disappear instantly the effect */
if( _Flick5Times != 5 && Seconds >= 15 ) _Flick5Times ++
/* Format the string to a smart one. Why like this?
Because, let's say, we give 100 seconds for countdown to measure,
you think it will be displayed so nice?
100 seconds will be displayed as 1 minute and 40 seconds.
*/
formatex( _String, charsmax( _String ), "%s^n%d:%02d %s", _MessageB[ _Player ],
floatround( Seconds / 60.0, floatround_floor ),
floatround( Seconds - 60.0 * floatround( Seconds / 60.0,
floatround_floor ), floatround_floor ), _MessageA[ _Player ] )
}
/* Switching dots with new values at every function call */
/* E.G.: 10 Seconds Remaining
9 Seconds Remaining .
8 Seconds Remaining . .
7 Seconds Remaining . . .
and so on and so forth >>
*/
switch( _Dot )
{
case 0: { add( _String, charsmax( _String ), ""); _Dot = 1; }
case 1: { add( _String, charsmax( _String ), "."); _Dot = 2; }
case 2: { add( _String, charsmax( _String ), ".."); _Dot = 3; }
case 3: { add( _String, charsmax( _String ), "..."); _Dot = 0; }
}
/* Set & display our hud message */
set_hudmessage( HudRandomColor[ 0 ], HudRandomColor[ 1 ], HudRandomColor[ 2 ],
0.10 /* ORIZONTAL */, 0.60 /* VERTICAL */, 0, _FadeIN, _FadeOUT )
ShowSyncHudMsg( _Player, HudSyncObject, _String )
/* Decrease the seconds depending the time off */
_Seconds[ _Player ] = Seconds - _TimeOff
/* Task finished. Start again a new one! */
set_task( _TimeOff, "MakeHudCountdown", CountdownTaskId + _Player, "", 0, "", 0 )
}
/* Countdown finished. Done... Seconds reached to 0.0 ! */
/* Reset global variables for a specified player */
else {
/* Clear messages */
_MessageB[ _Player ][ 0 ] = '^0'
_MessageA[ _Player ][ 0 ] = '^0'
/* Reset seconds */
_Seconds[ _Player ] = 0.0
/* Decrease by 1 the task instance */
_TaskInstances[ _Player ] --
/* Reset task id for countdown */
// CountdownTaskId = random_taskid( )
/* Calling the specified function */
if( strlen( _TaskResult[ _Player ] ) > 0 )
{
/*
I don't know what type of params it has the function,
so you can customize here how you want...
Only, don't forget to leave set_task intact!
*/
new _PID[ 1 ]; _PID[ 0 ] = _Player
set_task( 0.1, _TaskResult[ _Player ], _Player, _PID, charsmax( _PID ), "", 0 )
}
}
}
- Auxiliary functions ...
PHP Code:
/* Same as pev_valid or is_user_connected but more powerful */
/* May not be used to verify an different entity such as "func_*" */
/* Check player id through range 1 <= 32 */
is_user_valid( Player )
{
return ( 1 <= Player <= MaxPlayersNum )
}
/* Generate random task id based on time left */
random_taskid( )
{
return ( random_num( get_timeleft( ) / 60, get_timeleft( ) % 60 ) )
}
- I didn't explain how the source code can be used. Well follow my example:
PHP Code:
CreateHudCountdown(Player, const MessageB[], Seconds, const MessageA[] = "seconds remaining", Delay, const Result[] = "")
/*
Params:
- Player can be anybody from range 1<=32.
- MessageB, also known as first message behind the seconds... (Ex.: "You have")
- Seconds must be typed as a number without float! (Ex.: 10)
- MessageA, used in the end of message. Tip: Don't use dots or exclamation/question marks! (Ex.: "seconds remaining")
[ NEW ! ] - Delay to start the task if you want at a specified time in seconds.
[ NEW ! ] - Result is a public function which will be called once the countdown is finished.
*/
CreateHudCountdown(0, "Server is shutting down!", 20, "seconds remaining", 5, "DEMO_ServerShutDown")
- I attached into a separated file the entire code in case you want to see more clear. Both versions (first and the second which is newer) !
- Try It!... Waiting for new ideas if you have!.
Last edited by OCTAGEN; 04-18-2010 at 15:33.
Reason: Update.
|
|