26.07.2015, 19:59
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.
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.
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 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.