//===================================================================
// ZOMBIE TORRENT 2 - PERK SYSTEM
// Coded by Zedek the Plague Doctor
//
// Use if you want, I don't really give a shit
//===================================================================

#library "perksystem"
#include "zcommon.acs"

//=================
#define BACKGROUND_ID						50
#define PERK_BASE_ID						40
#define PERK_ICON_ID						39
#define PERK_NAME_ID						38
#define PERK_INFO_ID						37
#define PERK_BONUSES_ID						36

#define PERK_GLOBALNOTIFY_ID				55

#define PERK_COUNT							5

#define DATA_NAME							0
#define DATA_INFO							1
#define DATA_ICON							2
#define DATA_ITEM							3
// Allows for each perk having its own level
#define DATA_LEVEL							4
#define DATA_XP								5
#define DATA_XPGOAL							6
#define DATA_GRENADE						7
#define DATA_REDUCTION						8

#define ALIGN_LEFT							0.1

#define PERKMENU_TIME						0.1
#define PERKMENU_FADETIME					0.5

str ZT2Perks[PERK_COUNT][10] = {
	{"Juggernaut", "Gets in close and gets the job done.", "PERKSUPP", "Perk_Juggernaut", "PerkLevel_Juggernaut", "PerkXP_Juggernaut", "PerkXPGoal_Juggernaut", "Type-97 Grenade", "PowerReduction_Juggernaut"},
	{"Commando", "Make assault rifles your bitch.", "PERKCOMM", "Perk_Commando", "PerkLevel_Commando", "PerkXP_Commando", "PerkXPGoal_Commando", "Type-97 Grenade", ""},
	{"Demolitionist", "Explosions are fun. Make more.", "PERKDEMO", "Perk_Demo", "PerkLevel_Demo", "PerkXP_Demo", "PerkXPGoal_Demo", "Dynamite", "PowerReduction_Demo"},
	{"Rifleman", "Stealth and distance are key, best for the job.", "PERKSHAR", "Perk_Rifleman", "PerkLevel_Rifleman", "PerkXP_Rifleman", "PerkXPGoal_Rifleman", "Type-97 Grenade", ""},
	{"Pyromaniac", "Start your disco inferno today! Burn it.", "PERKFIRE", "Perk_Pyro", "PerkLevel_Pyro", "PerkXp_Pyro", "PerkXPGoal_Pyro", "Flamenade", "PowerReduction_Pyro"},
};

// PERK BONUSES LISTED IN A SEPARATE ARRAY FOR EASIER ORGANIZATION
str ZT2PerkInfo[PERK_COUNT] = {
	// Juggernaut
	"- Ammo bonus on all shotgun weapons\n- +1 extra grenade per level\n- +5 armor bonus per level\n- 25% resistance to all normal damage\n- $100 discount on shotgun weapons every level\n\n\cKLevel 10:\n\n\cJ- Additional ammo bonus",
	// Commando
	"- Ammo bonus on all fast-firing bullet weapons\n- +1 extra grenade per level\n- $100 discount on assault weapons every level\n\n\cKLevel 10:\n\n\cJ- Additional ammo bonus",
	// Demo
	"- Ammo bonus on all explosive weapons\n- +1 extra grenade per level\n- 25% chance of not using grenade ammo\n- 80% resistance to explosive damage\n- $100 discount on explosive weapons every level\n\n\cKLevel 10:\n\n\cJ- Additional ammo bonus\n- 50% chance of not using grenade ammo",
	// Rifleman
	"- Ammo bonus on all rifle/sniper weapons\n- +1 extra grenade per level\n- $100 discount on rifle / sniper weapons every level\n\n\cKLevel 10:\n\n\cJ- Additional ammo bonus",
	// Pyro
	"- Ammo bonus on all incendiary weapons\n- +1 extra grenade per level\n- 80% resistance to fire damage\n- $100 discount on incendiary weapons every level\n\n\cKLevel 10:\n\n\cJ- Additional ammo bonus",
};

//========================================================
// FORCED INVENTORY REMOVALS
// Scrapped feature fuck this
//========================================================

#define NADE_BASE_COUNT 5				// Base number of grenade ammo, should be the same for all classes
#define NADE_BONUS_COUNT 1				// +1 grenade per level

str GrenadeClasses[PERK_COUNT] = {
	"Type97Primary",			// Juggernaut
	"Type97Primary",			// Commando
	"DynamitePrimary",			// Demo
	"Type97Primary",			// Rifleman
	"FlamenadePrimary",			// Pyro
};

//========================================================
// SPECIFIC LEVEL UNLOCKS
//========================================================

#define LEVEL_UNLOCKS						2

