Amx Mod X!

pimpsta

New Adventurer
God of War
Joined
Jan 27, 2007
Messages
986
Reaction score
0
Alright, I finally got the amxmodx working on my server!

Amx Mod X & Metamod-P

changelevel / amx_map fixed

changed the level like 30 times and still working fine without a crash.

Votemap doesn't work...
 

pimpsta

New Adventurer
God of War
Joined
Jan 27, 2007
Messages
986
Reaction score
0
yes and check it for yourself.
the only thing I am trying to fix right now is the adminhelp.amxx and votemap...

Server is GoW Testing Amx Mod X [FN]
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
You'll need to re-write the bit that captures the vote-map events or it doesn't do you any good though. I doubt the old votemap plugin will work, even with the AMX compatiblity layer, as it uses a special Vexdum module.

In needs to be able to capture the map events:
touch_trans_XXX - where XXX is the map name to vote for when all players touch a transition
force_trans_XXX - where XXX is the map to force to (this is v. important)
single_trans_XXX - where XXX is the map name to vote for, if you only require ONE player to touch the transition.

And to get changelevel to work, you need to force all the players to drop and reconnect a few moments later as in the adminvote plugin - THAT bit you can probably port over to AMXmodX without any changes. ...and don't think just cuz it works once, you've got it - it HAS to drop the players and reconnect them. Only certain combinations of characters cause memory deallocation errors.

Bad thing is, the AMXmodX eats a LOT more resources than AMX2006. - But if you get this working, at least we won't be at the mercy of Steam, should they make a change that kills our AMX2006.

There must be new team members working for ModX - as last time I asked them for help with MSC, they told me to go f*ck myself on the basis that their mod was infallible and worked with everything without changes, and then ripped out bits I needed. (Which is another problem with ModX - they are constantly depreciating commands arbitrarily, which means you have to re-write half your plugins with every new release.)
 

pimpsta

New Adventurer
God of War
Joined
Jan 27, 2007
Messages
986
Reaction score
0
The issue was the metamod that wouldn't allow the amxx to work.
I had them to rewrite it for me last night and they did download MSC last night to test it out. They are new to it and don't understand much about the game. I have been getting a lot of resource and feedback from the development team. the original founder (David Anderson) is also helping me.

the trans work just fine. I have not got "memory deallocation errors" at all...
I can changelevel, or restart while they are playing. but in my console I don't see any reconnect. Where is the original votemap configure on amx?
when I look at your plugins it doesn't have the votemap.amx
I am using vote_map.xxx right now in my plugins.cfg

It doesn't seems to take up a lot of resource. It only have increased by 800 more than the amx2006
once I am done and everything is fixed. I will send it to you.
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
*sigh* Changelevel is changelevel, be it done by AMX or AMXmodX, or just by raw console - it doesn't matter, it's the same thing - you WILL still get memory dealloc with certain combitnations of characters.

when I look at your plugins it doesn't have the votemap.amx
I am using vote_map.xxx right now in my plugins.cfg
I've told you, about 50 times now... ><

The plugin is adminvote.sma

The source for the plugin (such as it is) is in:
\msc\addons\amx\examples\source\adminvote.sma
(as included with the betapack)

This is the bit that captures map events that you need to convert:
Code:
public alertmessage(atype, message[])
{


	if ( containi(message,"force_map_") > -1 )
	{
		new sstart = containi(message,"force_map_") + 10;
		new empty[32];
		g_touchmap[0] = empty;
		for ( new i = sstart; i < (strlen(message) -2); i++ )
		{
			g_touchmap[0][i - sstart] = message[i];
		}
		client_print(0,print_chat,"Forcing map change to: %s",g_touchmap)
		client_print(0,print_console,"Forcing map change to: %s",g_touchmap)

		g_Answer = "dochangelevel %s";
		g_execLen = format(g_Execute,255,g_Answer,g_touchmap) + 1;
		set_task(0.1,"delayedExec",0,g_Execute,g_execLen);

		return PLUGIN_HANDLED;
	}

	if ( containi(message,"player_died") > -1 ) g_lastplayerdied[0] = get_gametime();

	if ( containi(message,"game_playerspawn") > -1 ) g_lastplayerdied[0] = get_gametime();

	new Float:pdifference = get_gametime() - g_lastplayerdied[0];
	if ( pdifference < PLAYER_DIED_DELAY ) return PLUGIN_HANDLED;

	new Float:difference = get_gametime() - loadTime[0];
    if ( difference > TOUCH_DELAY )
	{
		if ( containi(message,"touch_trans_") > -1 )
		{
			new sstart = containi(message,"touch_trans_") + 12;
			new empty[32];
			new para_invalid[0] = ")"
			g_touchmap[0] = empty;
			for ( new i = sstart; i <= (strlen(message) -2); i++ )
			{
				if ( message[i] != para_invalid[0] ) g_touchmap[0][i - sstart] = message[i];
			}
			client_print(0,print_chat,"votemap:%s",g_touchmap);
			g_touched = 1;
			cmdVoteMap(1,1,1);
		}
	}
}
Note that it is important to capture game_playerspawn and player_died and make it delay capturing of the touch transition trigger event (touch_trans_XXX), as otherwise it'll start a vote for a map every time a player dies.

single_trans_xxx hasn't been applied to this plugin, but the game already sends the event.

This is the bit that disconnects and reconnects everyone. It can probably go more or less as-is, but you may have to give the server more time to reconnect to make up for the extra resources AMXmodX uses:

