Downloads containing bottry.mut

Downloads
Name Author Game Mode Rating
JJ2+ Only: Bottry (Only JJ2+) Moodler Mutator N/A Download file

File preview

/*
!botSpectate <Amount> - spectates bots if number of active players is higher than <Amount>. If 0, bots won't spectate.
*/
int SPECTATE_AT_X_PLAYERS = 0;
bool VOTE_BEFORE_SPECTATING_BOTS = true;
///MESSAGES SECTION - if you don't want any of these messages to appear, just change them to ""
///i.e. string SPEC_MSG1 = "";
///Do not delete the whole line! That will result in errors.
string SPEC_MSG1 = "Bots will now spectate.";
string SPEC_MSG2 = "";
//not voting is not counted as anything
string BOT_VOTE_MSG2 = "Bot vote will end in ";
string BOT_VOTE_MSG1 = "If you want bots to spectate type !vote yes, otherwise type !vote no.";
string VOTE_SENT_MSG = "|Vote has been sent!";
string ALREADY_VOTED_MSG = "|You have already voted. You cannot vote twice!";

bool alreadyVoted = false;
int botCount = 0, botVotesYes = 0, botVotesNo = 0;
int botVoteIsOn = -2;
array<bool> botIsSpectating(32, false);
array<bool> botPlayersList(32, false);

int timeout = 20; //interval to pick new player to follow
//int playerID = 1;
int playerID = 1;
int playerID2 = 0;
array<int> pID = {1,2,3,4};
bool botOn = false;
int disFlag = 2;

int specified=0;

