// PAUL Player Lua
// From anton ball
// Scripted by Basinga

// --------------------------------------
// Lua_Freeslot
// --------------------------------------

// Sounds
freeslot(
// General
"sfx_pdash","sfx_phijmp", "sfx_pbump")

// Closed captions
sfxinfo[sfx_pdash].caption = "Clutch"
sfxinfo[sfx_phijmp].caption = "Hi Jump"
sfxinfo[sfx_pbump].caption = "Bump"

//Sprites
freeslot(
"SPR2_DUCK")

//States
freeslot(
"S_PAUL_DASH_FLOAT",
"S_PAUL_DASH",
"S_PAUL_DASH_FALL",
"S_PAUL_DUCK"
)

states[S_PAUL_DUCK] = {
	sprite = SPR_PLAY,
	frame = SPR2_DUCK,
	tics = -1,
	action = nil,
	var1 = 0,
	var2 = 0,
	nextstate = S_PAUL_DUCK
}

states[S_PAUL_DASH_FLOAT] = {
	sprite = SPR_PLAY,
	frame = SPR2_JUMP|A,
	tics = 4,
	action = nil,
	var1 = 60,
	var2 = 0,
	nextstate = S_PAUL_DASH
}

states[S_PAUL_DASH] = {
	sprite = SPR_PLAY,
	frame = SPR2_JUMP|A,
	tics = 6,
	action = nil,
	var1 = 60,
	var2 = 0,
	nextstate = S_PAUL_DASH_FALL
}

states[S_PAUL_DASH_FALL] = {
	sprite = SPR_PLAY,
	frame = SPR2_JUMP|A,
	tics = 2,
	action = nil,
	var1 = 60,
	var2 = 0,
	nextstate = S_PAUL_DASH_FALL
}

//Kirby junk
if not kirbyabilitytable
    rawset(_G, "kirbyabilitytable", {})
end

kirbyabilitytable["paul"] = 3


local duckbutton1 = BT_CUSTOM1
local duckbutton2 = BT_CUSTOM2

local breakfloor = function(mo)
	if mo.subsector and mo.subsector.valid
	and mo.subsector.sector and mo.subsector.sector.valid
		local crumble = false
		for fof in mo.subsector.sector.ffloors()
			if not (fof.flags & FF_EXISTS) continue end -- Does it exist?
			if not (fof.flags & FF_BUSTUP) continue end -- Is it bustable?
			
			if mo.z + mo.momz + mo.height < fof.bottomheight continue end -- Are we too low?
			if mo.z + mo.momz > fof.topheight continue end -- Are we too high?  
			
			EV_CrumbleChain(fof) -- Crumble
		end
	end
end

//Taken from StephCharsOC to use the input angle
local function inputangle(player) 
	if (twodlevel or player.mo.flags2 & MF2_TWOD)
		return player.mo.angle
	else
		return (player.cmd.angleturn<<16 + R_PointToAngle2(0, 0, player.cmd.forwardmove*FRACUNIT, -player.cmd.sidemove*FRACUNIT))
	end
end	

//Taken from Kirby
local function buttonPressed(player, button)
	if(player.cmd.buttons & button)
		return true
	end
	return false
end
local function lockControl(player)
	player.pflags = $1|PF_STASIS
end
local function squishedCheck(player)
	local height = FixedMul(player.height, player.mo.scale)
	if(player.mo.ceilingz - player.mo.floorz < FixedMul(height, player.mo.scale))
		return true
	end
	return false
end

//Obtain the magnitude of momx and momy
local function getMagnitudeMoM(player)
	return abs(R_PointToDist2(0,0,player.mo.momx,player.mo.momy))
end

local function setMaxSpeed(player)
				//Set his current speed to the new max speed
				if getMagnitudeMoM(player) > skins[player.mo.skin].normalspeed and player.speed < 100*FRACUNIT 
					player.normalspeed = getMagnitudeMoM(player)
-- 					print ("Speed change!")
-- 					print (getMagnitudeMoM(player)/FRACUNIT)
-- 					print (player.normalspeed/FRACUNIT)
				end
				
end