str ZT2PerkUnlocks[LEVEL_UNLOCKS][2] = {
	{"Increased mag capacity", "All weapons specific to your perk get an additional\nammo boost on top of the initial addition."},
	{"Max perk level", "Congratulations! Ask for a perk reset or keep playing."},
};

int ZT2PerkUnlockLevels[LEVEL_UNLOCKS] = {
	10,
	25,
};

//=================

function int round(int fixedNumber)
{
	return (fixedNumber + 0.5) >> 16;
}

//=====================================================
// MAIN EXPERIENCE CAP
//=====================================================

script 549 ENTER
{
	TakeInventory("PerkXPGoal",999999);
	delay(1);
	GiveInventory("PerkXPGoal",100);
	
	ACS_ExecuteAlways(550,0,0,0,0);
	
	// Set all base goals to 100
	for (int m=0; m<PERK_COUNT; m++)
	{
		GiveInventory(ZT2Perks[m][DATA_XPGOAL],100);
	}
	
	SetAmmoCapacity("PerkXP",100);
	//Print(s:"New perk goal applied.");
}

//=====================================================
// SCRIPT FOR LOADING DATA
//=====================================================

script 550 (void) NET
{
	int perkNumber;
	
	for (int j=0; j<PERK_COUNT; j++)
	{
		 if (CheckInventory(ZT2Perks[j][DATA_ITEM]))
			perkNumber = j;
	}
	
	if (!PlayerIsLoggedIn(PlayerNumber()))
	{
		SetFont("TYPEWRIT");
        HudMessage(s:"\cGYou must login to load your perk data."; 1, 390, CR_WHITE, 0.5, 0.85, 2.0,0.25);
	}
	
	else
	{
	
	ResetLoadData();
	
	str accountName = GetPlayerAccountName(PlayerNumber());
	str namespace = strparam(s:accountName, s:"_perkdata");

	SetFont("TYPEWRIT");
    HudMessage(s:"\cILoading your perk data..."; 1, 390, CR_WHITE, 0.5, 0.85, 2.0,0.25);
	
	//==================================================================
	// START LOADING INFO FROM THE DATABASE
	//==================================================================
	
	int xpTotal = 0;
	int xpGoal = 0;
	int xpLevel = 0;
	
	for (int k=0; k<PERK_COUNT; k++)
	{
	
	if (k != perkNumber)
	{
	xpTotal = GetDBEntry(namespace, ZT2Perks[k][DATA_XP]);
	xpGoal = GetDBEntry(namespace, ZT2Perks[k][DATA_XPGOAL]);
	xpLevel = GetDBEntry(namespace, ZT2Perks[k][DATA_LEVEL]);
		
	GiveInventory(ZT2Perks[k][DATA_XP], xpTotal);
	Print(s:"Loaded ",s:ZT2Perks[k][DATA_XP],s:": ",d:xpTotal);
	GiveInventory(ZT2Perks[k][DATA_XPGOAL], xpGoal);
	Print(s:"Loaded ",s:ZT2Perks[k][DATA_XPGOAL],s:": ",d:xpGoal);
	GiveInventory(ZT2Perks[k][DATA_LEVEL], xpLevel);
	Print(s:"Loaded ",s:ZT2Perks[k][DATA_LEVEL],s:": ",d:xpLevel);
	
	Print(s:"XP: ",d:xpTotal,s:"\nXP Goal: ",d:xpGoal,s:"\nPerk Level: ",d:xpLevel,s:"\n\n\cDCongrats!");
	}
	
	}
	
	xpTotal = GetDBEntry(namespace, ZT2Perks[perkNumber][DATA_XP]);
	xpGoal = GetDBEntry(namespace, ZT2Perks[perkNumber][DATA_XPGOAL]);
	xpLevel = GetDBEntry(namespace, ZT2Perks[perkNumber][DATA_LEVEL]);
	
	//==================================================================
	// APPLY THE INFO WE LOADED
	//==================================================================
	
	SetAmmoCapacity("PerkXP",CheckInventory(ZT2Perks[perkNumber][DATA_XPGOAL]));
	
	GiveInventory("PerkXP",xpTotal);
	Print(s:"Loaded current XP:",d:CheckInventory(ZT2Perks[perkNumber][DATA_XP]));
	GiveInventory("PerkXPGoal",xpGoal);
	Print(s:"Loaded current XPGoal:",d:CheckInventory(ZT2Perks[perkNumber][DATA_XPGOAL]));
	GiveInventory("PerkLevel",xpLevel);
	Print(s:"Loaded current level:",d:CheckInventory(ZT2Perks[perkNumber][DATA_LEVEL]));
	
	SetFont("TYPEWRIT");
    HudMessage(s:"\cDPerk data in sync."; 1, 390, CR_WHITE, 0.5, 0.85, 2.0,0.25);
	}
}

