Downloads containing Race.mut

Downloads
Name Author Game Mode Rating
JJ2+ Only: Race.mut PurpleJazz Mutator N/A Download file

File preview

#pragma name "Race.mut"

class warp {
	int xTile, yTile;
}
array<warp> Warps;

uint lapDelay = 0;

array<uint64> lapTimes(0, 0);
array<uint> laps(0, 0);
uint64 currLapTime = 0;
uint64 totalLapTime = 0;
array<uint64> bestLapTime(1, 25200);

string formatTime(uint64 time) {
	return (time / (70 * 60)) + ':' + formatInt(time / 70 % 60, '0', 2) + ':' + formatInt(time * 100 / 7 % 1000, '0', 3);
}

array<string> positions = {"1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th", "11th", "12th", "13th", "14th", "15th", "16th", "17th", "18th", "19th", "20th", "21st", "22nd", "23rd", "24th", "25th", "26th", "27th", "28th", "29th", "30th", "31st", "32nd"};
uint playerPosition = 0;
array<bool> hasFinished(32, false);
array<string> playerRanking(32, "1st");
bool finished = false;
bool onLastLap = false;

bool raceNotStarted = false;

float cameraX = 0;
float cameraY = 0;

bool pressOnce = false;

class Waypoint {
	float xPos, yPos;
}
array<Waypoint> Waypoints;

void onLevelLoad() {
	jjAnimSets[ANIM::BRIDGE].load();
	//jjObjectPresets[OBJECT::BOUNCEONCE].behavior = Waypoint();
}

void onLevelBegin() {
	for (int x = 0; x < jjLayerWidth[4]; x++) {
		for (int y = 0; y < jjLayerHeight[4]; y++) {
			if (jjEventGet(x, y) == AREA::WARP && jjParameterGet(x, y, 16, 1) == 1) {
				warp Finish;
				Finish.xTile = x;
				Finish.yTile = y;
				Warps.insertLast(Finish);
			}
		}
	}
	
	cameraX = jjLocalPlayers[0].xPos;
	cameraY = jjLocalPlayers[0].yPos;
	
	if (jjIsServer) {
		if (jjEventGet(0, 0) == 255 && jjParameterGet(0, 0, 0, 5) > 0) {
			int maxLap = jjParameterGet(0, 0, 0, 8);
			if (jjMaxScore != maxLap) jjChat("/maxscore " + maxLap);
		}
	}
	
	for (int i = 0; i < jjLocalPlayerCount; i++) {
		jjLocalPlayers[i].score = 1;
	}
}

void onPlayer(jjPLAYER@ play) {
	if ((jjGameState == GAME::STOPPED || jjGameState == GAME::PREGAME) && jjGameTicks == 2) raceNotStarted = true;
	
	if (jjIsServer && jjGameTicks == 2) updateName(play, play.score, (play.score <= jjMaxScore? false:true), playerRanking[play.playerID]);	

	if (raceNotStarted) {
		if (jjGameState == GAME::STARTED) {
			play.cameraUnfreeze(true);
			raceNotStarted = false;
			play.invisibility = false;
			play.noFire = false;
			play.xPos = play.xOrg;
			play.yPos = play.yOrg;
			play.blink = 70;
		} else {
			play.xPos = 0;
			play.yPos = 0;
			play.keyJump = play.keyRun = false;
			if (!play.isConnecting) play.noFire = true;
			play.buttstomp = 121;
			play.invisibility = true;
			
			play.cameraFreeze(cameraX, cameraY, true, jjGameTicks <= 2? true:false);
			
			if (!play.keyLeft && !play.keyRight && !play.keyUp && !play.keyDown) {
				if (jjKey[0x01]) {
					cameraX = jjMouseX + play.cameraX;
					cameraY = jjMouseY + play.cameraY;
				}
			}
			
			if (play.keyLeft && cameraX > 0) cameraX -= 16;
			else if (play.keyRight && cameraX < jjLayerWidth[4]*32) cameraX += 16;
				
			if (play.keyUp && cameraY > 0) cameraY -= 16;
			else if (play.keyDown && cameraY < jjLayerHeight[4]*32) cameraY += 16;
		}
	}
	
	if (jjKey[0x02]) {
		if (!pressOnce) {
			Waypoint newWaypoint;
			newWaypoint.xPos = jjMouseX + play.cameraX;
			newWaypoint.yPos = jjMouseY + play.cameraY;
			Waypoints.insertLast(newWaypoint);
			pressOnce = true;
		}
	} else {
		pressOnce = false;
	}
	
	if (jjKey[0x2E]) {
		for (uint i = 1; i < Waypoints.length(); i++) {
			Waypoints.removeAt(i);
		}
	}
	
	if (play.health > 0 && play.health < jjMaxHealth) play.health = jjMaxHealth; //immortality from weapons

	if ((jjGameState == GAME::STARTED || jjGameState == GAME::OVERTIME) && !finished && !play.isSpectating && !play.isIdle) {
		totalLapTime++;
		currLapTime++;
	}
	
	for (uint i = 0; i < Warps.length(); i++) {
		warp@ Finish = Warps[i];
		if ((int(play.xPos)/32 == Finish.xTile && int(play.yPos)/32 == Finish.yTile) && play.score <= (jjMaxScore+1)) {
			if (lapDelay == 0) {
				play.score++;
				lapDelay = 140;
				if (play.score <= (jjMaxScore+1)) lapTimes.insertLast(currLapTime);
				updateName(play, play.score, (play.score <= jjMaxScore? false:true), playerRanking[play.playerID]);
				if (!jjIsServer) {
					if (play.score <= (jjMaxScore+1)) {
						jjSTREAM packet;
						packet.push(play.score);
						packet.push(totalLapTime);
						uint64 lapTime = currLapTime;
						packet.push(lapTime);
						jjSendPacket(packet);
					}
				} else {
					if (currLapTime < bestLapTime[0] && play.score > 1 && play.score <= (jjMaxScore+1)) {
						bestLapTime.insertLast(currLapTime);
						array<string> results;
						string name = play.nameUnformatted;
						while (jjRegexMatch(name, """(.*)\[(1?\d{1,2}|1st|2nd|3rd|4th|5th|6th|7th|8th|9th|10th|11th|12th|13th|14th|15th|16th|17th|18th|19th|20th|21st|22nd|23rd|24th|25th|26th|27th|28th|29th|30th|31st|32nd)\](\|*\*)?""", results)) {
							name = results[1];
							jjAlert("|||" + name + " has set a new best lap time of " + formatTime(currLapTime) + "!", true, STRING::SMALL);
						}
					}
				}
			} else if (lapDelay == 138) {
				currLapTime = 0;
				laps.insertLast(play.score - 1);
			}
		}
	}
	if (lapDelay > 0) lapDelay--;
	
	if (play.score == jjMaxScore) {
		setFinishWarp();
	}
	
	if (play.warpID == 256 && jjGameTicks > 2 && play.score <= (jjMaxScore+1)) {
		if (!jjIsServer) {
			if (lapDelay == 140 && play.score <= (jjMaxScore+1)) {
				jjSTREAM packet;
				packet.push(play.score);
				packet.push(totalLapTime);
				uint64 lapTime = currLapTime;
				packet.push(lapTime);
				jjSendPacket(packet);
			}
		} else {
			if (!hasFinished[play.playerID] && play.score <= (jjMaxScore+1)) {
				array<string> results;
				string name = play.nameUnformatted;
				while (jjRegexMatch(name, """(.*)\[(1?\d{1,2}|1st|2nd|3rd|4th|5th|6th|7th|8th|9th|10th|11th|12th|13th|14th|15th|16th|17th|18th|19th|20th|21st|22nd|23rd|24th|25th|26th|27th|28th|29th|30th|31st|32nd)\](\|*\*)?""", results)) {
					name = results[1];
					jjAlert("|||" + name + " has finished in " + positions[playerPosition] + " place! (" + formatTime(totalLapTime) + ")", true, STRING::SMALL);
				}
				playerPosition++;
				hasFinished[play.playerID] = true;
				updateName(play, play.score, (play.score <= jjMaxScore? false:true), positions[playerPosition-1]);
			}
		}
		finished = true;
	}
	
	if (jjIsServer) bestLapTime.sortAsc();
}

void setFinishWarp() {
	if (!onLastLap) {
		for (int x = 0; x < jjLayerWidth[4]; x++) {
			for (int y = 0; y < jjLayerHeight[4]; y++) {
				if (jjEventGet(x, y) == AREA::WARP && jjParameterGet(x, y, 16, 1) == 1 && jjParameterGet(x, y, 0, 8) != 255) {
					jjParameterSet(x, y, 0, 8, 255);
				}
			}
		}
		onLastLap = true;
	}
}

void onMain() {
	if (jjIsServer) {
		for (int i = 1; i < 32; i++) {
			jjPLAYER@ play = jjPlayers[i];
			if (play.isConnecting && play.isActive) updateName(play, 1, false, "");
		}
	}
}

