SmileYzn / MatchBot

Counter-Strike 1.6 Match Plugin for ReHLDS and ReGameDLL_CS
GNU General Public License v3.0
28 stars 15 forks source link

pause timer like that can u add this??? #109

Closed Escap3d closed 9 months ago

Escap3d commented 9 months ago

include

include

define AUTHOR "Esc"

define VERSION "1.0"

define PLUGIN "TACTICAL PAUSE"

define FREEZE_TIME get_member_game( m_iRoundTimeSecs ) // Actual round time

define mp_freezetime get_member_game( m_iIntroRoundTime ) // mp_freezetime

define IS_FREEZE_TIME get_member_game( m_bFreezePeriod ) // Check if game is in freezetime state

define HOLD_INTERVAL 1.0 // set_task delay

define PAUSE_BUYTIME 60.0 // mp_buytime while in pause

define UNPAUSE_MENU_RESULT 10.0 // stop the vote for unpausing (in seconds)

define TASK_SHOWPROGRESS 9486 // task id for showing the progress

define TASK_RESUME_VOTEMENU 9487 // task id for unpause votemenu

//RoundTimer Message static iMsgRoundTime //BuyTime cvars. new g_BuyTimePCvar static Float:g_BuyTimeOriginalPCvar //Boolean checks new bool:g_iPaused, g_iPauseQueued //Cvars new cvar_PauseDuration, cvar_PauseAmount, cvar_PauseBuyTime, cvar_NotifyPauseSet, cvar_UnpauseFeat, cvar_UnpauseVoteAmount, cvar_PauseFeat //Misc new g_iMaxPlayers, g_TeamPauses[ 3 ], g_WhoPaused

//VoteMenu new g_UnpauseVoteMenu, g_Votes[3], g_CurrentlyVoting

enum _:Teams { TERRORIST_TEAM, CT_TEAM } //Cmds new szPauseCmds[ ][ ] = { "say /pause", "say !pause", "say .pause", "say /p", "say !p", "say .p" }; new szUnpauseCmds[ ][ ] = { "say /unpause", "say !unpause", "say .unpause", "say /up", "say .up", "say !up" }

public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR)

//Client Cvars
for ( new i = 0; i < sizeof( szPauseCmds ); i++ ) 
    register_clcmd( szPauseCmds[ i ], "PauseCmd" )

for ( new i = 0; i < sizeof( szUnpauseCmds ); i++ )
    register_clcmd( szUnpauseCmds[ i ], "Resume_Function")

//Server cvars
/*
amx_pause_resume ->>
!!! No value, just removes all current pauses and resumes gameplay.
*/
register_concmd( "amx_pause_resume", "Pause_ResumeCmd", ADMIN_RCON, "Removes the pause and resumes the game.") // fuck the naming is always the hardest
/*
amx_pause_set ->>
!!! 0 = CT, 1 = TT, 2 = ALL(CT+TT)
!!! integer | amount of pauses to set.
!!! example: amx_pause_set 0 0 will reset the CT Team pause counter, so if you have amx_pause_amount 1 then the CT's can call a pause again.
*/
register_concmd( "amx_pause_set", "CmdPauseSet", ADMIN_RCON, "Resets the pause amount for teams, 0 = CT, 1 = TT, 2 = ALL(CT+TT)" )

//MAXPLAYERS
g_iMaxPlayers = get_member_game( m_nMaxPlayers )

//POINTERS
g_BuyTimePCvar = get_cvar_pointer( "mp_buytime" )

/*
amx_pause_enabled ->>
!!! 0 | disable pause
!!! 1 | enable pause
*/
cvar_PauseFeat = register_cvar( "amx_pause_enabled", "1", FCVAR_PROTECTED )
/*
amx_pause_duration ->>
!!! integer | amount of freezetime to be set!
*/
cvar_PauseDuration = register_cvar( "amx_pause_duration", "60", FCVAR_PROTECTED ) 
/*
amx_pause_amount ->>
!!! integer | the amount of times each team can call a pause for the match!
*/
cvar_PauseAmount = register_cvar( "amx_pause_amount", "2", FCVAR_PROTECTED )
/*
amx_pause_buytime ->>
!!! 0 | buytime not altered, not recommended!
!!! 1 | buytime altered to allow people to buy during the pause.
*/
cvar_PauseBuyTime = register_cvar( "amx_pause_buytime", "1", FCVAR_PROTECTED )
/*
amx_pause_set_notify ->>
!!! 0 | do not notify players when you modify their pause amounts
!!! 1 | recommended, notify players of the amount of pauses they can use
*/
cvar_NotifyPauseSet = register_cvar( "amx_pause_set_notify", "1", FCVAR_PROTECTED )
/*
amx_pause_allow_resume ->>
!!! 0 | do not allow players to start a vote for resuming the game (removing the "artificial pause")
!!! 1 | allow players to start a vote 
*/
cvar_UnpauseFeat = register_cvar( "amx_pause_allow_resume", "1", FCVAR_PROTECTED )
/*
amx_pause_resume_votes ->> 
!!! integer | the amount of people that need to vote "yes" to remove the current pause.
*/
cvar_UnpauseVoteAmount = register_cvar( "amx_pause_resume_votes", "4", FCVAR_PROTECTED )

