// ------------------------------------------
// Lua_TailsGuy
// Tails Guy's main lua, with his
// guns, swimming, and HUD!
// Damage gets its own lua though.
// ------------------------------------------
// Future update?
// Make rocket effect the same as ACZ TNT
// Make it take multiple bullets to deal damage
// More guns
// Guns replace match weapons
// ------------------------------------------
freeslot("MT_DOOMBULLET",
"MT_DOOMROCKET", "MT_DOOMSPLODE", "SPR_DMIS",
"S_DOOMROCKET1", "S_DOOMROCKET2", "S_DOOMSPLODE1", "S_DOOMSPLODE2", "S_DOOMSPLODE3", "S_DOOMSPLODE4",
"MT_ROCKETSPIKECOL", "S_ROCKETSPIKECOL",
"sfx_dgshot", "sfx_dgrokt", "sfx_dgrokb", "sfx_dgchan",
"SPR2_DOOM", "S_PLAY_DOOMSHOT")	// Oh boy, my first SPR2 freeslot! This deserves to be remembered. Defenetly.

local function ResetTGVars(player, health)
	if(player.tgvars == nil)
		player.tgvars = {}
	end
	
	player.tgvars.hurttime = 0
	player.tgvars.facetime = 0
	if(health)
		or(player.tgvars.health == 0)
		player.tgvars.health = 100
	end
	player.tgvars.prevrings = player.rings	// Used for increasing HP with rings
	
	// Weapons!
	player.tgvars.weapon = 0	// 0: Shotgun, 1: Rocket launcher, 2: Chaingun
	player.tgvars.shoottime = 0	// When above 0, play the shoot/reload animation
	player.tgvars.guntime = 0	// Max lenght of reload
	player.tgvars.shootanimtime = 0
	player.tgvars.prevbutt = player.cmd.buttons
	
	// Rocket stuff
	player.tgvars.rockethit = false
	player.tgvars.myrockethit = false
end

addHook("MapLoad", function()
	for player in players.iterate
		ResetTGVars(player, false)
	end
end)

local function TailsGuyCapable(player)
	if(P_PlayerInPain(player))
		or(player.exiting)
		or(player.powers[pw_nocontrol])
		or(player.pflags & (PF_SLIDING|PF_STASIS))
		return false
	end
	return true
end

// Copied and edited from sora.pk3 :eyes:
local function FireBullet(player, spread)
	local spreadangle = FixedAngle((P_RandomByte()*360/256)*FRACUNIT)
	local spreadmul	= FixedMul(P_RandomByte()*FRACUNIT/256, spread)-(spread/2)
	local spreadx = FixedAngle(FixedMul(cos(spreadangle), spreadmul))
	local spready = FixedAngle(FixedMul(sin(spreadangle), spreadmul))
	
	local bullet = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z+(player.mo.height/2), MT_DOOMBULLET)
	bullet.target = player.mo
	bullet.angle = player.mo.angle + spreadx
	local angle2 = player.aiming + spready
	P_InstaThrust(bullet, bullet.angle, FixedMul(mobjinfo[bullet.type].speed, cos(angle2)))
	bullet.momz = FixedMul(mobjinfo[bullet.type].speed, sin(angle2))
	P_TeleportMove(bullet, bullet.x+bullet.momx, bullet.y+bullet.momy, bullet.z+bullet.momz)
	return bullet
end