//=====================================================
// SCRIPT FOR GIVING THE PLAYER XP
//=====================================================

script 551 (int XP)
{
	int newperkgoal;
	int hasUnlock;
	int unlockNumber;
	int debug = GetCVar("cl_zombiedebugger");
	
	if (XP<=0)
	{
		if (debug)
			Print(s:"Tried to give 0 or less XP.");

		terminate;
	}
	
	if (PlayerNumber() < 0)
		terminate;
	
	//if (PlayerNumber() < 0)
	//{
		//if (debug)
			//Print(s:"Tried giving XP to a non-player.");
			
		//terminate;
	//}
	
	// Add to our perk info
	GiveInventory("PerkXP",XP);
	//Print(s:"You have been given ",d:XP,s:" XP.");
	
	// Level up
	if (CheckInventory("PerkXP") >= CheckInventory("PerkXPGoal") && CheckInventory("PerkLevel") < 25)
	{
		
		LocalAmbientSound("perks/levelup",128);
		GiveInventory("PerkLevel",1);
		
		TakeInventory("PerkXP",999999999);
		
		newperkgoal = round(CheckInventory("PerkXPGoal") * 1.5);
		
		TakeInventory("PerkXPGoal",999999999);
		
		GiveInventory("PerkXPGoal",newperkgoal);
		
		//Print(s:"New goal: ",d:newperkgoal);
		SetAmmoCapacity("PerkXP",newperkgoal);
		
		SetFont("TYPEWRIT");
        HudMessage(s:"\cKLEVEL UP: \cDYou are now level ",d:CheckInventory("PerkLevel"),s:"."; 1, 390, CR_WHITE, 0.5, 0.85, 2.0,0.25);
		
		int perkDisplay = "NULL";
		
		for (int q=0;q<PERK_COUNT;q++)
		{
			if (CheckInventory(ZT2Perks[q][DATA_ITEM]))
				perkDisplay = ZT2Perks[q][DATA_NAME];
		}
		
		SetFont("BIGFONT");
		HudMessageBold(n:0,s:" \cJis now a \cDLevel ",d:CheckInventory("PerkLevel"),s:" ",s:perkDisplay,s:"\cJ!"; 1, PERK_GLOBALNOTIFY_ID, CR_WHITE, 0.5, 0.7, 2.0,0.25);
		
		delay(35*4);
		// CHECK TO SEE IF WE HAVE ACHIEVED A PERK BONUS
		for (int p=0;p<LEVEL_UNLOCKS;p++)
		{
			if (CheckInventory("PerkLevel") == ZT2PerkUnlockLevels[p])
			{
				hasUnlock = 1;
				unlockNumber = p;
			}
		}
		
		if (hasUnlock)
		{
			LocalAmbientSound("perk/selectperk",128);
			FadeTo(1.0,1.0,1.0,0.5,0.05);
			Delay(5);
			FadeTo(0.0,0.0,0.0,0.0,0.2);
			SetFont("TYPEWRIT");
			HudMessage(s:"\cKPERK BONUS: \cD",s:ZT2PerkUnlocks[unlockNumber][0]; HUDMSG_TYPEON, 390, CR_WHITE, 1.5, 0.85, 4.0, 0.02, 1.0);
			delay(35);
			SetFont("BIGFONT");
			HudMessage(s:ZT2PerkUnlocks[unlockNumber][1]; HUDMSG_TYPEON, 389, CR_WHITE, 1.5, 0.89, 2.0, 0.02, 1.0);
		}
	}
}

//=====================================================
// SCRIPT FOR SAVING DATA
//=====================================================

script 552 (void) NET
{
	int perkNumber;
	
	for (int j=0; j<PERK_COUNT; j++)
	{
		 if (CheckInventory(ZT2Perks[j][DATA_ITEM]))
			perkNumber = j;
	}
	
	if (!PlayerIsLoggedIn(PlayerNumber()))
	{
		SetFont("TYPEWRIT");
        HudMessage(s:"\cGYou must login to save your perk data."; 1, 390, CR_WHITE, 0.5, 0.85, 2.0,0.25);
	}
	
	else
	{
	
	str accountName = GetPlayerAccountName(PlayerNumber());
	str namespace = strparam(s:accountName, s:"_perkdata");

	SetFont("TYPEWRIT");
    HudMessage(s:"\cISaving your perk data..."; 1, 390, CR_WHITE, 0.5, 0.85, 2.0,0.25);
	
	//==================================================================
	// START PUTTING INFO INTO THE DATABASE
	//==================================================================
	
	int xpTotal = 0;
	int xpGoal = 0;
	int xpLevel = 0;
	
	BeginDBTransaction();
	
	for (int k=0; k<PERK_COUNT; k++)
	{
	
	if (k != perkNumber)
	{
	xpTotal = CheckInventory(ZT2Perks[k][DATA_XP]);
	xpGoal = CheckInventory(ZT2Perks[k][DATA_XPGOAL]);
	xpLevel = CheckInventory(ZT2Perks[k][DATA_LEVEL]);
	
	SetDBEntry(namespace, ZT2Perks[k][DATA_XP], xpTotal);
	Print(s:"Saved ",s:ZT2Perks[k][DATA_XP],s:": ",d:xpTotal);
	SetDBEntry(namespace, ZT2Perks[k][DATA_XPGOAL], xpGoal);
	Print(s:"Saved ",s:ZT2Perks[k][DATA_XPGOAL],s:": ",d:xpGoal);
	SetDBEntry(namespace, ZT2Perks[k][DATA_LEVEL], xpLevel);
	Print(s:"Saved ",s:ZT2Perks[k][DATA_LEVEL],s:": ",d:xpLevel);

	Print(s:"XP: ",d:xpTotal,s:"\nXP Goal: ",d:xpGoal,s:"\nPerk Level: ",d:xpLevel,s:"\n\n\cDCongrats!");
	}
	
	}
	
	// Save current perk
	
	SetDBEntry(namespace, ZT2Perks[perkNumber][DATA_XP], CheckInventory("PerkXP"));
	Print(s:"Saved ",s:ZT2Perks[perkNumber][DATA_XP],s:": ",d:CheckInventory("PerkXP"));
	SetDBEntry(namespace, ZT2Perks[perkNumber][DATA_XPGOAL], CheckInventory("PerkXPGoal"));
	Print(s:"Saved ",s:ZT2Perks[perkNumber][DATA_XPGOAL],s:": ",d:CheckInventory("PerkXPGoal"));
	SetDBEntry(namespace, ZT2Perks[perkNumber][DATA_LEVEL], CheckInventory("PerkLevel"));
	Print(s:"Saved ",s:ZT2Perks[perkNumber][DATA_LEVEL],s:": ",d:CheckInventory("PerkLevel"));

	EndDBTransaction();
	
	//==================================================================
	// APPLY THE INFO WE LOADED
	//==================================================================
	
	SetFont("TYPEWRIT");
    HudMessage(s:"\cDData saved."; 1, 390, CR_WHITE, 0.5, 0.85, 2.0,0.25);
	}
}

//=====================================================
//
// PERK MENU
//
//=====================================================

