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

Create custom hud message for X seconds!


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
OCTAGEN
Junior Member
Join Date: Nov 2009
Old 04-16-2010 , 13:58   Create custom hud message for X seconds!
Reply With Quote #1

Ever wanted to display a hud message with countdown effect to someone or all players connected to your server ?


  1. 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/* Random Color From Range (140 - 155) */

    new _MessageB33 ][ 64 /* Message Before */
    new _MessageA33 ][ 32 /* Message After */
    new _TaskResult33 ][ 64 /* Name of the function to be called after countdown */
    new _TaskInstances33 /* Only 1 countdown is allowed to player */

    new Float:_Seconds33 ] = 0.0 /* Juggling Seconds */ 
  2. You wonder now what would I do with something like that ? Ok. I tell you why:
    1. _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.
    2. _MessageB is used to display a custom text message before the time remaining;
    3. _MessageA is used to display a custom text message after the time remaining.
    4. _TaskResult is a new variable used to store a public name function and call it after countdown.
    5. _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 <=
  3. 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 == ) && !is_user_validPlayer ) )
        {
            return 
        } 

        
    /* Copy B & A messages to global variables for later use */
        
    if( strlenMessageB ) <= )
        {
            
    /* Block continuing if message before doesn't have a specified string */
            
    return
        } else {
            
    copy_MessageB[Player], charsmax_MessageB ), MessageB )
        }
        
        if( !( 
    strlenMessageA ) == || !containMessageA"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] = floatminfloatSeconds ), floatclampfloatSeconds ), 5.060.0 60.0 /* 1 Hour */ ) )

        
    /* Start the task right now or delayed with all gathered information */
        
    new _Time_Left]
        
    formatex_Time_Leftcharsmax_Time_Left ), "%d:%02d", ( get_timeleft( ) / 60 ), ( get_timeleft( ) % 60 ) )
        
        new 
    _New_Delay
        
    formatex_New_Delaycharsmax_New_Delay ), "%d:%02d"floatroundDelay 60.0floatround_floor ),
        
    floatroundDelay 60.0 floatroundDelay 60.0floatround_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 */
            
    _TaskInstancesPlayer ] += 1
            
            
    /* Store the result right now, then start the task */
            
    if( strlenResult ) > )
            {
                
    copy_TaskResultPlayer ], charsmax_TaskResult ), Result )
            }
            
            
    /* Finally, start the task! */
            
    set_taskfloatmax0.1floatDelay ) ), "MakeHudCountdown"CountdownTaskId Player""0""
        }

  4. 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 MakeHudCountdownPlayer_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 == ) && !is_user_valid_Player ) )
        {
            return
        }
        
        
    /* Check multiple instances every time when this function is called */
        
    if( !( _TaskInstances_Player ] == ) && _TaskInstances_Player ] > )
        {
            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 */
            
    _String96 /* 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_Stringcharsmax_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 != 0.5 1.0
                _FadeOUT 
    Seconds >= 15 && _Flick5Times != 0.5 1.0
                
                
    /* Flicking will be always visible at startup for 5 seconds,
                   then it will disappear instantly the effect */
                
    if( _Flick5Times != && 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_Stringcharsmax_String ), "%s^n%d:%02d %s"_MessageB_Player ],
                
    floatroundSeconds 60.0floatround_floor ),
                
    floatroundSeconds 60.0 floatroundSeconds 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_Stringcharsmax_String ), ""); _Dot 1; }
                case 
    1: { add_Stringcharsmax_String ), "."); _Dot 2; }
                case 
    2: { add_Stringcharsmax_String ), ".."); _Dot 3; }
                case 
    3: { add_Stringcharsmax_String ), "..."); _Dot 0; }
            }
            
            
    /* Set & display our hud message */
            
    set_hudmessageHudRandomColor], HudRandomColor], HudRandomColor],
            
    0.10 /* ORIZONTAL */0.60 /* VERTICAL */0_FadeIN_FadeOUT )
            
    ShowSyncHudMsg_PlayerHudSyncObject_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""
        } 
        
        
    /* Countdown finished. Done... Seconds reached to 0.0 ! */
        /* Reset global variables for a specified player */
        
    else {
            
    /* Clear messages */
            
    _MessageB_Player ][ ] = '^0'
            
    _MessageA_Player ][ ] = '^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 ] ) > )
            {
                
    /* 
                   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]; _PID] = _Player
                set_task
    0.1_TaskResult_Player ], _Player_PIDcharsmax_PID ), "")
            }
        }

  5. 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_validPlayer 

        return ( 
    <= Player <= MaxPlayersNum )
    }  

    /* Generate random task id based on time left */
    random_taskid( )
    {
        return ( 
    random_numget_timeleft( ) / 60get_timeleft( ) % 60 ) )

  6. 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"
  7. 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) !
  8. Try It!... Waiting for new ideas if you have!.
