/* * CSB Captains Pick * Copyright (C) 2026 counter-strike-boost.com * * Captain draft. Two captains are chosen (the two highest-ranked players by * frags, or named by an admin) and pick the remaining players alternately from a * menu until both teams are full. Each pick is moved with cs_set_user_team, and a * HUD shows whose turn it is together with the current rosters. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. It is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See for details. */ #include #include #include new const PLUGIN[] = "CSB Captains Pick" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" new g_pEnabled new bool:g_bActive new g_iCapT, g_iCapCT new g_iTurn /* 1 = T captain picks, 2 = CT captain picks */ new bool:g_bAssigned[33] new g_iSync public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) g_pEnabled = register_cvar("csb_captains_enabled", "1") register_concmd("amx_captains", "cmdStart", ADMIN_MAP, "- start a captain draft") register_concmd("amx_captains_stop", "cmdStop", ADMIN_MAP, "- cancel the current draft") register_clcmd("say /pick", "cmdPick") register_clcmd("say_team /pick", "cmdPick") g_iSync = CreateHudSyncObj() set_task(1.0, "taskHud", 0, _, _, "b") } public client_disconnected(id) { if (!g_bActive) return if (id == g_iCapT || id == g_iCapCT) { client_print(0, print_chat, "^x04[CSB Draft]^x01 A captain left. Draft cancelled.") resetDraft() } } resetDraft() { g_bActive = false g_iCapT = 0 g_iCapCT = 0 g_iTurn = 0 for (new i = 1; i <= 32; i++) g_bAssigned[i] = false } public cmdStart(id, level, cid) { if (!cmd_access(id, level, cid, 1)) return PLUGIN_HANDLED if (!get_pcvar_num(g_pEnabled)) { console_print(id, "[CSB] Captain draft is disabled.") return PLUGIN_HANDLED } new players[32], num get_players(players, num, "c") if (num < 4) { console_print(id, "[CSB] Need at least 4 players.") return PLUGIN_HANDLED } resetDraft() /* two highest frag counts become captains */ new best1 = 0, best2 = 0 for (new i = 0; i < num; i++) { new pl = players[i] if (!best1 || get_user_frags(pl) > get_user_frags(best1)) { best2 = best1 best1 = pl } else if (!best2 || get_user_frags(pl) > get_user_frags(best2)) { best2 = pl } } g_iCapT = best1 g_iCapCT = best2 cs_set_user_team(g_iCapT, CS_TEAM_T) cs_set_user_team(g_iCapCT, CS_TEAM_CT) g_bAssigned[g_iCapT] = true g_bAssigned[g_iCapCT] = true g_bActive = true g_iTurn = 1 client_print(0, print_chat, "^x04[CSB Draft]^x01 Captains: ^x03%n^x01 (T) and ^x03%n^x01 (CT). Type /pick on your turn.", g_iCapT, g_iCapCT) openPickMenu(g_iCapT) return PLUGIN_HANDLED } public cmdStop(id, level, cid) { if (!cmd_access(id, level, cid, 1)) return PLUGIN_HANDLED resetDraft() client_print(0, print_chat, "^x04[CSB Draft]^x01 Draft cancelled by admin.") return PLUGIN_HANDLED } currentPicker() { return (g_iTurn == 1) ? g_iCapT : g_iCapCT } public cmdPick(id) { if (!g_bActive) return PLUGIN_HANDLED if (id != currentPicker()) { client_print(id, print_chat, "^x04[CSB Draft]^x01 It is not your turn.") return PLUGIN_HANDLED } openPickMenu(id) return PLUGIN_HANDLED } openPickMenu(cap) { if (!is_user_connected(cap)) return new title[64] formatex(title, charsmax(title), "\yCSB Draft^n\wPick a player (%s):", (g_iTurn == 1) ? "T" : "CT") new menu = menu_create(title, "pickHandler") new players[32], num, added = 0 get_players(players, num, "c") for (new i = 0; i < num; i++) { new pl = players[i] if (g_bAssigned[pl]) continue new entry[48], info[8] formatex(entry, charsmax(entry), "%n", pl) num_to_str(pl, info, charsmax(info)) menu_additem(menu, entry, info, 0) added++ } if (!added) { menu_destroy(menu) finishDraft() return } menu_setprop(menu, MPROP_EXIT, MEXIT_NEVER) menu_display(cap, menu, 0) } public pickHandler(id, menu, item) { if (item == MENU_EXIT || !g_bActive || id != currentPicker()) { menu_destroy(menu) return PLUGIN_HANDLED } new info[8], name[32], access, callback menu_item_getinfo(menu, item, access, info, charsmax(info), name, charsmax(name), callback) menu_destroy(menu) new pick = str_to_num(info) if (pick < 1 || pick > 32 || !is_user_connected(pick) || g_bAssigned[pick]) { openPickMenu(id) return PLUGIN_HANDLED } if (g_iTurn == 1) cs_set_user_team(pick, CS_TEAM_T) else cs_set_user_team(pick, CS_TEAM_CT) g_bAssigned[pick] = true client_print(0, print_chat, "^x04[CSB Draft]^x01 %n picked %n for %s.", id, pick, (g_iTurn == 1) ? "T" : "CT") /* alternate the turn */ g_iTurn = (g_iTurn == 1) ? 2 : 1 if (remaining() > 0) openPickMenu(currentPicker()) else finishDraft() return PLUGIN_HANDLED } remaining() { new players[32], num, left = 0 get_players(players, num, "c") for (new i = 0; i < num; i++) { if (!g_bAssigned[players[i]]) left++ } return left } finishDraft() { g_bActive = false client_print(0, print_chat, "^x04[CSB Draft]^x01 Teams are set. Good luck!") server_cmd("sv_restart 1") } public taskHud() { if (!g_bActive) return new cap = currentPicker() if (!is_user_connected(cap)) return new capName[32] get_user_name(cap, capName, charsmax(capName)) set_hudmessage(255, 180, 0, 0.02, 0.15, 0, 0.0, 1.1, 0.0, 0.0, -1) ShowSyncHudMsg(0, g_iSync, "DRAFT^n%s to pick (%s)^n%d player(s) left", capName, (g_iTurn == 1) ? "T" : "CT", remaining()) }