//MultiLang
register_dictionary( "pause.txt" )

//Message
iMsgRoundTime = get_user_msgid( "RoundTime" )

//Event
register_event( "HLTV", "event_new_round", "a", "1=0", "2=0" )

}

public event_new_round( ) {
/ Getting the latest mp_buytime cvar on event new round, since a lot of CW/PUG/MIX plugins modify it pre and post warmup, so getting it once in plugin_init() would make no sense. Alternatively this can be achieved with hook_cvar_change but I'm too stupid to understand how to use it in my use case. Cannot use pcvar_float for the sole reason that I need to store this as the original value before changing it / if ( get_pcvar_num( cvar_PauseBuyTime ) ) g_BuyTimeOriginalPCvar = get_cvar_float( "mp_buytime" ) / Fixes some edge cases of a round ending before the pause ends! Will remove the display progress function task and re-initialize the counter. / if ( task_exists( TASK_SHOWPROGRESS ) || task_exists( TASK_RESUME_VOTEMENU ) ) CleanReinitialize( )

if ( g_iPauseQueued ) 
    set_task( HOLD_INTERVAL, "@PauseFunc", _, _, _, "" )

}

public CleanReinitialize( ) { remove_task( TASK_SHOWPROGRESS ) remove_task( TASK_RESUME_VOTEMENU )

g_Votes[ 0 ] = 0
g_Votes[ 1 ] = 0
g_CurrentlyVoting = 0
g_iPaused = false

remove_task( mp_freezetime )
remove_task( TASK_SHOWPROGRESS )

for ( new playerid = 0; playerid < g_iMaxPlayers; playerid++ )
    if ( is_user_connected( playerid ) )
        rg_send_bartime( playerid, 0, true )

}

public NotifyFunc( const szTeam[32], const print_team, const amount ) { new iPlayers[ 32 ], iNum, Player get_players( iPlayers, iNum, "ec", szTeam ) for ( new i = 0; i < iNum; i++ ) { Player = iPlayers[ i ] client_print_color( Player, print_team, "%L", Player, "PAUSE_NEW_AMOUNT", amount ) }

return PLUGIN_HANDLED

}

public NotifyCall( const team, const amount ) { !( team ) ? NotifyFunc( "CT", print_team_blue, amount ) : NotifyFunc( "TERRORIST", print_team_red, amount )

if ( team == 2 )
{
    NotifyFunc( "CT", print_team_blue, amount )
    NotifyFunc( "TERRORIST", print_team_red, amount )
}
return PLUGIN_HANDLED

}

public CmdPauseSet( ) { /*

You can call this cvar from your own plugins by using server_cmd, example args[0] = team !! 0 = CT !! 1 = TT !! 2 = ALL(CT+TT)
args[1] = amount to set !! integer = TEAM'S PAUSES, 0 = reset. ** server_cmd( "amx_pause_set ^"2"^ ^"0^" ") ->> this will reset both teams available pauses by setting

*/ new args[ 2 ][ 32 ] read_argv( 1, args[ 0 ], sizeof( args ) ) // read argument number 1 (team) trim( args[ 0 ] ) // remove unexpected whitespaces read_argv( 2, args[ 1 ], sizeof( args ) ) // read argument number 2 (amount of pauses to set) trim( args[ 1 ] ) // remove unexpected whitespaces

new l_Team = str_to_num( args[ 0 ] )
new l_Amount = str_to_num( args[ 1 ] )

switch( l_Team )
{
    case 0: g_TeamPauses[ TERRORIST_TEAM ] = l_Amount
    case 1: g_TeamPauses[ CT_TEAM ] = l_Amount
    case 2: g_TeamPauses[ TERRORIST_TEAM ] = g_TeamPauses[ CT_TEAM ] = l_Amount
    default: server_print( "[Gameguard] Tactical PAUSE: CmdPauseReset function received invalid team.^n0 = CT^n1 = TT^n 2 = ALL(CT+TT)" ); // ignore this semicolon... my syntax highlight won't work otherwise??
}

if ( get_pcvar_num( cvar_NotifyPauseSet ) )
    NotifyCall( l_Team, l_Amount )

return PLUGIN_HANDLED

}