Code:
public cmdChangeLevel() {
  //force all players to delay reconnect to prevent map crash
  	for ( new iPlayer = 1; iPlayer <= g_maxplayers; iPlayer++ )
	{
		if ( is_user_connected(iPlayer) )
		{
			if(iPlayer == 1) continue 
			client_cmd(iPlayer," alias waiter1 ^"wait;wait;wait;wait;wait;wait;wait;wait;wait;wait^"");
			client_cmd(iPlayer, "wait")
			client_cmd(iPlayer, " alias tenwaiter ^"waiter1;waiter1;waiter1;waiter1;waiter1;waiter1;waiter1;waiter1;waiter1;waiter1^"");
			client_cmd(iPlayer, "wait")
			client_cmd(iPlayer, " alias delayrec ^"disconnect;toggleconsole;tenwaiter;tenwaiter;tenwaiter;tenwaiter;echo Reconnecting...;retry^"");
			client_cmd(iPlayer, "wait")
			client_cmd(iPlayer, "clear;wait;echo MAPCHANGE: YOU WILL BE RECONNECTED SHORTLY... PLEASE WAIT!");
			client_cmd(iPlayer, "wait")
			client_cmd(iPlayer, "delayrec");
		}
	}
	new nextmap[32]
	read_argv(1, nextmap, 31)

	//write next map to crashed.cfg, in case transition fails
	new recCommand[33];
	format(recCommand, 32, "map %s", nextmap);
	write_file("crashed.cfg",recCommand,0);
	server_cmd ("echo VOTEMAP: Wrote to crashed.cfg: %s", recCommand)
	
	//delay to give time for aliases to get to players
	g_passCommand = nextmap
	set_task(1.0, "secondphase")
}

public secondphase() {

  server_cmd("changelevel %s", g_passCommand)

}
 

pimpsta

New Adventurer
God of War
Joined
Jan 27, 2007
Messages
986
Reaction score
0
You also need to write that bug report so the AMXx dev team can see to if it possible to see what conflicting with your MSC mod with AMXx to crash with anything to do with timer. That might be fix for 1.8 when ever it released. Don't forget to include the information above I gave you before.
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
I've given them all that info several times, I don't deal with them anymore. Sick of having my posts deleted. Also sick of having features removed whenever I go, "Hey, that'd be useful!"

If you can get them to adapt their mod for you, more power to you, but my experience with them is that they aren't interested in compatibility with anything but the top end games (DOD/CS/TFC/NS). They aren't even interested in compatibility with older versions of their own mod, or linux, for that matter.
 

pimpsta

New Adventurer
God of War
Joined
Jan 27, 2007
Messages
986
Reaction score
0
Thothie,
It has to do with adminvote.amxx
I have sent them the sma file that we use on the old version. What they are going to do is rewrite the amxx for us and send it back. The reason why you couldn't get the amxx working before... because metamod-p wasn't release at the time. It was released 4/5/07. Bailpan remembered that he couldn't help you at the moment because they were waiting for the metamod-p to be release. Now they are creating a new amxx file for us with the old voting system and adminhelp.amxx too.
 

Shurik3n

New Adventurer
MSC Developer
RiP
Joined
Aug 15, 2006
Messages
1,357
Reaction score
0
Age
34
Well I hope AMXX gets fully compatible with mod because its something I'm really good at coding in, and since I hate AMX.
 

pimpsta

New Adventurer
God of War
Joined
Jan 27, 2007
Messages
986
Reaction score
0
Shurik3n said:
Well I hope AMXX gets fully compatible with mod because its something I'm really good at coding in, and since I hate AMX.

amxx is working right now but the only thing I got to finish is adminvote.amxx and adminhelp.amxx
adminhelp.amxx is what keep crashing the server a lot.
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
Comment it out, ya don't need it.

Gee... Maybe Shurik3n can re-code our vote system for AMXX. Since he hates coding for AMX... Despite the fact it's the same damned language. ;)
 

pimpsta

New Adventurer
God of War
Joined
Jan 27, 2007
Messages
986
Reaction score
0
maybe he can fix this!

L 04/19/2007 - 18:39:39: [AMXX] Plugin "adminhelp.amxx" failed to load: Module/Library "cstrike" required for plugin. Check modules.ini.
L 04/19/2007 - 18:39:39: [AMXX] Plugin "adminvote.amxx" failed to load: Module/Library "cstrike" required for plugin. Check modules.ini.


that is the old amx compiled to the new amxx...
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
Use the ModX adminhelp.sma - there's no reason to use the older AMX adminhelp. (There's actually no reason to use adminhelp.sma at all).
 

pimpsta

New Adventurer
God of War
Joined
Jan 27, 2007
Messages
986
Reaction score
0
I did... it doesn't work...
 

Thothie

Administrator
Staff member
Administrator
Moderator
MSC Archivist
Joined
Apr 8, 2005
Messages
16,342
Reaction score
326
Location
lost
They depreciated some of the commands it uses, but they neglected to remove the duplicates they had from the cstrike module. Download the proper DLL and stick it in modules, and edit the modules.ini accordingly... but again, I don't think you really need the plugin.
 

Shurik3n

New Adventurer
MSC Developer
RiP
Joined
Aug 15, 2006
Messages
1,357
Reaction score
0
Age
34
Thothie said:
Comment it out, ya don't need it.

Gee... Maybe Shurik3n can re-code our vote system for AMXX. Since he hates coding for AMX... Despite the fact it's the same damned language. ;)

They are both PAWN but the functions are named entirely different and I would much rather use engine or fakemeta than VexdUM.
 

pimpsta

New Adventurer
God of War
Joined
Jan 27, 2007
Messages
986
Reaction score
0
Alright, AMXX is working a lot better now. I know I haven't been around on this thread.