script 553 (void)
{
	int buttons;						// Player input
	int buttonUnpressed = false;		// Not pressing a button
	
	int cursorPos = 0;
	
	// Only let players open the menu
	if (PlayerNumber() < 0) {
		terminate;
	}
	
	//Don't allow this button to be pressed if you're spectating
	int playerTID = ActivatorTID();
	if (PlayerIsSpectator(PlayerNumber()) > 0)
		terminate;
	
	//If player is dead
	if ( CheckInventory("Health")<=0 )
		terminate;
	
	if (CheckInventory("MenuActive"))
		terminate;
	
	//Prevent each spacebar press from re-showing the menu
	if (CheckInventory("ShowPerkMenu") > 0) {	
		terminate;
	}
	
	SetWeapon("MenuWeapon");
	
	GiveInventory("ShowPerkMenu",1);
	SetHUDSize(1024,768,0);
	Delay(5);
	
	// While we have the item
	while (CheckInventory("ShowPerkMenu") > 0)
	{
		str perkIcon = "";
		str perkName = "";
		str perkDescription = "";
		
		SetPlayerProperty(0, 1, PROP_TOTALLYFROZEN); //Freeze the player
		buttons = GetPlayerInput(-1, INPUT_BUTTONS);
		
		SetFont("KFMENU");
		HudMessage(s:"a";HUDMSG_FADEOUT,BACKGROUND_ID,CR_WHITE,512.5,384.5,PERKMENU_TIME,PERKMENU_FADETIME);
		
		//=====================================================================
		// DRAW PERK NAMES
		//=====================================================================
		
		SetFont("SMALLFONT");
		for (int i=0;i<PERK_COUNT;i++)
		{
			if (i == cursorPos)
				HudMessage(s:"\cK> \cJ",d:CheckInventory(ZT2Perks[i][DATA_LEVEL]),s:": \cD",s:ZT2Perks[i][DATA_NAME];HUDMSG_FADEOUT,PERK_BASE_ID+i,CR_WHITE,300.0+ALIGN_LEFT,300.0+(12.0*i),PERKMENU_TIME,PERKMENU_FADETIME);
			else
				HudMessage(s:"\cJ",d:CheckInventory(ZT2Perks[i][DATA_LEVEL]),s:": ",s:ZT2Perks[i][DATA_NAME];HUDMSG_FADEOUT,PERK_BASE_ID+i,CR_WHITE,300.0+ALIGN_LEFT,300.0+(12.0*i),PERKMENU_TIME,PERKMENU_FADETIME);
		}
		
		SetFont("BIGFONT");
		HudMessage(s:ZT2Perks[cursorPos][DATA_NAME];HUDMSG_FADEOUT,PERK_NAME_ID,CR_WHITE,440.0+ALIGN_LEFT,410.0,PERKMENU_TIME,PERKMENU_FADETIME);
		SetFont("SMALLFONT");
		HudMessage(s:ZT2Perks[cursorPos][DATA_INFO],s:"\n\n\cDXP: ",d:CheckInventory(ZT2Perks[cursorPos][DATA_XP]),s:" / ",d:CheckInventory(ZT2Perks[cursorPos][DATA_XPGOAL]),s:"\n\cKLevel: ",d:CheckInventory(ZT2Perks[cursorPos][DATA_LEVEL]);HUDMSG_FADEOUT,PERK_INFO_ID,CR_WHITE,440.0+ALIGN_LEFT,440.0+0.1,PERKMENU_TIME,PERKMENU_FADETIME);
		SetFont(ZT2Perks[cursorPos][DATA_ICON]);
		HudMessage(s:"a";HUDMSG_FADEOUT,PERK_ICON_ID,CR_WHITE,730.0,420.0,PERKMENU_TIME,PERKMENU_FADETIME);
		SetFont("SMALLFONT");
		HudMessage(s:ZT2PerkInfo[cursorPos];HUDMSG_FADEOUT,PERK_BONUSES_ID,CR_WHITE,295.0+ALIGN_LEFT,535.1,PERKMENU_TIME,PERKMENU_FADETIME);
		
		//=====================================================================
		// CONTROL INPUT
		//=====================================================================
		
		if (!buttonUnpressed)
		{
			if (buttons & BT_BACK)
			{
				LocalAmbientSound("menu/cursor",128);
				buttonUnpressed = true;
				// LOOP BACK IF POSSIBLE
				if (cursorPos+1 > PERK_COUNT-1)
					cursorPos=0;
				else
					cursorPos++;
			}
			else if (buttons & BT_FORWARD)
			{
				LocalAmbientSound("menu/cursor",128);
				buttonUnpressed = true;
				// LOOP BACK IF POSSIBLE
				if (cursorPos-1 < 0)
					cursorPos=PERK_COUNT-1;
				else
					cursorPos--;
			}
			else if (buttons & BT_USE)
			{
				buttonUnpressed = true;
				SelectPerk(cursorPos);
			}
		}
		if (buttons == 0)
		{
			buttonUnpressed = false;
		}
		
		delay(1);
	}
}

// Force perk select
script 554 ENTER
{
	ACS_ExecuteAlways(553,0,0,0,0);		// Force perk select
	ACS_ExecuteAlways(555,0,0,0,0);		// Start perk bonus script
	ACS_ExecuteAlways(565,0,0,0,0);		// Low health script
}

//========================================================
// PERK BONUSES
// Always running
//
// Also controls showing the perk of other players
//========================================================

#define PERKINFO_ID				300

// player view height
#define PLAYER_VIEWHEIGHT 41

function bool CheckPlayerCrouching(void)
{
	bool val = false;
	
    if(GetActorViewHeight(ActivatorTID()) < PLAYER_VIEWHEIGHT << 16)
        val = true;
    else
        val = false;
    
    return val;
}