public PauseRequest( id, const g_PauseTeam, const print_team, const player_team ) { if ( g_TeamPauses[ g_PauseTeam ] == get_pcvar_num( cvar_PauseAmount ) ) return client_print_color( id, print_team, "%L", id, "PAUSE_NOMORE" )

client_print_color( 0, print_team, "%L", LANG_PLAYER, !( player_team == 1 ) ? "PAUSE_TAKEN_CT" : "PAUSE_TAKEN_TT" )
g_TeamPauses[ g_PauseTeam ]++

if ( IS_FREEZE_TIME )
    @PauseFunc( )
else {
    g_iPauseQueued = true
    client_print_color( id, print_team, "%L", id, "PAUSE_QUEUED" )
}

return PLUGIN_HANDLED

}

public PauseCmd( id ) { if ( !get_pcvar_num( cvar_PauseFeat ) ) return client_print_color( id, print_team_grey, "%L", id, "PAUSE_DISABLED" ) if ( g_iPaused ) return client_print_color( id, print_team_grey, "%L", id, "PAUSE_ALREADY" ) if ( g_iPauseQueued ) return client_print_color( id, print_team_grey, "%L", id, "PAUSE_ALREADY_QUEUED" )

new l_iPlayerTeam = get_member( id, m_iTeam )

switch ( l_iPlayerTeam )
{
    case 1: PauseRequest( id, g_TeamPauses[TERRORIST_TEAM], print_team_red, l_iPlayerTeam )
    case 2: PauseRequest( id, g_TeamPauses[CT_TEAM], print_team_blue, l_iPlayerTeam )
    default: return client_print_color( id, print_team_grey, "%L", id, "PAUSE_INVALID_TEAM" )
}

g_WhoPaused = l_iPlayerTeam

return PLUGIN_HANDLED

}

public Resume_Function( id ) { if ( !get_pcvar_num( cvar_UnpauseFeat ) ) return client_print_color( id, print_team_grey, "%L", id, "UNPAUSE_FEATURE_NOT_ENABLED" ) if ( !g_iPaused ) return client_print_color( id, print_team_grey, "%L", id, "UNPAUSE_UNAVAILABLE" ) if ( g_WhoPaused != get_member( id, m_iTeam ) ) return client_print_color( id, print_team_grey, "%L", id, "UNPAUSE_WRONG_TEAM" ) if ( g_CurrentlyVoting ) return client_print_color( id, print_team_grey, "%L", id, "UNPAUSE_ONGOING" )

g_UnpauseVoteMenu = menu_create( "RESUME_GAME", "Resume_Votemenu_Handler", true )
menu_additem( g_UnpauseVoteMenu, "VOTE_OPTION_1", "0" ) 
menu_additem( g_UnpauseVoteMenu, "VOTE_OPTION_2", "1" )
menu_setprop( g_UnpauseVoteMenu, MPROP_EXIT, MEXIT_NEVER ) // REMOVES THE EXIT OPTION (Players can still dismiss the menu)

new iPlayers[ 32 ], iPNum, Player, iCallerName[ 32 ]
get_players( iPlayers, iPNum, "ach" )
get_user_name( id, iCallerName, sizeof( iCallerName ) )

for ( new i = 0; i < iPNum; i++ )
{
    Player = iPlayers[ i ]
    menu_display( Player, g_UnpauseVoteMenu, 0 )
    g_CurrentlyVoting++
    client_print_color( Player, ( get_member( Player, m_iTeam ) == 1 ) ? print_team_red : print_team_blue , "%L", Player, "UNPAUSE_PLAYER_START_VOTE", iCallerName )
}

set_task(UNPAUSE_MENU_RESULT, "Resume_Votemenu_Result", TASK_RESUME_VOTEMENU)

return PLUGIN_HANDLED

}

