/**************************************************************************
 *		Who, what, why, where, when, how?                         *
 * WHO?  Joe "Caveman Noyes						  *
 * WHAT? A replacement for admin_vote_map that allows more than one map   *
 *       nomination, plugin_cavey_votemap.sma v1.5.0c                     *
 * WHY?  Gazbo ran a server called Frog (long story) and at the end of the*
 *       year he went back to the states with his girlfriend. Lots of 2nd *
 *       year students remembered his scripts, but they were never on the *
 *       adminmod plugins download page, so they are now back by popular  *
 *       demand.                                                          *
 * WHERE?Oh yeah, I am in Exeter University.                             *
 *  	 - http://gosh.ex.ac.uk/~py99jan/                                 *
 * WHEN? This was last saved 15:29 30/03/2002                             *
 * HOW?	 To install this, compile the script and place it in the dlls     *
 *       directory in CStrike. Then add a line at the TOP of your         *
 *       plugin.ini file that lists the compiled .amx.  It MUST go at the *
 *       top so that it stops the original admin_vote_map from running.   *
 * Help! ICQ me on 70710878 with any bugs and issues.  I will NOT help    *
 *       compiling or installing this plugin as it is all included on     *
 * 	 - www.adminmod.org 						  *
 * 	 or in this file.  Enjoy ;)					  *
 * 	 								  *
 * 	 Caveman							  *
 **************************************************************************/
 
 
#include <core>
#include <console>
#include <string>
#include <admin>
#include <adminlib>
 
/*Settings you can screw with*/
#define ACCESS_CANCEL_VOTE 2
	/*EXPLANATION Defines what level admin can cancel a vote.         */
#define NOMINATION_INTERVAL_SEC 120
	/*EXPLANATION Determins how long to allow for more maps to be     *
	 * added                                                          */
#define NOMINATION_RETRY_INTERVAL_SEC 30
	/*EXPLANATION If a vote fails due to another vote being called    *
	 * it will retry in this many seconds.                            */
#define MAX_NOMINATIONS 3
	/*EXPLANATION The maximum number of maps you will allow to be     *
	 * nominated. NOTE, this CANNOT exceed 8!!!! If you do, you run   *
	 * out of numbers in the vote menu, and do you really need more?  */
#define REMEMBER_MAPS 8
	/*EXPLANATION This sets the number of maps it remembers from past *
	 * votes.  The higher you set it, the more it remembers.  It will *
	 * not let you nominate any map that it remembers, so only enable *
	 * if you are sick of the same few maps.  Set it to 0 to disable. */
#define NEWMAP_TIME 0
	/*EXPLANATION This is how many minutes the script will block map  *
	 *  votes for, so it stops lamers changing the map immediatly     */
#define NOMINATE_MAX 0
	/*EXPLANATION This filters for how many maps one person can       *
         *  nominate per vote. Set to 0 to disable                        */
 
/*Static global variables*/
	/*EXPLANATION these are the strings that appear when somone starts*
	 * a map vote and should be used to explain how to add more maps  */
new NOMINATIONS_BEGUN_MSG1[] = "Map nominations have begun, map vote starts in 2 minutes.";
new NOMINATIONS_BEGUN_MSG2[] = "To nominate a map press the ^"~^", type ^"admin_vote_map <map_name>^", press ^"~^" again";
 
/*Global variables you should NOT screw with!*/
new NominatedMaps[MAX_NOMINATIONS][MAX_NAME_LENGTH];
new NominatedMapsIndex = 0;
new vote_canceled;
new MapNominator[MAX_NOMINATIONS];
#if REMEMBER_MAPS != 0
new RememberedMaps[REMEMBER_MAPS][MAX_NAME_LENGTH];
#endif
 
new STRING_VERSION[MAX_DATA_LENGTH] = "2.50.26";
 
InitializeNominatedMaps() {
	new MapCount;
	for(MapCount=0;MapCount<MAX_NOMINATIONS;MapCount++) {
		NominatedMaps[MapCount][0] = NULL_CHAR;
		MapNominator[MapCount] = 0;
	}
	NominatedMapsIndex = 0;
	return PLUGIN_HANDLED;
}
 
	/*EXPLANATION THis is the function users can make use of          */
