//firey-themed things
local P_TeleportMove = P_MoveOrigin or P_TeleportMove

sfxinfo[freeslot("sfx_flstp1")].caption = "Stomp"
sfxinfo[sfx_flstp1].flags = $|SF_X2AWAYSOUND
sfxinfo[freeslot("sfx_flstp2")].caption = "Stomp"
sfxinfo[sfx_flstp2].flags = $|SF_X2AWAYSOUND
sfxinfo[freeslot("sfx_flstp3")].caption = "Stomp"
sfxinfo[sfx_flstp3].flags = $|SF_X2AWAYSOUND

sfxinfo[freeslot("sfx_flcrsh")].caption = "Crush"
sfxinfo[sfx_flcrsh].flags = $|SF_X2AWAYSOUND
sfxinfo[freeslot("sfx_fluncr")].caption = "/"
sfxinfo[sfx_fluncr].flags = $|SF_X2AWAYSOUND

freeslot("S_FLARE_TRANSFORM", "SPR_NROV")
states[S_FLARE_TRANSFORM] = {SPR_NROV, FF_ANIMATE|FF_FULLBRIGHT, (G+1)*2, nil, G, 2, S_NULL}
local TRANSFORMDELAY = (E+1)*2

freeslot("MT_FLARE_THOK")
mobjinfo[MT_FLARE_THOK] = {
	spawnstate = S_THOK,
	spawnhealth = 1000,
	speed = 8,
	radius = 32*FRACUNIT,
	height = 64*FRACUNIT,
	mass = 16,
	flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY,
}
addHook("MobjThinker", function(mobj)
	mobj.type = MT_THOK
	mobj.frame = FF_TRANS70
	mobj.fuse = mobj.tics
	
	if mobj.target and mobj.target.player and mobj.target.player.narlare
		mobj.spritexscale = $*15/6
		mobj.spriteyscale = $*15/6
	end
end, MT_FLARE_THOK)

//super-compatible fire immunity code - thanks Logan8r for letting me use this!
addHook("ShouldDamage", function(target, inflictor, source, damage, dmgType)
	if target.skin == "flarethetrex"
	and (dmgType == DMG_FIRE or (inflictor and inflictor.flags & MF_FIRE)
	or (dmgType == DMG_CRUSHED and target.player and target.player.narlarecarry))
		return false
	end
end, MT_PLAYER)

if srb2p return end
-- Due to the exe nature of the mod, this only requires a one-time check.