//Produce trail
local function particleGhost(player)
	if not player.powers[pw_super]
			local ghost = P_SpawnGhostMobj(player.mo)
		//	ghost.scale = $-(TICRATE-player.milnespringtime*5/2)*$*2/TICRATE
		//	ghost.z = $+(TICRATE/2-player.milnespringtime)*player.mo.scale*3
			ghost.frame = 0
			ghost.colorized = true
			ghost.momx = player.mo.momx/2
			ghost.momy = player.mo.momy/2
			ghost.color = SKINCOLOR_RED
	end

end

//Activate/deactivate wall breaking properties
local function enableBreakingWallsAndFloors(player)
			P_SpawnThokMobj(player)
			player.charability = CA_GLIDEANDCLIMB
			player.charability2 = CA2_NONE
			player.panim = PA_ABILITY2
			breakfloor(player.mo)
end

//Activate/deactivate wall breaking properties
local function disableBreakingWallsAndFloors(player)
			P_SpawnThokMobj(player)
			player.charability = CA_NONE
			player.charability2 = CA2_NONE
			player.panim = PA_ABILITY2
end

//Dash Related

addHook("SpinSpecial", function(player, mobj)
	if not (player.mo and player.mo.valid and player.mo.skin == "paul") then return end
	
	if P_PlayerInPain(player)
	or (player.pflags & PF_SLIDING)
	or player.exiting
	or player.powers[pw_carry]
	or not player.mo.health
	or (player.panim == PA_PAIN and not (player.pflags&PF_JUMPED))
	or P_SuperReady(player)
	//or not P_IsObjectOnGround(mo)
	or player.mo.state == S_PAUL_DUCK
	or player.mo.state == S_PLAY_MELEE or player.mo.state == S_PLAY_FIRE
	or ((player.mo.state == S_PLAY_MELEE_FINISH or player.mo.state == S_PLAY_FIRE_FINISH) and player.mo.tics >= 8)
	or (P_IsObjectOnGround(player.mo) and ((player.cmd.forwardmove < 1 and player.cmd.forwardmove > -1) and (player.cmd.sidemove < 1 and player.cmd.sidemove > -1)))
		return
	end
	
	if player.powers[pw_super]
		//a specified angle and a specified speed amount
			if player.normalspeed > skins[player.mo.skin].normalspeed+skins[player.mo.skin].normalspeed/2
				P_InstaThrust(player.mo, inputangle(player), FixedMul(player.normalspeed, player.mo.scale)) //Spork saves the day #4
			else
				P_InstaThrust(player.mo, inputangle(player), FixedMul(skins[player.mo.skin].normalspeed + skins[player.mo.skin].normalspeed/2, player.mo.scale))
			end
			
			if player.mo.state != S_PAUL_DASH_FLOAT and player.mo.state != S_PAUL_DASH and player.mo.state != S_PAUL_DASH_FALL
				S_StartSound(player.mo, sfx_pdash)		
			end
			player.mo.state = S_PAUL_DASH_FLOAT 
			
			setMaxSpeed(player)
		
	else
		
		if player.mo.state != S_PAUL_DASH_FLOAT and player.mo.state != S_PAUL_DASH and player.mo.state != S_PAUL_DASH_FALL
		
		if player.pflags&PF_SPINDOWN
			return
		end
	
			//a specified angle and a specified speed amount
			if player.normalspeed > skins[player.mo.skin].normalspeed+skins[player.mo.skin].normalspeed/2
				P_InstaThrust(player.mo, inputangle(player), FixedMul(player.normalspeed, player.mo.scale)) //Spork saves the day #4
			else
				P_InstaThrust(player.mo, inputangle(player), FixedMul(skins[player.mo.skin].normalspeed + skins[player.mo.skin].normalspeed/2, player.mo.scale))
			end
			
 			S_StartSound(player.mo, sfx_pdash)		
			player.mo.state = S_PAUL_DASH_FLOAT 
			
			setMaxSpeed(player)
			
		end
		
	end
		

	
end)

addHook("PlayerThink", function(player)
	if not (player.mo and player.mo.valid and player.mo.skin == "paul") then return end
	
	//Forced back to normal
	player.height = skins[player.mo.skin].height
	player.jumpfactor = skins[player.mo.skin].jumpfactor
	//player.normalspeed = skins[player.mo.skin].normalspeed
	
	//Set speed back to normal if it's below the base speed
	if getMagnitudeMoM(player) < skins[player.mo.skin].normalspeed
-- 		print ("previous speed")
-- 		print (getMagnitudeMoM(player)/FRACUNIT)
-- 		print (player.normalspeed/FRACUNIT)
-- 		print (skins[player.mo.skin].normalspeed/FRACUNIT)
		player.normalspeed = skins[player.mo.skin].normalspeed
	end
	
	player.thrustfactor = skins[player.mo.skin].thrustfactor
	player.charflags = $&~SF_CANBUSTWALLS
	disableBreakingWallsAndFloors(player)
	 
	
	//Float when dashing
	if player.mo.state == S_PAUL_DASH_FLOAT
		if player.mo.momz*P_MobjFlip(player.mo) < 0 
					player.mo.momz = 0		
		end
-- 			P_SetObjectMomZ(player.mo,0*FRACUNIT,false)
		player.pflags = $ | (PF_THOKKED|PF_SPINNING)
		player.charflags = $|SF_CANBUSTWALLS
		enableBreakingWallsAndFloors(player)
		particleGhost(player)
	else 
		if player.mo.state == S_PAUL_DASH
			player.pflags = $ | (PF_THOKKED|PF_SPINNING)
			player.charflags = $|SF_CANBUSTWALLS
			enableBreakingWallsAndFloors(player)
			particleGhost(player)
		else
			if player.mo.state == S_PAUL_DASH_FALL
				particleGhost(player)
				player.pflags = $ | (PF_THOKKED|PF_SPINNING)
				player.charflags = $|SF_CANBUSTWALLS
				enableBreakingWallsAndFloors(player)
				P_RadiusAttack(player.mo,player.mo,60*FRACUNIT)
				//End Dash
				if P_IsObjectOnGround(player.mo) then
					player.pflags = $ & ~(PF_THOKKED|PF_SPINNING)
					player.mo.state = S_PLAY_FALL 
					P_RadiusAttack(player.mo,player.mo,80*FRACUNIT)
				end
			end
		end
	end
	
	//Crouch! (from kirby)
	if((((  ((player.cmd.buttons & duckbutton1) or (player.cmd.buttons & duckbutton2)  ) 
	or (player.cmd.buttons & BT_SPIN and ( ((player.cmd.forwardmove < 1 and player.cmd.forwardmove > -1) and (player.cmd.sidemove < 1 and player.cmd.sidemove > -1)) or ( player.mo.state == S_PAUL_DUCK) )  ) )
	and not(player.exiting)) or squishedCheck(player))
			and(P_IsObjectOnGround(player.mo))
			and not(P_PlayerInPain(player))
			and not(player.powers[pw_carry])
			and not(player.mo.eflags & MFE_GOOWATER))
			
			
			player.pflags = $ & ~(PF_THOKKED|PF_SPINNING)
			
			player.height = $1 / 6
			player.jumpfactor = 0
			player.mo.state = S_PAUL_DUCK
			
			// High jumping!
			if(buttonPressed(player, BT_JUMP))
			if player.powers[pw_super]
				if player.mo.eflags&MFE_UNDERWATER
					P_SetObjectMomZ(player.mo, 18*FRACUNIT, true)
				else
					P_SetObjectMomZ(player.mo, 25*FRACUNIT, true)
				end
				player.mo.state = S_PLAY_JUMP
				S_StartSound(player.mo,sfx_phijmp)
				
				setMaxSpeed(player)
			else
				if player.mo.eflags&MFE_UNDERWATER
					P_SetObjectMomZ(player.mo, 11*FRACUNIT, true)
				else
					P_SetObjectMomZ(player.mo, 15*FRACUNIT, true)
				end
				player.mo.state = S_PLAY_JUMP
				S_StartSound(player.mo,sfx_phijmp)	
				
				setMaxSpeed(player)
			end
				
				
			end
			
			// Can't move when ducking!
			if(player.mo.currentaxis)
				lockControl(player)
			end
			//player.normalspeed = 0
			player.thrustfactor = 0
			
			
			
	else
			if(player.mo.state == S_PAUL_DUCK)
				if(player.mo.momx-player.cmomx or player.mo.momy-player.cmomy)
					player.mo.state = S_PLAY_WALK
				else
					player.mo.state = S_PLAY_STND
				end
			end
	end
-- 		if player.mo.state != S_PAUL_DASH_FLOAT and player.mo.state != S_PAUL_DASH and player.mo.state != S_PAUL_DASH_FALL
			
-- 		end

	//Bonk Code from Steph, activated after the mobjcollide and significant speed was lost.
		
		local mobj = player.mo -- Just for laziness.
		if mobj.readyforbonk	
			
			if player.powers[pw_super]
				P_SetObjectMomZ(mobj, 20*FRACUNIT ,false)
				mobj.player.pflags = $&~PF_DRILLING&~PF_SPINNING|PF_JUMPED
			else
				if ( (mobj.readyforbonk > 12*FRACUNIT and player.speed < mobj.readyforbonk/4) 
				or (player.powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE)
					mobj.momx = mobj.readyforbonkx //Necessary for P_BounceMove to function properly.
					mobj.momy = mobj.readyforbonky
					P_BounceMove(mobj)
					mobj.momx = $/2 mobj.momy = $/2
					
					P_SetObjectMomZ(mobj, mobj.player.jumpfactor*(39/4), false)
					S_StartSound(mobj,sfx_pbump)
					
					mobj.player.pflags = $&~PF_DRILLING&~PF_SPINNING|PF_JUMPED
				end
			end
					
		mobj.readyforbonk = nil
		mobj.readyforbonkx = 0
		mobj.readyforbonky = 0
		end
	
	//Create dust when running
	
	if player.speed > player.runspeed and P_IsObjectOnGround(player.mo) and (leveltime % 3 == 0)
		P_SpawnMobjFromMobj(player.mo, 0, 0, 0, MT_SPINDUST)
		local particle = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_SPINDUST)
		particle.scale = player.mo.scale
	end

	
end)