Anyway, Adminhelp has been changed.

I had 4 players on the server with the new amxx. The next thing is I am going to try make a vote system to add on.

4pd7uwj.jpg
 

pimpsta

New Adventurer
God of War
Joined
Jan 27, 2007
Messages
986
Reaction score
0
I have been doing some research on these codes and I might need to make another type of amxx file for this to function. the votemap in console is now working, and trans is now working. I am working on the votemap in chat as these codes below. A lot of them does not work well with the amxx. I disable the VexdUM from the sma and amxx which will not need. Thothie, any ideas?


Code:
  new keys = (1<<0)|(1<<1)|(1<<2)
  new menu_msg[256]
  new players[32]
  new numplayers
  new Float:vote_time = get_cvar_float("amx_vote_time") + 2.0

  //get_user_name(player,arg,31)
  //get_players(players,numplayers) 

  //for(numplayers--;numplayers>=0;numplayers--){
  //  format(menu_msg,255,"\y%s %s?\w^n^n1. Exit^n2. Yes^n3. No", players[numplayers]) : ("%s %s?^n^n1.  Yes^n2.  No", players[numplayers]),
  //    voteban ? _T("Ban", players[numplayers]) : _T("Kick", players[numplayers]), arg) 
  //  show_menu(players[numplayers],keys,menu_msg,floatround(vote_time),voteban?"Ban ":"Kick ")
  //}

	//g_against = -1
	//g_for = -1 //not used yet

  for(numplayers--;numplayers>=0;numplayers--){
	format(menu_msg,255,"^n^n ^n^n^n^nKick player %s?^n^n1.  Exit Menu^n2.  Yes^n3.  No", arg, players[numplayers])
	keys = (1<<0)|(1<<1)|(1<<2)
	g_yesNoVote = 1
	show_menu(players[numplayers],keys,menu_msg,floatround(vote_time),voteban?"Ban ":"Kick ")
  }
  g_yesNoVote = 1

  //if voteban  
    //get_user_authid(player,g_optionName[0],31)
  //else
    //numtostr(get_user_userid(player),g_optionName[0],31)

  new authid[32],name[32]
  get_user_authid(id, name, 31)
  get_user_name(id,name,31)
  log_to_file(g_logFile,"Vote: ^"%s<%d><%s><>^" vote %s (target ^"%s^")",name,get_user_userid(id),authid,voteban ? "ban" : "kick",arg)
   
  switch(get_cvar_num("amx_show_activity")) {
    case 2:
      client_print(0,print_chat,_T("%s %s: vote %s for %s"),(get_user_flags(id) & ADMIN_USER) ? _T(g_playerTag) : _T(g_adminTag),name,voteban ? "ban" : "kick",arg )
    case 1:
      client_print(0,print_chat,_T("%s: vote %s for %s"),(get_user_flags(id) & ADMIN_USER) ? _T(g_playerTag) : _T(g_adminTag),voteban ? "ban" : "kick",arg)
  }
   
  g_execResult = true

  //set_cvar_float("amx_last_voting", get_gametime() + vote_time )

  g_voteRatio = get_cvar_float(voteban ? "amx_voteban_ratio" : "amx_votekick_ratio")

  g_Answer = voteban ? "banid 30.0 %s kick" : "kick #%s"

  set_task(vote_time,"checkVotes" , 99889988 )

  g_voteCaller = id

  console_print(id, _T(g_votingStarted) )  

  g_voteCount = {0,0,0,0}

  return PLUGIN_HANDLED
} 

public cmdChangeLevel() {
  //force all players to delay reconnect to prevent map crash
  	for ( new iPlayer = 1; iPlayer <= g_maxplayers; iPlayer++ )
	{
		if ( is_user_connected(iPlayer) )
		{
			if(iPlayer == 1) continue 
			client_cmd(iPlayer," alias waiter1 ^"wait;wait;wait;wait;wait;wait;wait;wait;wait;wait^"");
			client_cmd(iPlayer, "wait")
			client_cmd(iPlayer, " alias tenwaiter ^"waiter1;waiter1;waiter1;waiter1;waiter1;waiter1;waiter1;waiter1;waiter1;waiter1^"");
			client_cmd(iPlayer, "wait")
			client_cmd(iPlayer, " alias delayrec ^"disconnect;toggleconsole;tenwaiter;tenwaiter;tenwaiter;tenwaiter;echo Reconnecting...;retry^"");
			client_cmd(iPlayer, "wait")
			//client_cmd(iPlayer, "echo DEBUG: ^"quote test^" XD");
			client_cmd(iPlayer, "clear;wait;echo MAPCHANGE: YOU WILL BE RECONNECTED SHORTLY... PLEASE WAIT!");
			client_cmd(iPlayer, "wait")
			client_cmd(iPlayer, "delayrec");
		}
	}
	new nextmap[32]
	read_argv(1, nextmap, 31)

	//message_begin(MSG_ALL, SVC_INTERMISSION)
	//message_end()
	
	//write next map to crashed.cfg, in case transition fails
	new recCommand[33];
	format(recCommand, 32, "map %s", nextmap);
	write_file("crashed.cfg",recCommand,0);
	server_cmd ("echo VOTEMAP: Wrote to crashed.cfg: %s", recCommand)
	
	//delay to give time for aliases to get to players
	//g_passCommand = nextmap
	//set_task(1.0, "secondphase")
}

//thothie
public secondphase() {

  //getting tired, nothing but hacks now :D
  //this seemed the only way to add a delay to changelevel safely and still pass string
  server_cmd("changelevel %s", g_passCommand)

}