script 555 (void)
{
	int cPerk = -1;
	int amCap;
	int actID;
	int actNum;
	
	int displayPerk = "";
	int displayLevel = 0;
	int displayName = "";
	
	int showMessage = 0;
	
	actID = ActivatorTID();
	actNum = PlayerNumber();
	
	//=============================================
	// JUGGERNAUT
	//=============================================
	if (CheckInventory("Perk_Juggernaut") > 0)
	{
		int baseArmor = 5;
		
		baseArmor = 5+(5*CheckInventory("PerkLevel"));
		
		// ALWAYS HAVE CONSTANT ARMOR
		if (CheckInventory("BasicArmor") < baseArmor)
		{
			GiveInventory("ArmorBonus",baseArmor-CheckInventory("BasicArmor"));
		}
	}
	
	//=============================================
	// PYROMANIAC
	//=============================================
	
	if (CheckInventory("Perk_Pyro") > 0)
	{
		int flameCap = GetAmmoCapacity("FlamePrimary");
		int newCap = 300;
		
		if (CheckInventory("PerkLevel") >= 10)
			newCap = 400;
		
		if (flameCap < newCap)
			SetAmmoCapacity("FlamePrimary",300);
	}
	else
		SetAmmoCapacity("FlamePrimary",200);
	
	//=============================================
	//
	// SET GRENADE CAPS FOR ALL CLASSES
	//
	//=============================================
	
	// See what perk we're using first
	for (int m=0; m<PERK_COUNT; m++)
	{
		if (CheckInventory(ZT2Perks[m][DATA_ITEM]) > 0)
			cPerk = m;
	}
	
	// Apply a grenade bonus
	if (cPerk > -1)
	{
			amCap = GetAmmoCapacity(GrenadeClasses[cPerk]);
			if (amCap < NADE_BASE_COUNT+(NADE_BONUS_COUNT*CheckInventory("PerkLevel")))
			{
				SetAmmoCapacity(GrenadeClasses[cPerk],NADE_BASE_COUNT+(NADE_BONUS_COUNT*CheckInventory("PerkLevel")));
			}
	}
	
	//=============================================
	//
	// SHOW PLAYER INFO IF YOU'RE LOOKING AT SOMEONE
	//
	//=============================================
	SetActivatorToTarget(0);
	if (PlayerNumber() >= 0 && PlayerNumber() != actNum)
	{
		// Find perk name
		for (int mm=0; mm<PERK_COUNT; mm++)
		{
			if (CheckInventory(ZT2Perks[mm][DATA_ITEM]) > 0)
			{
				showMessage = 1;
				displayPerk = ZT2Perks[mm][DATA_NAME];
			}
		}
		
		displayLevel = CheckInventory("PerkLevel");
		displayName = StrParam(n:0);
	}
	SetActivator(actID);
	
	if (showMessage)
	{
	SetFont("TYPEWRIT");
    HudMessage(s:displayName; 1, PERKINFO_ID, CR_WHITE, 0.5, 0.75, 2.0,0.25);
	SetFont("BIGFONT");
	HudMessage(s:"Level ",d:displayLevel,s:" ",s:displayPerk; 1, PERKINFO_ID+1, CR_WHITE, 0.5, 0.77, 2.0,0.25);
	}
	
	ControlAmmoJunk(0);
	
	// CHECK CROUCHING
	TakeInventory("IsCrouched",1);
	
	if (CheckPlayerCrouching())
		GiveInventory("IsCrouched",1);
	
	delay(5);
	restart;
}

function void SelectPerk(int pos)
{
	ResetPerks(pos);
	
	SetWeapon("Order Pistol");
	
	SetPlayerProperty(0, 0, PROP_TOTALLYFROZEN); //Freeze the player
	SetHudSize(0, 0, FALSE);
	TakeInventory("ShowPerkMenu",1);
	LocalAmbientSound("perk/selectperk",128);
	SetFont("TYPEWRIT");
    HudMessage(s:"\cDYou are now a \cK",s:ZT2Perks[pos][DATA_NAME],s:"\cD!"; 1, 390, CR_WHITE, 0.5, 0.85, 4.0,0.25);
	GiveInventory(ZT2Perks[pos][DATA_ITEM],1);
	
	if (ZT2Perks[pos][DATA_REDUCTION] != "")
	GiveInventory(ZT2Perks[pos][DATA_REDUCTION],1);
	
	SetAmmoCapacity("PerkXP",CheckInventory(ZT2Perks[pos][DATA_XPGOAL]));
	
	GiveInventory("PerkLevel",CheckInventory(ZT2Perks[pos][DATA_LEVEL]));
	GiveInventory("PerkXP",CheckInventory(ZT2Perks[pos][DATA_XP]));
	GiveInventory("PerkXPGoal",CheckInventory(ZT2Perks[pos][DATA_XPGOAL]));
	
	ACS_ExecuteAlways(558, 0, 1, pos, 0);
}

function void ResetLoadData(void)
{
	TakeInventory("PerkLevel",9999999);
	TakeInventory("PerkXP",9999999);
	TakeInventory("PerkXPGoal",9999999);
}

function void ResetPerks(int Z)
{
	int perkNumber;
	
	// Find what perk we are
	for (int j=0; j<PERK_COUNT; j++)
	{
		 if (CheckInventory(ZT2Perks[j][DATA_ITEM]))
			perkNumber = j;
	}
	
	// Take all grenades and reduction
	for (int k=0; k<PERK_COUNT; k++)
	{
		TakeInventory(ZT2Perks[k][DATA_GRENADE],999999);
		TakeInventory(ZT2Perks[k][DATA_REDUCTION],999999);
	}
	
	if (Z != perkNumber)
	{
	
	TakeInventory(ZT2Perks[perkNumber][DATA_XP],9999999);
	TakeInventory(ZT2Perks[perkNumber][DATA_XPGOAL],9999999);
	TakeInventory(ZT2Perks[perkNumber][DATA_LEVEL],9999999);
	
	GiveInventory(ZT2Perks[perkNumber][DATA_XP],CheckInventory("PerkXP"));
	GiveInventory(ZT2Perks[perkNumber][DATA_XPGOAL],CheckInventory("PerkXPGoal"));
	GiveInventory(ZT2Perks[perkNumber][DATA_LEVEL],CheckInventory("PerkLevel"));
	
	}
	
	TakeInventory("Perk_Rifleman",1);
	TakeInventory("Perk_Demo",1);
	TakeInventory("Perk_Juggernaut",1);
	TakeInventory("Perk_Commando",1);
	
	TakeInventory("PerkLevel",99999);
	TakeInventory("PerkXP",99999);
	TakeInventory("PerkXPGoal",99999);
}