//Bonking into walls while diving or sliding
addHook("MobjMoveBlocked", function(mobj)
	if mobj and mobj.valid and mobj.player and mobj.skin == "paul"
	and (mobj.state == S_PAUL_DASH_FLOAT or mobj.state == S_PAUL_DASH or mobj.state == S_PAUL_DASH_FALL)
	and mobj.ceilingz - mobj.floorz >= FixedMul(skins[mobj.skin].height, mobj.scale)
	
		if mobj.player.powers[pw_super]
			if mobj.player.cmd.buttons & BT_SPIN
					mobj.readyforbonk = mobj.player.speed -- Save the player's speed value. Use it in the playerthink. 
					mobj.readyforbonkx = mobj.momx --Just CTRL+F "Bonk Code" to find the continuation of this.
					mobj.readyforbonky = mobj.momy
				end
		else
			if(mobj.player.speed >= 1*FRACUNIT)
				mobj.readyforbonk = mobj.player.speed -- Save the player's speed value. Use it in the playerthink. 
				mobj.readyforbonkx = mobj.momx --Just CTRL+F "Bonk Code" to find the continuation of this.
				mobj.readyforbonky = mobj.momy
			end
		end

	end
	
	
	
	end, MT_PLAYER)

addHook("JumpSpecial", function(player, mobj)
	//
	if (player.mo.state == S_PAUL_DASH or player.mo.state == S_PAUL_DASH_FLOAT)
	and P_IsObjectOnGround(player.mo)
		if player.mo.eflags & MFE_UNDERWATER
			P_SetObjectMomZ(player.mo, player.jumpfactor*11/20, false)
		else
			P_SetObjectMomZ(player.mo, player.jumpfactor*39/4, false)
		end
		
		player.mo.state = S_PAUL_DASH
		
		return true
	end
end)

hud.add(function(v, player, cam)
	
	local ypos = 168
	
	if player.powers[pw_super]
		v.drawString(75,ypos-22,"FIXED     ",
		V_HUDTRANS|V_PERPLAYER|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_YELLOWMAP, "right")
		v.drawString(74,ypos-12,"Gold      ",
		V_HUDTRANS|V_PERPLAYER|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_YELLOWMAP, "right")
		v.drawString(74,ypos-2,"Evil Baby",
		V_HUDTRANS|V_PERPLAYER|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_YELLOWMAP, "right")
		v.drawString(75,ypos+8,"(SHINY)",
		V_HUDTRANS|V_PERPLAYER|V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_YELLOWMAP, "left")
	end
		
end)

