#Library "Moth Man International"
#include "zcommon.acs"

// ----------------------------------------------------------------------------
//
// Some Russian Overkill scripts by KeksDose.
//
// Welp, the old scripts were broken so I rewrote them with newer ACS functions
// and multiplayer compatibility. The real point is actually the guided
// missiles script. Ahoy Perfect Dark Slayer secondary mode!
//
// Reuse as you wish, just credit me somewhere and leave the file intact.
//
// ----------------------------------------------------------------------------

#LibDefine PLAYER_TID		29167	// I hope those tids are free! :P
#LibDefine GM_TIDSTART		25000	// Where to search for free tids
#LibDefine GM_LOCKEDON		0		// Guided missile states
#LibDefine GM_TURNRIGHT		1
#LibDefine GM_TURNLEFT		-1
#LibDefine GM_DEATHFOV		150		// FOV for Stalin rocket
#LibDefine GM_HUD_WIDTH		1280	// HUD resolution for camera
#LibDefine GM_HUD_HEIGHT	720
#LibDefine GM_HUD_WIDTHRS	512		// HUD resolution for red screen FX
#LibDefine GM_HUD_HEIGHTRS	256
#LibDefine GM_HUD_WIDTHCH	1024	// HUD resolution for crosshair FX
#LibDefine GM_HUD_HEIGHTCH	512
#LibDefine GM_HUD_CAMERA	503		// HUDMessage id numbers or something
#LibDefine GM_HUD_CROSSHAIR	502
#LibDefine GM_HUD_REDSCREEN	501

Function Int GetFreeTid (Int Start)
{
	Int Tid = Start;
	
	While(ThingCount(T_NONE, Tid) > 0)
		Tid++;
	
	Return Tid;
}

// And the scripts!

Script 699 Enter
{
	Thing_ChangeTid(0, PLAYER_TID + PlayerNumber());

	TakeInventory("VortexOut", 1);
	TakeInventory("ChtonBeaconDeployed", 1);
	TakeInventory("MegaShellOut", 1);
	TakeInventory("SanctumDeployed", 1);
	TakeInventory("JelloOut", 1);
}

Script 707 (Void)
{
	SetResultValue(CheckInventory("ZwergClip"));
}

// Is this even used somewhere?

script 959 (int TidToAffect)
{
	while(1)
	{
		SetActorAngle(TidToAffect, GetActorAngle(PLAYER_TID + PlayerNumber()));
		delay(3);
	}
}

Script 709 (Int TurnSpeed)
{
	Int Tid = GetFreeTid(GM_TIDSTART);
	
	Thing_ChangeTid(0, Tid);
	
	Int PAngle = 0.0;
	Int PPitch = 0.0;
	Int Angle = 0.0;
	Int Pitch = 0.0;
	Int Speed = GetActorProperty(Tid, APROP_SPEED);
	Int Direction = GM_LOCKEDON;
	Int VelX = 0.0;
	Int VelY = 0.0;
	Int VelZ = 0.0;
	
	SetActivator(Tid, AAPTR_TARGET); // In this case, the firing actor.
	
	Angle = GetActorAngle(ActivatorTid());
	Pitch = GetActorPitch(ActivatorTid());
	
	While(GetActorProperty(Tid, APROP_HEALTH) > 0)
	{
		PAngle = GetActorAngle(ActivatorTid()); // Pointers are awesome.
		PPitch = GetActorPitch(ActivatorTid());
		
		// If we're not locked on, turn, doggammit!
		
		Angle = (Angle + (Direction * TurnSpeed)) % 1.0;
		
		If(Angle < 0.0)
			Angle += 1.0;
		
		// Do we need to turn?
		
		If((PAngle - Angle < TurnSpeed) && (PAngle - Angle > -TurnSpeed))
		{
			Direction = GM_LOCKEDON;
			Angle = PAngle;
		}
		
		// If so, calculate the turning direction...
		
		Else
		{
			If((Angle - PAngle + 1.0) % 1.0 > 0.5)
				Direction = GM_TURNRIGHT;
			
			Else
				Direction = GM_TURNLEFT;
		}
		
		// Slightly different treatment for the pitch.
		
		If(Pitch > PPitch + TurnSpeed) // Too low
			Pitch -= TurnSpeed;
		
		Else If(Pitch < PPitch - TurnSpeed) // Too high
			Pitch += TurnSpeed;
		
		Else
			Pitch = PPitch;
		
		VelX = FixedMul(FixedMul(Cos(Angle), Speed), Cos(Pitch));
		VelY = FixedMul(FixedMul(Sin(Angle), Speed), Cos(Pitch));
		VelZ = FixedMul(-Sin(Pitch), Speed);
		
		SetActorVelocity(Tid, VelX, VelY, VelZ, FALSE, FALSE);
		SetActorAngle(Tid, Angle);
		SetActorPitch(Tid, Pitch);
		
		Delay(Const:1);
	}
}