int xblueflag=0;
int yblueflag=0;
int xredflag=0;
int yredflag=0;
array<bool> def = {false, false, false, false};
array<bool> cap = {false, false, false, false};
void onPlayer(jjPLAYER@ botPlay){
	if(jjIsServer && SPECTATE_AT_X_PLAYERS != 0)
	{
		int activePlayers = 0;
		for(int i=0; i<32; i++)
		{
			if(jjPlayers[i].isInGame && !botPlayersList[i])
			{
				activePlayers++;
			}
			botIsSpectating[i] = jjPlayers[i].isSpectating; //spectate bots back if they unspectate
		}
		//debugBots(activePlayers);
		if(activePlayers >= SPECTATE_AT_X_PLAYERS)
		{
			if(VOTE_BEFORE_SPECTATING_BOTS)
			{
				if(botVoteIsOn == -2) botVoteIsOn = 30;
			}
			else
			{
				spectateBots(true);
			}
		}
		else if(activePlayers < SPECTATE_AT_X_PLAYERS)
		{
			spectateBots(false);
			botVoteIsOn = -2;
		}
	}

	//if(jjLocalPlayers[0].playerID == playerID2){
	if(botOn){
		for(int i=0; i<jjLocalPlayerCount; i++){
			if(jjLocalPlayers[i].playerID == botPlay.playerID){
				playerID = pID[i];
				break;
			}
		}
		jjPLAYER@ play = jjPlayers[playerID];

		bool is123=false;
		int v123;
		int v124;
		int vOffset=0;
		//char caption[256];
		string title;

		//int address = 0x005A4EEC;
		//char name[64];
		int value;
		//unsigned char byte1;
		float xPos;
		float yPos;
		float xPos2;
		float yPos2;

		int health;

		int team;
		int team2;
		int gamemode;
		int otherflag;
		int otherflagcarr=0;
		int myflag;
		int myflagcarr=0;

		//char chat[64];

		bool onwhine=false;
		int dir=0;
		int jumping=0;
		
		botPlay.keyRun = true; // J Press
		
		botPlay.keyLeft = true; // A Press (left)
		
		//time_t timer;
		//timer = time(NULL);
		
		//time_t tmptime;
		//srand ( time(NULL) );
		int rnd;
		
		//first while was here
		title=jjLevelName;
		
		if(specified==0){
			if(title=="Jungle's Edge") {
				specified=1;
				xblueflag=9;
				yblueflag=48;
				xredflag=122;
				yredflag=48;
			}
			else if(title=="City of the Sn00zE") {
				specified=2;
				xblueflag=13;
				yblueflag=37;
				xredflag=108;
				yredflag=35;
			}
			else if(title=="Mechanized Disaster") {
				specified=3;
				xblueflag=113;
				yblueflag=29;
				xredflag=28;
				yredflag=19;
			}
			else if(title=="The Canyon") {
				specified=4;
				xblueflag=15;
				yblueflag=35;
				xredflag=136;
				yredflag=35;
			}
			else if(title=="Death in the Sahara") {
				specified=5;
				xblueflag=6;
				yblueflag=27;
				xredflag=57;
				yredflag=4;
			}
			else if(title=="Rainbow Hills") {
				specified=6;
				xblueflag=10;
				yblueflag=64;
				xredflag=116;
				yredflag=64;
			}
			else if(title=="Galactic Warfare") {
				specified=7;
				xblueflag=142;
				yblueflag=10;
				xredflag=14;
				yredflag=9;
			}
			else if(title=="Ice Cream Island") {
				specified=8;
				xblueflag=60;
				yblueflag=17;
				xredflag=64;
				yredflag=70;
			}
			else if(title=="Fluid Surface Oscillator") {
				specified=9;
				xblueflag=106;
				yblueflag=65;
				xredflag=31;
				yredflag=61;
			}
			else if(title=="Facing worlds") {
				specified=10;
				xblueflag=26;
				yblueflag=39;
				xredflag=121;
				yredflag=39;
			}
			else if(title=="Quasar Quandary") {
				specified=11;
				xblueflag=7;
				yblueflag=34;
				xredflag=144;
				yredflag=34;
			}
			else if(title=="Golem Landscapes") {
				specified=12;
				xblueflag=49;
				yblueflag=80;
				xredflag=105;
				yredflag=80;
			}
			else if(title=="Sacrifice") {
				specified=13;
				xblueflag=23;
				yblueflag=28;
				xredflag=98;
				yredflag=28;
			}
			else if(title=="All Your Base CTF") {
				specified=14;
				xblueflag=101;
				yblueflag=27;
				xredflag=17;
				yredflag=36;
			}
			else if(title=="|Toxin |||||||Twister") {
				specified=15;
				xblueflag=50;
				yblueflag=22;
				xredflag=66;
				yredflag=22;
			}
			else if(title=="Swingin Jazz") {
				specified=16;
				xblueflag=70;
				yblueflag=33;
				xredflag=13;
				yredflag=34;
			}
			else if(title=="Zaitox Station 67") {
				specified=17;
				xblueflag=11;
				yblueflag=30;
				xredflag=116;
				yredflag=30;
			}
			else if(title=="Clipboard Chaos") {
				specified=18;
				xblueflag=125;
				yblueflag=26;
				xredflag=10;
				yredflag=26;
			}			
			else if(title=="n00bed! CtF v2") {
				specified=19;
				xblueflag=26;
				yblueflag=18;
				xredflag=130;
				yredflag=18;
			}
			else if(title=="The Marshland of Evil") {
				specified=20;
				xblueflag=10;
				yblueflag=68;
				xredflag=135;
				yredflag=16;
			}
			else if(title=="Happy Semiconductor CTF") {
				specified=21;
				xblueflag=14;
				yblueflag=36;
				xredflag=89;
				yredflag=35;
			}
			else if(title=="Medieval Skyscrapers") {
				specified=22;
				xblueflag=35;
				yblueflag=60;
				xredflag=113;
				yredflag=60;
			}
			else if(title=="Destiny Islands") {
				specified=23;
				xblueflag=7;
				yblueflag=120;
				xredflag=88;
				yredflag=119;
			}
			else if(title=="Gauntlet") {
				specified=24;
				xblueflag=24;
				yblueflag=36;
				xredflag=132;
				yredflag=36;
			}
			else if(title=="Megalo Fortress") {
				specified=25;
				xblueflag=4;
				yblueflag=22;
				xredflag=99;
				yredflag=22;
			}
			else if(title=="Destroyed Cassis Factory") {
				specified=27;
				xblueflag=22;
				yblueflag=41;
				xredflag=193;
				yredflag=41;
			}
			else if(title=="Atom Heart 243.5") {
				specified=29;
				xblueflag=25;
				yblueflag=31;
				xredflag=98;
				yredflag=31;
			}
			else if(title=="Knightmare Castle") {
				specified=30;
				xblueflag=4;
				yblueflag=48;
				xredflag=97;
				yredflag=48;
			}
			else if(specified!=32){
				specified = 31;
				int both = 0;
				for(int i=0; i<jjObjectCount; i++){
					if(jjObjects[i].eventID == OBJECT::CTFBASE){
						if(jjParameterGet(int(jjObjects[i].xPos/32), int(jjObjects[i].yPos/32), 0, 1) == 0){ //blue flag
							xblueflag = int(jjObjects[i].xPos/32);
							yblueflag = int(jjObjects[i].yPos/32);
							//jjAlert("blue "+xblueflag+" "+yblueflag);
							both++;
						}else if(jjParameterGet(int(jjObjects[i].xPos/32), int(jjObjects[i].yPos/32), 0, 1) == 1){ //red flag
							xredflag = int(jjObjects[i].xPos/32);
							yredflag = int(jjObjects[i].yPos/32);
							//jjAlert("red "+xredflag+" "+yredflag);
							both++;
						}
						if(both == 2) break;
					}
				}
				specified = 32;
			}
		}
		
		
		//if(tmptime-timer > timeout && timeout > 0 && specified==0) {
		if(specified == 0 && jjGameTicks % 70 == 0){
			//jjLocalPlayers[0].keyRun = false; // J Release
			
			//while(tmptime-timer > timeout) {
			//	//Sleep(50);
			//	srand ( clock() );
			//	rnd=rand()%32;
				
				
				xPos = play.xPos/32;
				yPos = play.yPos/32;
				team2 = play.team;
				
				//address = vOffset + 0x005A4EE0 + (0x5A4 * rnd) + 0x48;
				//ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&name,24,0);
				
				//cout << rnd <<"  "<<xPos<<"x"<<yPos<<endl;
				
				//if(gamemode==5 && team==team2) continue;
				//if(rnd==playerID2) continue;
				//if(rnd==playerID) continue;
				
				//if(xPos!=0 && yPos!=0) {
					//playerID=rnd;
					//timer = time(NULL);
					//break;
				//}
			//}
			botPlay.keyRun = true; // J Press
			botPlay.keyLeft = true; // A Press (left)
			
			
			//keybd_event(VkKeyScan(116), 0, 0, 0); // t Press (Chat)
			////Sleep(50);
			//keybd_event(VkKeyScan(116), 0,KEYEVENTF_KEYUP, 0); // t Release (Chat)
			//jjChat("||>> Attacking ||");
		}
		//tmptime = time(NULL);
		
		
		//address = vOffset + 0x005A4B68;
		//ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&value,4,0);
		gamemode=jjGameMode;
		
		team=botPlay.team;
		team2=play.team;
		
		//if(gamemode==5 && team==team2) {tmptime+=timeout;}
		jjLocalPlayers[0].keyFire = true;
		xPos = play.xPos / 32;
		yPos = play.yPos / 32;
		
		//if(xPos==0 && yPos==0) {tmptime+=timeout;}
		
		xPos2 = botPlay.xPos / 32; 
		yPos2 = botPlay.yPos / 32;
		
		//if(xPos2==0 && yPos2==0) continue;
		
		if(gamemode==5) {
			if(specified==1) {
				if(xPos2==106 && yPos2>=29 && yPos2<=30) {
					if(dir==0) botPlay.keyLeft = false; // A Release (left)
					botPlay.keyRight = true; // D Press (right)
					////Sleep(500);
					if(dir==0) {
						botPlay.keyRight = false; // D Release (right)
						////Sleep(50);
						botPlay.keyLeft = true; // A Press (left)
					}
					
				}
				else if(xPos2==69 && yPos2>=57 && yPos2<=69) {
					if(dir==0)
						botPlay.keyLeft = false; // A Release (left)
					if(jumping==1)
						botPlay.keyJump = false; // G Release (Jump)
					
					//Sleep(100);
					
					botPlay.keyRight = true; // D Press (right)
					//Sleep(250);
					if(dir==0) {
						botPlay.keyRight = false; // D Release (right)
						//Sleep(50);
						botPlay.keyLeft = true;// A Press (left)
						//Sleep(800);
					}
					
					if(jumping==1)
						botPlay.keyJump = true; // G Press (Jump)
					
				}
				else if(xPos2==66 && yPos2>=57 && yPos2<=69) {
					if(dir==1)
						botPlay.keyRight = false; // D Release (right)
					if(jumping==1)
						botPlay.keyJump = false; // G Release (Jump)
					
					//Sleep(100);
					
					botPlay.keyLeft = true;// A Press (left)
					//Sleep(200);
					if(dir==1) {
						botPlay.keyLeft = true;// A Release (left)
						//Sleep(50);
						botPlay.keyRight = true; // D Press (right)
						//Sleep(800);
					}
					
					if(jumping==1)
						botPlay.keyJump = true; // G Press (Jump)
					
				}
				else if(xPos2==66 && yPos2>=31 && yPos2<=33) {
					if(dir==1)
						botPlay.keyRight = false; // D Release (right)
					if(jumping==1)
						botPlay.keyJump = false; // G Release (Jump)
					
					//Sleep(100);
					
					botPlay.keyLeft = true;// A Press (left)
					//Sleep(200);
					if(dir==1) {
						botPlay.keyLeft = true;// A Release (left)
						//Sleep(50);
						botPlay.keyRight = true; // D Press (right)
					}
					
					if(jumping==1)
						botPlay.keyJump = true; // G Press (Jump)
					
				}
				else if(xPos2==69 && yPos2>=31 && yPos2==33) {
					if(dir==0)
						botPlay.keyLeft = false; // A Release (left)
					if(jumping==1)
						botPlay.keyJump = false; // G Release (Jump)
					
					//Sleep(100);
					
					botPlay.keyRight = true; // D Press (right)
					//Sleep(200);
					if(dir==0) {
						botPlay.keyRight = false; // D Release (right)
						//Sleep(50);
						botPlay.keyLeft = true;// A Press (left)
					}
					
					if(jumping==1)
						botPlay.keyJump = true; // G Press (Jump)
					
				}
				else if(xPos2>=40 && xPos2<=55 && yPos2>=40 && yPos2<=50) {
					if(dir==1) {
						yPos2=1;
					}
				}
				else if(xPos2>=82 && xPos2<=88 && yPos2>=40 && yPos2<=50) {
					if(dir==0) {
						yPos2=1;
					}
				}
				else if(xPos2==30 && yPos2>=57 && yPos2<=59) {
					if(dir==1)
						botPlay.keyRight = false; // D Release (right)
					if(jumping==1)
						botPlay.keyJump = false; // G Release (Jump)
					
					//Sleep(100);
					
					botPlay.keyLeft = true;// A Press (left)
					//Sleep(200);
					if(dir==1) {
						botPlay.keyLeft = true;// A Release (left)
						//Sleep(50);
						botPlay.keyRight = true; // D Press (right)
						//Sleep(800);
					}
					
					if(jumping==1)
						botPlay.keyJump = true; // G Press (Jump)
					
				}
			}
			else if(specified==21) { // Happy Semiconductor CTF
				
				
			}
			
			myflag = 0;
			otherflag = 0;
			if(team == 0){ // 0 = blue team, 1 = red team
				for(int i=0; i<32; i++){
					if(jjPlayers[i].isActive){
						if(jjPlayers[i].team == TEAM::BLUE && jjPlayers[i].flag != 0){
							myflagcarr = i;
							//if(botPlay.playerID == i) //will cap the flag if this is not commented
							myflag = 128;
						}else if(jjPlayers[i].team == TEAM::RED && jjPlayers[i].flag != 0){
							otherflagcarr = i;
							otherflag = 128;
						}
					}
				}
			}else{
				for(int i=0; i<32; i++){
					if(jjPlayers[i].isActive){
						if(jjPlayers[i].team == TEAM::RED && jjPlayers[i].flag != 0){
							myflagcarr = i;
							//if(botPlay.playerID == i) //will cap the flag if this is not commented
							myflag = 128;
						}else if(jjPlayers[i].team == TEAM::BLUE && jjPlayers[i].flag != 0){
							otherflagcarr = i;
							otherflag = 128;
						}
					}
				}
			}
			playerID2 = botPlay.playerID;
			//if(jjGameTicks%70 == 0) jjAlert("hmm "+specified+" "+myflag+" "+otherflag+" "+myflagcarr+" "+playerID2);
			
			/*if(team==0) {
				address = vOffset + 0x005FCCF0; // Red
				ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&value,1,0);
				byte1=(BYTE)value;
				otherflagcarr=byte1;
				
				address = vOffset + 0x005FCCF4; // Blue
				ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&value,1,0);
				byte1=(BYTE)value;
				myflagcarr=byte1;
			}
			else {
				address = vOffset + 0x005FCCF4; // Blue
				ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&value,1,0);
				byte1=(BYTE)value;
				otherflagcarr=byte1;
				
				address = vOffset + 0x005FCCF0; // Red
				ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&value,1,0);
				byte1=(BYTE)value;
				myflagcarr=byte1;
			}
		
			if(team==0) {
				address = vOffset + 0x005FCCF1; // Red
				ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&value,1,0);
				byte1=(BYTE)value;
				otherflag=byte1;
				
				address = vOffset + 0x005FCCF5; // Blue
				ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&value,1,0);
				byte1=(BYTE)value;
				myflag=byte1;
			}else {
				address = vOffset + 0x005FCCF5; // Blue
				ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&value,1,0);
				byte1=(BYTE)value;
				otherflag=byte1;
				
				address = vOffset + 0x005FCCF1; // Red
				ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&value,1,0);
				byte1=(BYTE)value;
				myflag=byte1;
			}*/
		
			health=play.health;
			
			if(health<2 && specified==21) { // Semi carrot
				xPos=46;
				yPos=48;
			}
			
			//if bot type = "def" then always defend flag regardless of these
			array<string> res;
			if(jjRegexSearch(botPlay.name, "\\[flag\\]", res, true)){
				//if(jjGameTicks%70==0) jjAlert('here'+res[0]);
				if(team==0) {
					xPos=xblueflag;
					yPos=yblueflag;
				}
				else {
					xPos=xredflag;
					yPos=yredflag;
				}
			}else if(def[botPlay.localPlayerID] == true || jjRegexSearch(botPlay.name, "\\[def\\]", true)){
				if(otherflag == 128) {
					playerID=otherflagcarr;
					for(int i=0; i<jjLocalPlayerCount; i++){
						if(jjLocalPlayers[i].playerID == botPlay.playerID){
							pID[i] = otherflagcarr;;
							break;
						}
					}
				}else{
					if(team==0) {
						xPos=xblueflag;
						yPos=yblueflag;
					}
					else {
						xPos=xredflag;
						yPos=yredflag;
					}
				}
			}else if(def[botPlay.localPlayerID] == false){
				if(myflag == 0 && specified>0) {
					if(team==0) {
						xPos=xredflag;
						yPos=yredflag;
					}
					else {
						xPos=xblueflag;
						yPos=yblueflag;
					}
				}else if(myflag == 128 && otherflag == 0 && myflagcarr==playerID2 && specified>0) {
					if(!jjRegexSearch(botPlay.name, "\\[cap\\]", true) || botPlay.flag != 0){
						if(team==0) {
							xPos=xblueflag;
							yPos=yblueflag;
						}
						else {
							xPos=xredflag;
							yPos=yredflag;
						}
					}else{
						if(team==0) {
							xPos=xredflag;
							yPos=yredflag;
						}
						else {
							xPos=xblueflag;
							yPos=yblueflag;
						}
					}
				}else if(otherflag == 128) {
					if(!jjRegexSearch(botPlay.name, "\\[cap\\]", true) || botPlay.flag != 0){
						playerID=otherflagcarr;
						for(int i=0; i<jjLocalPlayerCount; i++){
							if(jjLocalPlayers[i].playerID == botPlay.playerID){
								pID[i] = otherflagcarr;;
								break;
							}
						}
					}else{
						if(team==0) {
							xPos=xredflag;
							yPos=yredflag;
						}
						else {
							xPos=xblueflag;
							yPos=yblueflag;
						}
					}
				}
			}
		}
		
		if(xPos2>=13 && xPos2<=17 && yPos2>=46 && yPos2<=48 && specified==21) { // Semi
			xPos=16.8;
			yPos=49;
			
		}
		else if(xPos2>=81 && xPos2<=100 && yPos2>=47 && yPos2<=57 && specified==21) {
			if(xPos2>=94 && xPos2<=100 && yPos2>=47 && yPos2<=50) {
				if(xPos>=78 && xPos<=100 && yPos>=5 && yPos<=45) {
					xPos=99;
					yPos=42;
				}
			}
			else {
				if(xPos>=78 && xPos<=100 && yPos>=5 && yPos<=52) {
					xPos=97.5;
					yPos=57;
				}
			}
			
		}
		else if(xPos2>=95 && xPos2<=100 && yPos2>=24 && yPos2<=45 && specified==21) {
				xPos=96.5;
				yPos=43;
		}
		else if(xPos2>=74 && xPos2<=88 && yPos2>=40 && yPos2<=45 && specified==21) {
				xPos=78.5;
				yPos=41;
		}
		else if(xPos2>=42 && xPos2<=49 && yPos2>=30 && yPos2<=42 && specified==21) {
				xPos=44.5;
				yPos=41;
		}
		else if(xPos2>=19 && xPos2<=31 && yPos2>=34 && yPos2<=47 && specified==21) {
			if(xPos<xPos2) {
				xPos=28;
				yPos=40;
			}
		}
		else if(xPos2>=52 && xPos2<=62 && yPos2>=35 && yPos2<=44 && specified==21) {
			if(xPos<xPos2) {
				xPos=57;
				yPos=44;
			}
		}
		else if(xPos2>=37 && xPos2<=45 && yPos2>=52 && yPos2<=56 && specified==21) {
			if(xPos<xPos2 && yPos<yPos2) {
				xPos=42;
				yPos=53;
			}
		}
		

		
		//address = vOffset + 0x005A4EE0 + (0x5A4 * playerID) + 0x48;
		//ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&name,24,0);
		
		
		//address = vOffset + 0x005A4EE0 + (0x5A4 * playerID2) + 0x98;
		//ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&value,4,0);
		//onwhine=(bool)value;
		
		
		
		/*address = vOffset + 0x005A4EE0 + (0x5A4 * playerID) + 0x4E0;
		ReadProcessMemory(phandle,(LPCVOID)address,(LPVOID)&value,4,0);
		xcampos=value/2.0979/1000000;*/
		
		if(dir == 0 && xPos2-xPos<0) { // Go right
			botPlay.keyLeft = false; // A Release (left)
			botPlay.keyRight = true; // D Press (right)
			dir=1;
		}
		else if(dir == 1 && xPos2-xPos>0) { // Go left
			botPlay.keyRight = false; // D Release (right)
			
			botPlay.keyLeft = true;// A Press (left)
			dir=0;
		}
		/*if(dir == 0 && botPlay.xPos-xPos*32<0) { // Go right
			botPlay.keyLeft = false; // A Release (left)
			botPlay.keyRight = true; // D Press (right)
			dir=1;
		}else if(dir == 1 && botPlay.xPos-xPos*32>0) { // Go left
			botPlay.keyRight = false; // D Release (right)
			
			botPlay.keyLeft = true;// A Press (left)
			dir=0;
		}
		if(jjGameTicks%70==0) jjAlert("hmm: "+(botPlay.xPos-xPos*32)+" "+(xPos2-xPos)+" "+xPos2+" "+xPos+" "+botPlay.xPos+" "+xPos*32);
		*/
		
		if(yPos2-yPos>0) { // Jump (up)
			//addition (this if)
			//if(jumping == 1) botPlay.keyJump = true;
			if(jumping == 0 && (xPos2-xPos>=-disFlag && dir==1) || (xPos2-xPos<=disFlag && dir==0) && ((xPos == xredflag && yPos == yredflag) || (xPos == xblueflag && yPos == yblueflag))) botPlay.keyJump = false;
			else botPlay.keyJump = true; // G Press (Jump)
			if(((xPos == xredflag && yPos == yredflag) || (xPos == xblueflag && yPos == yblueflag)) && botPlay.yPos-yPos*32>16) botPlay.keyJump = true;
			//if(jjGameTicks%70 == 0) jjDebug((yPos2-yPos)+" ");
			botPlay.keyUp = true; // W Press (Up)
			jumping=1;
		}
		else if(jumping == 1 && yPos2-yPos<0) { // Stop jump, or buttstomp on whine
			botPlay.keyJump = false; // G Release (Jump)
			botPlay.keyUp = false; // W Release (Up)
			jumping=0;
		}
		if(onwhine==true && jumping==0 && yPos2-yPos<0) {
			botPlay.keyDown = true; // S Press (Down)
			//Sleep(100);
			botPlay.keyDown = true; // S Press (Down)
		}
		if((xPos2-xPos>=-disFlag && dir==1) || (xPos2-xPos<=disFlag && dir==0)) { // Slow down (up)
			//botPlay.keyRun = false; // J Release
		}
		else {
			botPlay.keyRun = true; // J Press
		}
		
		//addition (was not in original C++ code)
		if((xPos2-xPos>=-disFlag && dir==1) || (xPos2-xPos<=disFlag && dir==0)) {
			if(((xPos == xredflag && yPos == yredflag) || (xPos == xblueflag && yPos == yblueflag))) jumping = 0;
		}
		//if((xPos2-xblueflag>=-disFlag && dir==1) || (xPos2-xblueflag<=disFlag && dir==0)) jumping = 0;
		//if((xPos2-xredflag>=-disFlag && dir==1) || (xPos2-xredflag<=disFlag && dir==0)) jumping = 0;
		/*int rndSpeed = jjRandom() % 3;
		if((xPos2-xblueflag>=-disFlag && dir==1) || (xPos2-xblueflag<=disFlag && dir==0)) {
			if(rndSpeed == 2) botPlay.keyRun = false; // J Release
			else botPlay.keyRun = true; // J Press
		}else if((xPos2-xredflag>=-disFlag && dir==1) || (xPos2-xredflag<=disFlag && dir==0)) {
			if(rndSpeed == 2) botPlay.keyRun = false; // J Release
			else botPlay.keyRun = true; // J Press
		}else {
			botPlay.keyRun = true; // J Press
		}*/
		
		int max = 0;
		int pmax = 0;
		for(int i=2; i<=9; i++){
			if(botPlay.ammo[i] > max){
				max = botPlay.ammo[i];
				pmax = i;
			}
		}
		botPlay.currWeapon = pmax;
		if(jjGameTicks%2 == 1) botPlay.keyFire = true;
		if(jjGameTicks%2 == 0) botPlay.keyFire = false;
		
		//searching for a playerID to hunt if my flag is taken. Comment all of this "if" statement if you want it to cap.
		if(!jjRegexSearch(botPlay.name, "\\[cap\\]", false)){
			if(myflag == 128 && otherflag == 0 && myflagcarr != botPlay.playerID){
				for(int i=0; i<32; i++){
					if(jjPlayers[i].isInGame && jjPlayers[i].team != botPlay.team){
						playerID = i;
						break;
					}
				}
				pID[botPlay.localPlayerID] = playerID;
			}
		}
		//if(jjGameTicks%70 == 0) jjAlert("m3: "+botPlay.playerID+" "+playerID+" "+myflag+" "+otherflag);
		//xPos2 = jjPlayers[playerID].xPos/32;
		//yPos2 = jjPlayers[playerID].yPos/32;
	}
}