//thothie
public displayAdjacent_console(id) {

  //I really shouldn't have to do this (hack)
  //but for the life of me I can't get a dynamic global string echo to chat or console
  new map[33];
  get_mapname(map, 32);

	new ultra_enabled = get_cvar_num("ms_votemap_type");
	
	if ( ultra_enabled == 0 )
	{
		if ( contain(map,"calruin2") > -1 ) { client_print(id, print_console, "Adjacent Areas: sfor"); }
		if ( contain(map,"challs") > -1 ) { client_print(id, print_console, "Adjacent Areas: sfor"); }
		if ( contain(map,"daragoth") > -1 ) { client_print(id, print_console, "Adjacent Areas: helena deralia mines"); }
		if ( contain(map,"deralia") > -1 ) { client_print(id, print_console, "Adjacent Areas: daragoth"); }
		//this is to deal with duplicate name
		if ( contain(map,"edana") > -1 ) { 
		if ( contain(map,"edanasewers") > -1 ) 
		{ 
			client_print(id, print_console, "Adjacent Areas: edana"); 
		} 
			else 
		{
			client_print(id, print_console, "Adjacent Areas: thornlands edanasewers");
		}
		}
		if ( contain(map,"gatecity") > -1 ) { client_print(id, print_console, "Adjacent Areas: mscave"); }
		if ( contain(map,"goblintown") > -1 ) { client_print(id, print_console, "Adjacent Areas: mscave"); }
		if ( contain(map,"helena") > -1 ) { client_print(id, print_console, "Adjacent Areas: thornlands daragoth keledrosprelude2"); }
		if ( contain(map,"heras") > -1 ) { client_print(id, print_console, "Adjacent Areas: thornlands"); }
		if ( contain(map,"keledrosprelude2") > -1 ) { client_print(id, print_console, "Adjacent Areas: helena [bossmap]"); }
		if ( contain(map,"keledrosprelude2") > -1 ) { client_print(id, print_console, "Adjacent Areas: keledrosprelude2"); }
		if ( contain(map,"mines") > -1 ) { client_print(id, print_console, "Adjacent Areas: daragoth"); }
		if ( contain(map,"mscave") > -1 ) { client_print(id, print_console, "Adjacent Areas: gatecity goblintown thornlands"); }
		if ( contain(map,"sfor") > -1 ) { client_print(id, print_console, "Adjacent Areas: calruin2 [hiddenmap] thornlands"); }
		if ( contain(map,"thornlands") > -1 ) { client_print(id, print_console, "Adjacent Areas: heras helena sfor mscave edana"); }
	}
}

//thothie
public displayAdjacent_chat(id) {

  //I really shouldn't have to do this (hack)
  //but for the life of me I can't get a dynamic global string echo to chat or console
  new map[33];
  get_mapname(map, 32);

	new ultra_enabled = get_cvar_num("ms_votemap_type");
	if ( ultra_enabled == 0 )
	{

	  if ( contain(map,"calruin2") > -1 ) { client_print(id, print_chat, "Adjacent Areas: sfor"); }
	  if ( contain(map,"challs") > -1 ) { client_print(id, print_chat, "Adjacent Areas: sfor"); }
	  if ( contain(map,"daragoth") > -1 ) { client_print(id, print_chat, "Adjacent Areas: helena deralia mines"); }
	  if ( contain(map,"deralia") > -1 ) { client_print(id, print_chat, "Adjacent Areas: daragoth"); }
	  //this is to deal with duplicate name
	  if ( contain(map,"edana") > -1 ) { 
		if ( contain(map,"edanasewers") > -1 ) { 
			client_print(id, print_chat, "Adjacent Areas: edana"); 
		} else {
			client_print(id, print_chat, "Adjacent Areas: thornlands edanasewers");
	  	}
	  }
	  if ( contain(map,"gatecity") > -1 ) { client_print(id, print_chat, "Adjacent Areas: mscave"); }
	  if ( contain(map,"goblintown") > -1 ) { client_print(id, print_chat, "Adjacent Areas: mscave"); }
	  if ( contain(map,"helena") > -1 ) { client_print(id, print_chat, "Adjacent Areas: thornlands daragoth keledrosprelude2"); }
	  if ( contain(map,"heras") > -1 ) { client_print(id, print_chat, "Adjacent Areas: thornlands"); }
	  if ( contain(map,"keledrosprelude2") > -1 ) { client_print(id, print_chat, "Adjacent Areas: helena [bossmap]"); }
	  if ( contain(map,"keledrosruins") > -1 ) { client_print(id, print_chat, "Adjacent Areas: keledrosprelude2"); }
	  if ( contain(map,"mines") > -1 ) { client_print(id, print_chat, "Adjacent Areas: daragoth"); }
	  if ( contain(map,"mscave") > -1 ) { client_print(id, print_chat, "Adjacent Areas: gatecity goblintown thornlands"); }
	  if ( contain(map,"sfor") > -1 ) { client_print(id, print_chat, "Adjacent Areas: calruin2 [hiddenmap] thornlands"); }
	  if ( contain(map,"thornlands") > -1 ) { client_print(id, print_chat, "Adjacent Areas: heras helena sfor mscave edana"); }
	}
}

