Advertisement
Guest User

Untitled

a guest
Sep 12th, 2024
40
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 28.08 KB | None | 0 0
  1. // #define DEBUG
  2.  
  3. /*
  4.     Modes:
  5.         0: Always stay on one mod unless changed manually with admin command.  (Map votes only)
  6.         1: Play # maps then next mod will default to next in polymorph.ini (Map votes only)
  7.         2: Play # maps then next mod will be chosen by vote. (Map and Mod votes)
  8.        
  9.     Changelog:
  10.         0.6
  11.             Added function to set the default nextmap to be used when nextmod is set.
  12.             Added functionality to mod vote to choose options randomly and quantity can be limited with SELECTMODS (default 5) (requires re-compile)
  13.             Added current next mod indicator in cmdSetNextmod() function (aka amx_nextmod).
  14.             Drastically improved reading the .ini file (IMO).
  15.             Added beta amx_votemod which just starts the default vote for mod (which then calls the map vote)
  16.         0.7
  17.             Added check to disallow end of map vote if vote is already in progress from amx_votemod.
  18.             Added confirmation to the cmdSetNextMod() function (mod and map)
  19.             Added chat time (using mp_chattime cvar) when map is changed due to amx_votemod.
  20.             Fixed server crash when changing map due to amx_votemod.
  21.         0.8
  22.             Changed to using a folder for .ini and .cfg files.  /addons/amxmodx/configs/polymorph/ for readability
  23.             Added dynamic natives to enable retreiving and executing local variables and functions.
  24.             Removed gamename stuff because it can be done with a separate plugin with natives.
  25.             Added cvars for thismod and nextmod (used for example in Polymorph: GameName)
  26.             Added ML :(
  27.         1.0
  28.             Changed loading of MODs.  Mods are now loaded modularly.  One .ini file for each mod (in /polymorph).  No more polymorph.ini.  If MOD fails to load the whole plugin does not fail!
  29.         1.0.1
  30.             Added check for 0 mods loaded.  Set's plugin as failed.
  31.         1.0.2
  32.             Increased string length for variabls used for cvars in initModLoad() and loadMod() (now using STRLEN_DATA)
  33.         1.0.3 (2010/04/18)
  34.             Bug fix:  Nextmap is updated to reflect the nextmod's maps when there are no votes.
  35.         1.1.0
  36.             Removed cvar poly_mapspermod and moved setting to MOD file.
  37.         1.1.1
  38.             Updated error handling to be more accurate in initModLoad().
  39.         1.1.2
  40.             Fixed error when UpdatePluginFile() called with no mods loaded.
  41.  
  42. */
  43.  
  44. #include <amxmodx>
  45. #include <amxmisc>
  46.  
  47. // String Lengths
  48. #define STRLEN_DATA 128 // data from file and 'etc.' data
  49. #define STRLEN_PATH 128 // full file path
  50. #define STRLEN_NAME 32  // plugin Name e.g. "GunGame Mod"
  51. #define STRLEN_FILE 32  // single filename w/o path
  52. #define STRLEN_MAP 32   // map name
  53.  
  54. // Limits
  55. #define MODS_MAX 10     // Maximum number of mods.
  56.  
  57. // Number of main options in vote
  58. #define SELECTMODS 5
  59. #define SELECTMAPS 5
  60.  
  61. // Task IDs lol
  62. #define TASK_ENDOFMAP 3141
  63. #define TASK_FORCED_MAPCHANGE 314159
  64.  
  65. // ammount of time left (in seconds) to trigger end of map vote
  66. #define TIMELEFT_TRIGGER 129
  67.  
  68. #if defined DEBUG
  69.     new debug_voters = 0
  70. #endif
  71.  
  72. new g_szModNames[MODS_MAX][STRLEN_NAME] // Mod Names
  73. new Array:g_aModMaps[MODS_MAX]          // Per-mod Map Names List
  74. new Array:g_aModPlugins[MODS_MAX]       // Per-mod Plugin Names List
  75. new Array:g_aCfgList                    // Array to hold cvars for 'ThisMod'
  76.  
  77. new g_iMapNums[MODS_MAX]            // Number of maps for each mod
  78. new g_szThisMod[STRLEN_NAME]        // Name of 'ThisMod'
  79.  
  80. new g_iThisMod = -1         // Index of 'ThisMod'
  81. new g_iNextMod = 0          // Index of 'NextMod'
  82. new g_iModCount = 0         // Number of MODs loaded
  83.  
  84. new g_iMapsPlayed           // Number of maps played on current MOD.
  85. new g_iMapsPerMod[MODS_MAX] // Number of maps played before a MOD change.
  86.  
  87. new bool:g_isLastMap = false            // Number of maps played on current mod.
  88. new bool:g_selected = false
  89.  
  90. public plugin_precache()
  91. {
  92.    precache_sound("misc/nextmap.wav")
  93.    precache_sound("misc/nextmode.wav")
  94. }
  95.  
  96. // Voting stuff
  97. new g_voteNum
  98. new g_nextName[SELECTMAPS]
  99. new g_voteMapCount[SELECTMAPS + 2]
  100. new g_nextModId[MODS_MAX]
  101. new g_voteModCount[MODS_MAX + 2]
  102.  
  103. // Compatibility vars
  104. new g_teamScore[2]
  105. new g_coloredMenus
  106.  
  107. /* Cvar Pointers */
  108. // My cvars
  109. new g_pMode
  110. new g_pExtendMod // bool; allow extending mod
  111. new g_pExtendStep
  112. new g_pExtendMax
  113. new g_pThisMod
  114. new g_pNextMod
  115.  
  116. // Existing cvars
  117. new g_pNextmap
  118. new g_pTimeLimit
  119. new g_pVoteAnswers
  120. new g_pChatTime
  121.  
  122. /* Constants */
  123. // Voting delays
  124. new const iVoteTime = 15 // Time to display the menu.
  125. new const Float:fVoteTime = 15.0 // Time to choose an option.
  126. new const Float:fBetweenVote = 15.0 // Time between mod vote ending and map vote starting.
  127.  
  128.  
  129. public plugin_init()
  130. {
  131.     register_plugin("Polymorph: Mod Manager", "1.1.2", "Fysiks")
  132.     register_cvar("Polymorph", "v1.1.2 by Fysiks", FCVAR_SERVER|FCVAR_SPONLY)
  133.    
  134.     register_dictionary("mapchooser.txt")
  135.     // register_dictionary("polymorph.txt")
  136.     // register_dictionary("common.txt")
  137.    
  138.     /* Register Cvars */
  139.     g_pExtendMax = register_cvar("amx_extendmap_max", "90")
  140.     g_pExtendStep = register_cvar("amx_extendmap_step", "15")
  141.     g_pMode = register_cvar("poly_mode", "2")
  142.     g_pExtendMod = register_cvar("poly_extendmod", "1")
  143.     g_pThisMod = register_cvar("poly_thismod", "")
  144.     g_pNextMod = register_cvar("poly_nextmod", "")
  145.    
  146.     /* Client Commands */
  147.     register_clcmd("say nextmod", "sayNextmod")
  148.     register_clcmd("say thismod", "sayThismod")
  149.    
  150.     /* Console Commands */
  151.     register_concmd("amx_nextmod", "cmdSetNextmod", ADMIN_MAP, " - Set the next mod manually")
  152.     register_concmd("amx_votemod", "cmdVoteMod", ADMIN_MAP, " - Start a vote for the next mod")
  153.  
  154.     /* Server Commands */
  155. #if defined DEBUG
  156.     register_srvcmd("list", "function") // Debug
  157. #endif
  158.  
  159.     /* Compatibility */
  160.     g_coloredMenus = colored_menus()
  161.     if (cstrike_running())
  162.         register_event("TeamScore", "team_score", "a")
  163.  
  164.     /* Register Menus */
  165.     register_menucmd(register_menuid("Choose Nextmap:"), (-1^(-1<<(SELECTMAPS+2))), "countMapVotes")
  166.     register_menucmd(register_menuid("Choose Nextmod:"), (-1^(-1<<(SELECTMODS+2))), "countModVotes")
  167.    
  168. }
  169.  
  170. public plugin_cfg()
  171. {
  172.     /* Get Cvar Pointers */
  173.     g_pNextmap = get_cvar_pointer("amx_nextmap")
  174.     g_pTimeLimit = get_cvar_pointer("mp_timelimit")
  175.     g_pVoteAnswers = get_cvar_pointer("amx_vote_answers")
  176.     g_pChatTime = get_cvar_pointer("mp_chattime")
  177.  
  178.     new szData[STRLEN_DATA]
  179.     new szFilepath[STRLEN_PATH], szConfigDir[STRLEN_PATH]
  180.    
  181.     get_configsdir(szConfigDir, charsmax(szConfigDir))
  182.  
  183.     /* Get ThisMod Name */
  184.     formatex(szFilepath, charsmax(szFilepath), "%s/%s", szConfigDir, "plugins-polymorph.ini")
  185.     new f = fopen(szFilepath, "rt")
  186.     if(f)
  187.     {
  188.         fgets(f, szData, charsmax(szData))
  189.         fclose(f)
  190.         replace(szData, charsmax(szData), ";ThisMod:", "")
  191.         trim(szData)
  192.         parse(szData, g_szThisMod, charsmax(g_szThisMod))
  193.     }
  194.    
  195.     /*
  196.         Check for folder "/polymorph/"
  197.         If it exists, load MODs.
  198.      */
  199.     formatex(szFilepath, charsmax(szFilepath), "%s/%s", szConfigDir, "polymorph")
  200.     if( dir_exists(szFilepath) )
  201.     {
  202.         /* Load MODs */
  203.         initModLoad()
  204.     }
  205.     else
  206.     {
  207.         new error[64]
  208.         formatex(error, charsmax(error), "%s/ does not exist.", szFilepath)
  209.         set_fail_state(error)
  210.     }
  211.    
  212.     /* Set default nextmod/map depending on maps played and mode */
  213.     new szMapsPlayed[4]
  214.     get_localinfo("mapcount", szMapsPlayed, charsmax(szMapsPlayed))
  215.     g_iMapsPlayed = str_to_num(szMapsPlayed)
  216.     g_iMapsPlayed++
  217.  
  218.     switch( get_pcvar_num(g_pMode) )
  219.     {
  220.         case 0:
  221.         {
  222.             setNextMod(g_iThisMod)
  223.             g_isLastMap = false
  224.         }
  225.         case 1,2:
  226.         {
  227.             // Set default nextmod depending on how many maps have been played on this mod
  228.             if( !( g_iMapsPlayed < g_iMapsPerMod[g_iThisMod] ) ) // Do this in end map task too? to allow changing cvar mid map.
  229.             {
  230.                 g_isLastMap = true
  231.                 setNextMod((g_iThisMod + 1) % g_iModCount)
  232.             }
  233.             else
  234.             {
  235.                 setNextMod(g_iThisMod)
  236.             }
  237.         }
  238.         default: // Mode 0
  239.         {
  240.             setNextMod(g_iThisMod)
  241.             g_isLastMap = false
  242.         }
  243.     }
  244.     setDefaultNextmap()
  245.    
  246.     /* Set task to check when map ends */
  247.     set_task(20.0, "taskEndofMap", TASK_ENDOFMAP, "", 0, "b")
  248. }
  249.  
  250. public plugin_end()
  251. {
  252.     // If this map still qualifies to be the last then reset mapcount for next mod.
  253.     if( !( g_iMapsPlayed < g_iMapsPerMod[g_iThisMod] ) )
  254.     {
  255.         g_iMapsPlayed = 0
  256.     }
  257.  
  258.     new szMapsPlayed[4]
  259.     num_to_str(g_iMapsPlayed, szMapsPlayed, charsmax(szMapsPlayed))
  260.     set_localinfo("mapcount", szMapsPlayed)
  261.    
  262.     if( g_iThisMod != g_iNextMod )
  263.     {
  264.         UpdatePluginFile()
  265.     }
  266. }
  267.  
  268. /*
  269.     Plugin Natives
  270. */
  271. public plugin_natives()
  272. {
  273.     // Polymorph Natives.  Make it modular!
  274.     register_library("polymorph")
  275.     register_native("polyn_endofmap", "_polyn_endofmap")
  276.     register_native("polyn_get_thismod", "_polyn_get_thismod")
  277.     register_native("polyn_get_nextmod", "_polyn_get_nextmod")
  278.     register_native("polyn_votemod", "_polyn_votemod")
  279. }
  280.  
  281. // Native: Execute the end of map vote.
  282. public _polyn_endofmap(iPlugin, iParams)
  283. {
  284.     execEndofMap()
  285. }
  286.  
  287. // Native: Get this mod's name and return it's id
  288. public _polyn_get_thismod(iPlugin, iParams)
  289. {
  290.     new iChars = get_param(2)
  291.     new szModName[STRLEN_NAME]
  292.     copy(szModName, charsmax(szModName), g_szModNames[g_iThisMod])
  293.     set_string(1, szModName, iChars)
  294.     return g_iThisMod
  295. }
  296.  
  297. // Native: Get the next mod's name and returns it's id
  298. public _polyn_get_nextmod(iPlugin, iParams)
  299. {
  300.     new iChars = get_param(2)
  301.     new szModName[STRLEN_NAME]
  302.     copy(szModName, charsmax(szModName), g_szModNames[g_iNextMod])
  303.     set_string(1, szModName, iChars)
  304.     return g_iNextMod
  305. }
  306.  
  307. // Native: Start Mod Vote (and map vote), force mapchange.
  308. public _polyn_votemod()
  309. {
  310.     startModVote()
  311.     set_task(50.0, "intermission", TASK_FORCED_MAPCHANGE)
  312. }
  313.  
  314.  
  315. /*
  316.  *  Admin commands
  317.  */
  318. public cmdSetNextmod(id, level, cid)
  319. {
  320.     if(!cmd_access(id, level, cid, 1))
  321.         return PLUGIN_HANDLED
  322.    
  323.     if(read_argc() == 1)
  324.     {
  325.         console_print(id, "You are currently playing %s", g_szModNames[g_iThisMod]) // Need ML
  326.         console_print(id, "Available MODs are:") // Need ML
  327.        
  328.         // Print available mods (menu-like)
  329.         for(new i = 0; i < g_iModCount; i++)
  330.         {
  331.             console_print(id, i == g_iNextMod ? "%d) %s <<< Следующий мод" : "%d) %s", i+1, g_szModNames[i])
  332.             // console_print(id, i == g_iNextMod ? "%d) %s <<< Следующий мод" : "%d) %s", i+1, g_szModNames[i]) // Need ML
  333.         }
  334.        
  335.         new szCmdName[32]
  336.         read_argv(0, szCmdName, charsmax(szCmdName))
  337.         console_print(id, "To set the next mod, type ^"%s #^"", szCmdName)
  338.         // console_print(id, "%L", id, "SET_NEXTMOD", szCmdName) // ML
  339.     }
  340.     else
  341.     {
  342.         new szArg[3]
  343.         read_argv(1, szArg, charsmax(szArg))
  344.         if( isdigit(szArg[0]) )
  345.         {
  346.             new modid = str_to_num(szArg) - 1
  347.             if( 0 <= modid < g_iModCount )
  348.             {
  349.                 if( modid == g_iNextMod )
  350.                 {
  351.                     console_print(id, "Следующий мод уже выбран %s", g_szModNames[g_iNextMod]) // Need ML
  352.                 }
  353.                 else
  354.                 {
  355.                     setNextMod(modid)
  356.                     setDefaultNextmap()
  357.                     // Reset g_iMapsPlayed ??
  358.                     console_print(id, "Следующий мод уже выбран %s", g_szModNames[g_iNextMod])
  359.                     // console_print(id, "%L", id, "NEXTMOD_NOW", g_szModNames[g_iNextMod]) // ML
  360.  
  361.                     new szNextMap[STRLEN_MAP]
  362.                     get_pcvar_string(g_pNextmap, szNextMap, charsmax(szNextMap))
  363.                     console_print(id, "След. карта %s", szNextMap)
  364.                     // console_print(id, "%L", id, "NEXTMAP_NOW", szNextMap) // ML
  365.                 }
  366.             }
  367.             else
  368.             {
  369.                 console_print(id, "Invalid Option")
  370.                 // console_print(id, "%L", id, "INVALID_OPTION") // ML
  371.             }
  372.         }
  373.         else
  374.         {
  375.             console_print(id, "Invalid Option")
  376.             // console_print(id, "%L", id, "INVALID_OPTION") // ML
  377.         }
  378.     }
  379.     return PLUGIN_HANDLED
  380. }
  381.  
  382. public cmdVoteMod(id, level, cid)
  383. {
  384.     if(!cmd_access(id, level, cid, 1))
  385.         return PLUGIN_HANDLED
  386.  
  387.     // Start vote.
  388.     // if(vote task is running) then don't allow
  389.     if( get_timeleft() > TIMELEFT_TRIGGER && !task_exists(TASK_FORCED_MAPCHANGE) )
  390.     {
  391.         startModVote()
  392.         set_task(50.0, "intermission", TASK_FORCED_MAPCHANGE)
  393.     }
  394.     else
  395.     {
  396.         console_print(id, "Голосование еще не доступно")
  397.         // console_print(id, "%L", id, "VOTE_NOT_ALLOWED") // ML
  398.     }
  399.    
  400.     return PLUGIN_HANDLED
  401. }
  402.  
  403. /*
  404.  *  Say functions
  405.  */
  406. public sayNextmod()
  407. {
  408.     client_print(0, print_chat, "Следующий мод: %s", g_szModNames[g_iNextMod])
  409.     // client_print(0, print_chat, "%L %s", LANG_PLAYER, "NEXT_MOD", g_szModNames[g_iNextMod]) // ML
  410. }
  411.  
  412. public sayThismod()
  413. {
  414.     client_print(0, print_chat, "Текущий мод: %s", g_szModNames[g_iThisMod])
  415.     // client_print(0, print_chat, "%L %s", LANG_PLAYER, "THIS_MOD", g_szModNames[g_iThisMod]) // ML
  416. }
  417.  
  418.  
  419. /*
  420.  *  End of Map functions
  421.  */
  422. public taskEndofMap()
  423. {
  424.     new winlimit = get_cvar_num("mp_winlimit")   // Not using pcvars to allow cross-mod compatibility
  425.     new maxrounds = get_cvar_num("mp_maxrounds")
  426.    
  427.     if (winlimit)
  428.     {
  429.         new c = winlimit - 2
  430.        
  431.         if ((c > g_teamScore[0]) && (c > g_teamScore[1]))
  432.         {
  433.             g_selected = false
  434.             return
  435.         }
  436.     }
  437.     else if (maxrounds)
  438.     {
  439.         if ((maxrounds - 2) > (g_teamScore[0] + g_teamScore[1]))
  440.         {
  441.             g_selected = false
  442.             return
  443.         }
  444.     }
  445.     else
  446.     {
  447.         new timeleft = get_timeleft()
  448.        
  449.         if (timeleft < 1 || timeleft > TIMELEFT_TRIGGER)
  450.         {
  451.             g_selected = false
  452.             return
  453.         }
  454.     }
  455.    
  456.     if (g_selected)
  457.         return
  458.  
  459.     g_selected = true
  460.    
  461.     execEndofMap()
  462. }
  463.  
  464. public execEndofMap()
  465. {
  466.     // Disallow vote if someone put up vote for new mod already.
  467.     if( task_exists(TASK_FORCED_MAPCHANGE) )
  468.         return
  469.    
  470.     switch( get_pcvar_num(g_pMode) )
  471.     {
  472.         case 0,1:
  473.         {
  474.             startMapVote()
  475.         }
  476.         case 2:
  477.         {
  478.             if( g_isLastMap )
  479.             { // Time to decide on new mod.
  480.                 startModVote()
  481.             }
  482.             else
  483.             { // Stay on this mod ( so only do map vote)
  484.                 startMapVote()
  485.             }
  486.         }
  487.         default: // Mode 0
  488.         {
  489.             startMapVote()
  490.         }
  491.     }
  492.    
  493.     // g_selected = true
  494. }
  495.  
  496. /*
  497.  *  Vote functions
  498.  */
  499. public startModVote()
  500. {
  501.     // Display Mod Menu
  502.    
  503.     new menu[512], a = 0, mkeys = (1<<SELECTMODS + 1) // The "None" key
  504.     new pos = format(menu, 511, g_coloredMenus ? "\y%s:\w^n^n" : "%s:^n^n", "Голосование за следующий мод")
  505.     // new pos = format(menu, 511, g_coloredMenus ? "\y%L:\w^n^n" : "%L:^n^n", LANG_SERVER, "CHOOSE_NEXTMOD") // ML
  506.     new modNum = g_iModCount - 1 // -1 because we exclude current running mod.
  507.     new dmax = (modNum > SELECTMODS) ? SELECTMODS : modNum
  508.    
  509.     for (g_voteNum = 0; g_voteNum < dmax; ++g_voteNum)
  510.     {
  511.         do
  512.             a = random(g_iModCount)
  513.         while ( a == g_iThisMod || isModInMenu(a) )
  514.        
  515.         g_nextModId[g_voteNum] = a
  516.         pos += format(menu[pos], 511, "%d. %s^n", g_voteNum + 1, g_szModNames[a]);
  517.         mkeys |= (1<<g_voteNum)
  518.         g_voteModCount[g_voteNum] = 0
  519.         a++
  520.     }
  521.    
  522.     menu[pos++] = '^n'
  523.     g_voteModCount[SELECTMODS] = 0
  524.     g_nextModId[SELECTMODS] = g_iThisMod
  525.     g_voteModCount[SELECTMODS + 1] = 0
  526.    
  527.     if( get_pcvar_num(g_pExtendMod) )
  528.     {
  529.         pos += format(menu[pos], 511, "%d. Прод. %s^n", SELECTMODS + 1, g_szModNames[g_iThisMod])
  530.         // pos += format(menu[pos], 511, "%d. %L^n", SELECTMAPS + 1, LANG_SERVER, "EXTEND_MOD", g_szModNames[g_iThisMod]) // ML
  531.         mkeys |= (1<<SELECTMODS)
  532.     }
  533.  
  534.     format(menu[pos], 511, "%d. %L", SELECTMODS+2, LANG_SERVER, "NONE")
  535.    
  536.     show_menu(0, mkeys, menu, iVoteTime, "Голосование за след. мод:")
  537.    
  538.     set_task(fVoteTime, "checkModVotes")
  539.     client_print(0, print_chat, "Голосование за следующий мод...")
  540.     // client_print(0, print_chat, "%L", LANG_SERVER, "TIME_CHOOSE_MOD") // ML
  541.     client_cmd(0, "spk misc/nextmode")
  542.     log_amx("Vote: Voting for the next mod started")
  543. }
  544.  
  545. public countModVotes(id, key)
  546. {
  547.     // Count Mod Votes
  548.  
  549.     if (get_pcvar_num(g_pVoteAnswers))
  550.     {
  551.         new name[32]
  552.         get_user_name(id, name, 31)
  553.        
  554.         if (key == SELECTMODS)
  555.             client_print(0, print_chat, "%s выбрал продление мода", name)
  556.             // client_print(0, print_chat, "%L", LANG_PLAYER, "CHOSE_EXT_MOD", name) // ML
  557.         else if (key < SELECTMODS)
  558.             client_print(0, print_chat, "%L", LANG_PLAYER, "X_CHOSE_X", name, g_szModNames[g_nextModId[key]])
  559.     }
  560.     ++g_voteModCount[key]
  561.  
  562. #if defined DEBUG
  563.     debug_voters++
  564.     client_print(0, print_chat, "POLY_DEBUG: Someone just voted for %d", key)
  565.     server_print("POLY_DEBUG: Someone just voted for %d", key)
  566. #endif
  567.    
  568.     return PLUGIN_HANDLED
  569. }
  570.  
  571. public checkModVotes()
  572. {
  573. #if defined DEBUG
  574.     client_print(0, print_chat, "POLY_DEBUG: # of voters: %d", debug_voters)
  575.     server_print("POLY_DEBUG: # of voters: %d", debug_voters)
  576.     debug_voters = 0
  577. #endif
  578.    
  579.     // Check Mod Votes
  580.     new b = 0
  581.    
  582.     for (new a = 0; a < g_voteNum; ++a)
  583.         if (g_voteModCount[b] < g_voteModCount[a])
  584.             b = a
  585.  
  586.    
  587.     if (g_voteModCount[SELECTMODS] > g_voteModCount[b] )
  588.     {
  589.         setNextMod(g_iThisMod)
  590.         client_print(0, print_chat, "%s был продлен на одну карту", g_szModNames[g_iNextMod])
  591.         // client_print(0, print_chat, "%L", LANG_PLAYER, "CHO_FIN_EXT_MOD", g_szModNames[g_iNextMod]) // ML
  592.        
  593.         // Decrement maps played to only extend mod by one map.
  594.         new szMapsPlayed[4]
  595.         g_iMapsPlayed--
  596.         num_to_str(g_iMapsPlayed, szMapsPlayed, charsmax(szMapsPlayed))
  597.         set_localinfo("mapcount", szMapsPlayed)
  598.     }
  599.     else
  600.     {
  601.         setNextMod(g_nextModId[b]) // Set g_iNextMod
  602.        
  603.         client_print(0, print_chat, "Голосование завершено. След. мод %s", g_szModNames[g_iNextMod])
  604.         // client_print(0, print_chat, "%L", LANG_PLAYER, "CHO_FIN_NEXT_MOD", g_szModNames[g_iNextMod]) // ML
  605.         log_amx("Vote: Voting for the next mod finished. The nextmod will be %s", g_szModNames[g_iNextMod])
  606.     }
  607.  
  608.     // Set new default map to correspond to the next mod.
  609.     setDefaultNextmap()
  610.    
  611.     set_task(fBetweenVote, "startMapVote")
  612. }
  613.  
  614. public startMapVote()
  615. {
  616.     // Display Map Menu
  617.    
  618.     new menu[512], a, mkeys = (1<<SELECTMAPS + 1)
  619.  
  620.     new pos = format(menu, 511, g_coloredMenus ? "\y%L:\w^n^n" : "%L:^n^n", LANG_SERVER, "CHOOSE_NEXTM")
  621.     new mapNum = g_iMapNums[g_iNextMod]
  622.     new dmax = (mapNum > SELECTMAPS) ? SELECTMAPS : mapNum
  623.    
  624.     for (g_voteNum = 0; g_voteNum < dmax; ++g_voteNum)
  625.     {
  626.         a = random_num(0, mapNum - 1)
  627.        
  628.         while (isInMenu(a))
  629.             if (++a >= mapNum) a = 0
  630.        
  631.         g_nextName[g_voteNum] = a
  632.         pos += format(menu[pos], 511, "%d. %a^n", g_voteNum + 1, ArrayGetStringHandle(g_aModMaps[g_iNextMod], a));
  633.         mkeys |= (1<<g_voteNum)
  634.         g_voteMapCount[g_voteNum] = 0
  635.     }
  636.    
  637.     menu[pos++] = '^n'
  638.     g_voteMapCount[SELECTMAPS] = 0
  639.     g_voteMapCount[SELECTMAPS + 1] = 0
  640.    
  641.  
  642.     new mapname[32]
  643.     get_mapname(mapname, 31)
  644.     if( g_iThisMod == g_iNextMod ) // If staying on this mod allow extending the map.
  645.     {
  646.         if( get_pcvar_float(g_pTimeLimit) < get_pcvar_float(g_pExtendMax) )
  647.         {
  648.             pos += format(menu[pos], 511, "%d. %L^n", SELECTMAPS + 1, LANG_SERVER, "EXTED_MAP", mapname)
  649.             mkeys |= (1<<SELECTMAPS)
  650.         }
  651.     }
  652.  
  653.     format(menu[pos], 511, "%d. %L", SELECTMAPS+2, LANG_SERVER, "NONE")
  654.    
  655.     show_menu(0, mkeys, menu, iVoteTime, "Голосование за след. карту:")
  656.     set_task(fVoteTime, "checkMapVotes")
  657.     client_print(0, print_chat, "%L", LANG_SERVER, "TIME_CHOOSE")
  658.     client_cmd(0, "spk misc/nextmap")
  659.     log_amx("Vote: Voting for the nextmap started")
  660. }
  661.  
  662. public countMapVotes(id, key)
  663. {
  664.     if (get_pcvar_num(g_pVoteAnswers))
  665.     {
  666.         new name[32]
  667.         get_user_name(id, name, 31)
  668.        
  669.         if (key == SELECTMAPS)
  670.             client_print(0, print_chat, "%L", LANG_PLAYER, "CHOSE_EXT", name)
  671.         else if (key < SELECTMAPS)
  672.         {
  673.             new map[32];
  674.             ArrayGetString(g_aModMaps[g_iNextMod], g_nextName[key], map, charsmax(map))
  675.             client_print(0, print_chat, "%L", LANG_PLAYER, "X_CHOSE_X", name, map)
  676.         }
  677.     }
  678.     ++g_voteMapCount[key]
  679.    
  680.     return PLUGIN_HANDLED
  681. }
  682.  
  683. public checkMapVotes()
  684. {
  685.     new b = 0
  686.    
  687.     for (new a = 0; a < g_voteNum; ++a)
  688.         if (g_voteMapCount[b] < g_voteMapCount[a])
  689.             b = a
  690.  
  691.    
  692.     if (g_voteMapCount[SELECTMAPS] > g_voteMapCount[b]
  693.         && g_voteMapCount[SELECTMAPS] > g_voteMapCount[SELECTMAPS+1])
  694.     {
  695.         new mapname[32]
  696.        
  697.         get_mapname(mapname, 31)
  698.         new Float:steptime = get_pcvar_float(g_pExtendStep)
  699.         set_pcvar_float(g_pTimeLimit, get_pcvar_float(g_pTimeLimit) + steptime)
  700.         client_print(0, print_chat, "%L", LANG_PLAYER, "CHO_FIN_EXT", steptime)
  701.         log_amx("Vote: Voting for the nextmap finished. Map %s will be extended to next %.0f minutes", mapname, steptime)
  702.        
  703.         return
  704.     }
  705.    
  706.     new smap[32]
  707.     if (g_voteMapCount[b] && g_voteMapCount[SELECTMAPS + 1] <= g_voteMapCount[b])
  708.     {
  709.         ArrayGetString(g_aModMaps[g_iNextMod], g_nextName[b], smap, charsmax(smap));
  710.         set_pcvar_string(g_pNextmap, smap);
  711.     }
  712.     else // added 1.0.3
  713.     {
  714.         ArrayGetString(g_aModMaps[g_iNextMod], g_nextName[0], smap, charsmax(smap));
  715.         set_pcvar_string(g_pNextmap, smap);
  716.     }
  717.    
  718.     get_pcvar_string(g_pNextmap, smap, 31)
  719.     client_print(0, print_chat, "%L", LANG_PLAYER, "CHO_FIN_NEXT", smap)
  720.     log_amx("Vote: Voting for the nextmap finished. The nextmap will be %s", smap)
  721. }
  722.  
  723.  
  724. /*
  725.  *  Auxillary Functions
  726.  */
  727.  
  728. /* Set the 'NextMod' index */
  729. stock setNextMod(index)
  730. {
  731.     g_iNextMod = index
  732.     set_pcvar_string(g_pNextMod, g_szModNames[g_iNextMod])
  733. }
  734.  
  735. /* Set the default nextmap for the next mod */
  736. stock setDefaultNextmap()
  737. {
  738.     new szMapName[32]
  739.     ArrayGetString(g_aModMaps[g_iNextMod], 0, szMapName, charsmax(szMapName))
  740.     set_pcvar_string(g_pNextmap, szMapName)
  741. }
  742.  
  743. stock bool:loadMaps(szConfigDir[], szMapFile[], iModIndex)
  744. {
  745.     new szFilepath[STRLEN_PATH], szData[STRLEN_MAP]
  746.  
  747.     g_iMapNums[iModIndex] = 0
  748.     formatex(szFilepath, charsmax(szFilepath), "%s/%s", szConfigDir, szMapFile)
  749.  
  750.     new f = fopen(szFilepath, "rt")
  751.  
  752.     if(!f)
  753.         return false
  754.  
  755.     while(!feof(f))
  756.     {
  757.         fgets(f, szData, charsmax(szData))
  758.         trim(szData)
  759.         if(!szData[0] || szData[0] == ';' || (szData[0] == '/' && szData[1] == '/'))
  760.             continue
  761.         if(is_map_valid(szData))
  762.         {
  763.             ArrayPushString(g_aModMaps[iModIndex], szData)
  764.             g_iMapNums[iModIndex]++
  765.         }
  766.     }
  767.     fclose(f)
  768.     return true
  769. }
  770.  
  771. /**
  772.  *  Rewrite plugins-polymorph.ini for the next mod.
  773.  *  Will create the file if it does not exist.
  774.  *  Use only when you need to change the mod!!!
  775.  */
  776. stock UpdatePluginFile()
  777. {
  778.     new szMainFilePath[STRLEN_PATH]
  779.     new pMainFile
  780.    
  781.     get_configsdir(szMainFilePath, charsmax(szMainFilePath))
  782.     format(szMainFilePath, charsmax(szMainFilePath), "%s/plugins-polymorph.ini", szMainFilePath)
  783.    
  784.     pMainFile = fopen(szMainFilePath, "wt")
  785.    
  786.     if(pMainFile)
  787.     {
  788.         fprintf(pMainFile, ";ThisMod:^"%s^"^r^n", g_szModNames[g_iNextMod])
  789.         fputs(pMainFile, "; Warning: This file is re-written by Polymorph plugin.^r^n")
  790.         fprintf(pMainFile, "; Any content added manually will be lost.^r^n")
  791.        
  792.         if( g_iModCount > 0 )
  793.         {
  794.             new iPlugins_num, szPluginName[STRLEN_NAME]
  795.            
  796.             iPlugins_num = ArraySize(g_aModPlugins[g_iNextMod])
  797.                
  798.             for(new j = 0; j < iPlugins_num; j++)
  799.             {
  800.                 ArrayGetString(g_aModPlugins[g_iNextMod], j, szPluginName, charsmax(szPluginName))
  801.                 fprintf(pMainFile, "%s^r^n", szPluginName)
  802.             }
  803.         }
  804.         else
  805.         {
  806.             fputs(pMainFile, ";;;  ERROR  ;;;\r\n;;; No MODs Loaded ;;;")
  807.         }
  808.         fclose(pMainFile)
  809.     }
  810. }
  811.  
  812. bool:isInMenu(id)
  813. {
  814.     for (new a = 0; a < g_voteNum; ++a)
  815.         if (id == g_nextName[a])
  816.             return true
  817.     return false
  818. }
  819.  
  820. bool:isModInMenu(id)
  821. {
  822.     for (new a = 0; a < g_voteNum; ++a)
  823.         if (id == g_nextModId[a])
  824.             return true
  825.     return false
  826. }
  827.  
  828. public team_score()
  829. {
  830.     new team[2]
  831.    
  832.     read_data(1, team, 1)
  833.     g_teamScore[(team[0]=='C') ? 0 : 1] = read_data(2)
  834. }
  835.  
  836. /* Show Scoreboard to everybody. */
  837. public intermission()
  838. {
  839.     message_begin(MSG_ALL, SVC_INTERMISSION)
  840.     message_end()
  841.     set_task(get_pcvar_float(g_pChatTime), "changeMap")
  842. }
  843.  
  844. /* Change map. */
  845. public changeMap()
  846. {
  847.     new szNextmap[32]
  848.     get_pcvar_string(g_pNextmap, szNextmap, charsmax(szNextmap))
  849.     server_cmd("changelevel %s", szNextmap)
  850. }
  851.  
  852. /* Exec Cvars */
  853. public execCfg()
  854. {
  855.     new cfg_num = ArraySize(g_aCfgList)
  856.     for(new i = 0; i < cfg_num; i++)
  857.         server_cmd("%a", ArrayGetStringHandle(g_aCfgList, i))
  858.     ArrayDestroy(g_aCfgList)
  859. }
  860.  
  861. /* Initiate loading the MODs */
  862. stock initModLoad()
  863. {
  864.     g_iModCount = 0
  865.     new szFilepath[STRLEN_PATH], szConfigDir[STRLEN_PATH]
  866.     get_configsdir(szConfigDir, charsmax(szConfigDir))
  867.     formatex(szFilepath, charsmax(szFilepath), "%s/%s", szConfigDir, "polymorph")
  868.  
  869.     new filename[32]
  870.     g_aCfgList = ArrayCreate(STRLEN_DATA)
  871.  
  872.     new pDir = open_dir(szFilepath, filename, charsmax(filename))
  873.     if(pDir)
  874.     {
  875.         do
  876.         {
  877.             if( 47 < filename[0] < 58 )
  878.             {
  879.                 g_aModMaps[g_iModCount] = ArrayCreate(STRLEN_FILE)
  880.                 g_aModPlugins[g_iModCount] = ArrayCreate(STRLEN_FILE)
  881.                 if( loadMod(szFilepath, filename) )
  882.                 {
  883.                     server_print("MOD LOADED: %s %s", g_szModNames[g_iModCount], g_iThisMod == g_iModCount ? "<<<<<" : "") // Debug
  884.                     g_iModCount++
  885.                 }
  886.                 else
  887.                 {
  888.                     ArrayDestroy(g_aModMaps[g_iModCount])
  889.                     ArrayDestroy(g_aModPlugins[g_iModCount])
  890.                 }
  891.             }
  892.  
  893.         } while( next_file(pDir, filename, charsmax(filename)) && g_iModCount < MODS_MAX )
  894.         close_dir(pDir)
  895.     }
  896.    
  897.     /* Exec Configs if Mod found */
  898.     if( g_iModCount == 0 )
  899.     {
  900.         /* Zero mods loaded, set as failed */
  901.         setNextMod(0)
  902.         UpdatePluginFile()
  903.         log_amx("[Polymorph] Zero (0) mods loaded.")
  904.         set_fail_state("[Polymorph] Zero (0) mods were loaded.")
  905.     }
  906.     else if( g_iThisMod == -1 )
  907.     {
  908.         /* No mod found, set as failed, restart to fix. */
  909.         setNextMod(0)
  910.         UpdatePluginFile()
  911.         log_amx("[Polymorph] Mod not found. Restart server.")
  912.         set_fail_state("[Polymorph] Mod not found. Restart server.")
  913.     }
  914.     else
  915.     {
  916.         /* Set poly_thismod cvar */
  917.         set_pcvar_string(g_pThisMod, g_szModNames[g_iThisMod])
  918.        
  919.         /* Execute Mod Config */
  920.         set_task(4.0, "execCfg")
  921.     }
  922. }
  923.  
  924. /* Load individual MOD.  Return true on success */
  925. stock bool:loadMod(szPath[], szModConfig[])
  926. {
  927.     new filepath[STRLEN_PATH]
  928.     new szData[STRLEN_DATA], szPreCommentData[STRLEN_DATA]
  929.     new key[STRLEN_MAP], value[STRLEN_MAP]
  930.    
  931.     formatex(filepath, charsmax(filepath), "%s/%s", szPath, szModConfig)
  932.     new f = fopen(filepath, "rt")
  933.  
  934.     if(!f)
  935.         return loadFail(szModConfig)
  936.  
  937.     /* Traverse header space */
  938.     while(!feof(f) && szData[0] != '[')
  939.     {
  940.         fgets(f, szData, charsmax(szData))
  941.         trim(szData)
  942.     }
  943.  
  944.     /* Load MOD specific variables */
  945.     while( !feof(f) )
  946.     {
  947.         fgets(f, szData, charsmax(szData))
  948.         trim(szData)
  949.  
  950.         switch( szData[0] )
  951.         {
  952.             case 0, ';': continue; // Comment/Blank line.
  953.             case '[': break; // Next section found.
  954.         }
  955.  
  956.         parse(szData, key, charsmax(key), value, charsmax(value))
  957.  
  958.         if(equali(key, "name"))
  959.         {
  960.             copy(g_szModNames[g_iModCount], charsmax(g_szModNames[]), value)
  961.             if( equal(value, g_szThisMod) )
  962.             {
  963.                 g_iThisMod = g_iModCount
  964.             }
  965.         }
  966.         else if(equali(key, "mapspermod"))
  967.         {
  968.             g_iMapsPerMod[g_iModCount] = str_to_num(value) ? str_to_num(value) : 2 // Default to 2
  969.         }
  970.         else if(equali(key, "mapsfile"))
  971.         {
  972.             if( !loadMaps(szPath, value, g_iModCount) )
  973.             {
  974.                 fclose(f)
  975.                 return loadFail(szModConfig)
  976.             }
  977.         }
  978.     }
  979.  
  980.     /* Load MOD specific cvars */
  981.     while( !feof(f) )
  982.     {
  983.         fgets(f, szData, charsmax(szData))
  984.         trim(szData)
  985.        
  986.         switch( szData[0] )
  987.         {
  988.             case 0, ';': continue; // Comment/Blank line.
  989.             case '[': break; // Next section found.
  990.         }
  991.  
  992.         /* Retain cvars if we are loading 'ThisMod' */
  993.         if( g_iThisMod == g_iModCount )
  994.         {
  995.             strtok(szData, szPreCommentData, charsmax(szPreCommentData), "", 0, ';')
  996.             trim(szPreCommentData)
  997.             ArrayPushString(g_aCfgList, szPreCommentData)
  998.         }
  999.  
  1000.     }
  1001.  
  1002.     /* Load Plugins */
  1003.     while( !feof(f) )
  1004.     {
  1005.         fgets(f, szData, charsmax(szData))
  1006.         trim(szData)
  1007.  
  1008.         switch( szData[0] )
  1009.         {
  1010.             case 0, ';': continue; // Comment/Blank line.
  1011.             case '[': break; // Next section found.
  1012.         }
  1013.  
  1014.         strtok(szData, szPreCommentData, charsmax(szPreCommentData), "", 0, ';')
  1015.         trim(szPreCommentData)
  1016.         ArrayPushString(g_aModPlugins[g_iModCount], szPreCommentData)
  1017.     }
  1018.     // if all loads well increment g_iModCount
  1019.     // else clear used arrays and DO NOT increment g_iModCount
  1020.     fclose(f)
  1021.     return true
  1022. }
  1023.  
  1024. /* Log "failed to load mod" message. return false (meaning "failed to load") */
  1025. stock bool:loadFail(szModFile[])
  1026. {
  1027.     server_print("Failed to load mod from %s", szModFile) // Debug
  1028.     log_amx("[Polymorph] Failed to load configuration file %s", szModFile)
  1029.     return false
  1030. }
  1031.  
  1032. #if defined DEBUG
  1033. /* Debugging function */
  1034. public function()
  1035. {
  1036.     server_print("Printing:")
  1037.     for(new i = 0; i < g_iModCount; i++)
  1038.     {
  1039.         server_print("%s", g_szModNames[i])
  1040.  
  1041.         new plugs_num = ArraySize(g_aModPlugins[i])
  1042.         new plug_name[32]
  1043.         for(new j = 0; j < plugs_num; j++)
  1044.         {
  1045.             ArrayGetString(g_aModPlugins[i], j, plug_name, charsmax(plug_name))
  1046.             server_print("    %s", plug_name)
  1047.         }
  1048.        
  1049.         server_print("Maps:")
  1050.        
  1051.         new maps_num = ArraySize(g_aModMaps[i])
  1052.         new mapname[32]
  1053.         for(new j = 0; j < maps_num; j++)
  1054.         {
  1055.             ArrayGetString(g_aModMaps[i], j, mapname, charsmax(mapname))
  1056.             server_print("    %s", mapname)
  1057.         }
  1058.     }
  1059. }
  1060. #endif
  1061.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement