//////////////////////////////////////////////////////////////
// WAVESYST - Zombie Torrent 2 wave system script //
// ---------------------/////////////////////////////////////////////////////
// Originally coded by Zedek the Plague Doctor (Uboa) for Imp Attack //
// Recycled from Zombie Torrent and revamped for ZT2 //////////////////
////////////////////////////////////////////////////////////////

#library "wavesyst"
#import "playlist.acs"
#include "zcommon.acs"

#define ZOMBIE_CLASSCOUNT 7

str ZombieClassNames[ZOMBIE_CLASSCOUNT] = { 
	"BaseZombie", 
	"BaseZombieVar1",
	"BaseZombieVar2",
	"VaginaZombie", 
	"DogZombie", 
	"ZombieDogBlue", 
	"Eviscerator" 
};

#define PLAYER_BASE_TID 1000
#define p_BaseTID 1000
#define MAXPLAYERS 64

// ID
#define ID_WAVESTART			90

// Zombie classes

// Alignment variables for text

#define ALIGN_CENTER 0.4
#define ALIGN_CENTER_Y 0.0
#define ALIGN_LEFT 0.1
#define ALIGN_RIGHT 0.2

// Stinger
#define STINGER_ID			500
#define STINGERCOUNT 3
str stingerPic[STINGERCOUNT] = {
	"CHNSTING",		// Eviscerator
	"CRNSTING",		// Cranus
	"BOSSTING",
};

int stingerWaves[STINGERCOUNT] = {
	5,				// Eviscerator
	7,				// Cranus
	10,
};

// Blood
#define BLOOD_ID			1500
str bloodPics[5] = {
	"HUDBLUD1",
	"HUDBLUD2",
	"HUDBLUD3",
	"HUDBLUD4",
	"HUDBLUD5",
};

#define TRADER_TRACK_COUNT 4
str tradertracks[TRADER_TRACK_COUNT][3] = {
	{"TRADER1", "Susan's Blue Sheep", "Richard Henley"},
	{"TRADER2", "Squirrel Deck", "Meteorite Jesus"},
	{"TRADER3", "Cthulhu", "David Pittman"},
	{"TRADER4", "Mental Anguish", "Sonic Mayhem"},
};

// Tips
#define TIP_COUNT 			12
str tiptext[TIP_COUNT] = {
	"You can use your melee attack on a zombie's head.",
	"Backpacks and health kits always respawn.",
	"\cJYou can type \cDcl_keepshells 1 \cJin the console to make\nyour casings last forever.",
	"\cJBy typing \cDcl_noreloadsound 1 \cJin the console, you\ncan prevent your character from saying things\nwhen reloading.",
	"The trader is only open for so long. Figure out\nwhere it is beforehand to save time.",
	"Zombie Torrent 2 has extra keybinds that are not\nbound by default. Be sure to set them.",
	"You can change your character's voice by pressing\nthe voice change key. Bind this in the\nconfiguration menu.",
	"You can buy upgrades for your weapons in the trader.\nUse the second button on the bottom-right.",
	"Different perks have different abilities. Be sure to\nread them closely, they will affect your gameplay.",
	"Dynamite can be cooked, don't let the fuse run for\ntoo long or else you'll get a nasty explosion\nto the face.",
	"\cJYou can use the \cDzt_perksave \cJcommand in the\nconsole to save your perks on the server. Remember to also\nuse \cDzt_perkload\cJ.",
	"Zombie Torrent 2 has a functional headshot system, be\nsure to attack their weak points for massive damage.",
};

int prevrandom=0;
			
// Whether or not the map should actually use waves
world int 1:map_sandbox;
// Whether or not the map performs scripts when the trader opens
world int 2:func_trader;

// CUSTOM FIGHT MUSIC
global str 3:customtracks[];
global str 4:customsongs[];
global str 5:customartists[];
global int 6:customsongamount;

// Whether or not the map uses custom music
global int 7:custommusic;
// Whether or not the map uses custom trader music
global int 8:customtrader;

// CUSTOM TRADER MUSIC
global str 9:track_trader[];
global str 10:tradersongs[];
global str 11:traderartists[];
global int 12:tradersongamount;

// Whether or not the map uses custom boss music
global int 13:customboss;
// The track to use for custom boss music
global str 14:track_boss;
// Whether or not the map calls functions before wave 1
world int 15:func_prewave;

#define BACKGROUND_ID	301			// Background
#define SONG_ID			300			// Song name
#define ARTIST_ID		299			// Artist
#define FADE_ID			298			// White fade

int storedweapon[64];
// Wave number
int waveno=1;
// How many waves total
int maxwaves=10;
int waveminute=1;
int wavesecond=59;
int waveinprogress=0;
int wavestarting=0;
int game_hasbegan=0;
// How many seconds before the wave starts
int starttime=15;
// The current wave
int currentwave=0;
int isfighting=0;
str extrazero="";
int tradertime=59;
int trading=0;
int fightingboss=0;
int zombieskilled;
int zombiechecktimer;

// Zombiepool : How many zombies must be killed before the wave ends
int zombiepool=0;
// The default number of zombies that must be killed, scaled depending on wave
int pool_default=30;
int pool_increment=0;

int wavearray[11];

int tradePlayers[MAXPLAYERS];
int mapspot[MAXPLAYERS];
//---------------------------------------------------//
// BioDisplayMode (Top-right timer display mode:)
//
// 0 - Mid-wave
// 1 - Trader time
//---------------------------------------------------//
int BioDisplayMode;

function void saveCVar(int cvar, int val)
{
    int query = StrParam(s:"set ", s:cvar, s:" ", d:val);
    int query2 = StrParam(s:"archivecvar ", s:cvar);
    ConsoleCommand(query);
    ConsoleCommand(query2);
}

function int defaultCVar(int cvar, int defaultVal)
{
    int ret = GetCVar(cvar);
    if (ret == 0) { saveCVar(cvar, defaultVal); return defaultVal; }

    return ret;
}

function int ZT_DefaultCVar(int var, int val)
{
    //if (met_cvarinfo()) { return GetCVar(var); }
    return defaultCVar(var, val);
}

function void DisplayTrackInfo(str song, str artist)
{
	
	SetFont("MUSIFADE");
	HudMessageBold(s:"a"; HUDMSG_FADEOUT, FADE_ID, CR_WHITE, 0.0, 0.5, 0.1, 1.0);
		SetFont("MUSIBACK");
		HudMessageBold(s:"a"; HUDMSG_FADEINOUT, BACKGROUND_ID, CR_WHITE, 0.0, 0.5, 4.0, 1.0, 2.0);
		SetFont("TYPEWRIT");
		HudMessageBold(s:song; HUDMSG_FADEOUT, SONG_ID, CR_WHITE, 0.00015*30, 0.5, 5.0, 2.0);
		Setfont("BIGFONT");
		HudMessageBold(s:artist; HUDMSG_FADEOUT, ARTIST_ID, CR_WHITE, 0.00015*30, 0.525, 5.0, 2.0);
}

script 998 OPEN
{
  delay(2);
  ConsoleCommand("sv_survivalcountdowntime 0");
  ConsoleCommand("compat_clientssendfullbuttoninfo 1");
  ConsoleCommand("sv_itemrespawn 1");
}

// Used for giving money on Zombie deaths
script 30 (void)
{
if (zombiesKilled)
	SetResultValue(false);
else
	SetResultValue(true);
}

script 878 (void)
{
	Print(s:"availableTracks is ",d:availableTracks);
	Print(s:trackArtist[0]);
	Print(s:"END OF ARTIST");
	Print(s:trackSong[0]);
	Print(s:"END OF SONG");
	Print(a:(trackFile));
}

script 999 unloading {map_sandbox = 0;}

script 997 (void)
{
	int currentPic = 0;
	
	if (currentwave < 10)
	{
		delay(10);
		
		while (currentPic < 5)
		{
		AmbientSound("hudblood/splat",127);
		SetFont(bloodPics[currentPic]);
		HudMessageBold(s:"A"; HUDMSG_FADEOUT,BLOOD_ID,0,1.5,0.45,11.0,1.0);
		SetFont("SMALLFONT");
		currentPic ++;
		delay(10);
		}
	}
}

// Used to scale the monster's health based on skill
script 49 (void)
{
	int health;
	int skill;

	skill = GameSkill();

	health = GetActorProperty(0, AProp_SpawnHealth);

	switch (skill)
	{
		case 0:
		SetActorProperty(0, AProp_Health, round(health * 0.55));
		SetActorProperty(0, AProp_Speed, FixedMul(GetActorProperty(0,AProp_Speed),0.85));
		break;

		case 1:
		SetActorProperty(0, AProp_Health, round(health * 0.75));
		SetActorProperty(0, AProp_Speed, FixedMul(GetActorProperty(0,AProp_Speed),0.93));
		break;

		case 2:
		SetActorProperty(0, AProp_Health, round(health * 1.0));
		break;

		case 3:
		SetActorProperty(0, AProp_Health, round(health * 1.15));
		SetActorProperty(0, AProp_Speed, FixedMul(GetActorProperty(0,AProp_Speed),1.15));
		break;

		case 4:
		SetActorProperty(0, AProp_Health, round(health * 1.50));
		SetActorProperty(0, AProp_Speed, FixedMul(GetActorProperty(0,AProp_Speed),1.50));
		break;
	}
}