public admin_vote_map(HLCommand,HLData,HLUserName,UserIndex) {
	new Command[MAX_COMMAND_LENGTH];
	new Data[MAX_DATA_LENGTH];
	new User[MAX_NAME_LENGTH];
	new MapCount;
	new msg[MAX_TEXT_LENGTH] = "";
	new CurrentMapName[MAX_DATA_LENGTH];
	new temp[MAX_NAME_LENGTH];
	new TimeInto[MAX_NUMBER_LENGTH];	
 
	convert_string(HLCommand,Command,MAX_COMMAND_LENGTH);
	convert_string(HLData,Data,MAX_DATA_LENGTH);
	convert_string(HLUserName,User,MAX_NAME_LENGTH);
	currentmap(CurrentMapName,MAX_DATA_LENGTH);
 
	numtostr(maptime(0)/60, TimeInto);
#if NEWMAP_TIME != 0
	if (maptime(0)/60 < NEWMAP_TIME){
		snprintf(msg, MAX_TEXT_LENGTH, "[BEAST] You may not like this map, but at least play it for a few minutes");
		selfmessage(msg);
		snprintf(msg, MAX_TEXT_LENGTH, "[BEAST] %s was lame and tried to change the map after only %s minutes",User, TimeInto);
		say(msg);
		snprintf(msg, MAX_TEXT_LENGTH, "[BEAST] You may not vote for a new map within %d of a map change, %d remain", NEWMAP_TIME, NEWMAP_TIME - maptime(0)/60);
		selfmessage(msg);
		return PLUGIN_HANDLED;
	}
#endif
	for(MapCount=0;MapCount<MAX_NOMINATIONS;MapCount++) {
		if (streq(Data,NominatedMaps[MapCount])==1) {
	  		strcat(msg, "Map already nominated: ",  MAX_TEXT_LENGTH);
			strcat(msg, Data,  MAX_TEXT_LENGTH);
			selfmessage(msg);
			return PLUGIN_HANDLED;
		}
	}
	if (streq(Data,CurrentMapName)==1) {
		strcat(msg, "That is the current map you fool.",  MAX_TEXT_LENGTH);
		selfmessage(msg);
		return PLUGIN_HANDLED;
	}
#if REMEMBER_MAPS != 0
	for(MapCount=0;MapCount<REMEMBER_MAPS;MapCount++) {
		readfile("lastmaps.ini",RememberedMaps[MapCount],(MapCount+1),MAX_NAME_LENGTH);
		if (streq(Data,RememberedMaps[MapCount])==1) {
	  		strcat(msg, "Map nomination DENIED: ",  MAX_TEXT_LENGTH);
			strcat(msg, Data,  MAX_TEXT_LENGTH);
			strcat(msg, " Reason: Won recent vote",  MAX_TEXT_LENGTH);
			selfmessage(msg);
			return PLUGIN_HANDLED;
		}
	}
#endif
#if NOMINATE_MAX != 0
	new i;
	for(MapCount=0;MapCount<REMEMBER_MAPS;MapCount++) {
		if (UserIndex == MapNominator[MapCount]){
			i++;
		}
	}
	if (i >= NOMINATE_MAX ){
		strcat(msg, "You have already nominated enough maps, you may not nominate any more.",  MAX_TEXT_LENGTH);
		selfmessage(msg);
		return PLUGIN_HANDLED;
	}
#endif
	if (valid_map(Data) != 1) {
		selfmessage( "Invalid map name, please try again or use admin_listmaps");
		return PLUGIN_HANDLED;
 
	} else if (NominatedMapsIndex >= MAX_NOMINATIONS-1) {
		selfmessage("The maximum number of nominations has already been reached.");
		return PLUGIN_HANDLED;
 
	} else { 
		strcpy(NominatedMaps[NominatedMapsIndex],Data, MAX_NAME_LENGTH);
		MapNominator[NominatedMapsIndex] = UserIndex;
		if (NominatedMapsIndex == 0) {
			say(NOMINATIONS_BEGUN_MSG1);
			say(NOMINATIONS_BEGUN_MSG2);
			vote_canceled=0;  /*Un-cancels the vote*/
			set_timer("VoteOnNominatedMaps",NOMINATION_INTERVAL_SEC,1,"");
		}
		NominatedMapsIndex++;
		strcpy(" ",msg,  MAX_TEXT_LENGTH);
		numtostr(NominatedMapsIndex,temp);
		strcat(msg,temp,  MAX_TEXT_LENGTH);
		strcat(msg," (",  MAX_TEXT_LENGTH);
		strcat(msg,Data,  MAX_TEXT_LENGTH);
		strcat(msg,") has been added by ",  MAX_TEXT_LENGTH);
		strcat(msg,User,  MAX_TEXT_LENGTH);
		say(msg);
	}
	return PLUGIN_HANDLED;
}
 