// This is some special handling for Death Head's Stalin warhead. You view the
// rocket through the camera and super fancy shit happens which I don't want
// to put in the above script. Modularity, you know? :P

Script 710 (Int Tid) // The rocket's Tid
{
	Int RedAlpha = 0.0;		// Red screen glow
	Int CrossAlpha = 0.0;	// Crosshair glow
	
	SetActivator(Tid, AAPTR_TARGET); // back to the player since it's
									 // activated by the projectile itself.
	
	GiveInventory("CameraTrigger", 1);	// Why no Bool? Because Deathhead as a
										// weapon needs to know, too.
									 
	SetPlayerProperty(ActivatorTid(), ON, PROP_FROZEN);
	
	Str CameraTex = StrParam(s:"GMCAM", d:PlayerNumber()); // Thankfully this exists, or else I'd have a huge string array here...
	
	SetCameraToTexture(Tid, CameraTex, GM_DEATHFOV);
	SetHUDSize(GM_HUD_WIDTH, GM_HUD_HEIGHT, TRUE);
	SetFont(CameraTex);
	HUDMessage(s:"A"; HUDMSG_PLAIN, GM_HUD_CAMERA, CR_UNTRANSLATED, 0.5, 0.5, 0.0);
	
	While(CheckInventory("CameraTrigger"))
	{
		If(GetPlayerInput(-1, INPUT_BUTTONS) & BT_ALTATTACK && // Player CLICKS altfire
		 !(GetPlayerInput(-1, INPUT_OLDBUTTONS) & BT_ALTATTACK))
		{
			SetActorState(Tid, "Death", FALSE);
		}
		
		RedAlpha = Sin(Timer() * 300 % 0.5) / 5 + 0.5;
		CrossAlpha = Sin(Timer() * 600 % 0.5) / 2 + 0.5;
		
		SetHUDSize(GM_HUD_WIDTHRS, GM_HUD_HEIGHTRS, TRUE);
		SetFont("DAKTB");
		HUDMessage(s:"A"; HUDMSG_PLAIN, GM_HUD_REDSCREEN,
						  CR_UNTRANSLATED, 0.5, 0.5, 1.0, RedAlpha);
		
		SetHUDSize(GM_HUD_WIDTHCH, GM_HUD_HEIGHTCH, TRUE);
		SetFont("DAKTC");
		HUDMessage(s:"A"; HUDMSG_PLAIN, GM_HUD_CROSSHAIR, CR_UNTRANSLATED,
						  0.5, 0.5, 1.0, CrossAlpha);
		
		Delay(Const:1);
	}
	
	SetHUDSize(GM_HUD_WIDTH, GM_HUD_HEIGHT, TRUE);
	SetFont(CameraTex);
	HUDMessage(s:"A"; HUDMSG_FADEOUT, GM_HUD_CAMERA, CR_UNTRANSLATED, 0.5, 0.5, 0.0);
	
	SetHUDSize(GM_HUD_WIDTHRS, GM_HUD_HEIGHTRS, TRUE);
	SetFont("DAKTB");
	HUDMessage(s:"A"; HUDMSG_FADEOUT, GM_HUD_REDSCREEN, CR_UNTRANSLATED, 0.5, 0.5, 0.0);
	
	SetHUDSize(GM_HUD_WIDTHCH, GM_HUD_HEIGHTCH, TRUE);
	SetFont("DAKTC");
	HUDMessage(s:"A"; HUDMSG_FADEOUT, GM_HUD_CROSSHAIR, CR_UNTRANSLATED, 0.5, 0.5, 0.0);
									 
	SetPlayerProperty(ActivatorTid(), OFF, PROP_FROZEN);
}