// Used for DECORATE to return the game's difficulty
script 50 (void)
{
	int skill;

	skill = GameSkill();
	SetResultValue(skill);
}

Script 52 ENTER
{
	str preparetext;

	// Reset the player's inventory to keep them from keeping items throughout maps
	ClearInventory();
	GiveInventory("Machete",1);
	GiveInventory("OrderSecondary",50);
	GiveInventory("Order Pistol",1);
	GiveInventory("OrderPrimary",10);
	
	SetWeapon("Order Pistol");

	// Set default CVARs
	ZT_DefaultCVar("cl_zombiedebugger", 0);
	ZT_DefaultCVar("cl_noreloadsound", 0);
	ZT_DefaultCVar("cl_disablezthud", 0);
	ZT_DefaultCVar("cl_keepshells", 0);

	tradePlayers[PlayerNumber()] = 0;
	Thing_ChangeTID(0,p_BaseTID+PlayerNumber());//This assigns the TID

	ACS_ExecuteAlways(74,0,0,0,0); // Bio display code
	ACS_ExecuteAlways(76,0,0,0,0); // Gives health charge every 10 tics
	ACS_ExecuteAlways(77,0,0,0,0); // Debug script for zombie pool
	
	if (currentwave <= 0)
	{
		currentwave = 1;
		StartNextWave();
	}
}

// CVAR SHIT - USED FOR CHECKING SHELLS
script 823 (void)
{
	int value;

	value = GetCVar("cl_keepshells");
	if (value)
		SetResultValue(TRUE);
	else
		SetResultValue(FALSE);
}

script 74 (void)
{
	TakeInventory("HUDDummy_Pool",999);
	TakeInventory("HUDDummy_Wave",999);
	TakeInventory("HUDDummy_Trader",999);
	TakeInventory("HUDDummy_Bio",999);

	GiveInventory("HUDDummy_Pool",zombiepool);
	GiveInventory("HUDDummy_Wave",waveno);
	GiveInventory("HUDDummy_Trader",tradertime);
	GiveInventory("HUDDummy_Bio",BioDisplayMode);

	ACS_ExecuteAlways(75,0,0,0,0);
	delay(1);
	restart;
}

function int abs (int x)
{
    if (x < 0)
        return -x;

    return x;
}

str ArrowSprites[19] = { "ARRWA0", "ARRWB0", "ARRWC0", "ARRWD0", "ARRWE0", "ARRWF0", "ARRWG0", "ARRWH0", "ARRWI0", "ARRWJ0", "ARRWK0", "ARRWL0",
								"ARRWM0", "ARRWN0", "ARRWO0", "ARRWP0", "ARRWQ0", "ARRWR0", "ARRWS0" };