public VoteOnNominatedMaps () {
	new msg[MAX_TEXT_LENGTH] = "\yChange map to:-\w";
	new nochange[MAX_TEXT_LENGTH] = "No change of map";
	new strNumber[MAX_NUMBER_LENGTH];
	new iserror = 0;
 
	if(vote_canceled==1) {
		say("Map vote successully canceled");
		/*If an admin has canceled the vote, it bails and resets*/
		InitializeNominatedMaps();
		vote_canceled=0;
		return PLUGIN_HANDLED;
	} else if(vote_allowed()!=1) {
		say("Vote DELAYED for change map.");
		/*If it goes tits up cause someone held a vote, it tries again.*/
		set_timer("VoteOnNominatedMaps",NOMINATION_RETRY_INTERVAL_SEC,1,"");
		return PLUGIN_HANDLED;
	} else {
	/* NominatedMapsIndex should already be one past the player entered  *
	 * maps, this is okay becaue the nochange option uses a vote option. */
		switch(NominatedMapsIndex) {
			case 1:
				vote(msg,nochange,NominatedMaps[0],"HVoteMap","");
				// break;
#if MAX_NOMINATIONS > 1
			case 2:
				vote(msg,nochange,NominatedMaps[0],NominatedMaps[1],"HVoteMap","");
				// break;
#endif
#if MAX_NOMINATIONS > 2
			case 3:
				vote(msg,nochange,NominatedMaps[0],NominatedMaps[1],NominatedMaps[2],"HVoteMap","");
				// break;
#endif
#if MAX_NOMINATIONS > 3
			case 4:
				vote(msg,nochange,NominatedMaps[0],NominatedMaps[1],NominatedMaps[2],NominatedMaps[3],"HVoteMap","");
				// break;
#endif
#if MAX_NOMINATIONS > 4
			case 5:
				vote(msg,nochange,NominatedMaps[0],NominatedMaps[1],NominatedMaps[2],NominatedMaps[3],NominatedMaps[4],"HVoteMap","");
				// break;
#endif
#if MAX_NOMINATIONS > 5
			case 6:
				vote(msg,nochange,NominatedMaps[0],NominatedMaps[1],NominatedMaps[2],NominatedMaps[3],NominatedMaps[4],NominatedMaps[5],"HVoteMap","");
				// break;
#endif
#if MAX_NOMINATIONS > 6
			case 7:
				vote(msg,nochange,NominatedMaps[0],NominatedMaps[1],NominatedMaps[2],NominatedMaps[3],NominatedMaps[4],NominatedMaps[5],NominatedMaps[6],"HVoteMap","");
				// break;
 
#endif
#if MAX_NOMINATIONS > 7
			case 8:
				vote(msg,nochange,NominatedMaps[0],NominatedMaps[1],NominatedMaps[2],NominatedMaps[3],NominatedMaps[4],NominatedMaps[5],NominatedMaps[6],NominatedMaps[7],"HVoteMap","");
				// break;
#endif
			default:
				iserror = 1;
		}
		// It seems the Small compiler has a bug which allows only one
		// statement per case.
		if(iserror) {
			strcpy("Voting CANCLED. Internal script error.",msg,  MAX_TEXT_LENGTH);
			numtostr(NominatedMapsIndex,strNumber);
			strcat(msg, strNumber,  MAX_TEXT_LENGTH);
			say(msg);
			InitializeNominatedMaps();
		}
	}
	return PLUGIN_HANDLED;
}
 