Attached Files
File Type: sma Get Plugin or Get Source (CreateHudCountdown.sma - 686 views - 8.7 KB)

Last edited by OCTAGEN; 04-18-2010 at 15:33. Reason: Update.
OCTAGEN is offline
Dr.G
Senior Member
Join Date: Nov 2008
Old 04-16-2010 , 14:19   Re: Create custom hud message for X seconds!
Reply With Quote #2

Nice avatar.

What where you thinkin when you made this wonderfull stock:

PHP Code:
stock CreateSimpleTask(Float:Time, const Function[], ProcessID

    
set_task(Time, Function, ProcessID""0""0


That set_task was too easy to use, so you wanted to pimp it in somekinda weird way, but really didnt know how, so this is the result?
__________________
Dr.G is offline
xPaw
Retired AMX Mod X Moderator
Join Date: Jul 2008
Old 04-16-2010 , 14:27   Re: Create custom hud message for X seconds!
Reply With Quote #3

Strange stock, gj anyway
__________________
xPaw is offline
YamiKaitou
Has a lovely bunch of coconuts
Join Date: Apr 2006
Location: Texas
Old 04-16-2010 , 15:17   Re: Create custom hud message for X seconds!
Reply With Quote #4

Setting the time for a task to 0.0 is actually the same as setting it to 0.1. If you want to call the function right now, then just call it normally without the task
__________________
ProjectYami Laboratories

I do not browse the forums regularly anymore. If you need me for anything (asking questions or anything else), then PM me (be descriptive in your PM, message containing only a link to a thread will be ignored).
YamiKaitou is offline
OCTAGEN
Junior Member
Join Date: Nov 2009
Old 04-17-2010 , 07:40   Re: Create custom hud message for X seconds!
Reply With Quote #5




@ Dr.G:
That stock I extracted from a .inc file (writen by me, of course), where there were more functions than you saw. However, even that doesn't matter for me, it's alright.

@ YamiKaitou:
I agree with you there. But as still no problems did not appear, I think it's good and with set_task.




Please say how it worked if you tried.
I need comments after your testing to be sure that isn't big bugs and then we shall see if it's time to improve it somehow.


OCTAGEN is offline
Arkshine
AMX Mod X Plugin Approver
Join Date: Oct 2005
Old 04-17-2010 , 07:42   Re: Create custom hud message for X seconds!
Reply With Quote #6

Is it possible to use the normal font size, please ? No need to do that.

Quote:
I agree with you there. But as still no problems did not appear, I think it's good and with set_task.
You still using a native for nothing. I don't think it's good.
__________________

Last edited by Arkshine; 04-17-2010 at 07:48.
Arkshine is offline
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 04-17-2010 , 22:43   Re: Create custom hud message for X seconds!
Reply With Quote #7

Quote:
Originally Posted by OCTAGEN View Post
@ Dr.G:
That stock I extracted from a .inc file (writen by me, of course), where there were more functions than you saw. However, even that doesn't matter for me, it's alright.

@ YamiKaitou:
I agree with you there. But as still no problems did not appear, I think it's good and with set_task.
You should take peoples advice and not act like your code cannot be improved. If people make valid recommendations for corrections to your code, don't say "I don't care, it's ok"; you should make the corrections as suggested. Since you're posting this code as a tutorial, it should be coded as good/proper as possible so people can learn the correct way to do things.

Here you're doing the same check twice. Also, just because the index is in the valid player range (1 -> get_maxplayers), it does not mean the player is connected.
Code:
stock bool:is_user_valid(Player) {
    if(!(Player > get_maxplayers() || Player <= 0) && /* Connected, but not reaching an invalid id */
    (1 <= Player <= get_maxplayers()) && /* Second method to verify if it's connected */
    !is_user_hltv(Player)) /* Not allowed HLTV on server! */     {         return true     }             return false }
Here's an improvement
PHP Code:
stock bool:is_user_validPlayer )
{
    return ( ( 
<= Player <= get_maxplayers() ) && is_user_connectedPlayer ) && !is_user_hltvPlayer ) && !is_user_botPlayer ) );

You should also cache get_maxplayers() and CreateHudSyncObj() values to reduce your native calls and use formatex() instead of format().
__________________

Last edited by Bugsy; 04-17-2010 at 23:02.
Bugsy is offline
OCTAGEN
Junior Member
Join Date: Nov 2009
Old 04-18-2010 , 02:26   Re: Create custom hud message for X seconds!
Reply With Quote #8

Quote:
Originally Posted by Bugsy
You should take peoples advice and not act like your code cannot be improved. If people make valid recommendations for corrections to your code, don't say "I don't care, it's ok"; you should make the corrections as suggested. Since you're posting this code as a tutorial, it should be coded as good/proper as possible so people can learn the correct way to do things.
Let me tell you something! You know what annoys me most?
That almost everyone who saw the code stopped only to stocks that seemed most banal rather than correcting the original code.