// Called by script 52, controls the hud message
script 75 (void) CLIENTSIDE
{
	int pooldraw;
	str tradertext;

	int it_tradertime;
	int it_zombiepool;
	int it_biodisplaymode;
	int it_waveno;

	int angletotrader;
	int angle_trader;
	int angle_player;
	int finalangle;

	int x1;
	int x2;

	int y1;
	int y2;

	str extra;

	int imagetochoose;

	it_tradertime = CheckInventory("HUDDummy_Trader");
	it_zombiepool = CheckInventory("HUDDummy_Pool");
	it_biodisplaymode = CheckInventory("HUDDummy_Bio");
	it_waveno = CheckInventory("HUDDummy_Wave");

	if (it_tradertime<10)
		extra = "0";
	else
		extra = "";

	if (it_tradertime >= 0)
		tradertext = StrParam(s:"\cK00:", s:extra, d:it_tradertime);
	else
		tradertext = "00:00";

	switch (it_biodisplaymode)
	{
		case 1:
			if (!GetCvar("cl_disablezthud"))
			{
				SetFont("BIOTIME2");
				HudMessageUnscaled (-100.0, 100.0, "a", 1, 1, 3);
				
				if (it_waveno < 10)
				{
					pooldraw = it_zombiepool;
					if (pooldraw < 0)
						pooldraw = 0;
					SetFont("BIGWRITR");
					HudMessageUnscaled (-100.0, 90.0, StrParam(d:pooldraw), 1, 1, 2);
					SetFont("TYPEWRIT");
					HudMessageUnscaled (-100.0, 125.0, StrParam(d:it_waveno,s:" / 10"), 1, 1, 1);
				}
				else
				{
					SetFont("BIOTIME3");
					HudMessageUnscaled (-100.0, 100.0, "a", 1, 1, 3);
				
					SetFont("BIGWRITR");
					HudMessageUnscaled (-100.0, 90.0, "\cKBOSS", 1, 1, 2);
					SetFont("TYPEWRIT");
				}
			}
		break;

		case 2:
			if (!GetCvar("cl_disablezthud"))
			{
			SetFont("BIOTIME1");
			HudMessageUnscaled (-100.0, 100.0, "a", 1, 1, 2);
			SetFont("TYPEWRIT");
			HudMessageUnscaled (-100.0, 100.0, tradertext, 1, 1, 1);
			}

			//angle_trader = GetActorAngle(50) >> 8 ;
			//angle_player = GetActorAngle(ActivatorTID()) >> 8 ;

		//Tan(angle) = lengthOfOppositeSide / lengthOfAdjacentSide
		//x1 = GetActorX(ActivatorTID());
		//y1 = GetActorY(ActivatorTID());

		//x2 = GetActorX(50);
		//y2 = GetActorY(50);

		//angletotrader = 360 - (FixedDiv(VectorAngle (x2 - x1, y2 - y1), 0.708) >> 8);

		//imagetochoose = round(angle_player - angletotrader / 10);
		//SetFont("SMALLFONT");
		//Print(s:"Your angle is ",d:angle_player,s:"\nTrader's angle is ",d:angletotrader,s:"\n\nTan is ",d:abs(angle_player - angletotrader),s:"\n\nPlayer is ",d:x1 >> 8,s:";",d:y1 >> 8,s:"\nTrader is ",d:x2 >> 8,s:";",d:y2 >> 8,s:"\nImage is ",d:imagetochoose);

		break;
	}
}

// Health Script - Used for giving syringe health charge
Script 76 (void)
{
TakeInventory("TauntTimer",1);
delay(1);
restart;
}

// Zombie debug script, for seeing zombie pool.
Script 77 (void)
{
int value;
value = GetCVar("cl_zombiedebugger");
	//if (value)
		//Print(s:"Zombiepool is ",d:zombiepool,s:"\nZombiekilled is ",d:zombieskilled);
delay(1);
restart;
}

// Resets TID and says that the player is not in the trader
Script 51 RESPAWN
{
	tradePlayers[PlayerNumber()] = 0;
	Thing_ChangeTID(ActivatorTID(), 0);
	Thing_ChangeTID(0,p_BaseTID+PlayerNumber());//This assigns the TID
	
	// Check to see if we have any grenades
	if (CheckInventory("Type-97 Grenade") <= 0)
		GiveInventory("Type-97 Grenade",1);
}

// Does the same as above
script 53 (int p) DISCONNECT
{
	tradePlayers[p] = 0;
	Thing_ChangeTID(ActivatorTID(), 0);
}

// Called when the map opens, disables all spawners and forces player anti-block
script 54 OPEN
{
	if (GameType () != GAME_TITLE_MAP && !map_sandbox)
	{
		// Force unblocking of players
		if (!GetCvar("sv_UnblockPlayers"))
		ConsoleCommand("sv_UnblockPlayers 1");
		// Deactivates all zombie spawners.
		SetActorState(200,"Static",0);
		SetActorState(201,"Static",0);
		SetActorState(202,"Static",0);
		SetActorState(203,"Static",0);
		SetActorState(204,"Static",0);
		SetActorState(205,"Static",0);
		SetActorState(206,"Static",0);
		SetActorState(207,"Static",0);
		SetActorState(208,"Static",0);
		SetActorState(209,"Static",0);
		SetActorState(210,"Static",0);
	}
}

// Shows the wave starting font
script 55 (void)
{
	str preparetext;
	int tip;
	
	tip = random(0,TIP_COUNT-1);
			SetFont("SMALLFONT");
			HudMessageBold(s:"\cKRemember:\n\cJ",s:tiptext[tip]; HUDMSG_TYPEON, 100, CR_WHITE, 1.5, 0.48, 5.0, 0.05, 1.0);

	while (wavestarting==1 && game_hasbegan==1)
		{
			SetFont("BIGFONT");
			HudMessageBold(s:"Wave ", d:currentwave, s:" is starting in ", d:starttime, s:" seconds..."; HUDMSG_PLAIN, ID_WAVESTART, CR_WHITE, 0.5, 0.45, 3.0);

			delay(1);
		}
}