void onReceive(jjSTREAM &in packet, int clientID) {
	if (jjIsServer) {
		int playerLap;
		uint64 clientTime;
		uint64 clientLapTime;
		packet.pop(playerLap);
		packet.pop(clientTime);
		packet.pop(clientLapTime);
		jjPLAYER@ play = jjPlayers[clientID];
		play.score = playerLap;
		
		if (!hasFinished[play.playerID] && playerLap > jjMaxScore) {
		array<string> results;
			string name = play.nameUnformatted;
			while (jjRegexMatch(name, """(.*)\[(1?\d{1,2}|1st|2nd|3rd|4th|5th|6th|7th|8th|9th|10th|11th|12th|13th|14th|15th|16th|17th|18th|19th|20th|21st|22nd|23rd|24th|25th|26th|27th|28th|29th|30th|31st|32nd)\](\|*\*)?""", results)) {
				name = results[1];
				jjAlert("|||" + name + " has finished in " + positions[playerPosition] + " place! (" + formatTime(clientTime) + ")", true, STRING::SMALL);
			}
			playerPosition++;
			hasFinished[play.playerID] = true;
			playerRanking[play.playerID] = positions[playerPosition - 1];
		}
		
		updateName(play, playerLap, (playerLap <= jjMaxScore? false:true), playerRanking[play.playerID]);
			
		if (clientLapTime < bestLapTime[0] && playerLap > 1) {
			bestLapTime.insertLast(clientLapTime);
			array<string> results;
			string name = play.nameUnformatted;
			while (jjRegexMatch(name, """(.*)\[(1?\d{1,2}|1st|2nd|3rd|4th|5th|6th|7th|8th|9th|10th|11th|12th|13th|14th|15th|16th|17th|18th|19th|20th|21st|22nd|23rd|24th|25th|26th|27th|28th|29th|30th|31st|32nd)\](\|*\*)?""", results)) {
				name = results[1];
				jjAlert("|||" + name + " has set a new best lap time of " + formatTime(clientLapTime) + "!", true, STRING::SMALL);
			}
		}
			
	}
}

void updateName(jjPLAYER@ play, uint lap, bool finished, string pos) {
	array<string> results;
	string name = play.nameUnformatted;
	while (jjRegexMatch(name, """(.*)\[(1?\d{1,2}|1st|2nd|3rd|4th|5th|6th|7th|8th|9th|10th|11th|12th|13th|14th|15th|16th|17th|18th|19th|20th|21st|22nd|23rd|24th|25th|26th|27th|28th|29th|30th|31st|32nd)\](\|*\*)?""", results)) {
		name = results[1];
	}
	string nick = name;
	if (!finished)
		nick += ("[" + lap + "]");
	else nick += ("[" + pos + "]");

	if (play.name != nick)
		play.setName(nick);
}

bool onDrawHealth(jjPLAYER@ play, jjCANVAS@ canvas) {
	if (!jjLocalPlayers[0].isSpectating && !jjLocalPlayers[0].isIdle) {
		if (!raceNotStarted) {
			canvas.drawString(8, jjGameMode == GAME::BATTLE? 40 : 68, play.score <= jjMaxScore? "Lap " + play.score + " / " + jjMaxScore : "|Finished!", STRING::MEDIUM, STRING::NORMAL);
			canvas.drawString(10, jjGameMode == GAME::BATTLE? 68 : 96, "" + formatTime(totalLapTime), STRING::MEDIUM, STRING::NORMAL);
			for (uint i = 0; i < laps.length(); i++) {
				canvas.drawString(8, ((jjGameMode == GAME::BATTLE? 98 : 126) + (i * 16)), "||||" + laps[i] + ". " + formatTime(lapTimes[i]), STRING::SMALL, STRING::NORMAL);
			}
		} else {
			canvas.drawString(244 - (jjResolutionWidth <= 640? 80:0), 152, "Race not started yet!", STRING::MEDIUM, STRING::NORMAL);
			canvas.drawString(84 - (jjResolutionWidth <= 640? 84:0), 190, "|Use the |||movement keys||||| or |||left click and drag||||| to move the camera", STRING::SMALL, STRING::NORMAL);
			canvas.drawString(172 - (jjResolutionWidth <= 640? 80:0), 206, "|Click the |||right mouse button||||| to set ||waypoints", STRING::SMALL, STRING::NORMAL);
			canvas.drawString(222 - (jjResolutionWidth <= 640? 80:0), 222, "|Press |||delete||||| to erase all ||waypoints", STRING::SMALL, STRING::NORMAL);
		}
	}
	return true;
}

void onDrawLayer4(jjPLAYER@ play, jjCANVAS@ canvas) {
	for (uint i = 0; i < Waypoints.length(); i++) {
		Waypoint@ waypoint = Waypoints[i];
		jjDrawResizedSprite(waypoint.xPos, waypoint.yPos, ANIM::BRIDGE, 5, 0, 2, 2, SPRITE::NORMAL);
	}
}