addHook("ThinkFrame", function()
	for player in players.iterate do
		local mo = player.mo
		local skin = skins[player.skin]
		
		if not mo
			player.narlare = 0
			player.charflags = ($ &~ SF_NOSPEEDADJUST) | (skin.flags | SF_NOSPEEDADJUST)
			continue
		elseif mo.skin ~= "flarethetrex" then
			if player.narlare
				mo.destscale = player.narlare
				player.narlare = 0
			end
			continue
		end
		
		//form-based hitbox & camera tweaking
		if not player.powers[pw_super] then  -- normal stats
			if player.narlare
				mo.destscale = player.narlare
				player.camerascale = skin.camerascale
				mo.radius = FixedMul(skin.radius, mo.scale)
				player.height = skin.height
				player.normalspeed = skin.normalspeed
				player.runspeed = skin.runspeed
				player.charflags = ($ &~ SF_CANBUSTWALLS) | (skin.flags | SF_CANBUSTWALLS)
				player.narlare = 0
			end
			
		elseif player.powers[pw_super] != 1
			player.normalspeed = FRACUNIT*20
			player.runspeed = FRACUNIT*18
			mo.radius = mo.scale*40
			
			--Higher gravity
			if player.powers[pw_carry]
				player.narlarecarry = true
			elseif not P_IsObjectOnGround(mo) and player.pflags & PF_JUMPED
			and not player.narlarecarry
				mo.momz = $ + P_GetMobjGravity(mo)/2
			elseif player.narlarecarry and P_IsObjectOnGround(mo)
				player.narlarecarry = false
			end
			
			--Turning into Narlare
			if not player.narlare
				mo.destscale = $*2
				player.camerascale = FRACUNIT*5/4
				player.charflags = $ | SF_CANBUSTWALLS
				player.height = FRACUNIT*88
				
				player.narlare = mo.destscale
				player.narlarestarpost = player.starpostnum
				
			--Fix for startposts saving your larger scale when super
			elseif player.starpostnum != player.narlarestarpost
				player.starpostscale = player.narlare
				player.narlarestarpost = player.starpostnum
			end
			
			--Minecart state
			if player.powers[pw_carry] == CR_MINECART
				mo.state = S_TAILSOVERLAY_PLUS30DEGREES
			end
			
			--Stomping
			local frames = 1
			if player.panim == PA_WALK or player.panim == PA_RUN
				frames = skins[player.skin].sprites[mo.sprite2].numframes or $
			end
			
			local hitfloor = false
			if player.narlarelanding
				player.narlarelanding = $ - 1
			else
				hitfloor = mo.eflags & MFE_JUSTHITFLOOR and mo.eflags & MFE_ONGROUND
				and not player.powers[pw_carry] and not player.powers[pw_justlaunched]
			end
			
			if (hitfloor
			or ((P_IsObjectOnGround(mo) or player.powers[pw_carry] == CR_ROLLOUT)
			and (player.panim == PA_WALK or player.panim == PA_RUN))
			and (((mo.frame & FF_FRAMEMASK) + 1) % max(frames/2, 1)) == 0 and mo.tics == 1)
				if hitfloor
					S_StartSound(mo, sfx_flstp3)
					
					player.narlarelanding = 5
					flarecircle(mo, mo.eflags & MFE_UNDERWATER and MT_SMALLBUBBLE or MT_DUST,
					8, 6*mo.scale, 0, mo.scale*2/3, 2)
					
				elseif ((mo.frame & FF_FRAMEMASK)/3) & 1
					S_StartSound(mo, sfx_flstp2)
				else
					S_StartSound(mo, sfx_flstp1)
				end
				
				if player == displayplayer and not splitscreen
					if hitfloor
						P_StartQuake(16*mo.scale, 2)
					else
						P_StartQuake(8*mo.scale, 2)
					end
				end
			end
			
			if mo.state == S_PLAY_MELEE_LANDING and mo.tics == TICRATE/3 - 1
			and player == displayplayer and not splitscreen
				P_StartQuake(16*mo.scale, mo.tics)
			end
			
		--Transformation effects
		elseif mo.state == S_PLAY_SUPER_TRANS1 and mo.tics == 1 then
			mo.state = S_PLAY_SUPER_TRANS2
			mo.tics = $ + TRANSFORMDELAY
			
		elseif mo.state == S_PLAY_SUPER_TRANS2
		and mo.tics == TRANSFORMDELAY
			local thok = P_SpawnMobjFromMobj(mo, 0,0,0, MT_OVERLAY)
			thok.state = S_FLARE_TRANSFORM
			thok.target = mo
			
			if not player.narlare
				mo.radius = mo.scale*40
				
				player.camerascale = FRACUNIT*5/4
				player.charflags = $ | SF_CANBUSTWALLS
				player.height = FRACUNIT*88
				
				player.narlare = mo.destscale
				mo.destscale = $*2
				player.narlarestarpost = player.starpostnum
			end
			S_StartSound(mo, sfx_s3k9f)
			player.pflags = $ &~ PF_JUMPED
		end
		
		//trying to balance "realism" and controllability with the reward of having Super in the first place was tricky
		//but i think i got somewhere
		//controllability was important bc Super at 2xscale is HARD to control 
	end
end)

//Crush solid objects running over them
mobjinfo[freeslot("MT_FLARE_CRUSHER")] = {
	spawnstate = S_INVISIBLE,
	flags = MF_SCENERY|MF_NOGRAVITY|MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING
}