//thothie
public listMaps(id) {

	if ( g_invalid_select == 1 )
	{
		g_invalid_select = 0
		return PLUGIN_HANDLED;
	}

//  get_cvar_string ("custommaps",g_customMaps,1279)
  
  client_print(id, print_console, "Format is votemap [mapname], example: votemap edana");
  if ( g_votedFromChat == 1 ) client_print(id, print_chat, "Format is votemap [mapname], example: votemap edana");

	new ultra_enabled = get_cvar_num("ms_votemap_type");

	if ( ultra_enabled == 0 ) client_print(0,print_console,"[Votetype: Normal] You may vote for adjacent maps, root towns, and custom maps.");
	if ( ultra_enabled == VOTE_ULTRA ) client_print(0,print_console,"[Votetype: Ultra] You may vote for any map you can name, save boss and gauntlet maps.");
	if ( ultra_enabled == VOTE_RESTRICT ) client_print(0,print_console,"[Votetype: Restricted] You may only vote at transitions, root towns, and these custom maps:");

	if ( g_votedFromChat == 1 )
	{
		if ( ultra_enabled == 0 ) client_print(0,print_chat,"[Votetype: Normal] You may vote for adjacent maps, root towns, and custom maps.");
		if ( ultra_enabled == VOTE_ULTRA ) client_print(0,print_chat,"[Votetype: Ultra] You may vote for any map you can name, save boss and gauntlet maps.");
		if ( ultra_enabled == VOTE_RESTRICT ) client_print(0,print_chat,"[Votetype: Restricted] You may only vote at transitions, root towns, and these custom maps:");
	}
	
	if ( ultra_enabled == 0 )
	{
		//if ( g_votedFromChat == 1 ) client_print(id, print_chat, "You may vote for the following maps:");
		//client_print(id, print_console, "You may vote for the following maps:");
		displayAdjacent_console(id);
		if ( g_votedFromChat == 1 ) displayAdjacent_chat(id);
		client_print(id, print_console, "Root Towns: %s", g_rootTowns);
		if ( g_votedFromChat == 1 ) client_print(id, print_chat, "Root Towns: %s", g_rootTowns);
	}

	//parse custom maps into g_cmap_names
	new new_name[32];
	new cmap_counter = 0;
	new r = 0;
	copy(g_cmap_names[0],32,new_name);
	new bool:store_flag = false;
	for ( new i = 0; i < (strlen(g_customMaps)); i++ )
	{
		store_flag = true;
		if ( g_customMaps[i] == 32 ) store_flag = false;
		if ( g_customMaps[i] == 59 ) store_flag = false;
		if ( g_customMaps[i] == 44 ) store_flag = false;
		if ( g_customMaps[i] == 124 ) store_flag = false;
		//client_print(id, print_console, "debug: reading %s",g_customMaps[i]);
		if ( store_flag )
		{
			copy(g_cmap_names[cmap_counter][r],1,g_customMaps[i]);
			++r;
		}
		if ( !store_flag || i == strlen(g_customMaps)-1 ) 
		{
			//client_print(id, print_console, "debug: WROTE %s of %d",g_cmap_names[cmap_counter],cmap_counter);
			++cmap_counter;
			r = 0;
			copy(g_cmap_names[cmap_counter],32,new_name);
		}
	}

	if ( ultra_enabled != VOTE_RESTRICT )
	{
		//client_print(id, print_console, "Custom Maps (fast downloads):")
		//if ( g_votedFromChat == 1 ) client_print(id, print_chat, "Custom Maps (fast downloads):");
	}

	//parse g_cmap_names into cmap_string and echo to console
	new cmap_string[256];
	new cmap_clear[256];
	new maplen = 0;
	new header[] = "Custom Maps (fast downloads):"
	for ( new i = 0; i < cmap_counter; i++ ) //switch to r if cause error
	{
		maplen = strlen(g_cmap_names[i]);
		add(cmap_string,255,g_cmap_names[i]);
		add(cmap_string,255," ")
		//client_print(id, print_console, "debug: got %s map ( %d of %d len %d ) stringisnow: %s",g_cmap_names[i],i,cmap_counter,maplen,cmap_string);
		if ( strlen(cmap_string) > 60 || i == cmap_counter-1 )
		{
			client_print(id, print_console, "%s %s",header, cmap_string);
			if ( g_votedFromChat == 1 ) client_print(id, print_chat, "%s %s",header, cmap_string);
			add(header,1,cmap_clear)
			copy(cmap_string,256,cmap_clear);
		}
	}

	g_votedFromChat = 0
}