If indeed you have read the entire source (but I don't think), not just that piece of stock, you prove yourself that you've seen a little mistakes at original basis functions.

Conclusion: Every time you came with a new idea, DON'T COPY someone else's advice! Because I can't do no improvement with having the same correction. Do I make myself clear ?

PHP Code:
stock bool:is_user_validPlayer )
{
    return ( ( 
<= Player <= get_maxplayers() ) && is_user_connectedPlayer ) && !is_user_hltvPlayer ) && !is_user_botPlayer ) );

Very good. I will use it from now on.
OCTAGEN is offline
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 04-18-2010 , 08:33   Re: Create custom hud message for X seconds!
Reply With Quote #9

Quote:
Originally Posted by OCTAGEN View Post
[...] Do I make myself clear ?
No
__________________
Bugsy is offline
Arkshine
AMX Mod X Plugin Approver
Join Date: Oct 2005
Old 04-18-2010 , 09:54   Re: Create custom hud message for X seconds!
Reply With Quote #10

Here a deep look.
Yes, I've tested the plugin.

First, it would be nice if you could change the font size, it hurts the eyes and doesn't improve the readability at all. Please use the normal font size.

About your comments :
  • Quote:
    This code is easy to understand and it has smart functions to run properly without any additional modules required!
    This sentence is weird and doesn't make sense. So, a code would be smart if it doesn't use additional modules ? It won't change nothing if another module was required. What it matters is how you use the natives/forwards whatever the modules used.
  • Quote:
    That almost everyone who saw the code stopped only to stocks that seemed most banal rather than correcting the original code.
    Just because it's banal it should not improved or something? I hope you are joking.
    Quote:
    If indeed you have read the entire source (but I don't think), not just that piece of stock, you prove yourself that you've seen a little mistakes at original basis functions.
    Don't worry there are severals things to say.
    Quote:
    Conclusion: Every time you came with a new idea, DON'T COPY someone else's advice! Because I can't do no improvement with having the same correction. Do I make myself clear ?
    What. (?!)
    Quote:
    (I will ignore stupid advices, as I said I want smart and new ideas!).
    Could you stop to be that pretentious, please? Like if your code is perfect and doesn't need improvements. Your code can be improved, espacially for such function which can be called often. What said Bugsy is perfectly right, you should follow them.

About your code :
  • CreateHudCountdown() :
    - You say "for a target id (use 0 for all players)" ; there the first bug, using 0 won't do nothing since you won't pass is_user_valid() check.
    - You use strcat() + strlen() (?!) to concatenate two string. Why ? Here we want just to save the original message, so use simply copy() + charsmax() ; you save 2 natives and the original content will be overwritten.
    - CreateSimpleTask() : I don't see the slightest advantage to use a task here to call directly a function. Plus, 0.0 will interpretated as 0.1. So, 1) you use extra native ( think about the code generated with that ) when you should not, 2) You lead people to wrong and confusing information : using 0.0 is not possible and using it in a task doesn't make sense. You could use a task to delay the beginning but that's not the purpose there.
  • MakeHudCountdown():
    - In the function header, "Player" is not well named because what it passes is not the player's index but the task id. It should be called something like "TaskID". Less confusing.
    - GetUserTaskId() : I don't think it's worth to create a stock just for that. You could simply add a comment to provide more informations if you want. Anyway, instead of using a call + return, I would suggest to create a macro.
    - You can see _Seconds[_Player] is used more than 2 times. I would suggest to cache the value. It will avoid to re-index the array each time. More information there.
    - You can replace format() by formatex(), it's faster. Why, see here.
    - CreateHudSyncObj() is something you need to create one time. Cache the value in plugin_init() for example.
  • ClearCountdownVariables() :
    - A simple way to clear an array whitout native is to so something : _MessageB[Player][0] = '^0';.
    - "/* Return to original function */", I don't understand the purpose to write "return" nor the comment. You don't need to write that. Plus you are already at the end of the function, it makes no sense.
  • is_user_valid() :
    - get_maxplayers() won't change in-game, that's something you should cache in plugin_init() for example.
    - Bugsy has given you a better stock, but I'm not sure it's worth to check bot/htlv. At least I would cache them since it's something which won't change ; using a bit ( there is a tuto ) instead of array of 33 cells.
  • CreateSimpleTask() :
    - I don't see the slightest advantages to do that. By default the params are already like that. If it's an issue with the name you could instead use a macro. But using a stock just for that is damn pointless.

Too bad you can't control the location/color of the message.
That's all, my first thoughts about that.
__________________

Last edited by Arkshine; 04-18-2010 at 13:06.
Arkshine 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:42.


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