I haven't looked at the source code, but by the looks of it, it would be nice to have something like this for an event system. Also, I created a map voting/management system a while back, mind including it here or something? It would make this somehow more complex and it might turn out to be good for events and such.
pawn Код:
// [ DEVELOPMENT GAMEMODE ]
// INCLUDES:
#include <a_samp>
#include <sscanf2>
#include <foreach>
#include <zcmd>
// DEFINES:
// GENERAL:
#define MAX_MAPS 100
#define MAX_MAP_INFO 2
#define MAX_PAGE_RESULTS 20
#define VOTE_INTERVAL 30
#define INTERVAL_TIME 180000
// FUNCTIONS:
#define function%0(%1) forward%0(%1); public%0(%1)
#define isnull(%1) ((!(%1[0])) || (((%1[0]) == '\1') && (!(%1[1]))))
#define strcpy(%0,%1,%2) strcat((%0[0] = '\0', %0), %1, %2)
#define GetPageCount(%0,%1) floatround((%1 - 1) / %0, floatround_floor) + 1
#define plural_singular(%0,%1,%2) ((%0) == 1)?((#%1)):((#%2))
// DIALOGS:
#define DIALOG_OK 0
#define DIALOG_MAP_NAME 1
#define DIALOG_MAP_POSITION 2
#define DIALOG_MAP_CONFIRMATION 3
#define DIALOG_MAP_LIST 4
#define DIALOG_MAP_VOTE 5
#define DIALOG_MAP_VOTE_OPTIONS 6
// DATABASE:
#define DATABASE_PATH "maps.db"
#define TABLE_MAPS "Maps"
#define MAP_NAME "name"
#define MAP_POSITION "position"
// MAP INFO:
#define MAP_INFO_NAME 0
#define MAP_INFO_POSITION 1
// ARRAYS AND ENUMERATORS:
enum eMapInfo
{
map_name[128],
Float:map_x,
Float:map_y,
Float:map_z,
Float:map_angle,
map_votes
};
new aMapInfo[MAX_MAPS][eMapInfo];
// VARIABLES:
// GENERAL:
new gMapCount,
gVoteCountDown,
gTopVotes,
gLeadingMap;
// DATABASE:
new DB:database;
// TIMERS:
new gtmMapVoting,
gtmLoadMap,
gtmChangeMap;
// TEXTDRAWS:
new Text:tCountDown;
// PER-PLAYER VARIABLES:
// GENERAL:
new pNewMapString[MAX_PLAYERS][MAX_MAP_INFO][128],
pLastPage[MAX_PLAYERS],
pMap[MAX_PLAYERS];
// STATES:
new bool:sVoting[MAX_PLAYERS] = false;
// MAIN:
main()
{
print("Development Mode: map_voting.amx");
}
// CALLBACKS:
public OnGameModeInit()
{
LoadDatabase();
LoadTextdraws();
new query[144], DBResult:result, results, position[128], count;
format(query, sizeof(query), "SELECT `%s`, `%s` FROM `%s`",
MAP_NAME,
MAP_POSITION,
TABLE_MAPS);
result = db_query(database, query);
results = db_num_rows(result);
gMapCount = results;
if(results != 0)
{
if(count <= MAX_MAPS)
{
db_get_field_assoc(result, MAP_NAME, aMapInfo[count][map_name], 128);
db_get_field_assoc(result, MAP_POSITION, position, sizeof(position));
format(position, sizeof(position), "%s", ReplaceString(",", " ", position));
sscanf(position, "ffff", aMapInfo[count][map_x], aMapInfo[count][map_y], aMapInfo[count][map_z], aMapInfo[count][map_angle]);
count ++;
while(db_next_row(result))
{
if(count > MAX_MAPS) break;
db_get_field_assoc(result, MAP_NAME, aMapInfo[count][map_name], 128);
db_get_field_assoc(result, MAP_POSITION, position, sizeof(position));
format(position, sizeof(position), "%s", ReplaceString(",", " ", position));
sscanf(position, "ffff", aMapInfo[count][map_x], aMapInfo[count][map_y], aMapInfo[count][map_z], aMapInfo[count][map_angle]);
count ++;
}
}
}
db_free_result(result);
gtmChangeMap = SetTimer("ChangeMap", INTERVAL_TIME, true);
return 1;
}
public OnGameModeExit()
{
return 1;
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case DIALOG_OK: return 1;
case DIALOG_MAP_NAME:
{
if(!response) return 1;
else if(response)
{
if(isnull(inputtext)) return ShowEnterMapName(playerid);
strcpy(pNewMapString[playerid][MAP_INFO_NAME], inputtext, 128);
return ShowEnterMapPosition(playerid);
}
}
case DIALOG_MAP_POSITION:
{
if(!response) return ShowEnterMapName(playerid);
else if(response)
{
if(isnull(inputtext)) return ShowEnterMapPosition(playerid);
strcpy(pNewMapString[playerid][MAP_INFO_POSITION], inputtext, 128);
return ShowAddMapConfirmation(playerid);
}
}
case DIALOG_MAP_CONFIRMATION:
{
if(!response) return ShowEnterMapPosition(playerid);
else if(response)
{
new query[256];
format(query, sizeof(query), "INSERT INTO `%s` ", TABLE_MAPS);
format(query, sizeof(query), "%s(`%s`,", query, MAP_NAME);
format(query, sizeof(query), "%s`%s`) ", query, MAP_POSITION);
format(query, sizeof(query), "%sVALUES('%s',", query, pNewMapString[playerid][MAP_INFO_NAME]); // MAP_NAME
format(query, sizeof(query), "%s'%s')", query, pNewMapString[playerid][MAP_INFO_POSITION]); // MAP_POSITION
db_query(database, query);
gMapCount ++;
strcpy(aMapInfo[gMapCount][map_name], pNewMapString[playerid][MAP_INFO_NAME], 128);
sscanf(pNewMapString[playerid][MAP_INFO_POSITION], "ffff", aMapInfo[gMapCount][map_x], aMapInfo[gMapCount][map_y], aMapInfo[gMapCount][map_z], aMapInfo[gMapCount][map_angle]);
}
}
case DIALOG_MAP_LIST:
{
if(!response) return 1;
else if(response)
{
pLastPage[playerid] ++;
return ShowMaps(playerid);
}
}
case DIALOG_MAP_VOTE:
{
if(!response)
{
new pages = GetPageCount(MAX_PAGE_RESULTS, gMapCount);
if(pLastPage[playerid] < pages) pLastPage[playerid] ++;
return ShowMaps(playerid);
}
else if(response)
{
new mapid = (((MAX_PAGE_RESULTS * pLastPage[playerid]) - MAX_PAGE_RESULTS) + listitem);
pMap[playerid] = mapid;
return ShowMapVoteOptions(playerid);
}
}
case DIALOG_MAP_VOTE_OPTIONS:
{
if(!response) return ShowMaps(playerid);
else if(response)
{
switch(listitem)
{
case 0: // Vote for map
{
new string[144], mapid = pMap[playerid];
aMapInfo[mapid][map_votes] ++;
if(aMapInfo[mapid][map_votes] > gTopVotes)
{
gTopVotes = aMapInfo[mapid][map_votes];
gLeadingMap = mapid;
}
format(string, sizeof(string), "You have voted for the map: %s.", aMapInfo[mapid][map_name]);
SendClientMessage(playerid, -1, string);
sVoting[playerid] = false;
}
case 1: // Previous page
{
if(pLastPage[playerid] > 1) pLastPage[playerid] --;
return ShowMaps(playerid);
}
case 2: // Next page
{
new pages = GetPageCount(MAX_PAGE_RESULTS, gMapCount);
if(pLastPage[playerid] < pages) pLastPage[playerid] ++;
return ShowMaps(playerid);
}
}
}
}
}
return 1;
}
// COMMANDS:
CMD:voteoff(playerid, cmd[], cmdtext[])
{
KillTimer(gtmChangeMap);
return 1;
}
CMD:voteon(playerid, cmd[], cmdtext[])
{
KillTimer(gtmChangeMap);
gtmChangeMap = SetTimer("ChangeMap", INTERVAL_TIME, true);
return 1;
}
CMD:addmap(playerid, cmd[], cmdtext[])
{
if(IsPlayerVoting(playerid)) return SendClientMessage(playerid, -1, "You cannot use this command while voting for a map.");
if(gMapCount >= MAX_MAPS) return SendClientMessage(playerid, -1, "The max amount of maps has been reached, you cannot create another one.");
ShowEnterMapName(playerid);
return 1;
}
CMD:maps(playerid, cmd[], cmdtext[])
{
if(IsPlayerVoting(playerid)) return SendClientMessage(playerid, -1, "You cannot use this command while voting for a map.");
pLastPage[playerid] = 1;
ShowMaps(playerid);
return 1;
}
CMD:forcevote(playerid, params[])
{
if(IsPlayerVoting(playerid)) return SendClientMessage(playerid, -1, "You cannot use this command while voting for a map.");
if(gMapCount <= 0) return SendClientMessage(playerid, -1, "There are no maps for players to vote for.");
gTopVotes = 0;
gLeadingMap = 0;
for(new i = 0; i < gMapCount; i ++)
{
aMapInfo[i][map_votes] = 0;
}
foreach(new i: Player)
{
sVoting[i] = true;
pLastPage[i] = 1;
ShowMaps(i);
}
gVoteCountDown = VOTE_INTERVAL;
KillTimer(gtmMapVoting);
gtmMapVoting = SetTimer("MapVoting", 1000, true);
return 1;
}
// FUNCTIONS:
stock LoadDatabase()
{
new query[128];
database = db_open(DATABASE_PATH);
format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `%s` ", TABLE_MAPS);
format(query, sizeof(query), "%s(`%s`,", query, MAP_NAME);
format(query, sizeof(query), "%s`%s`)", query, MAP_POSITION);
db_query(database, query);
}
stock LoadTextdraws()
{
tCountDown = TextDrawCreate(321.000000, 411.000000, "");
TextDrawAlignment(tCountDown, 2);
TextDrawBackgroundColor(tCountDown, 255);
TextDrawFont(tCountDown, 2);
TextDrawLetterSize(tCountDown, 0.319999, 1.400000);
TextDrawColor(tCountDown, -1);
TextDrawSetOutline(tCountDown, 0);
TextDrawSetProportional(tCountDown, 1);
TextDrawSetShadow(tCountDown, 1);
TextDrawSetSelectable(tCountDown, 0);
return 1;
}
stock ShowEnterMapName(playerid)
{
new string[144];
strcat(string, "{FFFFFF}Please enter the name of the map below.");
return ShowPlayerDialog(playerid, DIALOG_MAP_NAME, DIALOG_STYLE_INPUT, "{FFFF00}Add Map: Map Name", string, "Submit", "Close");
}
stock ShowEnterMapPosition(playerid)
{
new string[256];
strcat(string, "{FFFFFF}Please enter the position of the map's spawn below.\n");
strcat(string, "Example: {9C00FF}0.0 0.0 0.0 0.0, 0.0, 0.0, 0.0, 0.0\n");
strcat(string, "or 0.0,0.0,0.0,0.0 (x, y, z, angle).\n\n");
strcat(string, "{FF0000}Using the wrong syntax might cause issues.");
return ShowPlayerDialog(playerid, DIALOG_MAP_POSITION, DIALOG_STYLE_INPUT, "{FFFF00}Add Map: Map Position", string, "Submit", "Back");
}
stock ShowAddMapConfirmation(playerid)
{
new string[256], temp[128];
strcat(string, "{FFFFFF}You are about to add a new map.\n");
format(temp, sizeof(temp), "- Name: %s\n", pNewMapString[playerid][MAP_INFO_NAME]);
strcat(string, temp);
format(temp, sizeof(temp), "- Position: %s\n\n", pNewMapString[playerid][MAP_INFO_POSITION]);
strcat(string, temp);
strcat(string, "Are these fields correct?");
return ShowPlayerDialog(playerid, DIALOG_MAP_CONFIRMATION, DIALOG_STYLE_MSGBOX, "{FFFF00}Add Map: Confirmation", string, "Yes", "No");
}
stock ShowMaps(playerid)
{
new title[128], string[300], pages = GetPageCount(MAX_PAGE_RESULTS, gMapCount), resultcount = ((MAX_PAGE_RESULTS * pLastPage[playerid]) - MAX_PAGE_RESULTS), bool:nextpage = false;
strcat(string, "ID\tName\tVotes");
for(new i = resultcount; i < gMapCount; i ++)
{
resultcount ++;
if(resultcount <= MAX_PAGE_RESULTS * pLastPage[playerid])
{
format(string, sizeof(string), "%s\n%d\t%s\t%s", string, resultcount, aMapInfo[i][map_name], ConvertToAmount(aMapInfo[i][map_votes]));
}
else if(resultcount > MAX_PAGE_RESULTS * pLastPage[playerid])
{
nextpage = true;
break;
}
}
if(IsPlayerVoting(playerid))
{
format(title, sizeof(title), "{414DE9}Maps - Page %s of %s", ConvertToAmount(pLastPage[playerid]), ConvertToAmount(pages));
if(nextpage) return ShowPlayerDialog(playerid, DIALOG_MAP_VOTE, DIALOG_STYLE_TABLIST_HEADERS, title, string, "Options", "Next");
ShowPlayerDialog(playerid, DIALOG_MAP_VOTE, DIALOG_STYLE_TABLIST_HEADERS, title, string, "Options", "");
}
else
{
format(title, sizeof(title), "{414DE9}Maps - Page %s of %s", ConvertToAmount(pLastPage[playerid]), ConvertToAmount(pages));
if(nextpage ) return ShowPlayerDialog(playerid, DIALOG_MAP_LIST, DIALOG_STYLE_TABLIST_HEADERS, title, string, "Next", "Close");
ShowPlayerDialog(playerid, DIALOG_OK, DIALOG_STYLE_TABLIST_HEADERS, title, string, "Close", "");
}
return 1;
}
stock ShowMapVoteOptions(playerid)
{
new title[128], string[256];
format(string, sizeof(string), "{FFFFFF}Vote for map\n");
format(string, sizeof(string), "%sPrevious page\n", string);
format(string, sizeof(string), "%sNext page", string);
format(title, sizeof(title), "{414DE9}Map: %s", aMapInfo[pMap[playerid]][map_name]);
return ShowPlayerDialog(playerid, DIALOG_MAP_VOTE_OPTIONS, DIALOG_STYLE_LIST, title, string, "Select", "Back");
}
stock ConvertToAmount(value)
{
new string[128], count = -1;
valstr(string, value);
for(new i = strlen(string); i > 0; i --)
{
count++;
if(count == 3)
{
strins(string, ",", i);
count = 0;
}
}
return string;
}
stock ReplaceString(search[], replace[], source[])
{
new string[256], length;
for(new i = 0; i < strlen(source); i ++)
{
if(strlen(search) > 1 && i != (strlen(source) - 1))
{
new bool:match = false, start = i;
for(new j = 0; j < strlen(search) && !match; j ++)
{
if(source[i] != search[j] && j == 0)
{
string[length] = source[i];
match = true;
}
else
{
if(source[i] == search[j]) i ++;
else match = true;
}
}
if(match == true)
{
while(start <= i)
{
string[length] = source[start];
length ++;
start ++;
}
}
else
{
for(new j; j < strlen(replace); j ++)
{
string[length] = replace[j];
length ++;
}
i = (start + (strlen(search) - 1));
}
}
else
{
if(strlen(search) == 1 && source[i] == search[0])
{
for(new j; j < strlen(replace); j ++)
{
string[length] = replace[j];
length ++;
}
}
else
{
string[length] = source[i];
length ++;
}
}
}
string[length] = EOS;
return string;
}
function bool:IsPlayerVoting(playerid) return sVoting[playerid];
function MapVoting()
{
new string[144];
if(gVoteCountDown > 0)
{
if(gLeadingMap == 0 && gTopVotes == 0)
{
format(string, sizeof(string), "~r~MAP VOTING: ~y~%s~n~~p~~h~N/A (N/A votes)", ConvertToAmount(gVoteCountDown));
}
else
{
format(string, sizeof(string), "~r~MAP VOTING: ~y~%s~n~~p~~h~%s (%s %s)", ConvertToAmount(gVoteCountDown), aMapInfo[gLeadingMap][map_name], \
ConvertToAmount(aMapInfo[gLeadingMap][map_votes]), plural_singular(aMapInfo[gLeadingMap][map_votes], "vote", "votes"));
}
TextDrawSetString(tCountDown, string);
TextDrawShowForAll(tCountDown);
}
else if(gVoteCountDown == 0)
{
foreach(new i: Player)
{
ShowPlayerDialog(i, -1, DIALOG_STYLE_MSGBOX, " ", " ", " ", " ");
}
if(gLeadingMap == 0 && gTopVotes == 0)
{
format(string, sizeof(string), "~r~NEXT MAP:~n~~p~~h~Random (0 votes)");
}
else
{
format(string, sizeof(string), "~r~NEXT MAP:~n~~p~~h~%s (%s %s)", aMapInfo[gLeadingMap][map_name], ConvertToAmount(aMapInfo[gLeadingMap][map_votes]), \
plural_singular(aMapInfo[gLeadingMap][map_votes], "vote", "votes"));
}
TextDrawSetString(tCountDown, string);
TextDrawShowForAll(tCountDown);
}
else if(gVoteCountDown <= -3)
{
TextDrawHideForAll(tCountDown);
KillTimer(gtmMapVoting);
new selected;
if(gLeadingMap == 0 && gTopVotes == 0) selected = random(gMapCount);
else selected = gLeadingMap;
GameTextForAll("Loading Map...", 5000, 5);
foreach(new i: Player)
{
TogglePlayerControllable(i, false);
SetPlayerPos(i, aMapInfo[selected][map_x], aMapInfo[selected][map_y], aMapInfo[selected][map_z]);
SetPlayerFacingAngle(i, aMapInfo[selected][map_angle]);
SetCameraBehindPlayer(i);
KillTimer(gtmLoadMap);
gtmLoadMap = SetTimer("LoadMap", 5000, false);
}
}
gVoteCountDown --;
return 1;
}
function LoadMap()
{
GameTextForAll("Map Loaded!", 3000, 5);
foreach(new i: Player)
{
TogglePlayerControllable(i, true);
}
return 1;
}
function ChangeMap()
{
if(gMapCount > 0)
{
gTopVotes = 0;
gLeadingMap = 0;
for(new i = 0; i < gMapCount; i ++)
{
aMapInfo[i][map_votes] = 0;
}
foreach(new i: Player)
{
sVoting[i] = true;
pLastPage[i] = 1;
ShowMaps(i);
}
gVoteCountDown = VOTE_INTERVAL;
KillTimer(gtmMapVoting);
gtmMapVoting = SetTimer("MapVoting", 1000, true);
}
return 1;
}
So, basically you can add server-called maps (name and position), let people vote and then bring them there after an interval has surpassed itself. You can also force them to vote for a map. Example: "DM event coming up: Vote for a map!" and then they have to vote; otherwise, other actions will be taken once the interval is over, depending whether they voted or not.
So what you do is create a group of objects with the dynamic map system and as an add-on with the map voting system you can make it so it loads that group of objects which composes a server map and let the system do the rest.
If you do not want to, then it's all good. It would a great addition, though.