addHook("MobjThinker", function(mo)
	local player = mo.player
	if(player and player.valid)
		if(player.tgvars == nil)
			ResetTGVars(player, true)
		end
		
		if(mo.health == 0)
			player.tgvars.health = 100	// Reset health when dying
		end
		
		if not(mo.skin == "tailsguy")
			or not(mo.health)
			player.tgvars.prevrings = player.rings
			player.tgvars.prevbutt = player.cmd.buttons
			return
		end
		
		// Tails Guy can't use shields!
		player.pflags = $1|PF_THOKKED
		
		// This is here so he doesn't flash yellow in special stages
		if(player.powers[pw_carry] == CR_NIGHTSMODE)
			player.charflags = $1 & !SF_SUPER
			return
		else
			player.charflags = $1|SF_SUPER
		end
		
		// Face on HUD
		player.tgvars.facetime = $1 + 1
		if(player.tgvars.facetime > 95)
			player.tgvars.facetime = 0
		end
		if(player.tgvars.hurttime)
			player.tgvars.hurttime = $1 - 1
		end
		
		// HP stuff
		if(player.rings - player.tgvars.prevrings == 1)
			player.tgvars.health = $1 + 1
			if(player.tgvars.health > 150)
				player.tgvars.health = 150
			end
		elseif(player.tgvars.health < 100)
			and(player.rings > player.tgvars.prevrings)
			player.tgvars.health = $1 + player.rings - player.tgvars.prevrings
			if(player.tgvars.health > 100)
				player.tgvars.health = 100
			end
		end
		player.tgvars.prevrings = player.rings
		
		// Swimming!
		if(mo.eflags & MFE_UNDERWATER)
			if(player.cmd.buttons & BT_JUMP)
				and not(player.powers[pw_nocontrol])
				and not(P_PlayerInPain(player))
				and not(P_IsObjectOnGround(mo))
				and(mo.momz <= 6*mo.scale*P_MobjFlip(mo))
				if(mo.state >= S_PLAY_STND and mo.state <= S_PLAY_DASH)
					or(mo.state == S_PLAY_JUMP)
					or(mo.state == S_PLAY_SPRING)
					mo.state = S_PLAY_FALL
				end
				P_SetObjectMomZ(mo, FRACUNIT/3, true)
			end
		end
		
		// Switch weapons
		local buttonf = BT_CUSTOM3
		local buttonb = BT_CUSTOM2
		
		if not(G_RingSlingerGametype())
			buttonf = $1|BT_WEAPONNEXT
			buttonb = $1|BT_WEAPONPREV
		end
		
		if not(player.tgvars.shoottime)
			if(player.cmd.buttons & buttonf)
				and not(player.tgvars.prevbutt & buttonf)
				player.tgvars.weapon = ($1 + 1)%3
				player.tgvars.facetime = -TICRATE/3
				S_StartSound(nil, sfx_menu1, player)
			elseif(player.cmd.buttons & buttonb)
				and not(player.tgvars.prevbutt & buttonb)
				player.tgvars.weapon = $1 - 1
				if(player.tgvars.weapon < 0)
					player.tgvars.weapon = 2
				end
				player.tgvars.facetime = -TICRATE/3
				S_StartSound(nil, sfx_menu1, player)
			end
		end
		
		// Schuut
		if(player.tgvars.shoottime)
			player.tgvars.shoottime = $1 - 1
		end
		if(player.tgvars.shootanimtime)
			if(player.tgvars.shootanimtime > 11)
				mo.state = S_PLAY_DOOMSHOT
			else
				mo.state = S_PLAY_WAIT
			end
			player.tgvars.shootanimtime = $1 - 1
		end
		
		if((player.cmd.buttons & BT_USE) or ((player.cmd.buttons & BT_ATTACK) and not G_RingSlingerGametype()))
			and(player.tgvars.shoottime == 0 or(player.tgvars.weapon == 2 and player.tgvars.shoottime <= TICRATE*10/11))
			and(TailsGuyCapable(player))
			mo.state = S_PLAY_DOOMSHOT
			player.tgvars.shootanimtime = 14
			player.tgvars.shoottime = TICRATE
			player.tgvars.guntime = player.tgvars.shoottime
			if(player.tgvars.weapon == 0)
				S_StartSound(mo, sfx_dgshot)
				local bnum = 0
				while(bnum < 12)
					FireBullet(player, FRACUNIT*10)
					bnum = $1 + 1
				end
			elseif(player.tgvars.weapon == 1)
				S_StartSound(mo, sfx_dgrokt)
				local rocket = P_SPMAngle(mo, MT_DOOMROCKET, mo.angle, 1)
				if(rocket and rocket.valid)
					P_TeleportMove(rocket, rocket.x, rocket.y, rocket.z + 4*FRACUNIT)
					rocket.target = mo
				end
			else
				S_StartSound(mo, sfx_dgchan)
				local bullet = P_SPMAngle(mo, MT_DOOMBULLET, mo.angle, 1)
				if(bullet and bullet.valid)	// Make sure our bullet exists! (i.e., didn't get shot straight into a wall)
					P_TeleportMove(bullet, bullet.x, bullet.y, bullet.z + 4*FRACUNIT)
				end
			end
		end
		
		if(player.tgvars.shoottime >= TICRATE*10/11)
			player.drawangle = mo.angle	// Gotta face the thing you're shooting!
		end
		
		player.normalspeed = skins[mo.skin].normalspeed
		if(player.tgvars.weapon == 2)
			and(player.tgvars.shoottime)
			player.normalspeed = $1 / 4
		end
		
		player.tgvars.prevbutt = player.cmd.buttons
	end
end, MT_PLAYER)