//==============================================================
// CALLED BY C4
//==============================================================

script 556 (int mode)
{
	int bombTID = 0;
	
	// If we're throwing a C4
	if (mode==0)
	{
		Thing_ChangeTID(0, 1337);
		delay(1);
		SetActivatorToTarget(0);
		bombTID = ActivatorTID() + 100;
		delay(1);
		Thing_ChangeTID(1337,bombTID);
	}
	
	// If we're blowing up C4
	if (mode==1)
	{
		bombTID = ActivatorTID() + 100;
		SetActorState(bombTID,"Detonate");
	}
}

//==============================================================
// CALLED BY TNT
//==============================================================

script 557 (int mode)
{
	int TNTtimer = 0;
	
	// Figure out how much time we have left
	
	if (mode==0)
	{
	Thing_ChangeTID(0, 1338);
	delay(1);
	SetActivatorToTarget(0);
	TNTtimer = CheckInventory("FuseTimer") - 12;
	delay(1);
	GiveActorInventory(1338,"TNTTimer",TNTtimer);
	//PrintBold(s:"TNT timer given: ",d:TNTtimer);
	Thing_ChangeTID(1338,0);
	}
	
	// Count down a timer
	
	if (mode==1)
	{
	GiveInventory("TNTTimer",1);
	if (CheckInventory("TNTTimer") >= 15)
		SetActorState(0,"Boom");
	}
}

//==============================================================
// SCRIPT 558
//
// Controls grenade functions, called by pretty much
// anything and everything that uses grenades
//
// Making new perks requires an edit of the array that
// controls this script

//--------------------------
// SCRIPT MODES:
//
// 0: Switch to grenade
// 1: Give appropriate grenade
//--------------------------
//==============================================================

script 558 (int nadeMode, int perk, int autoPerk)
{
	int finalPerk = -1;
	
	// If we have auto-perk turned on then find our current perk
	// Called from weapons
	
	if (autoPerk == 1)
	{
		for (int l=0;l<PERK_COUNT;l++)
		{
			if (CheckInventory(ZT2Perks[l][DATA_ITEM]) > 0)
				finalPerk = l;
		}
	}
	
	else
	{
		finalPerk = perk;
	}
	
	// SWITCH TO GRENADE
	if (nadeMode == 0 && finalPerk > -1)
	{
		GiveInventory("QuickGrenading",1);
		SetWeapon(ZT2Perks[finalPerk][DATA_GRENADE]);
	}
	
	// GIVE GRENADE
	if (nadeMode == 1)
	{
		GiveInventory(ZT2Perks[finalPerk][DATA_GRENADE], 1);
	}
}

//=========================================================================
// MELEE MOVEMENT SCRIPT
// Used for melee weapons
// Controls attack based on which key you're pressing like KF2
//=========================================================================
script 559 (void)
{
	int buttons = GetPlayerInput(-1, INPUT_BUTTONS);
	
	// MOVE LEFT
	if (buttons == BT_MOVELEFT || (buttons & BT_MOVELEFT && buttons & BT_ATTACK))
	{
		SetResultValue(0);
	}
	// MOVE RIGHT
	else if (buttons == BT_MOVERIGHT || (buttons & BT_MOVERIGHT && buttons & BT_ATTACK))
	{
		SetResultValue(1);
	}
	// MOVE UP OR DOWN
	else if ((buttons == BT_FORWARD || buttons == BT_BACK) || ((buttons & BT_FORWARD || buttons & BT_BACK) && buttons & BT_ATTACK))
	{
		SetResultValue(2);
	}
	else
		SetResultValue(3);
}

script 560 (void) // Automatic fire.
{
	while(CheckInventory("SynthFireActive"))
	{
		if((GetPlayerInput(-1, INPUT_BUTTONS) & BT_ATTACK))
		{
			giveinventory("SynthFireLeft",1);
			while(getplayerinput(-1, INPUT_BUTTONS) & BT_ATTACK) { delay(1); }
			takeinventory("SynthFireLeft",1);
		}
		delay(1);
	}
}