addHook("MobjFuse", function(mobj)
	local tracer = mobj.tracer
	if tracer and tracer.narlarecrushed
		tracer.z = tracer.narlarez
		tracer.flags = tracer.narlarecrushed
		tracer.narlarecrushed = nil
		
		if tracer.flags & MF_ENEMY
		or tracer.type == MT_SPIKE or tracer.type == MT_WALLSPIKE
			P_KillMobj(tracer, mobj, mobj.target or mobj)
		elseif tracer.flags & MF_SHOOTABLE
			P_DamageMobj(tracer, mobj, mobj.target or mobj)
		else
			tracer.renderflags = tracer.narlarerender
			S_StartSound(tracer, sfx_fluncr)
			
			flarecircle(tracer, tracer.eflags & MFE_UNDERWATER and MT_SMALLBUBBLE or MT_DUST,
			8, 6*tracer.scale, 0, tracer.scale*2/3, 2)
		end
	end
end, MT_FLARE_CRUSHER)

addHook("MobjMoveCollide", function(mo, mobj)
	local player = mo.player
	if not player or not (player.narlare and player.powers[pw_super])
	or not mobj or mobj.narlarecrushed
	or (((mobj.flags &~ (MF_SOLID|MF_NOTHINK|MF_PUSHABLE|MF_SCENERY|MF_NOGRAVITY|MF_SLIDEME))
	or not (mobj.flags & MF_SOLID)) and not (mobj.flags & (MF_ENEMY|MF_MONITOR))
	and not (mobj.type == MT_STARPOST and P_MobjFlip(mobj) > 0))
	or (not P_IsObjectOnGround(mobj) and mobj.type != MT_SPIKE and mobj.type != MT_WALLSPIKE)
	--or not (player.speed or not P_IsObjectOnGround(mo))
	or not (mobj.z - mobj.scale + mobj.momz <= mo.z + mo.height + mo.momz
	and mobj.z + mobj.height + mobj.momz + mobj.scale >= mo.z  + mo.momz) then return end
	
	if not P_IsObjectOnGround(mobj) then P_KillMobj(mobj, mo, mo) return end
	
	S_StartSound(mo, sfx_flcrsh)
	flarecircle(mobj, mo.eflags & MFE_UNDERWATER and MT_SMALLBUBBLE or MT_DUST,
	8, 6*mo.scale, 0, mo.scale*2/3, 2)
	if player == displayplayer and not splitscreen
		P_StartQuake(16*mo.scale, 2)
	end
	
	local crusher = P_SpawnMobjFromMobj(mobj, 0,0,0, MT_FLARE_CRUSHER)
	crusher.target = mo
	crusher.tracer = mobj
	crusher.fuse = (mobj.flags & MF_MONITOR) and TICRATE or TICRATE*5
	
	mobj.narlarerender = mobj.renderflags
	mobj.narlarez = mobj.z
	mobj.narlarecrushed = mobj.flags
	
	mobj.renderflags = $ | RF_NOSPLATBILLBOARD | RF_FLOORSPRITE
	if mobj.type == MT_STARPOST then return end
	
	mobj.flags = MF_NOTHINK | MF_NOCLIP | MF_NOCLIPHEIGHT
	if P_MobjFlip(mobj) < 0
		mobj.z = $ + mobj.height
	end
	
	mobj.angle = R_PointToAngle2(mo.x, mo.y, mobj.x, mobj.y)
end, MT_PLAYER)

//KIRBY KIRBY KIRBY THAT'S A NAME YOU SHOULD KNOW

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

kirbyabilitytable["flarethetrex"] = 1

//you can tell which one of us is more experienced with lua lmao

//MusicChange hook for Narlok's theme, disable this in persona
if srb2p then return end

addHook("MusicChange", function(oldmusic, newmusic, flags, looping)
	if newmusic != "_super" then return end
	
	if (consoleplayer and skins[consoleplayer.skin].name == "flarethetrex")
	or (secondarydisplayplayer and skins[secondarydisplayplayer.skin].name == "flarethetrex")
		return "NARLOK"
	end
end)