local shotgunanim = {}
local shotgunanimlength = 17
shotgunanim[16] = 4
shotgunanim[15] = 5
shotgunanim[14] = 0
shotgunanim[13] = 0
shotgunanim[12] = 1
shotgunanim[11] = 1
shotgunanim[10] = 2
shotgunanim[9] = 2
shotgunanim[8] = 3
shotgunanim[7] = 3
shotgunanim[6] = 2
shotgunanim[5] = 2
shotgunanim[4] = 1
shotgunanim[3] = 1
shotgunanim[2] = 0
shotgunanim[1] = 0
shotgunanim[0] = 0

local rocketanim = {}
local rocketanimlength = 12
rocketanim[11] = 0
rocketanim[10] = 2
rocketanim[9] = 3
rocketanim[8] = 4
rocketanim[7] = 5
rocketanim[6] = 1
rocketanim[5] = 1
rocketanim[4] = 1
rocketanim[3] = 1
rocketanim[2] = 0
rocketanim[1] = 0
rocketanim[0] = 0

local chainanim = {}
local chainanimlength = 12
chainanim[11] = 2
chainanim[10] = 3
chainanim[9] = 0
chainanim[8] = 1
chainanim[7] = 0
chainanim[6] = 1
chainanim[5] = 0
chainanim[4] = 1
chainanim[3] = 0
chainanim[2] = 1
chainanim[1] = 1
chainanim[0] = 0

// Not accessable to lua, understandable
local flashingtics = 3*TICRATE