script 561 (void)
{
	while(CheckInventory("SynthFireActive"))
	{
		if((GetPlayerInput(-1, INPUT_BUTTONS) & BT_ALTATTACK))
		{
			GiveInventory("SynthFireRight",1);
			while(GetPlayerInput(-1, INPUT_BUTTONS) & BT_ALTATTACK) { delay(1); }
			TakeInventory("SynthFireRight",1);
		}
		delay(1);
	}
}

script 562 (void) // The semi-automatic kind.
{
	while(CheckInventory("SynthFireActive"))
	{
		if((getplayerinput(-1, INPUT_BUTTONS) & BT_ATTACK) && !(getplayerinput(-1, INPUT_OLDBUTTONS) & BT_ATTACK))
		{
			giveinventory("SynthFireLeft",1);
			delay(1);
			takeinventory("SynthFireLeft",1);
		}
		delay(1);
	}
}

script 563 (void)
{
	while(CheckInventory("SynthFireActive"))
	{
		if((getplayerinput(-1, INPUT_BUTTONS) & BT_ALTATTACK) && !(getplayerinput(-1, INPUT_OLDBUTTONS) & BT_ALTATTACK))
		{
			giveinventory("SynthFireRight",1);
			delay(1);
			takeinventory("SynthFireRight",1);
		}
		delay(1);
	}
}

// Called by keyconf
script 564 (void) NET
{
	ACS_ExecuteAlways(553,0,0,0,0);		// Force perk select
}

// LOW HEALTH SCRIPT
script 565 (void)
{	
	if (GetActorProperty(0,APROP_Health) > 0)
	{
		if (GetActorProperty(0,APROP_Health) > 0 && GetActorProperty(0,APROP_Health) <= 10)
		{
		GiveInventory("PowerRedScreen",1);
		LocalAmbientSound("player/heartbeat",127);
		FadeTo(255,0,0,0.25,0.14);
		delay(5);
		FadeTo(0,0,0,0.0,0.14);
		delay(5);
		}
		else if (GetActorProperty(0,APROP_Health) > 10 && GetActorProperty(0,APROP_Health) <= 25)
		{
		TakeInventory("PowerRedScreen",1);
		LocalAmbientSound("player/heartbeat",127);
		FadeTo(255,0,0,0.15,0.3);
		delay(11);
		FadeTo(0,0,0,0.0,0.3);
		delay(11);
		}
		else
		{
		TakeInventory("PowerRedScreen",1);
		}
	}
	else
	{
		TakeInventory("PowerRedScreen",1);
	}
	delay(1);
	restart;
}

// Returns fixed point value
function int floor(int fixedNumber)
{
	return fixedNumber & 0xFFFF0000;
}

//---SPREAD ADJUST SCRIPT-----------------------------
script 566 (int mainSpread)
{
	int isSemiAuto = CheckInventory("SemiAutomatic");
	int isCrouching = CheckInventory("IsCrouched");
	int baseSpread = 0.0;
	int roundSpread = 0;
	
	baseSpread = mainSpread * 1.0;
	
	// Semi automatic gives 50% accuracy bonus
	if (isSemiAuto)
	{
		baseSpread = FixedMul(baseSpread,0.5);
		//Print(s:"New spread: ",f:baseSpread);
	}
		
	// Crouching gives 20% accuracy bonus
	if (isCrouching)
	{
		baseSpread = FixedMul(baseSpread,0.8);
		//Print(s:"New spread: ",f:baseSpread);
	}
		
	//Print(s:"Semi-Automatic: ",d:isSemiAuto,s:"\nCrouched: ",d:isCrouching,s:"\nSpread: ",f:baseSpread,s:"\nSpread Round: ",d:round(baseSpread));
		
	SetResultValue(round(baseSpread));
}

//==================================================================
// AMMO HUD DISPLAY
// Used because SBARINFO is a fucking cunt and doesn't
// like to accept items with spaces in it
//==================================================================

function int ControlAmmoJunk(int unused)
{
	//================================================================
	// M79: INCENDIARY AMMO
	//================================================================
	if (CheckInventory("M79 Grenade Launcher Incendiary"))
	{
		if (!CheckInventory("M79IncendiaryHUD"))
			GiveInventory("M79IncendiaryHUD",1);
	}
	else
		TakeInventory("M79IncendiaryHUD",1);
		
	//================================================================
	// M79: SHOTGUN AMMO
	//================================================================
	if (CheckInventory("M79 Grenade Launcher Shotgun"))
	{
		if (!CheckInventory("M79ShotgunHUD"))
			GiveInventory("M79ShotgunHUD",1);
	}
	else
		TakeInventory("M79ShotgunHUD",1);
		
	return true;
}