bool onLocalChat(string &in text, CHAT::Type type){
	array<string> string_parts = text.split(" ");
	if(jjRegexMatch(string_parts[0], """[!:~]bot""", true)){ //bot and target = playerID
		//jjOBJ@ Bot = jjObjects[jjAddObject(OBJECT::EGGPLANT, jjLocalPlayers[0].xPos+64, jjLocalPlayers[0].yPos, 0)];
		botOn = !botOn;
		if(string_parts.length > 1) playerID = parseInt(string_parts[1]);
		sendBotIdToServer();
		for(int l = 0; l<jjLocalPlayerCount; l++){
			if(playerID == jjLocalPlayers[l].playerID || (jjPlayers[playerID].team == jjLocalPlayers[l].team && jjGameMode == GAME::CTF)){
				bool okID = false;
				for(int i = jjLocalPlayers[l].playerID; i < 32; i++){
					if(jjPlayers[i].isInGame){
						if(jjPlayers[i].playerID != jjLocalPlayers[l].playerID && (jjPlayers[i].team != jjLocalPlayers[l].team || jjGameMode != GAME::CTF)){
							pID[l] = i;
							okID = true;
							break;
						}
					}
				}
				if(!okID){
					for(int i = 0; i < jjLocalPlayers[l].playerID; i++){
						if(jjPlayers[i].isInGame){
							if(jjPlayers[i].playerID != jjLocalPlayers[l].playerID && (jjPlayers[i].team != jjLocalPlayers[l].team || jjGameMode != GAME::CTF)){
								pID[l] = i;
								okID = true;
								break;
							}
						}
					}
				}
			}
		}
		
		saveFile();
		return true;
	}else if(jjRegexMatch(string_parts[0], """[!:~]def""", true) || jjRegexMatch(text, """[!:~]def""", true)){
		if(string_parts.length == 1){
			def[0] = true;
			def[1] = true;
			def[2] = true;
			def[3] = true;
		}else if(0 <= parseInt(string_parts[1]) && parseInt(string_parts[1]) <= 3){
			def[parseInt(string_parts[1])] = true;
		}else{
			def[0] = true;
		}
		return true;
	}else if(jjRegexMatch(string_parts[0], """[!:~]atk""", true) || jjRegexMatch(text, """[!:~]atk""", true)){
		if(string_parts.length == 1){
			def[0] = false;
			def[1] = false;
			def[2] = false;
			def[3] = false;
		}else if(0 <= parseInt(string_parts[1]) && parseInt(string_parts[1]) <= 3){
			def[parseInt(string_parts[1])] = false;
		}else{
			def[0] = false;
		}
		return true;
	}else if(jjRegexMatch(string_parts[0], """[!:~]botSpectate""", true) && string_parts.length >= 2 && jjIsServer){
		SPECTATE_AT_X_PLAYERS = parseInt(string_parts[1]);
		saveFile();
		return true;
	}else if(jjRegexMatch(string_parts[0], """[!:~]vote""", true)){
		if(!alreadyVoted){
			if(jjRegexMatch(string_parts[1], """yes""", true)) sendVote(1);
			else if(jjRegexMatch(string_parts[1], """no""", true)) sendVote(0);
			
			if(VOTE_SENT_MSG != "") jjAlert(VOTE_SENT_MSG, false);
		}else{
			if(ALREADY_VOTED_MSG != "") jjAlert(ALREADY_VOTED_MSG, false);
		}
		alreadyVoted = true;
		return true;
	}
	return false;
}