public Resume_Votemenu_Handler( id, g_UnpauseVoteMenu, item ) { if ( item == MENU_EXIT || !g_CurrentlyVoting ) return PLUGIN_HANDLED

new data[ 6 ], iPlayerName[ 32 ]
new access, callback
new iPlayers[ 32 ], iPNum, Player
get_players( iPlayers, iPNum, "ache", ( get_member(id, m_iTeam) == 2 ) ? "CT" : "TERRORIST" )

menu_item_getinfo( g_UnpauseVoteMenu, item, access, data, sizeof( data ), iPlayerName, sizeof( iPlayerName ), callback )
new voteid = str_to_num( data )

for (new i = 0; i < iPNum; i++ )
{
    Player = iPlayers[ i ]
    get_user_name( id, iPlayerName, sizeof( iPlayerName ) )
    client_print_color( Player, ( get_member( Player, m_iTeam ) == 1 ) ? print_team_red : print_team_blue , "%L", Player, "UNPAUSE_PLAYER_VOTED", iPlayerName, Player, ( ( item == 0 ) ? "OPTION_YES" : "OPTION_NO" ) )
}

g_Votes[ voteid ]++
/*
If this vote is decisive, then don't wait for the task, remove it and call the result function.
I guess it's better because people won't have to wait the additional x seconds
*/
if ( g_Votes[ 0 ] >= get_pcvar_num( cvar_UnpauseVoteAmount ) )
{
    remove_task( TASK_RESUME_VOTEMENU )
    Resume_Votemenu_Result()
}

return PLUGIN_HANDLED

}

public Resume_Votemenu_Result( ) { new iPlayers[ 32 ], iPNum, Player get_players( iPlayers, iPNum, "e", ( g_WhoPaused == 2 ) ? "CT" : "TERRORIST")

if ( g_Votes[ 0 ] >= get_pcvar_num( cvar_UnpauseVoteAmount ) )
{
    for ( new i = 0; i < iPNum; i++ )
    {
        Player = iPlayers[ i ]
        client_print_color( Player, ( g_WhoPaused == 2 ) ? print_team_blue : print_team_red, "%L", Player, "UNPAUSE_VOTE_SUCCESS" )
    }
    Pause_ResumeCmd()
}
else
{
    for ( new i = 0; i < iPNum; i++ )
    {
        Player = iPlayers[ i ]
        client_print_color( Player, ( g_WhoPaused == 2 ) ? print_team_blue : print_team_red, "%L", Player, "UNPAUSE_VOTE_FAIL" )
    }
}

g_Votes[ 0 ] = 0
g_Votes[ 1 ] = 0
g_CurrentlyVoting = 0

return PLUGIN_HANDLED

}

public Pause_ResumeCmd( ) { CleanReinitialize( ) Pause( mp_freezetime ) }

public ShowPauseText( ) { set_dhudmessage( 255, 255, 255, -1.0, 0.60, .holdtime = HOLD_INTERVAL - 0.1, .fadeintime = 0.1, .fadeouttime = 0.2 ) show_dhudmessage( 0, "%L", LANG_PLAYER, "PAUSE_TEXT", RemainingTime() )

if ( RemainingTime() <= 1 )
    g_iPaused = false

}

@PauseFunc( ){ g_iPaused = true

if ( g_iPauseQueued )
    g_iPauseQueued = false

Pause( get_pcvar_num( cvar_PauseDuration ) )
DisplayPauseProgress( )
set_task( get_pcvar_float(cvar_PauseDuration) - 0.1 , "Pause", mp_freezetime, _, _)

}

public Pause( const iSecAmount ) { new Float:lGameTime = get_gametime( ) //Sets the gametime. set_member_game( m_fRoundStartTime, lGameTime ) set_member_game( m_fRoundStartTimeReal, lGameTime ) set_member_game( m_iRoundTimeSecs, iSecAmount ) //Checks for BuyTime cvar. if ( get_pcvar_num( cvar_PauseBuyTime ) ) (IS_FREEZE_TIME && g_iPaused) ? set_pcvar_float(g_BuyTimePCvar, PAUSE_BUYTIME) : set_pcvar_float(g_BuyTimePCvar, g_BuyTimeOriginalPCvar)

//Updates the round timer
message_begin( MSG_ALL, iMsgRoundTime )
write_short( FREEZE_TIME )
message_end( )

}

stock DisplayPauseProgress( ) { for ( new player = 0; player < g_iMaxPlayers; player++ ) { if ( is_user_connected( player ) && is_user_alive( player ) ) rg_send_bartime( player, FREEZE_TIME, true ) }

set_task( HOLD_INTERVAL, "ShowPauseText", TASK_SHOWPROGRESS, _, _, "a", get_pcvar_num( cvar_PauseDuration ) - 1 ) // - 1 = https://github.com/s1lentq/ReGameDLL_CS/blob/dd243eaa0b5befb96bab8f113f43bc79e9bba098/regamedll/dlls/multiplay_gamerules.cpp#L456 is the reason for the - 1

return HC_CONTINUE

}

stock Float:RemainingTime( ) { return ( float ( get_member_game ( m_iRoundTimeSecs ) ) - get_gametime( ) + Float:get_member_game ( m_fRoundStartTimeReal ) ); }

SmileYzn commented 9 months ago

.menu should work to call pause. I did not want to register a lot of commands in pug for each feature. Since an simple menu can contain all commands