script 56 (void)
{
	int x = GetZombieCount();
	int xres;
	int yres;

	// If the wave is still starting...
	if (starttime > 1)
	{
		
		if (starttime == 4) {AnnouncerSound("three", 0);}
		if (starttime == 3) {AnnouncerSound("two", 0);}
		if (starttime == 2) {AnnouncerSound("one", 0);}
		starttime --;

			// Display an extra message with the number being red
			if (starttime <= 3)
			{
				SetFont("BIGFONT");
				HudMessageBold(s:"\cJWave ", d:currentwave, s:" is starting in \cG", d:starttime, s:" \cJseconds..."; 1, ID_WAVESTART, CR_WHITE, 0.5, 0.45, 0.2,0.25);
			}
		// Wait 1 second and restart the timer script
		delay(35);
		restart;
	}

	// If the timer has ended, then start the wave
	else
	{
		isfighting=1;
		wavestarting=0;

		BioDisplayMode = 1;

		AnnouncerSound("fight",0);
		ACS_ExecuteAlways(58,0,0,0,0); // Zombie pool control script
		if (func_prewave){ACS_Execute(90,0,13,0,0);}

		ClearWaveStarting();

		SetFont("FIGHTHUD");
		HudMessageBold(s:"A"; HUDMSG_FADEINOUT,9493,0,1.5,0.5,2.0,0.5,1.5);
		SetFont("SMALLFONT");

		zombiepool=pool_default+pool_increment;
		ACS_Execute(81,0,0,0); // Starts the wave music.

		// Lets the spawners know that they can spawn zombies
		SetActorState(201,"Spawning",0);
		for (int j=0; j<10; j+=1)
		{
			if (wavearray[j])
				SetActorState(200+j,"Spawning",0);
		}
	}

	while (game_hasbegan==1 && isfighting==1)
	{
		if (wavesecond < 10){extrazero="0";}
		else{extrazero="";}

		if (!fightingboss)
		{
			BioDisplayMode = 1;
		}

		delay(1);
	}
}

script 58 (void)
{
	// Count the number of zombies that are left
	int x = GetZombieCount();

	// Self-explanatory
	if (zombiepool < 0)
		zombiepool = 0;

	// If no more zombies need to be killed...
	if (zombiepool < 1)
	{
		Thing_DeActivate(200+waveno);
		if (wavearray[9]){SetMusic("",0,0);}

		// Disable all spawners
		for (int k=0; k<10; k+=1)
		{
			SetActorState(200+k,"Static",0);
		}

		waveno++; // Goes to the next wave
		wavearray[waveno]=1;
		BioDisplayMode = 0;

		// Clears the zombie count and gibs any remaining zombies if the system breaks
		zombiesKilled = 1;
		Thing_Destroy (0, 1) ;
		zombiesKilled = 0;

		ACS_Terminate(60,0); // Stops the zombies from spawning
		ACS_Execute(59,0,0,0,0); // Ends the wave
		terminate;
	}

	delay(5);
	restart;
}

// End of wave script
script 59 (void)
{
	int randomizer;
	int randomizercap;
	int hPos = 0;
	
	str tsong = "";
	str tartist = "";
	
	ACS_Terminate(56,0);
	ACS_Terminate(57,0);
	ACS_Terminate(58,0);

	// We're not fighting a wave anymore
	isfighting=0;
	wavestarting=0;
	ClearWaveStarting();

	delay(35);

	// Sets the trader time up, scaling based on level
	tradertime=90-(10*(GameSkill()+1));
	pool_increment += 10+(2*PlayerCount());
	// Call the trader function script if the map uses it
	if (func_trader==1){ACS_Execute(90,0,11,0,0);}
	// Open the trader door, tag 100 by default
	Door_Open(100,100);
	// Reset the killed zombies for this wave
	zombieskilled=0;

	BioDisplayMode = 2;

	SetFont("TRADOPEN");
	HudMessageBold(s:"A"; HUDMSG_FADEINOUT, 9493, 0, 1.5, 0.5, 2.0,0.5,1.5);
	SetFont("SMALLFONT");

	// If we're going into wave 10, display a warning message for the boss
	if (wavearray[10])
	{
		SetFont("DETHCOME");
		HudMessageBold(s:"A"; HUDMSG_FADEINOUT, 9493, 0, 1.5, 0.5, 4.0,1.0,1.5);
		SetFont("SMALLFONT");
	}
	
	//=================================================================
	// PLAY TRADER MUSIC
	//=================================================================
	
	if (!customtrader)
		randomizercap = availableTraderTracks;
	else
		randomizercap = tradersongamount-1;
	
	if (randomizercap > 0)
	{
		randomizer = random(0, randomizercap);
	}
	else
	{
		randomizer = 0;
	}
	
	if (!customtrader)
	{
		tsong = trackTraderSong[randomizer];
		tartist = trackTraderArtist[randomizer];
		SetMusic(trackTraderFile[randomizer],0);
	}
	else
	{
		tsong = tradersongs[randomizer];
		tartist = traderartists[randomizer];
		SetMusic(track_trader[randomizer],0);
	}

	// We're trading
	trading=1;

	// Trader timer script
	ACS_Execute(63,0,0,0,0);
	DisplayTrackInfo(tsong, tartist);
}