// Old scripts from AEoD:
 
/*#DEFINE ISPEED 15
#DEFINE FSPEED 15.0
#DEFINE TURNSPEED 0.017
int flyin = 0;

// This is the main scrip for the bullet time. It sets the camera and cotrols the movement according
// to "TURNSPEED" defined above.

script 960 (void)
{
	int a, olda;
	int p, oldp, ud, spd, oldspd;
	int ip, ia;
	int x, y, z;
	int origa = getactorangle(21000);
	int origp = getactorPitch(21000);
	GiveActorInventory(21000, "CameraTrigger", 1);
	thing_changetid(0, 22001);
	setcameratotexture(22001, "CAMERT", 150);
	//ChangeCamera(22001, 0, 0);
	a = origa;
	p = origp;
	sethudsize(800, 600, 0);
	setfont("CAMERT");
	hudmessage(s:"A"; 0, 600, -1, 400.0, 300.0, 0);
	spd = 0;
	flyin = 1;
	p = getactorPitch(21000);
	a = getactorangle(21000);
	while(flyin && ThingCount (T_NONE, 22001))
	{
		oldspd = ISPEED-spd;

		ip = -getplayerinput(0, INPUT_PITCH);
		if(ip > TURNSPEED) ip = TURNSPEED;
		if(ip < -TURNSPEED) ip = -TURNSPEED;
		p += ip;

		ud = 0;
		if(p > 0) ud = 1;
		spd = abs(fixedmul(fixedmul(p,4.0),FSPEED)>>16);
		ThrustThingZ(22001, spd*4, ud, 0);
		olda = a;

		ia = getplayerinput(0, INPUT_YAW);
		if(ia > TURNSPEED) ia = TURNSPEED;
		if(ia < -TURNSPEED) ia = -TURNSPEED;
		a += ia;

		ThrustThing((olda>>8)+128, oldspd, 1, 22001);
		ThrustThing(a>>8, ISPEED-spd, 1, 22001);
		SetActorAngle(22001, a);
		SetActorPitch(22001, p);
		delay(1);
	}
	while(ThingCount (T_NONE, 22001))
	{
		delay(1);
	}
	hudmessage(s:" "; 0, 600, -1, 320.0, 200.0, 1);
	TakeActorInventory(21000, "CameraTrigger", 1);
	setActorAngle(21000, origa);
	setActorPitch(21000, origP);
}

//This one is called by the projectile's death, just to record that it was destroyed
script 961 (void)
{
	flyin = 0;
}
	
function int abs (int x)
{
    if (x < 0)
        return -x;

    return x;
}

//this is the red screen effect, will loop until the projectile terminates it manually
Script 962 (void)
{
	int id=500;
	int i=0;
	SetHudSize(320,200,1);
	while(1)
	{
		SetFont("DAKTB");
		HudMessage(s:"a";HUDMSG_FADEINOUT,id,0,0.3,0.5,0.5,0.2,0.2);
		id--;
		i++;
		if(i<4)
			i=0;
		delay(random(10,15));
	}
}

//crosshair
Script 965 (void)
{
	int id=250;
	int i=0;
	SetHudSize(320,200,1);
	while(1)
	{
		SetFont("DAKTC");
		HudMessage(s:"a";HUDMSG_PLAIN,id,0,0.3,0.5,0.5);
		id--;
		i++;
		if(i<4)
			i=0;
		delay(random(10,15));
	}
}

// this one is to give the token of death, basically to trigger the explosion of the bullet
script 963 (void)
{
	GiveActorInventory(22001,"DieToken",1);
}

// this one cancels the weird FOV effect used in 960 without changing the camera, when the 
// projectile explodes
script 964 (void)
{
	setcameratotexture(22001, "CAMERT", 90);
}
*/