
   /* AMX Mod script.
   *
   * Based on AdminMod's HLDSLD Voting
   * (c) 2003, OLO
   * This file is provided as is (no warranties).
   *
   * For AMX 0.9.4 and higher
   */
   #include <amxmod>
   #include <amxmisc>
   new RTV_RATIO       = 60   // ratio in percentage
   new RTV_FREQUENCY   = 60   // frequnecy in seconds
   new RTV_EXTEND      = 10   // extend in minutes
   new RTV_MAXEXTEND   = 3    // how many times we can extend a map
   new RTV_DURATION    = 180  // how long we want to have a vote
   new RTV_TIME        = 210  // when auto vote comes at end of map (0 is
   disabled)
   enum VoteStatus {
     VoteNotBegun,
     VoteInProgress,
     VoteFinished
   }
   #define MAX_MAPS      64
   #define INVALID_MAP   -1
   new VoteStatus:g_voteStatus = VoteNotBegun
   new g_mapNames[MAX_MAPS][32]
   new g_mapNum
   new g_extendNum
   new g_userVote[33]
   new g_lastVote
   new  g_prefix[] = ""         // Prefix for messages (For example "RTV:
   ")
   public plugin_init(){
     register_plugin("Rock The Vote","0.9.4","default")
     register_clcmd( "say" , "handleSay" )
     register_concmd(   "amx_rtv",   "cmdRTV",   ADMIN_CFG,  "-  displays
   available commands for Rock The Vote")
     if ( vaultdata_exists( "RTV_RATIO" ) )
       loadSettings( 0 )
     else
       saveSettings( 0 )
     if  (  RTV_TIME  )   set_task(  float  (RTV_TIME)  , "startVoting" ,
   99669966, "" , 0 , "d" )
   }
   set_vaultdata_num( string[], value ){
     new buffer[8]
     numtostr(  value, buffer, 7 )
     return set_vaultdata( string , buffer )
   }
   set_rtvvalue( id, &value, string[], arg[] , argc ){
     if ( argc < 3 )
       console_print( id, "%s%s is set to %d", g_prefix, string , value )
     else  {
       value = strtonum ( arg )
       console_print( id, "%s%s changed to %d", g_prefix,string , value )
     }
   }
   public cmdRTV( id , level , cid )
   {
     if (!cmd_access(id,level,cid,0))
       return PLUGIN_HANDLED
     new arg1[32]
     read_argv(1, arg1, 31)
     if ( equali( "rockthevote" , arg1  ) )
       rockTheVote( id )
     else  if ( equali( "cancelvote" , arg1  ) )
       cancelVote( id )
     else  if ( equali( "denymap" , arg1  ) )  {
       read_argv(2, arg1, 31)
       denyMap( id,  arg1 )
     }
     else if ( equali( "save" , arg1  )  )
       saveSettings( id )
     else if ( equali( "load" , arg1  )  )
       loadSettings( id )
     else  {
       new arg2[8], argc = read_argc()
       read_argv(2, arg2, 7)
       if  (  equali(  "ratio"  , arg1  ) ) set_rtvvalue ( id, RTV_RATIO,
   arg1 , arg2, argc )
       else    if   (   equali(   "freq"   ,   arg1  )   )   set_rtvvalue
   (id,  RTV_FREQUENCY, arg1 , arg2, argc )
       else  if  (  equali(  "extend"  ,  arg1  )  )  set_rtvvalue  ( id,
   RTV_EXTEND, arg1 , arg2, argc )
       else  if  (  equali(  "maxextend"  ,  arg1  ) ) set_rtvvalue ( id,
   RTV_MAXEXTEND, arg1 , arg2, argc )
       else  if  (  equali(  "duration"  ,  arg1  )  ) set_rtvvalue ( id,
   RTV_DURATION, arg1 , arg2, argc )
       else  if ( equali( "time" , arg1  ) )set_rtvvalue ( id,  RTV_TIME,
   arg1 , arg2, argc )
       else{
         console_print( id , "Usage:  amx_rtv <command> [value]"  )
         console_print( id , "^trockthevote - start the voting" )
         console_print( id , "^tcancelvote - stop the voting"  )
         console_print(  id  ,  "^tdenymap <map> - remove votes for given
   map"   )
         console_print( id , "^tsave - save settings to vault"   )
         console_print( id , "^tload - load settings from vault" )
         console_print( id , "^tratio <value> - sets ratio in percentage"
   )
         console_print( id , "^tfreq <value> - sets frequnecy in seconds"
   )
         console_print(   id   ,  "^textend  <value>  -  sets  extend  in
   minutes"  )
         console_print(  id  , "^tmaxextend <value> - sets how many times
   we can extend a map"   )
         console_print(  id , "^tduration <value> - sets how long we want
   to have a vote"   )
         console_print(  id , "^ttime <value> - sets when auto vote comes
   at end of map (0 is disabled)"   )
       }
     }
     return PLUGIN_HANDLED
   }
   announce( pub, priv, {Float,_}:... ) {
     new msg[192]
     format_args( msg, 191, 2  )
     client_print(pub,print_chat,msg)
     console_print(priv, msg )
   }
   saveSettings( id ){
     if ( set_vaultdata_num( "RTV_RATIO", RTV_RATIO  ) &&
       set_vaultdata_num( "RTV_FREQUENCY", RTV_FREQUENCY  ) &&
       set_vaultdata_num( "RTV_EXTEND", RTV_EXTEND  ) &&
       set_vaultdata_num( "RTV_MAXEXTEND", RTV_MAXEXTEND  ) &&
       set_vaultdata_num( "RTV_DURATION", RTV_DURATION  ) &&
       set_vaultdata_num( "RTV_TIME", RTV_TIME  ) )
       console_print(  id, "%sSettings has been successfully saved to the
   vault",g_prefix)
     else  console_print(   id,   "%sFailed   to  save  settings  to  the
   vault",g_prefix)
   }
   loadSettings( id ){
     if ( vaultdata_exists( "RTV_RATIO" ) )  {
       RTV_RATIO = get_vaultdata( "RTV_RATIO"  )
       RTV_FREQUENCY = get_vaultdata( "RTV_FREQUENCY" )
       RTV_EXTEND = get_vaultdata( "RTV_EXTEND" )
       RTV_MAXEXTEND = get_vaultdata( "RTV_MAXEXTEND" )
       RTV_DURATION = get_vaultdata( "RTV_DURATION" )
       RTV_TIME = get_vaultdata("RTV_TIME"  )
       console_print(   id,  "%sSettings  loaded  successfully  from  the
   vault", g_prefix )
     }
     else  console_print(  id,  "%sCouldn't load settings from the vault.
   Data are missing or are corrupted",g_prefix )
   }
   resetVoteData( )
   {
     g_mapNum = 0
     for(new i = 1; i < 33; ++i)
       g_userVote[ i ] = INVALID_MAP
   }
   findMapId( mapname[] )
   {
     for(new i = 0;  i < g_mapNum; ++i )
       if ( equali( mapname, g_mapNames[ i ]  ) )
         return i
     return INVALID_MAP
   }
   calculateWinning( announce )
   {
     new winner = INVALID_MAP
     new mapVotes[MAX_MAPS] = { 0, ... }
     new a, plnum, players[32]
     get_players( players, plnum, "c"  )
     new maxVotes = plnum * RTV_RATIO / 100
     for(new i = 0; i < plnum; ++i) {
       a = g_userVote[ players[ i ] ]
       if ( a != INVALID_MAP ){
         if ( ++mapVotes[ a ] >= maxVotes ){
           maxVotes = mapVotes[ a ]
           winner = a
         }
       }
     }
     if ( announce  ) {
       if ( winner ==  INVALID_MAP )
         client_print(0,  print_chat ,"%sNo map has the %i votes required
   yet",  g_prefix,maxVotes )
       else {
         new mapname[32]
         if ( equali( g_mapNames[ winner ], "extend"  ) )
           format(mapname, 31, "Extend for %i minutes", RTV_EXTEND )
         else
           copy( mapname , 31, g_mapNames[ winner ]   )
         client_print(0,print_chat,"%s%s   is   winning   with   %i  %s",
   g_prefix,mapname , maxVotes, (maxVotes == 1 ) ? "vote" : "votes" )
       }
     }
     return winner
   }
   processVote( id , name[]  ) {
     new extend = 0
     if (  g_voteStatus != VoteInProgress )
       client_print(  id  ,print_chat  ,  "%sThere  is  no  map  vote  in
   progress",g_prefix)
     else  if  (  is_map_valid(  name  )  ||  (  ( extend = equali( name,
   "extend" ) ) == 1 ) )  {
       new playername[32]
       get_user_name( id , playername , 31)
       if ( extend && g_extendNum >= RTV_MAXEXTEND )
         client_print(id,print_chat,"%sSorry,  %s,  the  map  can  not be
   extended any longer",g_prefix, playername )
       else  {
         if (  g_userVote[ id ] != INVALID_MAP )
           client_print(  id  , print_chat ,"%sRemoving previous vote for
   %s", g_prefix,g_mapNames[ g_userVote[ id ] ] )
         if  ( ( g_userVote[ id ] = findMapId( name ) ) ==  INVALID_MAP )
   {
             if ( g_mapNum < MAX_MAPS )  {
               g_userVote[ id ] = g_mapNum
               copy( g_mapNames[ g_mapNum++ ] , 31 , name )
             }
         }
         new mapname[32]
         if ( extend )
           format(mapname, 31 , "Extend for %i minutes", RTV_EXTEND )
         else
           copy( mapname, 31, g_mapNames[ g_userVote[ id ] ]  )
         new votes = 0
         new players[32], plnum
         get_players( players, plnum  )
         for(new i = 0; i < plnum; ++i )
           if ( g_userVote[ players[ i ] ] == g_userVote[ id ] )
             votes++
         announce( 0 , id , "%sVote by %s -- %s now has %d %s", g_prefix,
             playername  ,  mapname  ,  votes,  ( votes == 1 ) ? "vote" :
   "votes" )
         calculateWinning( 1 )
       }
     }
     else  client_print(  id , print_chat, "%sSorry, %s, that map was not
   found on this server",g_prefix, name )
   }
   cancelVote( id ){
     if ( g_voteStatus == VoteInProgress ) {
       remove_task( 99779977 )
       g_voteStatus = VoteFinished
       g_lastVote = floatround( get_gametime() )
       announce( 0, id, "%sVoting has been cancelled!" ,g_prefix )
     }
     else    announce(   id,   id,   "%sThere   is   no   map   vote   in
   progress",g_prefix  )
   }
   rockTheVote( id ){
     if ( g_voteStatus == VoteInProgress )
       announce( id, id, "%sA map vote is already in progress",g_prefix )
     else  if ( floatround( get_gametime() ) - g_lastVote < RTV_FREQUENCY
   ) {
       new mintime = RTV_FREQUENCY / 60
       announce(id  ,  id  , "%sA map vote is not allowed within %i %s of
   %s", g_prefix,
         mintime, (mintime == 1) ? "minute" : "minutes" , g_lastVote ? "a
   previous vote" : "the map start" )
     }
     else  {
       resetVoteData( )
       new mintime = RTV_DURATION / 60
       announce(0,  id,  "%sMap  voting  has been enabled for %i %s.  Say
   'vote <mapname>' to vote",g_prefix,
         mintime , (mintime == 1) ? "minute" : "minutes" )
       announce(0,  id, "%sSay 'vote extend' to keep playing this map for
   more %i %s", g_prefix,
         RTV_EXTEND, (RTV_EXTEND == 1) ? "minute" : "minutes" )
       new param[1]
       param[0] = id
       set_task( float ( RTV_DURATION ), "endMapVote" , 99779977 ,param ,
   1 )
       g_voteStatus = VoteInProgress
     }
   }
   denyMap( id, name[] ){
     new mapid
     if ( g_voteStatus != VoteInProgress )
       announce( id ,id, "%sThere is no map vote in progress" , g_prefix)
     else if ( (mapid = findMapId( name ))  == INVALID_MAP )
       announce(id,id,"%sThere are no votes for that map",g_prefix)
     else  {
       new votesRemoved = 0
       for (new i = 1; i < 33; ++i ) {
         if ( g_userVote[i] == mapid ) {
           g_userVote[i] = INVALID_MAP
           votesRemoved++
         }
       }
       client_print(0,id,"%s%i   %s   for   %s   removed",   g_prefix   ,
   votesRemoved,
         (votesRemoved == 1) ? "vote" : "votes" , name )
     }
   }
   public handleSay( id , level, cid ){
     new said[48], cmd[16], name[32]
     read_args( said, 47 )
     remove_quotes( said )
     parse( said , cmd , 15 , name , 31 )
     if ( equali( cmd, "vote" ) )
       processVote( id, name )
     else if ( get_user_flags( id ) & ADMIN_LEVEL_A  )   {
       if ( equali( cmd, "cancelvote" ) )
         cancelVote( id )
       else if ( equali( cmd, "rockthevote" ) )
         rockTheVote( id )
       else if ( equali( cmd, "denymap" ) )
         denyMap( id , name )
     }
     return PLUGIN_CONTINUE
   }
   public startVoting( )
     rockTheVote( 0 )
   new g_votingOver[] = "Voting is now over."
   public endMapVote( param[] ) {
     if ( g_voteStatus != VoteInProgress ) return
     new winner = calculateWinning( 0 )
     if ( winner == INVALID_MAP )
       announce(0,0    ,"%s%s    No    map    got    enough    votes   to
   win",g_prefix,g_votingOver)
     else if ( equali( g_mapNames[ winner ], "extend" ) )  {
       announce(0,0,"%s%s  The  map  will  be  extended  for more %i %s",
   g_prefix,g_votingOver,
         RTV_EXTEND,(RTV_EXTEND == 1) ? "minute" : "minutes" )
       set_cvar_num(  "mp_timelimit"  ,  get_cvar_num( "mp_timelimit" ) +
   RTV_EXTEND  )
       g_extendNum++
       if ( RTV_TIME && !task_exists( 99669966 ) )
           set_task( float(RTV_TIME) , "startVoting" , 99669966, "" , 0 ,
   "d" )
     }
     else  {
       remove_task( 99669966 )
       set_cvar_string( "amx_nextmap" , g_mapNames[ winner ] )
       if ( param[0] ) {
         announce(0,0,"%s%s     Changing     map     to     %s",g_prefix,
   g_votingOver,g_mapNames[ winner ] )
         set_cvar_float( "mp_timelimit" , 0.0001 )
       }
       else    announce(0,0,"%s%s   Next   map   is   now   %s",g_prefix,
   g_votingOver, g_mapNames[ winner ] )
     }
     g_lastVote = floatround( get_gametime() )
     g_voteStatus = VoteFinished
   }
   public client_disconnect(id)
     g_userVote[ id ] = INVALID_MAP