// Starts the next round, called when tradertime ends
script 62 (void)
{
	// We're not fighting a wave just yet
	isfighting=0;
	// Yes, we're waiting for the wave to start
	wavestarting=1;
	starttime=15;
	// Reset the wave timer, unused because it was scrapped
	waveminute=1;
	wavesecond=59;
	// Move to the next wave
	currentwave++;
	waveno = currentwave;

	BioDisplayMode = 0;
	
	if (currentwave<10)
			AmbientSound("wave/midwave",127);
	
	// Show stingers
	for (int st=0; st<STINGERCOUNT; st++)
	{
	if (currentwave == stingerWaves[st])
			{
			AmbientSound("stinger/eviscerator",128);
			SetFont(stingerPic[st]);
			HudMessageBold(s:"A"; HUDMSG_FADEINOUT,STINGER_ID,0,1.5,0.75,2.0,0.5,1.5);
			SetFont("SMALLFONT");
			}
	}

	// Closes the trader door
	Door_Close(100,100);

	// Call the wave function depending on the wave number
	// Does certain things before the wave actually starts, like Invasion
	ACS_Execute(90,0,waveno,0,0);

	// If the map uses custom trader functions, then execute them
	if (func_trader==1){ACS_Execute(90,0,12,0,0);}

	// Boot players out of the trader if they're still standing in the room when it closes
	teleportPlayers(mapspot[PlayerNumber()]);

	// If we're on wave 10, then execute the boss script
	// Otherwise, continue as normal
	if (currentwave==10){ACS_Execute(70,0,0,0,0);}
	else{StartNextWave(); ACS_Execute(56,0,0,0,0);}
}

// Trader timer, controls the timer and closes the trader if it ends
script 63 (void)
{

	// If we're still trading and the timer's still running
	if (tradertime >= 0 && trading)
	{
		// Slaps an extra 0 on if the seconds are less than 10
		if (tradertime<10){extrazero="0";}
		else{extrazero="";}

		delay(1);
	}

	// If the trader time is up, then start the next wave
	if (tradertime < 0)
	{
		AnnouncerSound("preparetofight",0);
		trading=0;
		SetMusic("");
			
		ACS_Execute(62,0,0,0,0);
		ACS_ExecuteAlways(997,0,0,0,0);
		terminate;
	}

	tradertime--;
	delay(35);
	restart;
}

// Boss wave script, used to control all the fancy junk that happens
// No boss is even coded yet, ignore this for now

script 70 (void)
{
	game_hasbegan=1;
	wavestarting=0;

	SetFont("BIGFONT");
	PrintBold(s:"Roasterock spawning in 5...");
	delay(35);
	PrintBold(s:"Roasterock spawning in 4...");
	delay(35);
	PrintBold(s:"Roasterock spawning in 3...");
	delay(35);
	PrintBold(s:"Roasterock spawning in 2...");
	delay(35);
	PrintBold(s:"Roasterock spawning in 1...");
	delay(35);
	
	if (!customboss)
	{
	SetMusic("QUAKEDM1",0);
	DisplayTrackInfo("KI Fulgore Theme", "Mick Gordon");
	}
	else{SetMusic(track_boss,0);}

	SpawnSpotFacing("Roasterock",210,700);
	SetActorState(700,"SpawnTaunt",0);

	ChangeCamera(211,1,0);
	Delay(35*3);
	ChangeCamera(0,1,0);

	BioDisplayMode = 1;

	ACS_Execute(90,0,10,0,0);
	fightingboss=1;
	AnnouncerSound("fight",0);
	SetActorState(700,"Spawn",0);

	SetFont("FIGHTHUD");
	HudMessageBold(s:"A"; HUDMSG_FADEINOUT,9493,0,1.5,0.5,2.0,0.5,1.5);
	SetFont("SMALLFONT");
}