public cmdVoteMap(id,level,cid) {

  //Thothie - lots of minor edits in here

  g_against = -1
  g_for = -1 //not used yet

  get_cvar_string ("custommaps",g_customMaps,512)
  
  new Float:voting = get_cvar_float("amx_last_voting")

  if ( voting > get_gametime() ) {  
    console_print(id, _T(g_alredyVoting))
    if ( g_votedFromChat == 1 )  client_print(id,print_chat,g_alredyVoting)
    return PLUGIN_HANDLED
  } 

  if ( voting && voting + get_cvar_float("amx_vote_delay") > get_gametime() ) { 
    console_print(id, g_notAllowed )
    if ( g_votedFromChat == 1 ) client_print(id,print_chat,g_notAllowed)
    return PLUGIN_HANDLED
  }   

  new argc = read_argc()

	if ( argc < 2 )
	{
		listMaps(id);
		return PLUGIN_HANDLED;
	}

	if ( g_touched != 1 )
	{
		new Float:difference = get_gametime() - loadTime[0];
		if ( difference < NT_VOTE_DELAY )
		{
			console_print(id,"Map voting is not permitted 90 seconds after map change, except by transition.")
		    client_print(id,print_chat,"Map voting is not permitted 90 seconds after map change, except by transition.")
		    return PLUGIN_HANDLED
		}

	if (argc > 5)
	argc = 5

  	g_validMaps = 0
  	g_optionName[0][0] = g_optionName[1][0] = g_optionName[2][0] = g_optionName[3][0] = 0

  	for(new i = 1; i < argc; ++i)
	{ 
  		read_argv(i,g_optionName[g_validMaps],31)
  		if (is_map_valid(g_optionName[g_validMaps])) 
		{
			g_optionName[0]=g_optionName[g_validMaps]
  			g_validMaps++;
  		}
	} //next i

	if ( is_map_valid(g_optionName[0]) ) g_validMaps = 1;

	if ( is_map_valid(g_optionName[0]) == 0 )
	{
		 g_validMaps = 0;
		//listMaps(id)
		
		if ( argc > 3 )
		{
			client_print(0,print_chat,"Map %s not found on server.",g_optionName[0]);
		}

		if ( argc <= 3 ) listMaps(id);
		
		return PLUGIN_HANDLED
	}

	//Thothie - Check for map legality
	new alias_calruin[] = "calruin"
	new alias_keledrosprelude[] = "keledrosprelude"
	new map_to_convert[32]
	copy(map_to_convert,31,g_optionName[0])
	if ( equali(map_to_convert,alias_calruin) ) copy(g_optionName[0],31,"calruin2")
	if ( equali(map_to_convert,alias_keledrosprelude) ) copy(g_optionName[0],31,"keledrosprelude2")
	if ( g_validMaps == 1 ) getLegalMaps( g_optionName[0] );

	if ( g_validMaps == 0 ) 
	{
		new ultra_enabled = get_cvar_num("ms_votemap_type");
		if ( ultra_enabled == 0 ) listMaps(id)
		return PLUGIN_HANDLED;
	}


  } //EndIf g_touched != 1

	if ( g_touched == 1 )
	{
		g_optionName[0] = g_touchmap[0]
		g_touched = 0
		//client_print(0,print_chat,"Debug Starting Vote for:%s",g_optionName[0]);
	}

  new menu_msg[256]
  new keys = 0
  new players[32]
  new numplayers
  new Float:vote_time = get_cvar_float("amx_vote_time") + 2.0

  get_players(players,numplayers,"c")

  for(numplayers--;numplayers>=0;numplayers--){
	format(menu_msg,255,"^n^n ^n^n^n^nChange map to %s?^n^n1.  Exit Menu^n2.  Yes^n3.  No", g_optionName[0])
	keys = (1<<0)|(1<<1)|(1<<2)
	g_yesNoVote = 1
	show_menu(players[numplayers],keys,menu_msg,floatround(vote_time),"Change map to ")
  }
   
  new authid[32],name[32]

  g_execResult = true

  set_cvar_float("amx_last_voting", get_gametime() + vote_time )

  g_voteRatio = get_cvar_float("amx_votemap_ratio")

  g_Answer = "dochangelevel %s"

  set_task(vote_time,"checkVotes" , 99889988 )    

  g_voteCaller = id

  console_print(id, _T(g_votingStarted) )

  g_voteCount = { 0,0, 0,0 }

  return PLUGIN_HANDLED
} 