const string Filename = "bottry.asdat";
void onLevelLoad(){
	jjSTREAM load(Filename);
	if(!load.isEmpty()) {
		load.pop(botOn);
		load.pop(SPECTATE_AT_X_PLAYERS);
		
		if(botOn) sendBotIdToServer();
		if(botOn){
			bool okID = false;
			for(int l = 0; l<jjLocalPlayerCount; l++){
				for(int i = jjLocalPlayers[l].playerID; i < 32; i++){
					if(jjPlayers[i].isInGame){
						if(jjPlayers[i].playerID != jjLocalPlayers[l].playerID && (jjPlayers[i].team != jjLocalPlayers[l].team || jjGameMode != GAME::CTF)){
							pID[l] = i;
							okID = true;
							break;
						}
					}
				}
				if(!okID){
					for(int i = 0; i < jjLocalPlayers[l].playerID; i++){
						if(jjPlayers[i].isInGame){
							if(jjPlayers[i].playerID != jjLocalPlayers[l].playerID && (jjPlayers[i].team != jjLocalPlayers[l].team || jjGameMode != GAME::CTF)){
								pID[l] = i;
								okID = true;
								break;
							}
						}
					}
				}
			}
		}
	}
	//jjAlert("p: "+playerID);
}

void spectateBots(bool shouldSpectate)
{
	for(int i=0; i<32; i++)
	{
		if(jjPlayers[i].isActive)
		{
			if(botPlayersList[i] == true && botIsSpectating[i] != shouldSpectate)
			{
				jjChat("/forcespectate "+(i+1)+" "+(shouldSpectate ? "on" : "off"));
				if(shouldSpectate) sendSpectateMessageToBot(i);
				botIsSpectating[i] = shouldSpectate;
			}
		}
	}
}
void sendBotIdToServer()
{
	if(!jjIsServer)
	{
		jjSTREAM mySTREAM;
		string message = "botID";
		for(int i=0; i<jjLocalPlayerCount; i++)
		{
			message += " "+jjLocalPlayers[i].playerID;
		}
		mySTREAM.push(message);
		jjSendPacket(mySTREAM);
	}
	else
	{
		for(int i=0; i<jjLocalPlayerCount; i++)
		{
			setBotList(jjLocalPlayers[i].playerID);
		}
	}
}
void onReceive(jjSTREAM &in packet, int clientID) 
{
	string e;
	packet.pop(e);
	array<string> string_parts = e.split(" ");
	if(jjRegexMatch(string_parts[0], "botID", true))
	{
		for(uint i=1; i<string_parts.length; i++)
		{
			int newBotID = parseInt(string_parts[i]);
			setBotList(newBotID);
		}
	}
	else if(jjRegexMatch(string_parts[0], "botVote", true) && jjIsServer)
	{
		int vote;
		packet.pop(vote);
		if(vote == 1)
		{
			botVotesYes++;
		}
		else
		{
			botVotesNo++;
		}
	}
	else if(jjRegexMatch(e, "botMsg", true))
	{
		if(SPEC_MSG1 != "") jjAlert(SPEC_MSG1);
		if(SPEC_MSG2 != "") jjAlert(SPEC_MSG2);
	}
}
void setBotList(int newBotID)
{
	botPlayersList[newBotID] = !botPlayersList[newBotID];
}
void saveFile()
{
	jjSTREAM save;
	save.push(botOn);
	//save.push(playerID);
	save.push(SPECTATE_AT_X_PLAYERS);
	save.save(Filename);
}
void debugBots(int activePlayers)
{
	if(jjGameTicks%70 == 0)
	{
		string debug = "Amount: "+SPECTATE_AT_X_PLAYERS+"="+activePlayers+" Bots: ";
		for(int i=0; i<32; i++)
		{
			if(botPlayersList[i]) debug += " "+i;
		}
		jjAlert(debug);
	}
}
void sendSpectateMessageToBot(int botPlayerId)
{
	if(jjIsServer && jjPlayers[botPlayerId].isLocal)
	{
		if(SPEC_MSG1 != "") jjAlert(SPEC_MSG1);
		if(SPEC_MSG2 != "") jjAlert(SPEC_MSG2);
	}
	else
	{
		jjSTREAM mySTREAM;
		string message = "botMsg";
		mySTREAM.push(message);
		jjSendPacket(mySTREAM, botPlayerId);
	}
}

void sendVote(int vote)
{
	if(!jjIsServer)
	{
		jjSTREAM mySTREAM;
		mySTREAM.push("botVote");
		mySTREAM.push(vote);
		jjSendPacket(mySTREAM);
	}
	else
	{
		if(vote == 1) botVotesYes++;
		else botVotesNo++;
	}
}

void botSpectateVotesCountdown()
{
	if(botVoteIsOn >= 0 && jjGameTicks%70 == 0)
	{
		if(botVoteIsOn == 0)
		{
			jjAlert("Bot spectate vote complete. Yes: "+botVotesYes+"   No: "+botVotesNo, true);
			if(botVotesYes > botVotesNo)
			{
				spectateBots(true);
			}
		}
		else if(botVoteIsOn % 10 == 0)
		{
			if(BOT_VOTE_MSG1 != "") jjAlert(BOT_VOTE_MSG1, true);
			if(BOT_VOTE_MSG2 != "") jjAlert(BOT_VOTE_MSG2+" "+botVoteIsOn+" seconds", true);
		}
		botVoteIsOn--;
	}
}

void onMain()
{
	if(jjIsServer)
	{
		botSpectateVotesCountdown();
	}
}