public HVoteMap(WinningOption,HLData,VoteCount,UserCount) {
	new VoteSubject[MAX_DATA_LENGTH];
	new VoteMap[MAX_NAME_LENGTH];
	new msg[MAX_TEXT_LENGTH] = "";
	new strNumber[MAX_NUMBER_LENGTH];
#if REMEMBER_MAPS != 0
	new MapCount;
#endif
 
	// WinningOption == 0 if nothing was vote for.
	// WinningOption == 1 referrs to the vote to not change the map.
	if (WinningOption == 0 || WinningOption == 1) {
		strcat(VoteSubject,"keeping current map",  MAX_TEXT_LENGTH);
	} else {
		/*Set VoteMap to be the name of the map which won the voter          */
		strcpy(VoteMap,NominatedMaps[WinningOption-2], MAX_NAME_LENGTH);
		if(valid_map(VoteMap) != 1) {
			strcat(msg,"Vote IGNORED for ",  MAX_TEXT_LENGTH);
			strcat(msg,VoteSubject,  MAX_TEXT_LENGTH);
			strcat(msg,".",  MAX_TEXT_LENGTH);
			say(msg);
			say("An invalid map won the vote.");
			InitializeNominatedMaps();
			return PLUGIN_HANDLED;
		} else {
			strcat(VoteSubject,"changing map to ",  MAX_TEXT_LENGTH);
			strcat(VoteSubject,VoteMap,  MAX_TEXT_LENGTH);
		}
	}
	if( vote_canceled!=0 ) {
		strcat(msg,"Vote CANCELED for map change by admin",  MAX_TEXT_LENGTH);
		say(msg);
	} else {
		strcat(msg,"Vote passed FOR ",  MAX_TEXT_LENGTH);
		strcat(msg,VoteSubject,  MAX_TEXT_LENGTH);
		strcat(msg,". ",  MAX_TEXT_LENGTH);
		say(msg);
 
		msg = "";
		strcat(msg,"Map selection based on which recieved the most votes, this one recieved ",  MAX_TEXT_LENGTH);
		numtostr(VoteCount,strNumber);
		strcat(msg,strNumber,  MAX_TEXT_LENGTH);
		strcat(msg," votes.",  MAX_TEXT_LENGTH);
		say(msg);
 
#if REMEMBER_MAPS != 0
		resetfile("lastmaps.ini");
		for(MapCount=1;MapCount<REMEMBER_MAPS;MapCount++) {
			writefile("lastmaps.ini",RememberedMaps[MapCount],-1);
		}
		writefile("lastmaps.ini",VoteMap,-1);
#endif
 
		if (WinningOption !=0 && WinningOption !=1 && vote_canceled==0 ) {
			/*exec("admin_command admin_execall +showscores");*/
			changelevel(VoteMap,4);
		}
 
	}
	InitializeNominatedMaps();
	return PLUGIN_HANDLED;
}
 
public admin_cancelmapvote(HLCommand,HLData,HLUserName,UserIndex) {
	new Text[MAX_TEXT_LENGTH];
 
	if (NominatedMapsIndex != 0){
		vote_canceled=1;	
		snprintf(Text, MAX_TEXT_LENGTH, "Admin attempting to cancel map vote");
		say(Text);
	}
	return PLUGIN_CONTINUE;
}
 
public plugin_init() {
	plugin_registerinfo("Caveys Menu Map Vote 1.5","Allows multiple maps to be nominated",STRING_VERSION);
	plugin_registercmd("admin_vote_map","admin_vote_map",ACCESS_VOTE_MAP,"admin_vote_map <map>: Starts map nominations before the vote to change the map.");
	plugin_registercmd("admin_cancel_vote","admin_cancelmapvote",ACCESS_CANCEL_VOTE,"admin_cancel_vote: Cancels the current map vote");
 
	return PLUGIN_CONTINUE;
}