//thothie
public getLegalMaps( checkMap[] ) {

  //Hoping to have legal and custom maps read in by file later

  new map[33];
	new mapvalidator = is_map_valid(checkMap)
  get_mapname(map, 32);


	new ultra_enabled = get_cvar_num("ms_votemap_type");

	//if ( ultra_enabled == 0 ) client_print(0,print_chat,"[Votetype: Normal]");
	//if ( ultra_enabled == VOTE_ULTRA ) client_print(0,print_chat,"[Votetype: Ultra]");
	//if ( ultra_enabled == VOTE_RESTRICT ) client_print(0,print_chat,"[Votetype: Restricted]");

	g_adjacentMaps = "none known";
	if ( contain(map,"calruin2") > -1 ) { g_adjacentMaps = "sfor"; }
	if ( contain(map,"challs") > -1 ) { g_adjacentMaps = "sfor"; }
	if ( contain(map,"daragoth") > -1 ) { g_adjacentMaps = "helena deralia mines"; }
	if ( contain(map,"deralia") > -1 ) { g_adjacentMaps = "daragoth"; }
	//this is to deal with duplicate name
	if ( contain(map,"edana") > -1 ) { 
	if ( contain(map,"edanasewers") > -1 ) { 
		g_adjacentMaps = "edana"; 
	} 
	else
	{
		g_adjacentMaps = "thornlands edanasewers";
	}
	}
	if ( contain(map,"gatecity") > -1 ) { g_adjacentMaps = "mscave"; }
	if ( contain(map,"goblintown") > -1 ) { g_adjacentMaps = "mscave"; }
	if ( contain(map,"helena") > -1 ) { g_adjacentMaps = "thornlands daragoth keledrosprelude2"; }
	if ( contain(map,"heras") > -1 ) { g_adjacentMaps = "thornlands"; }
	if ( contain(map,"keledrosprelude2") > -1 ) { g_adjacentMaps = "helena [bossmap]"; }
	if ( contain(map,"keledrosruins") > -1 ) { g_adjacentMaps = "keledrosprelude2"; }
	if ( contain(map,"mines") > -1 ) { g_adjacentMaps = "daragoth"; }
	if ( contain(map,"mscave") > -1 ) { g_adjacentMaps = "gatecity goblintown thornlands"; }
	if ( contain(map,"sfor") > -1 ) { g_adjacentMaps = "calruin2 [hiddenmap] thornlands"; }
	if ( contain(map,"thornlands") > -1 ) { g_adjacentMaps = "heras helena sfor mscave edana"; }

	if ( ultra_enabled == VOTE_RESTRICT ) g_adjacentMaps = "";

	g_validMaps = 0;

	new bool:MapIsCustom = false;
	if ( contain(g_adjacentMaps, checkMap) > -1 ) 
	{
		client_print(0,print_console,"debug: Found %s in adjacent maps", checkMap);
		g_validMaps = 1;
	}
	if ( contain(g_rootTowns, checkMap) > -1 )
	{
		client_print(0,print_console,"debug: Found %s in root towns", checkMap);
		g_validMaps = 1;
	}
	if ( SearchCustom(checkMap) )
	{
		client_print(0,print_console,"debug: Found %s in custom maps: %s", checkMap, g_customMaps);
		MapIsCustom = true;
		g_validMaps = 1;
	}

	new bool:IsBossMap = false;
	if ( contain(checkMap,"ww2") > -1 ) IsBossMap = true;
	if ( contain(checkMap,"ww3") > -1 ) IsBossMap = true;
	if ( contain(checkMap,"highlands") > -1 ) IsBossMap = true;
	if ( contain(checkMap,"lostcastle") > -1 ) IsBossMap = true;
	if ( contain(checkMap,"skycastle") > -1 ) IsBossMap = true;
	if ( contain(checkMap,"orcplace") > -1 ) IsBossMap = true;
	if ( contain(checkMap,"old_helena") > -1 ) IsBossMap = true;
	if ( contain(checkMap,"keledrosruins") > -1 ) IsBossMap = true;
	if ( IsBossMap ) 
	{
		g_validMaps = 0;
		client_print(0,print_chat,"You may only vote for boss and gauntlet maps from transitions.");
		g_invalid_select = 1;
	}


	if ( is_map_valid(checkMap) != 1 ) 
	{
		client_print(0,print_chat,"Map %s found on server.",checkMap);
		g_invalid_select = 1;
	}

	new this_map[256];
	new req_map[256];
	new comp_results = 0;
	get_mapname(this_map,255);
	copy(req_map,strlen(checkMap),checkMap);
	//client_print(0,print_console,"debug: this_map %s req_map %s checkMap %s",this_map,req_map,checkMap);
	if ( equali(this_map,req_map) )
	{
		client_print(0,print_console,"You cannot vote for a map you are already on.");
		client_print(0,print_chat,"You cannot vote for a map you are already on.");
		g_invalid_select = 1;
	}
	if ( strlen(checkMap) < 2 )
	{
		client_print(0,print_console,"No map name provided");
		g_validMaps = 0;
		g_invalid_select = 1;
		mapvalidator = 0;
		
	}
	if ( g_validMaps == 0 )
	{
		if ( mapvalidator == 1 ) 
		{
			if ( g_invalid_select == 0 )
			{
				if ( ultra_enabled == 0 )
				{
					if ( !MapIsCustom || !IsBossMap ) client_print(0,print_chat,"[Votetype: Normal] You may only vote for %s from an adjoining map.",checkMap);
					if ( MapIsCustom ) client_print(0,print_chat,"[Votetype: Normal] You may only vote for %s from a transition.",checkMap);
				}
				if ( ultra_enabled == VOTE_RESTRICT ) client_print(0,print_chat,"[Votetype: Restricted] You may only vote for %s at a transition.",checkMap);
			}
		}
		g_invalid_select = 1;
	}


	//client_print(0,print_console,"debug: ms_votemap_type returned %d for [%s] exist %d invalid %d g_valid %d",ultra_enabled,checkMap,mapvalidator,g_invalid_select,g_validMaps);


  //set_cvar_string ("adjacentmaps",g_adjacentMaps); - this wont work either

}

//thothie
public vote_check(id,level,cid) {

  //read in command 
  new saytext[64];  
  read_args(saytext,63);  
  //server_cmd ("say Debug: A Player Said %s", saytext);

  if ( contain(saytext,"Votemap") > -1 ) { 
	g_votedFromChat = 1;
	cmdVoteMap(id,level,cid);
  }

  if ( contain(saytext,"VOTEMAP") > -1 ) { 
	g_votedFromChat = 1;
	cmdVoteMap(id,level,cid);
  }


  if ( contain(saytext,"votemap") > -1 ) { 
	g_votedFromChat = 1;
	cmdVoteMap(id,level,cid);
  }

  if ( contain(saytext,"votekick") > -1 ) { 
	g_votedFromChat = 1;
	cmdVoteKickBan(id,level,cid);
  }

  if ( contain(saytext,"votepvp") > -1 ) { 
	g_votedFromChat = 1;
	cmdVotePVP(id,level,cid);
  }
}

public alertmessage(atype, message[])
{


	if ( containi(message,"force_map_") > -1 )
	{
		new sstart = containi(message,"force_map_") + 10;
		new empty[32];
		g_touchmap[0] = empty;
		for ( new i = sstart; i < (strlen(message) -2); i++ )
		{
			g_touchmap[0][i - sstart] = message[i];
		}
		client_print(0,print_chat,"Forcing map change to: %s",g_touchmap)
		client_print(0,print_console,"Forcing map change to: %s",g_touchmap)
		//client_print(0,print_chat,"Forcing map change to: %s",g_touchmap)
		//client_print(0,print_console,"Forcing map change to: %s",g_touchmap)
		//cmdChangeLevel(g_touchmap)

		g_Answer = "dochangelevel %s";
		g_execLen = format(g_Execute,255,g_Answer,g_touchmap) + 1;
		set_task(0.1,"delayedExec",0,g_Execute,g_execLen);

		return PLUGIN_HANDLED;
	}

	if ( containi(message,"player_died") > -1 ) g_lastplayerdied[0] = get_gametime();

	if ( containi(message,"game_playerspawn") > -1 ) g_lastplayerdied[0] = get_gametime();

	new Float:pdifference = get_gametime() - g_lastplayerdied[0];
	if ( pdifference < PLAYER_DIED_DELAY ) return PLUGIN_HANDLED;

	new Float:difference = get_gametime() - loadTime[0];
    if ( difference > TOUCH_DELAY )
	{
		if ( containi(message,"touch_trans_") > -1 )
		{
			new sstart = containi(message,"touch_trans_") + 12;
			new empty[32];
			new para_invalid[0] = ")"
			g_touchmap[0] = empty;
			for ( new i = sstart; i <= (strlen(message) -2); i++ )
			{
				if ( message[i] != para_invalid[0] ) g_touchmap[0][i - sstart] = message[i];
			}
			client_print(0,print_chat,"votemap:%s",g_touchmap);
			g_touched = 1;
			cmdVoteMap(1,1,1);
		}
	}
}