// Check if we can spawn zombies yet or we are over the pool already
// Called via DECORATE in zombie spawners

script 65 (void)
{
	int x = GetZombieCount();
	int y;
	if (x >= ZombiePool) {y = 0;}
	else {y = 1; ACS_Execute(66,0,0,0);}
	SetResultValue(y);
}

script 66 (int ztimer)
{
	ztimer += 1;
	int x = GetZombieCount();
	if (ztimer >= 10 && zombiepool<=4 && x == 0) {zombiepool-=4; terminate;}
	delay(35);
	restart;
}

// OTHER JUNK

// Called when a zombie dies, subtracts from the zombie pool and gives the player money
script 72 (int argue, int money, int XP)
{
zombiepool --;
zombieskilled++;
ACS_Execute(801,0,0,0,0);

// LOOP THROUGH SETACTIVATORTOTARGET UNTIL WE FIND A PLAYER

int attempts = 0;
int success = 0;

	while (PlayerNumber() < 0 && attempts < 5 && !success)
	{
		SetActivatorToTarget(0);
		if (PlayerNumber() >= 0)
		{
			success = 1;
			GiveInventory("Money",money);
			ACS_ExecuteAlways(551,0,XP,0,0);
		}
		
		attempts++;
		
		delay(1);
	}

}

// Prints firing mode messages on the screen, primarily used for colors
script 80 (int casing)
{
switch (casing)
{

case 0:
Print(s:"\cJFiring mode set to \cKSemi-Automatic\cJ.");
break;

case 1:
Print(s:"\cJFiring mode set to \cKFully-Automatic\cJ.");
break;

case 2:
Print(s:"\cJFiring mode set to \cKSingle-Shot\cJ.");
break;

case 3:
Print(s:"\cJFiring mode set to \cKFour-Shot\cJ.");
break;

case 4:
Print(s:"\cJFiring mode set to \cKTwo-Shot\cJ.");
break;
}
}
// Randomizes the music and ensures that we don't play the same track twice in a row
script 81 (void)
{
	int hPos = 0;
	int randomizer;
	int randomizercap;
	
	str wsong = "";
	str wartist = "";
	
	if (!custommusic)
		randomizercap = availableTracks;
	else
		randomizercap = customsongamount-1;
	
	if (randomizercap > 0)
	{
		randomizer = random(0, randomizercap);
	}
	else
	{
		randomizer = 0;
	}
	
	prevrandom=randomizer;
	
	if (!custommusic)
	{
		wsong = trackSong[randomizer];
		wartist = trackArtist[randomizer];
		SetMusic(trackFile[randomizer],0);
	}
	else
	{
		wsong = customsongs[randomizer];
		wartist = customartists[randomizer];
		SetMusic(customtracks[randomizer],0);
	}
	
	DisplayTrackInfo(wsong, wartist);
}

// Dynamically changes crosshairs based on selected weapon
// Called in DECORATE
script 82 (int xhair) CLIENTSIDE
{
	int hairtochange = StrParam(s:"crosshair ", d:xhair);
	ConsoleCommand(hairtochange);
}


//script and function for teleporting players at trader [OL]
script 20 (int spot)
{
    if (LineSide() == SIDE_FRONT)
	{
        tradePlayers[PlayerNumber()] = 1;
		mapspot[PlayerNumber()] = 300+PlayerNumber();
	}
    else
        tradePlayers[PlayerNumber()] = 0;
}

function void teleportPlayers(int xxz)
{
	for (int x; x < MAXPLAYERS; ++x)
        if (tradePlayers[x])
		{
			SetActivator(x+p_baseTID);
			TakeInventory("MenuActive",1);

			SetFont("BIGFONT");
			HudMessageUnscaled ((GetCvar("vid_defwidth") / 2)* -1.0, -70.0, "\cJYou can't stay in the shop after it closes!", 1, 1, 4);

            Teleport(mapspot[x], 0, 0);
		}
}

