Скомпилируйте, пожалуйста плагин
Инклуд
Ошибки компилятора
C-подобный:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Ultimate Mapchooser - Rock The Vote *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#pragma semicolon 1
#include <sourcemod>
#include <umc-core>
#include <umc_utils>
#include <csgo_colors>
#undef REQUIRE_PLUGIN
//Auto update
#include <updater>
#if AUTOUPDATE_DEV
#define UPDATE_URL "http://www.ccs.neu.edu/home/steell/sourcemod/ultimate-mapchooser/dev/updateinfo-umc-rockthevote.txt"
#else
#define UPDATE_URL "http://www.ccs.neu.edu/home/steell/sourcemod/ultimate-mapchooser/updateinfo-umc-rockthevote.txt"
#endif
//Plugin Information
public Plugin:myinfo =
{
name = "[UMC] Rock The Vote",
author = "Steell",
description = "Extends Ultimate Mapchooser to provide RTV map voting.",
version = PL_VERSION,
url = "http://forums.alliedmods.net/showthread.php?t=134190"
};
//Changelog:
/*
3.3.2 (3/4/2012)
Updated UMC Logging functionality
Added ability to view the current mapcycle of all modules
3.3.1 (12/13/11)
Updated sm_umc_rtv_postvoteaction cvar to allow for normal RTV votes after a vote has taken place.
*/
////----CONVARS-----/////
new Handle:cvar_filename = INVALID_HANDLE;
new Handle:cvar_scramble = INVALID_HANDLE;
new Handle:cvar_vote_time = INVALID_HANDLE;
new Handle:cvar_strict_noms = INVALID_HANDLE;
new Handle:cvar_runoff = INVALID_HANDLE;
new Handle:cvar_runoff_sound = INVALID_HANDLE;
new Handle:cvar_runoff_max = INVALID_HANDLE;
new Handle:cvar_vote_allowduplicates = INVALID_HANDLE;
new Handle:cvar_vote_threshold = INVALID_HANDLE;
new Handle:cvar_fail_action = INVALID_HANDLE;
new Handle:cvar_runoff_fail_action = INVALID_HANDLE;
new Handle:cvar_rtv_enable = INVALID_HANDLE;
new Handle:cvar_rtv_changetime = INVALID_HANDLE;
new Handle:cvar_rtv_delay = INVALID_HANDLE;
new Handle:cvar_rtv_minplayers = INVALID_HANDLE;
new Handle:cvar_rtv_postaction = INVALID_HANDLE;
new Handle:cvar_rtv_needed = INVALID_HANDLE;
new Handle:cvar_rtv_interval = INVALID_HANDLE;
new Handle:cvar_rtv_mem = INVALID_HANDLE;
new Handle:cvar_rtv_catmem = INVALID_HANDLE;
new Handle:cvar_rtv_type = INVALID_HANDLE;
new Handle:cvar_rtv_dontchange = INVALID_HANDLE;
new Handle:cvar_rtv_startsound = INVALID_HANDLE;
new Handle:cvar_rtv_endsound = INVALID_HANDLE;
new Handle:cvar_voteflags = INVALID_HANDLE;
new Handle:cvar_enterflags = INVALID_HANDLE;
new Handle:cvar_enterbonusflags = INVALID_HANDLE;
new Handle:cvar_enterbonusamt = INVALID_HANDLE;
////----/CONVARS-----/////
//Mapcycle KV
new Handle:map_kv = INVALID_HANDLE;
new Handle:umc_mapcycle = INVALID_HANDLE;
//Memory queues.
new Handle:vote_mem_arr = INVALID_HANDLE;
new Handle:vote_catmem_arr = INVALID_HANDLE;
//Array of players who have RTV'd
new Handle:rtv_clients = INVALID_HANDLE;
//Stores whether or not players have seen the long RTV message.
new bool:rtv_message[MAXPLAYERS+1];
//Keeps track of a delay before we are able to RTV.
new Float:rtv_delaystart;
//How many people are required to trigger an RTV.
new rtv_threshold;
//Flags
new bool:rtv_completed; //Has an rtv been completed?
new bool:rtv_enabled; //Is RTV enabled right now?
new bool:vote_completed; //Has UMC completed a vote?
new bool:rtv_inprogress; //Is the rtv vote in progress?
//Sounds to be played at the start and end of votes.
new String:vote_start_sound[PLATFORM_MAX_PATH], String:vote_end_sound[PLATFORM_MAX_PATH],
String:runoff_sound[PLATFORM_MAX_PATH];
//************************************************************************************************//
// SOURCEMOD EVENTS //
//************************************************************************************************//
//Called when the plugin is finished loading.
public OnPluginStart()
{
cvar_enterbonusflags = CreateConVar(
"sm_umc_rtv_enteradminflags_bonusflags",
"",
"If specified, players with any of these admin flags will be given bonus RTV entrance votes, of the amount determined by \"sm_umc_rtv_enteradminflags_bonusamt\"."
);
cvar_enterbonusamt = CreateConVar(
"sm_umc_rtv_enteradminflags_bonusamt",
"2",
"The amount of entrance votes to be given to players who have at least one of the admin flags specified by \"sm_umc_rtv_enteradminflags_bonusflags\".",
0, true, 1.0
);
cvar_voteflags = CreateConVar(
"sm_umc_rtv_voteadminflags",
"",
"Specifies which admin flags are necessary for a player to participate in a vote. If empty, all players can participate."
);
cvar_enterflags = CreateConVar(
"sm_umc_rtv_enteradminflags",
"",
"Specifies which admin flags are necessary for a player to enter RTV. If empty, all players can participate."
);
cvar_fail_action = CreateConVar(
"sm_umc_rtv_failaction",
"0",
"Specifies what action to take if the vote doesn't reach the set theshold.\n 0 - Do Nothing,\n 1 - Perform Runoff Vote",
0, true, 0.0, true, 1.0
);
cvar_runoff_fail_action = CreateConVar(
"sm_umc_rtv_runoff_failaction",
"0",
"Specifies what action to take if the runoff vote reaches the maximum amount of runoffs and the set threshold has not been reached.\n 0 - Do Nothing,\n 1 - Change Map to Winner",
0, true, 0.0, true, 1.0
);
cvar_runoff_max = CreateConVar(
"sm_umc_rtv_runoff_max",
"0",
"Specifies the maximum number of maps to appear in a runoff vote.\n 1 or 0 sets no maximum.",
0, true, 0.0
);
cvar_vote_allowduplicates = CreateConVar(
"sm_umc_rtv_allowduplicates",
"1",
"Allows a map to appear in the vote more than once. This should be enabled if you want the same map in different categories to be distinct.",
0, true, 0.0, true, 1.0
);
cvar_vote_threshold = CreateConVar(
"sm_umc_rtv_threshold",
"0",
"If the winning option has less than this percentage of total votes, a vote will fail and the action specified in \"sm_umc_rtv_failaction\" cvar will be performed.",
0, true, 0.0, true, 1.0
);
cvar_runoff = CreateConVar(
"sm_umc_rtv_runoffs",
"0",
"Specifies a maximum number of runoff votes to run for any given vote.\n 0 disables runoff votes.",
0, true, 0.0
);
cvar_runoff_sound = CreateConVar(
"sm_umc_rtv_runoff_sound",
"",
"If specified, this sound file (relative to sound folder) will be played at the beginning of a runoff vote. If not specified, it will use the normal start vote sound."
);
cvar_rtv_catmem = CreateConVar(
"sm_umc_rtv_groupexclude",
"0",
"Specifies how many past map groups to exclude from RTVs.",
0, true, 0.0
);
cvar_rtv_startsound = CreateConVar(
"sm_umc_rtv_startsound",
"",
"Sound file (relative to sound folder) to play at the start of a vote."
);
cvar_rtv_endsound = CreateConVar(
"sm_umc_rtv_endsound",
"",
"Sound file (relative to sound folder) to play at the completion of a vote."
);
cvar_strict_noms = CreateConVar(
"sm_umc_rtv_nominate_strict",
"0",
"Specifies whether the number of nominated maps appearing in the vote for a map group should be limited by the group's \"maps_invote\" setting.",
0, true, 0.0, true, 1.0
);
cvar_rtv_interval = CreateConVar(
"sm_umc_rtv_interval",
"240",
"Time (in seconds) after a failed RTV before another can be held.",
0, true, 0.0
);
cvar_rtv_dontchange = CreateConVar(
"sm_umc_rtv_dontchange",
"1",
"Adds a \"Don't Change\" option to RTVs.",
0, true, 0.0, true, 1.0
);
cvar_rtv_postaction = CreateConVar(
"sm_umc_rtv_postvoteaction",
"0",
"What to do with RTVs after another UMC vote has completed.\n 0 - Allow, success = instant change,\n 1 - Deny,\n 2 - Hold a normal RTV vote",
0, true, 0.0, true, 2.0
);
cvar_rtv_minplayers = CreateConVar(
"sm_umc_rtv_minplayers",
"0",
"Number of players required before RTV will be enabled.",
0, true, 0.0, true, float(MAXPLAYERS)
);
cvar_rtv_delay = CreateConVar(
"sm_umc_rtv_initialdelay",
"30",
"Time (in seconds) before first RTV can be held.",
0, true, 0.0
);
cvar_rtv_changetime = CreateConVar(
"sm_umc_rtv_changetime",
"0",
"When to change the map after a successful RTV:\n 0 - Instant,\n 1 - Round End,\n 2 - Map End",
0, true, 0.0, true, 2.0
);
cvar_rtv_needed = CreateConVar(
"sm_umc_rtv_percent",
"0.65",
"Percentage of players required to trigger an RTV vote.",
0, true, 0.0, true, 1.0
);
cvar_rtv_enable = CreateConVar(
"sm_umc_rtv_enabled",
"1",
"Enables RTV.",
0, true, 0.0, true, 1.0
);
cvar_rtv_type = CreateConVar(
"sm_umc_rtv_type",
"0",
"Controls RTV vote type:\n 0 - Maps,\n 1 - Groups,\n 2 - Tiered Vote (vote for a group, then vote for a map from the group).",
0, true, 0.0, true, 2.0
);
cvar_vote_time = CreateConVar(
"sm_umc_rtv_duration",
"20",
"Specifies how long a vote should be available for.",
0, true, 10.0
);
cvar_filename = CreateConVar(
"sm_umc_rtv_cyclefile",
"umc_mapcycle.txt",
"File to use for Ultimate Mapchooser's map rotation."
);
cvar_rtv_mem = CreateConVar(
"sm_umc_rtv_mapexclude",
"4",
"Specifies how many past maps to exclude from RTVs. 1 = Current Map Only",
0, true, 0.0
);
cvar_scramble = CreateConVar(
"sm_umc_rtv_menuscrambled",
"0",
"Specifies whether vote menu items are displayed in a random order.",
0, true, 0.0, true, 1.0
);
//Create the config if it doesn't exist, and then execute it.
AutoExecConfig(true, "umc-rockthevote");
//Register the rtv command, hooks "!rtv" and "/rtv" in chat.
RegConsoleCmd("sm_rtv", Command_RTV);
RegConsoleCmd("sm_rockthevote", Command_RTV);
//Make listeners for player chat. Needed to recognize chat commands ("rtv", etc.)
AddCommandListener(OnPlayerChat, "say");
AddCommandListener(OnPlayerChat, "say2"); //Insurgency Only
AddCommandListener(OnPlayerChat, "say_team");
//Hook all necessary cvar changes
HookConVarChange(cvar_rtv_mem, Handle_RTVMemoryChange);
HookConVarChange(cvar_rtv_enable, Handle_RTVChange);
HookConVarChange(cvar_rtv_needed, Handle_ThresholdChange);
//Initialize our memory arrays
new numCells = ByteCountToCells(MAP_LENGTH);
vote_mem_arr = CreateArray(numCells);
vote_catmem_arr = CreateArray(numCells);
//Initialize rtv array
rtv_clients = CreateArray();
//Load the translations file
LoadTranslations("ultimate-mapchooser.phrases");
#if AUTOUPDATE_ENABLE
if (LibraryExists("updater"))
{
Updater_AddPlugin(UPDATE_URL);
}
#endif
}
#if AUTOUPDATE_ENABLE
//Called when a new API library is loaded. Used to register UMC auto-updating.
public OnLibraryAdded(const String:name[])
{
if (StrEqual(name, "updater"))
{
Updater_AddPlugin(UPDATE_URL);
}
}
#endif
//************************************************************************************************//
// GAME EVENTS //
//************************************************************************************************//
//Called after all config files were executed.
public OnConfigsExecuted()
{
DEBUG_MESSAGE("Executing RTV OnConfigsExecuted")
//We have not completed an RTV.
rtv_completed = false;
rtv_enabled = false;
rtv_inprogress = false;
//UMC hasn't done any votes.
vote_completed = false;
//Set the amount of time required before players are able to RTV.
rtv_delaystart = GetConVarFloat(cvar_rtv_delay);
new bool:reloaded = ReloadMapcycle();
//Setup RTV if...
// ...the RTV cvar is enabled.
if (reloaded && GetConVarBool(cvar_rtv_enable))
{
rtv_enabled = true;
//Set RTV threshold.
UpdateRTVThreshold();
//Make timer to activate RTV (player's cannot RTV before this timer finishes).
MakeRTVTimer();
}
//Setup vote sounds.
SetupVoteSounds();
//Grab the name of the current map.
decl String:mapName[MAP_LENGTH];
GetCurrentMap(mapName, sizeof(mapName));
decl String:groupName[MAP_LENGTH];
UMC_GetCurrentMapGroup(groupName, sizeof(groupName));
if (reloaded && StrEqual(groupName, INVALID_GROUP, false))
{
KvFindGroupOfMap(umc_mapcycle, mapName, groupName, sizeof(groupName));
}
//Add the map to all the memory queues.
new mapmem = GetConVarInt(cvar_rtv_mem);
new catmem = GetConVarInt(cvar_rtv_catmem);
AddToMemoryArray(mapName, vote_mem_arr, mapmem);
AddToMemoryArray(groupName, vote_catmem_arr, (mapmem > catmem) ? mapmem : catmem);
if (reloaded)
RemovePreviousMapsFromCycle();
}
//Called when a client enters the server. Required for updating the RTV threshold.
public OnClientPutInServer(client)
{
//Update the RTV threshold if...
// ...RTV is enabled.
if (GetConVarBool(cvar_rtv_enable))
UpdateRTVThreshold();
}
//Called when a player types in chat. Required to handle user commands.
public Action:OnPlayerChat(client, const String:command[], argc)
{
//Return immediately if...
// ...nothing was typed.
if (argc == 0) return Plugin_Continue;
//Get what was typed.
decl String:text[13];
GetCmdArg(1, text, sizeof(text));
//Handle RTV client-command if...
// ...RTV is enabled AND
// ...the client typed a valid RTV command AND
// ...the required number of clients for RTV hasn't been reached already AND
// ...the client isn't the console.
if (StrEqual(text, "rtv", false) || StrEqual(text, "rockthevote", false))
{
AttemptRTV(client);
}
return Plugin_Continue;
}
//Called after a client has left the server. Required for updating the RTV threshold.
public OnClientDisconnect_Post(client)
{
//Remove this client from people who have seen the extended RTV message.
rtv_message[client] = false;
new index;
//Remove the client from the RTV array if...
// ...the client is in the array to begin with.
while ((index = FindValueInArray(rtv_clients, client)) != -1)
RemoveFromArray(rtv_clients, index);
//Recalculate the RTV threshold.
UpdateRTVThreshold();
//Start RTV if...
// ...we haven't had an RTV already AND
// ...the new amount of players on the server as passed the required threshold.
if (!rtv_completed && GetArraySize(rtv_clients) >= rtv_threshold)
{
CGOPrintToChatAll("\x03[UMC]\x01 %t", "Player Disconnect RTV");
StartRTV();
}
}
//Called at the end of a map.
public OnMapEnd()
{
DEBUG_MESSAGE("Executing RTV OnMapEnd")
//Empty array of clients who have entered RTV.
ClearArray(rtv_clients);
}
//************************************************************************************************//
// COMMANDS //
//************************************************************************************************//
//sm_rtv or sm_rockthevote
public Action:Command_RTV(client, args)
{
AttemptRTV(client);
return Plugin_Handled;
}
//************************************************************************************************//
// SETUP //
//************************************************************************************************//
//Parses the mapcycle file and returns a KV handle representing the mapcycle.
Handle:GetMapcycle()
{
//Grab the file name from the cvar.
decl String:filename[PLATFORM_MAX_PATH];
GetConVarString(cvar_filename, filename, sizeof(filename));
//Get the kv handle from the file.
new Handle:result = GetKvFromFile(filename, "umc_rotation");
//Log an error and return empty handle if...
// ...the mapcycle file failed to parse.
if (result == INVALID_HANDLE)
{
LogError("SETUP: Mapcycle failed to load!");
return INVALID_HANDLE;
}
//Success!
return result;
}
//Sets up the vote sounds.
SetupVoteSounds()
{
//Grab sound files from cvars.
GetConVarString(cvar_rtv_startsound, vote_start_sound, sizeof(vote_start_sound));
GetConVarString(cvar_rtv_endsound, vote_end_sound, sizeof(vote_end_sound));
GetConVarString(cvar_runoff_sound, runoff_sound, sizeof(runoff_sound));
//Gotta cache 'em all!
CacheSound(vote_start_sound);
CacheSound(vote_end_sound);
CacheSound(runoff_sound);
}
//Reloads the mapcycle. Returns true on success, false on failure.
bool:ReloadMapcycle()
{
if (umc_mapcycle != INVALID_HANDLE)
{
CloseHandle(umc_mapcycle);
umc_mapcycle = INVALID_HANDLE;
}
if (map_kv != INVALID_HANDLE)
{
CloseHandle(map_kv);
map_kv = INVALID_HANDLE;
}
umc_mapcycle = GetMapcycle();
return umc_mapcycle != INVALID_HANDLE;
}
//
RemovePreviousMapsFromCycle()
{
map_kv = CreateKeyValues("umc_rotation");
KvCopySubkeys(umc_mapcycle, map_kv);
FilterMapcycleFromArrays(map_kv, vote_mem_arr, vote_catmem_arr, GetConVarInt(cvar_rtv_catmem));
}
//************************************************************************************************//
// CVAR CHANGES //
//************************************************************************************************//
//Called when the cvar to enable RTVs has been changed.
public Handle_RTVChange(Handle:convar, const String:oldVal[], const String:newVal[])
{
//If the new value is 0, we ignore the change until next map.
//Update (in this case set) the RTV threshold if...
// ...the new value of the changed cvar is 1.
if (StringToInt(newVal) == 1)
UpdateRTVThreshold();
}
//Called when the number of excluded previous maps from RTVs has changed.
public Handle_RTVMemoryChange(Handle:convar, const String:oldValue[], const String:newValue[])
{
//Trim the memory array for RTVs.
//We pass 1 extra to the argument in order to account for the current map, which should
//always be excluded.
TrimArray(vote_mem_arr, StringToInt(newValue));
}
//Called when the cvar specifying the required RTV threshold percentage has changed.
public Handle_ThresholdChange(Handle:cvar, const String:oldVal[], const String:newVal[])
{
//Recalculate the required threshold.
UpdateRTVThreshold();
//Start an RTV if...
// ...the amount of clients who have RTVd is greater than the new RTV threshold.
if (GetArraySize(rtv_clients) >= rtv_threshold)
StartRTV();
}
//************************************************************************************************//
// ROCK THE VOTE //
//************************************************************************************************//
//Tries to enter the given client into RTV.
AttemptRTV(client)
{
//Get the number of clients who have RTV'd.
new size = GetArraySize(rtv_clients);
if (!rtv_enabled || !GetConVarBool(cvar_rtv_enable) || size >= rtv_threshold || client == 0)
return;
decl String:flags[64];
GetConVarString(cvar_enterflags, flags, sizeof(flags));
if (!ClientHasAdminFlags(client, flags))
{
CGOPrintToChat(
client,
"\x03[UMC]\x01 %t",
"No RTV Admin"
);
return;
}
new clients = GetRealClientCount();
new minPlayers = GetConVarInt(cvar_rtv_minplayers);
DEBUG_MESSAGE("Checking RTV Entry Validity")
//Print a message if...
// ...an RTV has already been completed OR
// ...a vote has already been completed and RTVs after votes aren't allowed.
if (rtv_completed || (vote_completed && GetConVarInt(cvar_rtv_postaction) == 1))
{
DEBUG_MESSAGE("RTV Already Completed? -- %s", rtv_completed ? "true" : "false")
DEBUG_MESSAGE("Vote Already Completed? -- %s", vote_completed ? "true" : "false")
DEBUG_MESSAGE("Change Map On Post? -- %s", GetConVarBool(cvar_rtv_postaction) ? "true" : "false")
CGOPrintToChat(client, "\x03[UMC]\x01 %t", "No RTV Nextmap");
return;
}
//Otherwise, print a message if...
// ...the number of players on the server is less than the minimum required to RTV.
else if (clients < minPlayers)
{
CGOPrintToChat(
client,
"\x03[UMC]\x01 %t",
"No RTV Player Count",
minPlayers - clients
);
return;
}
//Otherwise, print a message if...
// ...it is too early to RTV.
else if (rtv_delaystart > 0)
{
CGOPrintToChat(client, "\x03[UMC]\x01 %t", "No RTV Time", rtv_delaystart);
return;
}
//Otherwise, accept RTV command if...
// ...the client hasn't already RTV'd.
else if (FindValueInArray(rtv_clients, client) == -1)
{
//Get the flags for bonus RTV entrance points
GetConVarString(cvar_enterbonusflags, flags, sizeof(flags));
//Calc the amount of entrance points for this user
new amt = strlen(flags) > 0 && ClientHasAdminFlags(client, flags)
? GetConVarInt(cvar_enterbonusamt)
: 1;
//Apply entrance points
size += amt;
while (amt-- > 0)
{
//Add client to RTV array.
PushArrayCell(rtv_clients, client);
}
//Get the name of the client.
decl String:name[MAX_NAME_LENGTH];
GetClientName(client, name, sizeof(name));
//Display an RTV message to a client for...
// ...each client on the server.
for (new i = 1; i <= MaxClients; i++)
{
if (IsClientInGame(i))
{
//Display initial (long) RTV message if...
// ...the client hasn't seen it yet.
if (!rtv_message[i])
{
//Remember that the client has now seen this message.
rtv_message[i] = true;
CGOPrintToChat(
i,
"\x03[UMC]\x01 %t %t (%t)",
"RTV Entered",
name,
"RTV Info Msg",
"More Required",
rtv_threshold - size
);
}
else //Otherwise, print the standard message.
{
CGOPrintToChat(
i,
"\x03[UMC]\x01 %t (%t)",
"RTV Entered",
name,
"More Required",
rtv_threshold - size
);
}
}
}
//Start RTV if...
// ...the new size has surpassed the threshold required to RTV.
if (size >= rtv_threshold)
{
//Start the vote if...
// ...there isn't one happening already.
if (!IsVoteInProgress())
{
CGOPrintToChatAll("\x03[UMC]\x01 %t", "RTV Start");
StartRTV();
}
else //Otherwise, display a message.
{
CGOPrintToChat(client, "\x03[UMC]\x01 %t", "Vote In Progress");
MakeRetryVoteTimer(StartRTV);
}
}
}
//Otherwise, display a message to the client if...
// ...the client has already RTV'd.
else if (FindValueInArray(rtv_clients, client) != -1)
{
CGOPrintToChat(
client,
"\x03[UMC]\x01 %t (%t)",
"RTV Already Entered",
"More Required",
rtv_threshold - size
);
}
}
//Creates the RTV timer. While this timer is active, players are not able to RTV.
MakeRTVTimer()
{
DEBUG_MESSAGE("Enabling RTV; setting rtv_completed flag to false")
//We are re-enabling RTV at this point.
rtv_completed = false;
if (rtv_delaystart > 0)
{
//Log a message
LogUMCMessage("RTV will be made available in %.f seconds.", rtv_delaystart);
//Create timer that lasts every second.
CreateTimer(
1.0,
Handle_RTVTimer,
INVALID_HANDLE,
TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT
);
}
else
{
//rtv_enabled = true;
LogUMCMessage("RTV is now available.");
}
}
//Callback for the RTV timer, is called every second the timer is running.
public Action:Handle_RTVTimer(Handle:timer)
{
//Continue ticking if...
// ...there is still time left on the counter.
if (--rtv_delaystart >= 0.0)
return Plugin_Continue;
//If there isn't time left on the counter...
//rtv_enabled = true;
LogUMCMessage("RTV is now available.");
//Stop the timer.
return Plugin_Stop;
}
//Recalculated the RTV threshold based off of the given playercount.
UpdateRTVThreshold()
{
decl String:flags[64];
GetConVarString(cvar_voteflags, flags, sizeof(flags));
new count = GetClientWithFlagsCount(flags);
rtv_threshold = (count > 1)
? RoundToCeil(float(count) * GetConVarFloat(cvar_rtv_needed))
: 1;
}
//Starts an RTV.
public StartRTV()
{
LogUMCMessage("Starting RTV.");
//Clear the array of clients who have entered RTV.
ClearArray(rtv_clients);
DEBUG_MESSAGE("Disabling RTV; setting rtv_completed flag to true")
rtv_completed = true;
new postAction = GetConVarInt(cvar_rtv_postaction);
//Change the map immediately if...
// ...there has already been an end-of-map vote AND
// ...the cvar that handles RTV actions after end-of-map votes specifies to change the map.
if (vote_completed && postAction == 0)
{
//Get the next map set by the vote.
decl String:temp[MAP_LENGTH];
GetNextMap(temp, sizeof(temp));
LogUMCMessage("End of map vote has already been completed, changing map.");
//Change to it.
ForceChangeInFive(temp, "RTV");
}
//Otherwise, build the RTV vote if...
// ...a vote hasn't already been completed.
else if (!vote_completed || postAction == 2)
{
//Do nothing if...
// ...there is a vote already in progress.
if (IsVoteInProgress())
{
LogUMCMessage("There is a vote already in progress, cannot start a new vote.");
MakeRetryVoteTimer(StartRTV);
return;
}
rtv_inprogress = true;
decl String:flags[64];
GetConVarString(cvar_voteflags, flags, sizeof(flags));
DEBUG_MESSAGE("Vote Flags: \"%s\"", flags)
new clients[MAXPLAYERS+1];
new numClients;
GetClientsWithFlags(flags, clients, sizeof(clients), numClients);
//Start the UMC vote.
new bool:result = UMC_StartVote(
"core",
map_kv, //Mapcycle
umc_mapcycle, //Complete Mapcycle
UMC_VoteType:GetConVarInt(cvar_rtv_type), //Vote Type (map, group, tiered)
GetConVarInt(cvar_vote_time), //Vote duration
GetConVarBool(cvar_scramble), //Scramble
vote_start_sound, //Start Sound
vote_end_sound, //End Sound
false, //Extend option
0.0, //How long to extend the timelimit by,
0, //How much to extend the roundlimit by,
0, //How much to extend the fraglimit by,
GetConVarBool(cvar_rtv_dontchange), //Don't Change option
GetConVarFloat(cvar_vote_threshold), //Threshold
UMC_ChangeMapTime:GetConVarInt(cvar_rtv_changetime), //Success Action (when to change the map)
UMC_VoteFailAction:GetConVarInt(cvar_fail_action), //Fail Action (runoff / nothing)
GetConVarInt(cvar_runoff), //Max Runoffs
GetConVarInt(cvar_runoff_max), //Max maps in the runoff
UMC_RunoffFailAction:GetConVarInt(cvar_runoff_fail_action), //Runoff Fail Action
runoff_sound, //Runoff Sound
GetConVarBool(cvar_strict_noms), //Nomination Strictness
GetConVarBool(cvar_vote_allowduplicates), //Ignore Duplicates
clients,
numClients
);
if (!result)
{
LogUMCMessage("Could not start UMC vote.");
}
}
}
//************************************************************************************************//
// ULTIMATE MAPCHOOSER EVENTS //
//************************************************************************************************//
//Called when a vote fails, either due to Don't Change or no votes.
public UMC_OnVoteFailed()
{
if (rtv_inprogress)
{
DEBUG_MESSAGE("RTV Failed. Setting completion flags to false.")
rtv_inprogress = false;
vote_completed = false;
rtv_delaystart = GetConVarFloat(cvar_rtv_interval);
MakeRTVTimer();
}
}
//Called when UMC has set a next map.
public UMC_OnNextmapSet(Handle:kv, const String:map[], const String:group[], const String:display[])
{
DEBUG_MESSAGE("Next Map has been set by UMC. Setting vote_completion flag to true")
vote_completed = true;
rtv_inprogress = false;
}
//Called when UMC requests that the mapcycle should be reloaded.
public UMC_RequestReloadMapcycle()
{
if (!ReloadMapcycle())
rtv_enabled = false;
else
RemovePreviousMapsFromCycle();
}
//Called when UMC requests that the mapcycle is printed to the console.
public UMC_DisplayMapCycle(client, bool:filtered)
{
PrintToConsole(client, "Module: Rock The Vote");
if (filtered)
{
new Handle:filteredMapcycle = UMC_FilterMapcycle(
map_kv, umc_mapcycle, false, true
);
PrintKvToConsole(filteredMapcycle, client);
CloseHandle(filteredMapcycle);
}
else
{
PrintKvToConsole(umc_mapcycle, client);
}
}
Инклуд
C-подобный:
//Header file for Ultimate Mapchooser v3.0 by Steell.
#if defined _umc_core_included
#endinput
#endif
#define _umc_core_included
#pragma semicolon 1
#define PL_VERSION "3.4.6-dev"
#define UMC_DEBUG 1
#define AUTOUPDATE_ENABLE 0
#define AUTOUPDATE_DEV 0
//SourceMod Malarky
public SharedPlugin:__pl_umccore =
{
name = "umccore",
file = "umc-core.smx",
#if defined REQUIRE_PLUGIN
required = 1,
#else
required = 0,
#endif
};
public __pl_umccore_SetNTVOptional()
{
MarkNativeAsOptional("UMC_AddWeightModifier");
MarkNativeAsOptional("UMC_StartVote");
MarkNativeAsOptional("UMC_GetCurrentMapGroup");
MarkNativeAsOptional("UMC_GetRandomMap");
MarkNativeAsOptional("UMC_SetNextMap");
MarkNativeAsOptional("UMC_IsMapNominated");
MarkNativeAsOptional("UMC_NominateMap");
MarkNativeAsOptional("UMC_CreateValidMapArray");
MarkNativeAsOptional("UMC_CreateValidMapGroupArray");
MarkNativeAsOptional("UMC_IsMapValid");
//MarkNativeAsOptional("UMC_IsGroupValid");
MarkNativeAsOptional("UMC_FilterMapcycle");
MarkNativeAsOptional("UMC_IsVoteInProgress");
MarkNativeAsOptional("UMC_StopVote");
MarkNativeAsOptional("UMC_RegisterVoteManager");
MarkNativeAsOptional("UMC_UnregisterVoteManager");
MarkNativeAsOptional("UMC_VoteManagerVoteCompleted");
MarkNativeAsOptional("UMC_VoteManagerVoteCancelled");
MarkNativeAsOptional("UMC_VoteManagerClientVoted");
MarkNativeAsOptional("UMC_FormatDisplayString");
MarkNativeAsOptional("UMC_IsNewVoteAllowed");
}
#define INVALID_GROUP ""
#define MAP_LENGTH PLATFORM_MAX_PATH
#define MAP_TRIE_MAP_KEY "map"
#define MAP_TRIE_GROUP_KEY "group"
#define DONT_CHANGE_OPTION "?DontChange?"
#define EXTEND_MAP_OPTION "?Extend?"
enum UMC_VoteType
{
VoteType_Map = 0,
VoteType_Group,
VoteType_Tier,
};
enum UMC_ChangeMapTime
{
ChangeMapTime_Now = 0,
ChangeMapTime_RoundEnd,
ChangeMapTime_MapEnd,
};
enum UMC_VoteFailAction
{
VoteFailAction_Nothing = 0,
VoteFailAction_Runoff,
};
enum UMC_RunoffFailAction
{
RunoffFailAction_Nothing = 0,
RunoffFailAction_Accept,
};
enum UMC_VoteResponse
{
VoteResponse_Success = 0,
VoteResponse_Runoff,
VoteResponse_Tiered,
VoteResponse_Fail,
};
/**
* Called when a nomination was removed from UMC.
*
* @param map The name of the map
* @param client The client that the nomination belonged to.
*
* @noreturn
*/
//Commented out to compile on SourceMod 1.7 or newer
//forward OnNominationRemoved(const String:map[], client);
/**
* Called when a map's weight is being reweighted. Allows plugin to modify the
* weight by calling UMC_AddWeightModifier.
*
* @param kv The mapcycle being used.
* @param map The name of the map we're reweighting.
* @param group The group that the map belongs to.
* @noreturn
*/
forward UMC_OnReweightMap(Handle:kv, const String:map[], const String:group[]);
/**
* Called when a group's weight is being reweighted.
*
* @param kv The mapcycle being used
* @param group The group being reweighted.
*
* @noreturn
*/
forward UMC_OnReweightGroup(Handle:kv, const String:group[]);
/**
* Adds a MapWeightModifier to UMC's internal modifier list.
*
* @param amt Amount to modify the currently weighted map's weight with.
*
* @noreturn
*/
native UMC_AddWeightModifier(Float:amt);
/**
* Called when a map is being considered for exclusion.
*
* @param kv The mapcycle being used.
* @param map The name of the map being considered.
* @param group The group that the map belongs to.
* @param isNomination Specifies whether this is a nominated map or not.
* @param forMapChange Whether or not this map will be used this game frame for a mapchange.
*
* @return Plugin_Continue to keep the map, Plugin_Stop to exclude the map.
*/
forward Action:UMC_OnDetermineMapExclude(Handle:kv, const String:map[], const String:group[],
bool:isNomination, bool:forMapChange);
/**
* Starts a UMC map vote.
*
* @param id
* @param mapcycle The mapcycle to use for the vote.
* @param originalMapcycle Original mapcycle, contains all information the user has defined.
* @param type The type of vote.
* @param time How long the vote should remain acive (in seconds).
* @param scramble Determines if the vote menu is scrambled.
* @param startSound Sound to be played when the vote starts (must be precached already).
* @param endSound Sound to be played when the vote ends (must be precached already).
* @param extendOption Determines if an "Extend Map" option is displayed.
* @param timestep How long to extend the time limit.
* @param roundstep How long to extend the round limit.
* @param fragstep How long to extend the frag limit.
* @param dontChangeOption Determines if a "Don't Change" option is displayed.
* @param threshold Percentage winning vote must exceed in order for the vote to change the map.
* @param successAction Action to be taken if the vote is successful (threshold was exceeded).
* @param failAction Action to be taken if the vote is unsuccessful (threshold wasn't exceeded).
* @param maxRunoffs Maximum amount of runoffs that will be performed. 0 = no max
* @param maxRunoffMaps Maximum amount of maps that appear in runoffs. 0 = no max
* @param runoffFailAction Action to be taken should the maximum amount of runoffs is reached and there is still no winning map.
* @param runoffSound Sound to be played when the runoff vote starts (must be precached already).
* @param nominationStrictness Specifies how nominations should be handled.
* @param allowDuplicates Determines if the same map (in different groups) can appear in the vote.
* @param clients String of flags required for players to see the vote.
* @param numClients Number of clients to read from clients array.
* @param runExclusion Determines if UMC will filter the mapcycle through the Map Exclusion system.
*
* @return True on success, false on failure.
*/
native bool:UMC_StartVote(const String:id[], Handle:mapcycle, Handle:originalMapcycle,
UMC_VoteType:type, time, bool:scramble, const String:startSound[], const String:endSound[],
bool:extendOption, Float:timestep, roundstep, fragstep, bool:dontChangeOption, Float:threshold,
UMC_ChangeMapTime:successAction, UMC_VoteFailAction:failAction, maxRunoffs, maxRunoffMaps,
UMC_RunoffFailAction:runoffFailAction, const String:runoffSound[], bool:nominationStrictness,
bool:allowDuplicates, const clients[], numClients, bool:runExclusion=true);
/**
* Fetches a random map from a given map group in a given mapcycle.
*
* @param mapcycle The mapcycle to use for the vote.
* @param originalMapcycle Original mapcycle, contains all information the user has defined.
* @param group Group to look for a map in. If INVALID_GROUP then it will look in all groups.
* @param buffer Buffer to store the fetched map in.
* @param size Max size of the buffer.
* @param groupBuffer Buffer to store the group of the map in.
* @param gBufferSize Max size of the group buffer.
* @param isNomination Whether or not this map should be treated as a nomination.
* @param forMapChange Whether or not this map will be used this game frame for a mapchange.
*
* @return True on success, false on failure.
*/
native bool:UMC_GetRandomMap(Handle:mapcycle, Handle:originalMapcycle, const String:group[],
String:buffer[], size, String:groupBuffer[], gBufferSize,
bool:isNomination, bool:forMapChange);
/**
* Sets the next map and map group for UMC.
*
* @param mapcycle Mapcycle containing the map and map group. Should contain all information the user has defined.
* @param map The name of the map
* @param group The name of the map group containing the map.
* @param when When the map should be changed to the set next map.
*
* @noreturn
*/
native UMC_SetNextMap(Handle:mapcycle, const String:map[], const String:group[],
UMC_ChangeMapTime:when);
/**
* Determines if the given map from the given group is nominated.
*
* @param map The name of the map.
* @param group The name of the map group containing the map.
*
* @return True if the map is nominated, false otherwise.
*/
native bool:UMC_IsMapNominated(const String:map[], const String:group[]);
/**
* Nominates a map for UMC.
*
* @param mapcycle Mapcycle containing the nomination. Should contain all information the user has defined.
* @param map The name of the map.
* @param group The name of the map group containing the map.
* @param client The client who is nominating this map.
* @param nominationGroup The group which this nomination should be associated with. If INVALID_GROUP, it will be associated with the given group.
*
* @return True on success, false otherwise.
*/
native bool:UMC_NominateMap(Handle:mapcycle, const String:map[], const String:group[], client,
const String:nominationGroup[]=INVALID_HANDLE);
/**
* Determines if the given group is valid (has at least 1 valid map in it) for the given mapcycle.
*
* @param mapcycle Mapcycle containing the group. Should contain all information the user has defined.
* @param group The group to be checked.
*
* @return True if the group is valid, false otherwise.
*/
//native bool:UMC_IsGroupValid(Handle:mapcycle, const String:group[]);
/**
* Determines if the given map is valid for the given mapcycle.
*
* @param mapcycle Mapcycle containing the map. Should contain all information the user has defined.
* @param map The name of the map.
* @param group The name of the group containing the map.
* @param isNom
* @param forMapChange
*
* @return True if the map is valid, false otherwise.
*/
native bool:UMC_IsMapValid(Handle:mapcycle, const String:map[], const String:group[], bool:isNom,
bool:forMapChange);
/**
* Returns a copy of the given mapcycle with all invalid maps and groups filtered out.
*
* @param mapcycle Mapcycle to filter. Should contain all information the user has defined.
* @param isNomination Are we filtering for nomination?
* @param forMapChange Are we filtering for maps we will be using this frame for a map change?
*
* @return Handle to the new mapcycle KV.
*/
native Handle:UMC_FilterMapcycle(Handle:mapcycle, Handle:originalMapcycle, bool:isNomination,
bool:forMapChange);
/**
* Returns an array consisting of all the valid maps in the given mapcycle.
*
* @param mapcycle Mapcycle to look for maps in.
* @param originalMapcycle Original mapcycle, contains all information that the user has defined.
* @param group Group to select maps from. If INVALID_GROUP, all groups are looked in.
* @param isNom Are these maps to be considered nominations?
* @param forMapChange Are any of these maps going to be used to change the map this game frame?
*
* @return Handle to the new array containing all of the valid map tries.
*/
native Handle:UMC_CreateValidMapArray(Handle:mapcycle, Handle:originalMapcycle,
const String:group[], bool:isNom, bool:forMapChange);
/**
* Returns an array consisting of all the valid groups in the given mapcycle. A valid group is a
* group with 1 or more valid maps in it.
*
* @param kv Mapcycle to look for maps in.
* @param originalMapcycle Original mapcycle, contains all information that the user has defined.
* @param isNom Are the maps in these groups to be considered nominations?
* @param forMapChange Are any of the maps in these groups going to be used to change the map this game frame?
*
* @return Handle to the new array containing all of the valid map groups.
*/
native Handle:UMC_CreateValidMapGroupArray(Handle:kv, Handle:originalMapcycle, bool:isNom,
bool:forMapChange);
/**
* Called when has extended the map.
*
* @noreturn
*/
forward UMC_OnMapExtended();
/**
* Called when a vote has failed. This can be due to the Don't Change option winning the vote or the
* winning map not winning by a high enough percentage.
*
* @noreturn
*/
forward UMC_OnVoteFailed(); //UMC_FailReason:reason);
/**
* Called immediately after UMC has set a next map.
*
* @param kv The mapcycle used for the vote.
* @param map The name of the winning map.
* @param group The group of the winning map.
* @param display The "display name" of the winning map.
*
* @noreturn
*/
forward UMC_OnNextmapSet(Handle:kv, const String:map[], const String:group[],
const String:display[]);
/**
* Called when the "sm_umc_reload" command is used. If your plugin has its own mapcycle, you should
* reload it in this forward.
*
* @noreturn
*/
forward UMC_RequestReloadMapcycle();
/**
* Retrieves the name of the current map group.
*
* @param buffer Buffer to store the group name in.
* @param size Maximum length of the buffer.
*
* @noreturn
*/
native UMC_GetCurrentMapGroup(String:buffer[], size);
/**
* Determines if UMC currently has a vote in progress.
*
* @param id
*
* @return True if vote is in progress, false otherwise.
*/
native bool:UMC_IsVoteInProgress(const String:id[]);
/**
* Stops a UMC vote that is currently in progress.
*
* @param id
*
* @return True on success, false otherwise.
*/
native bool:UMC_StopVote(const String:id[]);
/**
* Callback for when a vote is to be started by UMC. Note that all Handles will be freed after the
* call is complete, so if you want to store them, make sure to clone them first with CloneHandle.
*
* @param duration
* @param vote_items
* @param clients
* @param extend
* @param dontChange
* @param startSound
*
* @return Plugin_Continue on success, Plugin_Stop to prevent the vote.
*/
functag UMC_VoteHandler Action:public(duration, Handle:vote_items, const clients[], numClients,
const String:startSound[]);
/**
*
*/
functag UMC_VoteCancelledHandler public();
functag UMC_VoteInProgressHandler bool:public();
/**
* Registers a new VoteManager for UMC votes.
*
* @param id Unique string identifier for this VoteManager.
* @param callback Function to be called when a vote is ready to be started.
* @param cancelCallback Function to be called when a vote is cancelled.
* @param progressCallback Function to be called to check if a vote is in progress. Set to INVALID_FUNCTION to use IsVoteInProgress()
*
* @noreturn
*/
native UMC_RegisterVoteManager(const String:id[], UMC_VoteHandler:mapCallback,
UMC_VoteHandler:groupCallback,
UMC_VoteCancelledHandler:cancelCallback,
UMC_VoteInProgressHandler:progressCallback=INVALID_FUNCTION);
/**
*
*/
functag UMC_VoteResponseHandler public(UMC_VoteResponse:response, const String:param[]);
/**
* Notifies UMC that the current vote has completed.
*
* @param id Id of the Vote Manager which has completed.
* @param voteOptions adt_array of options in the vote
* @param callback Callback for processing the results of the vote.
*
* @noreturn
*/
native UMC_VoteManagerVoteCompleted(const String:id[], Handle:voteOptions,
UMC_VoteResponseHandler:callback);
/**
* Notifies UMC that the current vote has been cancelled by the vote Handler. This will cause the
* UMC_VoteCancelledHandler provided to UMC_RegisterVoteManager to be called as well.
*
* @param id ID of the Vote Manager to cancel.
*/
native UMC_VoteManagerVoteCancelled(const String:id[]);
/**
* Unregisters a Vote Manager from UMC.
*
* @param id ID of the Vote Manager to unregister.
*/
native UMC_UnregisterVoteManager(const String:id[]);
/**
* Called when UMC requests a Map Cycle to be displayed.
*
* @param client Client to display the Map Cycle to.
* @param filtered If true, it is requested that mapcycle only shows maps which pass UMC exclusion.
*/
forward UMC_DisplayMapCycle(client, bool:filtered);
/**
*
*/
forward UMC_VoteStarted(const String:voteManagerId[], const clients[], numClients,
Handle:voteOptions);
/**
*
*/
forward UMC_VoteEnded(const String:voteManagerId[], UMC_VoteResponse:reason);
/**
*
*/
forward UMC_ClientVoted(const String:voteManagerId[], client, Handle:option);
/**
*
*/
native UMC_VoteManagerClientVoted(const String:id[], client, Handle:option);
/**
*
*/
forward UMC_OnFormatTemplateString(String:template[], maxlen, Handle:kv, const String:map[],
const String:group[]);
/**
*
*/
native UMC_FormatDisplayString(String:display[], maxlen, Handle:mapcycle, const String:map[],
const String:group[]);
/**
* Is a new vote allowed on this vote manager?
*
* @param id ID of the Vote Manager to check. Defaults to "core".
* @return True if we can start a new vote, false otherwise.
*/
native bool:UMC_IsNewVoteAllowed(const String:id[]="core");
Ошибки компилятора
C-подобный:
//// umc-rockthevote.sp
//
// ******\include\umc-core.inc(407) : error 418: deprecated syntax; see https://wiki.alliedmods.net/SourcePawn_Transitional_Syntax#Typedefs
// ******\include\umc-core.inc(407) : error 001: expected token: "-identifier-", but found "public"
// ******\include\umc-core.inc(407) : error 122: expected type expression