public cmdVotePVP(id,level,cid) {

  new Float:voting = get_cvar_float("amx_last_voting")

  if (voting > get_gametime()){  
    console_print(id, g_alredyVoting)
    if ( g_votedFromChat == 1 )  client_print(id,print_chat,g_alredyVoting)
    return PLUGIN_HANDLED
  } 

  if (voting && voting + get_cvar_float("amx_vote_delay") > get_gametime()) { 
    console_print(id, g_notAllowed )
    if ( g_votedFromChat == 1 ) client_print(id,print_chat,g_notAllowed)
    return PLUGIN_HANDLED
  }     

  new Float:PVPvote_enabled = get_cvar_float("amx_allow_pvp_vote")

	if ( PVPvote_enabled < 1 )
	{
	    console_print(id,"PvP Votes are disabled on this server.")
	    if ( g_votedFromChat == 1 ) client_print(id,print_chat,"PvP Votes are disabled on this server.")
		return PLUGIN_HANDLED
	}

  new keys = 0
  new menu_msg[256]
  new players[32]
  new numplayers
  new Float:vote_time = get_cvar_float("amx_vote_time") + 2.0
  new Float:pvp_mode = get_cvar_float("ms_pklevel") + 0.0

  get_players(players,numplayers,"c")

  g_against = -1
	g_for = -1 //not used yet

	g_yesNoVote = 1

	if ( pvp_mode <= 0 )
	{
		//client_print(0,print_chat,"ENABLEVOTE:debug %d",pvp_mode)
		for(numplayers--;numplayers>=0;numplayers--){
			format(menu_msg,255,"^n^n ^n^n^n^nEnable PVP on next map %s?^n^n1.  Exit Menu^n2.  Yes^n3.  No", numplayers)
			keys = (1<<0)|(1<<1)|(1<<2)
			g_yesNoVote = 1
			show_menu(players[numplayers],keys,menu_msg,floatround(vote_time),"Change map to ")
		}
		g_Answer = "ms_pklevel 1"
	}

	if ( pvp_mode >= 1 )
	{
		//client_print(0,print_chat,"DISABLEVOTE:debug %d",pvp_mode)
		for(numplayers--;numplayers>=0;numplayers--)
		{
			format(menu_msg,255,"^n^n ^n^n^n^nDisable PVP on next map %s?^n^n1.  Exit Menu^n2.  Yes^n3.  No", players[numplayers])
			keys = (1<<0)|(1<<1)|(1<<2)
			g_yesNoVote = 1
			show_menu(players[numplayers],keys,menu_msg,floatround(vote_time),"Change map to ")
		}
		g_Answer = "ms_pklevel 0"
	}

  
	new authid[32],name[32]
	
	g_execResult = true
	
	set_cvar_float("amx_last_voting", get_gametime() + vote_time )
	
	g_voteRatio = get_cvar_float("amx_votemap_ratio")
	
	//g_Answer = "dochangelevel %s"
	
	set_task(vote_time,"checkVotes" , 99889988 )    
	
	g_voteCaller = id
	
	console_print(id, _T(g_votingStarted) )
	
	g_voteCount = { 0,0, 0,0 }
	
	return PLUGIN_HANDLED
} 


public clear_crap() {

	new menu_msg[256];
	new players[32];
	new numplayers;
	new keys = (1<<0)|(1<<1);
	get_players(players,numplayers,"c");

	for(numplayers--;numplayers>=0;numplayers--)
	{
		format(menu_msg,255," ", players[numplayers])
		show_menu(players[numplayers],keys,menu_msg,0.1,"nadda ")
	}
}


public SearchCustom(search_map[])
{
	//parse custom maps into g_cmap_names
	new new_name[32];
	new cmap_counter = 0;
	new r = 0;
	copy(g_cmap_names[0],32,new_name);
	new bool:store_flag = false;
	for ( new i = 0; i < (strlen(g_customMaps)); i++ )
	{
		store_flag = true;
		if ( g_customMaps[i] == 32 ) store_flag = false;
		if ( g_customMaps[i] == 59 ) store_flag = false;
		if ( g_customMaps[i] == 44 ) store_flag = false;
		if ( g_customMaps[i] == 124 ) store_flag = false;
		//client_print(id, print_console, "debug: reading %s",g_customMaps[i]);
		if ( store_flag )
		{
			copy(g_cmap_names[cmap_counter][r],1,g_customMaps[i]);
			++r;
		}
		if ( !store_flag || i == strlen(g_customMaps)-1 ) 
		{
			//client_print(id, print_console, "debug: WROTE %s of %d",g_cmap_names[cmap_counter],cmap_counter);
			if ( equali(search_map,g_cmap_names[cmap_counter]) ) return true;
			++cmap_counter;
			r = 0;
			copy(g_cmap_names[cmap_counter],32,new_name);
		}
	}
}
 
Top