f0.gg-kreedzsrv/amxmodx/scripting/rtv.sma
2021-07-25 14:20:46 +02:00

418 lines
12 KiB
Plaintext

/* Todo:
* countdown
*/
#include <amxmodx>
#include <amxmisc>
#define MAX_NOMINATIONS 4
#define MAX_MAPS_IN_VOTE 6
#define ID_EXTEND MAX_MAPS_IN_VOTE
#define TASK_VOTE 0
new Array:g_mapName;
new g_mapCount;
new g_voting;
new Float:g_lastVoteTime;
new g_mapChoices[MAX_MAPS_IN_VOTE + 1];
new g_mapVoteCount[MAX_MAPS_IN_VOTE + 1];
new g_numChoices;
new g_countDown;
new g_numPlayersVoted;
new g_maxClients;
new const g_prefix[] = "^1[^4f0.gg^1]";
new g_nextmap[32];
new g_nomination[33] = {-1, ...};
new bool:g_voted[33];
new bool:g_rocked[33];
new CvarExtendMax, CvarExtendStep;
new CvarRtvWait, CvarRtvRatio;
new CvarTimeLimit;
public plugin_init() {
register_plugin("rtv", "0.1", "Flummi");
register_menucmd(register_menuid("MapVoteMenu"), 1023, "CountMapVote");
register_clcmd("say", "CmdSay");
CvarExtendStep = register_cvar("mapvote_extend_step", "15");
CvarExtendMax = register_cvar("mapvote_extend_max", "90");
CvarRtvWait = register_cvar("mapvote_rtv_wait", "15");
CvarRtvRatio = register_cvar("mapvote_rtv_ratio", "0.7");
CvarTimeLimit = get_cvar_pointer("mp_timelimit");
g_maxClients = get_maxplayers() - 1;
g_mapName = ArrayCreate(32);
g_lastVoteTime = get_gametime() - 1000;
loadConfigs();
set_task(10.0, "CheckEndOfMap", 1337, _, _, "b");
pause("ac", "mapchooser.amxx");
}
public client_disconnected(id) {
g_rocked[id] = false;
g_voted[id] = false;
g_nomination[id] = -1;
}
public CmdSay(id) {
new arg[72];
read_args(arg, charsmax(arg));
remove_quotes(arg);
new arg1[32], arg2[32];
parse(arg, arg1, charsmax(arg1), arg2, charsmax(arg2));
new mapId = arrayFindString(g_mapName, arg1);
if(mapId != -1) {
nominateMap(id, mapId);
return PLUGIN_HANDLED;
}
else if(equal(arg1, "/nom") || equal(arg1, "/nominate")) {
ShowNominationMenu(id, arg2);
return PLUGIN_HANDLED;
}
else if(equal(arg1, "rtv") || equal(arg1, "rockthevote")) {
rockTheVote(id);
return PLUGIN_HANDLED;
}
return PLUGIN_CONTINUE;
}
public ShowNominationMenu(id, const match[]) {
new buffer[64];
formatex(buffer, charsmax(buffer), "Nomination \w(search: %s)\y", match);
new menu = menu_create(buffer, "HandleMenuNomination");
for(new mapId = 0; mapId < g_mapCount; mapId++) {
static mapName[32];
ArrayGetString(g_mapName, mapId, mapName, charsmax(mapName));
if(contain(mapName, match) > -1 || !match[0]) {
static info[2];
formatex(buffer, charsmax(buffer), mapName);
if(isMapNominated(mapId))
add(buffer, charsmax(buffer), "\r (nominated)");
info[0] = mapId;
menu_additem(menu, buffer, info);
}
}
menu_setprop(menu, MPROP_NUMBER_COLOR, "\y");
menu_display(id, menu);
}
public HandleMenuNomination(id, menu, item) {
if(item == MENU_EXIT) {
menu_destroy(menu);
return;
}
new dummy, info[2], tmpname[32];
menu_item_getinfo(menu, item, dummy, info, charsmax(info), tmpname, charsmax(tmpname), dummy);
new mapId = info[0]
if(!nominateMap(id, mapId))
client_print_color(id, print_chat, "%s Map ^"^4%s^1^" has already been nominated.", g_prefix, tmpname);
menu_destroy(menu);
}
public CheckEndOfMap() {
if(g_voting)
return;
if(get_timeleft() < 130)
MakeMapVote();
}
public MakeMapVote() {
g_voting = 1;
g_lastVoteTime = get_gametime();
g_numChoices = 0;
new nomination[32], numNominations = 0;
for(new i = 1; i <= g_maxClients; i++)
if(g_nomination[i] != -1)
nomination[numNominations++] = g_nomination[i];
new maxChoices = min(g_mapCount, MAX_MAPS_IN_VOTE);
new maxNomination = min(numNominations, MAX_NOMINATIONS);
while(g_numChoices < maxChoices) {
static map;
if(g_numChoices < maxNomination) {
new i = random(numNominations);
while(isMapInMenu((map = nomination[i])))
if(++i >= numNominations)
i = 0;
}
else { // Add random maps
map = random(g_mapCount);
while(isMapInMenu(map))
if(++map >= g_mapCount)
map = 0;
}
g_mapChoices[g_numChoices++] = map;
}
g_mapChoices[ID_EXTEND] = (get_pcvar_float(CvarTimeLimit) < get_pcvar_float(CvarExtendMax));
arrayset(g_mapVoteCount, 0, sizeof g_mapVoteCount);
arrayset(g_voted, false, sizeof g_voted);
remove_task(TASK_VOTE);
set_task(1.0, "ShowMapVote", TASK_VOTE, _, _, "a", 7);
set_task(6.0, "CheckMapVotes", TASK_VOTE);
g_countDown = 5;
g_numPlayersVoted = 0;
}
public ShowMapVote() {
new numPlayers = countRealPlayers();
static menu[512], len, keys;
for(new player = 1; player <= g_maxClients; player++) {
if(!is_user_connected(player) || is_user_bot(player))
continue;
if(g_voting == 1)
len = formatex(menu, charsmax(menu), "\yvoting will start soon...^n^n");
else if(g_voting == 2)
len = formatex(menu, charsmax(menu), "\yvote for the next map^n^n");
else
len = formatex(menu, charsmax(menu), "\yvoting results^n^n");
keys = 0;
len += formatex(menu[len], 511-len, "\r1. \wCheckpoint^n");
keys |= (1 << 0);
len += formatex(menu[len], 511-len, "\r2. \wGocheck^n^n");
keys |= (1 << 1);
for(new i = 2; i < (g_numChoices + 2); i++) {
new map = g_mapChoices[i-2];
if(g_voting != 2)
len += formatex(menu[len], 511-len, "\y%d. \w%a", i+1, ArrayGetStringHandle(g_mapName, map));
else
len += formatex(menu[len], 511-len, "\r%d. \w%a", i+1, ArrayGetStringHandle(g_mapName, map));
if(g_voting == 3 || (g_voted[player] && g_mapVoteCount[i - 2]))
len += formatex(menu[len], 511-len, " \y(%d%%)", (g_mapVoteCount[i - 2] * 100 / (numPlayers | 1)));
menu[len++] = '^n';
keys |= (1 << i);
}
new i = ID_EXTEND;
if(g_voting != 1 && g_mapChoices[i]) {
static mapName[32];
get_mapname(mapName, charsmax(mapName));
len += formatex(menu[len], 511-len, "^n%s9. \wextend %s", g_voting == 2 ? "\r" : "\y", mapName);
if(g_voting == 3 || (g_voted[player] && g_mapVoteCount[i]))
len += formatex(menu[len], 511-len, " \y(%d%%)", (g_mapVoteCount[i] * 100 / (numPlayers | 1)));
keys |= MENU_KEY_9;
}
if(g_voting != 3 && g_countDown <= 10)
len += formatex(menu[len], 511-len, "^n^n\wremaining time: %d", max(0, g_countDown));
show_menu(player, keys, menu, 5, "MapVoteMenu");
}
g_countDown--;
}
public CountMapVote(id, key) {
if(key == 0) {
client_cmd(id, "say /cp");
ShowMapVote();
return;
}
else if(key == 1) {
client_cmd(id, "say /gc");
ShowMapVote();
return;
}
if(g_voting == 2 && !g_voted[id]) {
new username[32];
get_user_name(id, username, charsmax(username));
new tmpmap[32];
ArrayGetString(g_mapName, g_mapChoices[key - 2], tmpmap, charsmax(tmpmap));
if((key + 1) == 9) {
g_mapVoteCount[ID_EXTEND]++;
g_numPlayersVoted++;
g_voted[id] = true;
client_print_color(0, print_chat, "%s %s chose map extending", g_prefix, username);
}
else {
g_mapVoteCount[key - 2]++;
g_numPlayersVoted++;
g_voted[id] = true;
client_print_color(0, print_chat, "%s %s chose %s", g_prefix, username, tmpmap);
}
}
ShowMapVote();
}
public CheckMapVotes() {
if(g_voting == 1) {
g_voting = 2;
client_cmd(0, "spk Gman/Gman_Choose%d", random_num(1, 2));
remove_task(TASK_VOTE);
set_task(1.0, "ShowMapVote", TASK_VOTE, _, _, "a", 15);
set_task(16.0, "CheckMapVotes", TASK_VOTE);
g_countDown = 15;
return;
}
new numPlayers = countRealPlayers();
g_voting = 3;
ShowMapVote();
new best;
for(new i = 0; i <= MAX_MAPS_IN_VOTE; i++)
if(g_mapVoteCount[i] > g_mapVoteCount[best])
best = i;
new sameVotes[MAX_MAPS_IN_VOTE + 1], num = 0;
for(new i = 0; i <= MAX_MAPS_IN_VOTE; i++)
if(g_mapVoteCount[i] > 0 && g_mapVoteCount[i] == g_mapVoteCount[best])
sameVotes[num++] = i;
if(num > 1) {
best = sameVotes[random(num)];
client_print_color(0, print_chat, "%s since there are %d results that are the same, one of them is randomly selected.", g_prefix, num);
}
new mapName[32];
if(best == ID_EXTEND || (g_numPlayersVoted == 0 && numPlayers != 0)) { // extend map
g_voting = 0;
get_mapname(mapName, charsmax(mapName));
if(get_timeleft() < 130)
set_cvar_float("mp_timelimit", get_cvar_float("mp_timelimit") + get_pcvar_float(CvarExtendStep));
client_print_color(0, print_chat, "%s voting is over. %s will be extended by %d minutes.", g_prefix, mapName, get_pcvar_num(CvarExtendStep));
}
else {
ArrayGetString(g_mapName, g_mapChoices[best], g_nextmap, charsmax(g_nextmap));
server_print("(after vote) g_nextmap: %s", g_nextmap);
set_cvar_string("amx_nextmap", g_nextmap);
set_task(10.0, "changeLevel", TASK_VOTE);
message_begin(MSG_ALL, SVC_INTERMISSION);
message_end();
client_print_color(0, print_chat, "%s voting is over. the next map will be %s.", g_prefix, g_nextmap);
}
}
public changeLevel() {
server_print("(changeLevel) g_nextmap: %s", g_nextmap);
client_print_color(0, print_chat, "%s changing map to %s...", g_prefix, g_nextmap);
server_cmd("changelevel ^"%s^"", g_nextmap);
}
loadConfigs() {
new currentMap[32];
get_mapname(currentMap, charsmax(currentMap));
new filePath[100];
get_configsdir(filePath, charsmax(filePath));
add(filePath, charsmax(filePath), "/maps.ini");
new file = fopen(filePath, "r");
if(file) {
while(!feof(file)) {
static data[64];
fgets(file, data, charsmax(data));
static mapName[32];
parse(data, mapName, charsmax(mapName));
if(is_map_valid(mapName) && !equal(currentMap, mapName) && !isMapExists(mapName)) {
ArrayPushString(g_mapName, mapName);
g_mapCount++;
}
}
fclose(file);
}
if(!g_mapCount)
set_fail_state("Could not load any map.");
}
rockTheVote(id) {
if(g_voting) {
client_print_color(id, print_chat, "%s voting is in progress", g_prefix);
return;
}
new Float:timeWait = g_lastVoteTime + get_pcvar_float(CvarRtvWait) - get_gametime();
if(timeWait > 0.0) {
client_print_color(id, print_chat, "%s next vote in (%.f seconds)", g_prefix, timeWait);
return;
}
if(g_rocked[id]) {
g_rocked[id] = false;
client_print_color(id, print_chat, "%s you canceled the vote to change the map.", g_prefix);
return;
}
g_rocked[id] = true;
new maxVotes = floatround(get_pcvar_float(CvarRtvRatio) * countRealPlayers());
new numVotes = countRocked();
if(numVotes >= maxVotes) {
arrayset(g_rocked, false, sizeof g_rocked);
MakeMapVote();
client_print_color(0, print_chat, "%s %n voted to change the map.", g_prefix, id);
}
else
client_print_color(0, print_chat, "%s %n rocked the vote (%d players are needed).", g_prefix, id, maxVotes - numVotes);
}
bool:nominateMap(id, map) {
if(isMapNominated(map))
return false;
g_nomination[id] = map;
client_print_color(0, print_chat, "%s %n nominated the map %a.", g_prefix, id, ArrayGetStringHandle(g_mapName, map));
return true;
}
stock bool:isMapInMenu(map) {
for(new i = 0; i < g_numChoices; i++)
if(g_mapChoices[i] == map)
return true
return false;
}
stock bool:isMapExists(const map[]) {
return (arrayFindString(g_mapName, map) != -1);
}
stock arrayFindString(Array:which, const string[]) {
new size = ArraySize(which);
for(new i = 0; i < size; i++) {
static buffer[128];
ArrayGetString(g_mapName, i, buffer, charsmax(buffer));
if(equal(string, buffer))
return i;
}
return -1;
}
stock bool:isMapNominated(map) {
for(new i = 1; i <= g_maxClients; i++)
if(g_nomination[i] == map)
return true;
return false;
}
stock countRocked() {
new count = 0;
for(new i = 1; i <= g_maxClients; i++)
if(g_rocked[i])
count++;
return count;
}
stock countRealPlayers() {
new count = 0;
for(new i = 1; i <= g_maxClients; i++)
if(is_user_connected(i) && !is_user_bot(i))
count++;
return count;
}