function void HudMessageUnscaled (int xoffset, int yoffset, str text, int alignx, int aligny, int id)
{
	int vidres_x = GetCVar("vid_defwidth");
	int vidres_y = GetCVar("vid_defheight");
	int vidres_xFixed = vidres_x * 1.0;
	int vidres_yFixed = vidres_y * 1.0;
	int vidres_xCenter = FixedDiv(vidres_xFixed, 2.0);
	int vidres_yCenter = FixedDiv(vidres_yFixed, 2.0);
	int alignvar_x;
	int alignvar_y;

	int finaloffset_x;
	int finaloffset_y;

	if (yoffset < 0) { finaloffset_y = vidres_yFixed + yoffset; }
	else { finaloffset_y = yoffset; }

	if (xoffset < 0) { finaloffset_x = vidres_xFixed + xoffset; }
	else { finaloffset_x = xoffset; }

	switch (alignx)
	{
		case 0:
		alignvar_x = ALIGN_LEFT;
		break;

		case 1:
		alignvar_x = ALIGN_CENTER;
		break;

		case 2:
		alignvar_x = ALIGN_RIGHT;
		break;
	}

	switch (aligny)
	{
		case 0:
		alignvar_y = ALIGN_LEFT;
		break;

		case 1:
		alignvar_y = ALIGN_CENTER_Y;
		break;

		case 2:
		alignvar_y = ALIGN_RIGHT;
		break;
	}

	SetHUDSize(vidres_x, vidres_y, false);
	HudMessage(s:text; HUDMSG_PLAIN | HUDMSG_FADEOUT, 725+id, CR_WHITE, finaloffset_x + alignvar_x, finaloffset_y + alignvar_y, 2.0);
}



script 801 (void)
{
	delay(500);
	int x = GetZombieCount();
	//if (zombiepool>0 && x <= 0 && zombieskilled>=zombiepool){zombiepool = 0;}
	if (zombiepool < 0)
		zombiepool = 0;

	if (x<=0 && zombiepool > 0)
		zombiepool = 0;

	//if (GetCVar ("cv_zombiedebugger") == 1){PrintBold(s:"Pool: ",d:zombiepool,s:"\nZombies: ",d:x);}
}

script 805 (int casing1)
{
	switch (casing1)
	{

		case 0:
		GiveInventory("HealingWeapon",1);
		SetWeapon("HealingWeapon");
		break;

		case 1:
		TakeInventory("HealingWeapon",1);
		break;

	}
}

// Set the Dethroner's health based on player number.
script 204 (void)
{
SetActorProperty(0, APROP_HEALTH, 10000+5000*PlayerCount());
}

// Gets the number of zombies in the wave
function int GetZombieCount (void)
{
	int x;

	for (int l=0; l < ZOMBIE_CLASSCOUNT; l ++)
	{
		x = x + ThingCountName(ZombieClassNames[l], 0);
	}

	return x;
}

function void StartNextWave (void)
{
	int tip;
	
	if (GameType () != GAME_TITLE_MAP && !map_sandbox && ThingCountName("StopWaveProgress",0) <= 0)
	{

		if (!game_hasbegan)
		{
			tip = random(0,TIP_COUNT-1);
			SetFont("SMALLFONT");
			HudMessageBold(s:"\cKRemember:\n\cJ",s:tiptext[tip]; HUDMSG_TYPEON, 100, CR_WHITE, 1.5, 0.48, 5.0, 0.05, 1.0);
			SetMusic("",0,0);
			game_hasbegan=1;
			wavestarting=1;
			ACS_Execute(56,0,0,0,0); // Start the timer code.
			AnnouncerSound("preparetofight",0);
			ACS_ExecuteAlways(997,0,0,0,0);
			SetMusic("");
			
			if (currentwave<10)
				AmbientSound("wave/midwave",127);
		}

		ACS_Execute(55,0,0,0,0);

	}

	if (map_sandbox || ThingCountName("StopWaveProgress",0) <= 0)
	{
		HudMessageBold(s:""; HUDMSG_PLAIN, 1, CR_WHITE, 0.01, 0.85, 1.0); // Remove the "Wave starting" display
	}
}

// Returns integer value
function int round(int fixedNumber)
{
	return (fixedNumber + 0.5) >> 16;
}

function void ClearWaveStarting (void)
{
	HudMessageBold(s:""; HUDMSG_PLAIN, 1, CR_WHITE, 0.01, 0.85, 1.0); // Remove the "Wave starting" display
	HudMessageBold(s:""; HUDMSG_PLAIN, 2, CR_WHITE, 0.01, 0.85, 1.0); // Remove the "Wave starting" display
	HudMessageBold(s:""; HUDMSG_PLAIN, 3, CR_WHITE, 0.01, 0.85, 1.0); // Remove the "Wave starting" display
	HudMessageBold(s:""; HUDMSG_PLAIN, ID_WAVESTART, CR_WHITE, 0.01, 0.85, 1.0); // Remove the "Wave starting" display
}