local function fps_sprites(v, player, cam)
	
	if not(player.mo)
		or(player.powers[pw_carry] == CR_NIGHTSMODE)
		or not(player.mo.skin == "tailsguy")
		return
	end
	
	if(v.shotgun == nil)
		v.shotgun = {}
		v.shotgun[0] = v.cachePatch("SHOTGUN1")
		v.shotgun[1] = v.cachePatch("SHOTGUN2")
		v.shotgun[2] = v.cachePatch("SHOTGUN3")
		v.shotgun[3] = v.cachePatch("SHOTGUN4")
		v.shotgun[4] = v.cachePatch("SHOTGNF1")
		v.shotgun[5] = v.cachePatch("SHOTGNF2")
		
		v.rocket = {}
		v.rocket[0] = v.cachePatch("ROCKET1")
		v.rocket[1] = v.cachePatch("ROCKET2")
		v.rocket[2] = v.cachePatch("ROCKETF1")
		v.rocket[3] = v.cachePatch("ROCKETF2")
		v.rocket[4] = v.cachePatch("ROCKETF3")
		v.rocket[5] = v.cachePatch("ROCKETF4")
		
		v.chaingun = {}
		v.chaingun[0] = v.cachePatch("CHAINGN1")
		v.chaingun[1] = v.cachePatch("CHAINGN2")
		v.chaingun[2] = v.cachePatch("CHAINGF1")
		v.chaingun[3] = v.cachePatch("CHAINGF2")
		
		v.statusbar	= v.cachePatch("STBAR2")
		
		v.tailsface1 = v.cachePatch("TGFACEL1")
		v.tailsface2 = v.cachePatch("TGFACEL2")
		v.tailsface3 = v.cachePatch("TGFACEL3")
		v.tailsfaceow = v.cachePatch("TGFACEOW")
		v.tailsfaceevil = v.cachePatch("TGFACEVL")
		
		v.gunstop = 0	// 0: Idle pos, FRACUNIT: Bobbing
		v.gunpos = 0
		v.gundir = 1
	end
	
	// And for his special ability, he weilds a gun
	if not(cam.chase)
		if not(player.tgvars.shoottime)
			and(R_PointToDist2(0, 0, player.cmd.forwardmove*FRACUNIT, player.cmd.sidemove*FRACUNIT))
			// Need control!
			and not(P_PlayerInPain(player))
			and not(player.exiting)
			and not(player.powers[pw_nocontrol])
			and not(player.pflags & (PF_SLIDING|PF_STASIS))
			and not(player.powers[pw_carry])
			v.gunstop = $1 + FRACUNIT/(TICRATE/4)
		else
			if(player.tgvars.shoottime)
				v.gunstop = $1 - FRACUNIT/(TICRATE/10)
			else
				v.gunstop = $1 - FRACUNIT/(TICRATE/4)
			end
		end
		
		if(v.gunstop <= 0)
			v.gunstop = 0
			v.gunpos = 0
		elseif(v.gunstop > FRACUNIT)
			v.gunstop = FRACUNIT
		end
		
		local maxangle = 40
		local speed = (((FRACUNIT-abs(v.gunpos))/2)+(FRACUNIT/2))/(TICRATE/3)
		local angle = FixedAngle(v.gunpos*maxangle)
		
		if(v.gundir == 1)
			v.gunpos = $1 + speed
			if(v.gunpos > FRACUNIT)
				v.gunpos = FRACUNIT
				v.gundir = 0
			end
		else
			v.gunpos = $1 - speed
			if(v.gunpos < -FRACUNIT)
				v.gunpos = -FRACUNIT
				v.gundir = 1
			end
		end
		
		local posx1 = sin(angle)*42
		local posy1 = (cos(angle)*36)+(cos(FixedAngle(maxangle*FRACUNIT))*32)
		local posx2 = 0
		local posy2 = 32*FRACUNIT
		
		local totalposx = FixedMul(posx1, v.gunstop)
		local totalposy = FixedMul(posy1, v.gunstop)+FixedMul(posy2, FRACUNIT-v.gunstop)
		
		local gunsprite = v.shotgun
		local gunframe = 0
		local anim = shotgunanim
		local length = shotgunanimlength
		if(player.tgvars.weapon == 1)
			gunsprite = v.rocket
			anim = rocketanim
			length = rocketanimlength
		elseif(player.tgvars.weapon == 2)
			gunsprite = v.chaingun
			anim = chainanim
			length = chainanimlength
		end
		if(player.tgvars.shoottime)
			gunframe = anim[(player.tgvars.shoottime-1)*length/player.tgvars.guntime]
		end
		v.draw(totalposx/FRACUNIT, totalposy/FRACUNIT, gunsprite[gunframe], V_SNAPTOBOTTOM)
		if(player.tgvars.weapon == 0)
			if(gunframe == 4 or gunframe == 5)
				v.draw(totalposx/FRACUNIT, totalposy/FRACUNIT, gunsprite[0], V_SNAPTOBOTTOM)
			end
		elseif(player.tgvars.weapon == 1)
			if(gunframe == 2)
				v.draw(totalposx/FRACUNIT, totalposy/FRACUNIT, gunsprite[0], V_SNAPTOBOTTOM)
			elseif(gunframe > 2)
				v.draw(totalposx/FRACUNIT, totalposy/FRACUNIT, gunsprite[1], V_SNAPTOBOTTOM)
			end
		else
			if(gunframe == 2)
				v.draw(totalposx/FRACUNIT, totalposy/FRACUNIT, gunsprite[0], V_SNAPTOBOTTOM)
			elseif(gunframe == 3)
				v.draw(totalposx/FRACUNIT, totalposy/FRACUNIT, gunsprite[1], V_SNAPTOBOTTOM)
			end
		end
	end
	

	// Status bar!
	v.draw(320, 200, v.statusbar, V_SNAPTOBOTTOM|V_SNAPTORIGHT)
	if(player.tgvars.health >= 100)
		and(player.mo.health > 0)	// Still alive
		v.drawString(206+38, 180, player.tgvars.health, V_SNAPTOBOTTOM|V_SNAPTORIGHT)
	elseif(player.mo.health > 0)	// Still alive
		v.drawString(210+38, 180, player.tgvars.health, V_SNAPTOBOTTOM|V_SNAPTORIGHT)
	else
		v.drawString(214+38, 180, "0", V_SNAPTOBOTTOM|V_SNAPTORIGHT)
	end
	
	// Tails face
	if not(player.powers[pw_flashing] > 0 and player.powers[pw_flashing] < flashingtics and not (leveltime & 1))
		if(player.powers[pw_super])
			v.draw(320, 200, v.tailsfaceevil, V_SNAPTOBOTTOM|V_SNAPTORIGHT)
		elseif(player.tgvars.hurttime)
			or(player.mo.state == S_PLAY_GASP)	// Looks kinda like gasping
			v.draw(320, 200, v.tailsfaceow, V_SNAPTOBOTTOM|V_SNAPTORIGHT)
		elseif(player.tgvars.facetime > ((70/3) + (70/3)))
			v.draw(320, 200, v.tailsface1, V_SNAPTOBOTTOM|V_SNAPTORIGHT)
		elseif(player.tgvars.facetime > 70/3)
			v.draw(320, 200, v.tailsface3, V_SNAPTOBOTTOM|V_SNAPTORIGHT)
		elseif(player.tgvars.facetime >= 0)
			v.draw(320, 200, v.tailsface2, V_SNAPTOBOTTOM|V_SNAPTORIGHT)
		else
			v.draw(320, 200, v.tailsfaceevil, V_SNAPTOBOTTOM|V_SNAPTORIGHT)
		end
	end

end
hud.add(fps_sprites, player)
