--dash rings, writen by Lighto
freeslot("MT_LGREYDR",
		"MT_LBLUEDR",
		"MT_LYELLDR",
		"MT_LREDDR",
		"MT_LGREYDRDIAG",
		"MT_LBLUEDRDIAG",
		"MT_LYELLDRDIAG",
		"MT_LREDDRDIAG",
		"MT_LGREYDRVERT",
		"MT_LBLUEDRVERT",
		"MT_LYELLDRVERT",
		"MT_LREDDRVERT")
	 


local mtf_flags = {
	"MTF_EXTRA",
	"MTF_OBJECTFLIP",
	"MTF_SPECIAL",
	"MTF_AMBUSH",
}
local dhsrnglocalv = 2
if dhsrngversion and dhsrngversion < dhsrnglocalv then
	return
end
rawset(_G, "dhsrngversion", dhsrnglocalv)

for i = 1, #mtf_flags
	rawset(_G, mtf_flags[i], 2^(i-1))
end


local function K_SpawnSparkleTrailL(mo)
	local rad = (mo.radius*2)>>FRACBITS
	local sparkle
	local i

	for i = 0, 1 do

		local newx = mo.x - mo.momx*2 + (P_RandomRange(-rad, rad)<<FRACBITS)
		local newy = mo.y - mo.momy*2 + (P_RandomRange(-rad, rad)<<FRACBITS)
		local newz = mo.z - mo.momz*2 + (P_RandomRange(0, mo.height>>FRACBITS)<<FRACBITS)

		sparkle = P_SpawnMobj(newx, newy, newz, MT_SPARKLETRAIL)
		--K_FlipFromObject(sparkle, mo); whythats not exposed ????
		sparkle.eflags = (sparkle.eflags & ~MFE_VERTICALFLIP)|(mo.eflags & MFE_VERTICALFLIP)
		sparkle.flags2 = (sparkle.flags2 & ~MF2_OBJECTFLIP)|(mo.flags2 & MF2_OBJECTFLIP)

		if (sparkle.eflags & MFE_VERTICALFLIP) then
			sparkle.z = $ + mo.height - FixedMul(mo.scale, sparkle.height)
		end
		
		sparkle.target = mo
		sparkle.destscale = mo.destscale
		sparkle.scale = mo.scale
		sparkle.color = mo.color
	end
	sparkle.state =  S_KARTINVULN_LARGE1
end

addHook("ThinkFrame", do
	if leveltime == 1 then
		local gh,gv,yh,yv,rh,rv,bh,bv
		for l in lines.iterate do
			if not l 
			or l and not l.valid
			or not(l.special >=750
			and l.special <=753) then continue end
			
			if l.special == 750 then
				gh = l.frontside.textureoffset
				gv = l.frontside.rowoffset
			elseif l.special == 751 then
				yh = l.frontside.textureoffset
				yv = l.frontside.rowoffset
			elseif l.special == 752 then
				rh = l.frontside.textureoffset
				rv = l.frontside.rowoffset
			elseif l.special == 753 then
				bh = l.frontside.textureoffset
				bv = l.frontside.rowoffset
			end
		end
		for dashring in thinkers.iterate("mobj") do
			if dashring 
			and (dashring.type ~= MT_LGREYDR
			and dashring.type ~=  MT_LBLUEDR
			and dashring.type  ~= MT_LYELLDR
			and dashring.type  ~= MT_LREDDR
			and dashring.type  ~= MT_LGREYDRDIAG
			and dashring.type  ~= MT_LBLUEDRDIAG
			and dashring.type  ~= MT_LYELLDRDIAG
			and dashring.type  ~= MT_LREDDRDIAG
			and dashring.type  ~= MT_LGREYDRVERT
			and dashring.type  ~= MT_LBLUEDRVERT
			and dashring.type  ~= MT_LYELLDRVERT
			and dashring.type  ~= MT_LREDDRVERT) 
			or not dashring
			or (dashring and not dashring.valid)
			or dashring.isdashring  then continue end
			dashring.isdashring = true	
			if (dashring.type == MT_LGREYDR
			or dashring.type == MT_LGREYDRDIAG
			or dashring.type == MT_LGREYDRVERT) then
				dashring.color = 4
				dashring.prefcolor = dashring.color
				dashring.activecolor = 2
				dashring.greytier = true
			end
			if (dashring.type == MT_LBLUEDR
			or dashring.type == MT_LBLUEDRDIAG
			or dashring.type == MT_LBLUEDRVERT) then
				dashring.color = 85
				dashring.prefcolor = dashring.color
				dashring.activecolor = 72
				dashring.bluetier = true
			end
			if (dashring.type == MT_LYELLDR
			or dashring.type == MT_LYELLDRDIAG
			or dashring.type == MT_LYELLDRVERT) then
				dashring.color = 47
				dashring.prefcolor = dashring.color
				dashring.activecolor = 55
				dashring.yellowtier = true
			end
			if (dashring.type == MT_LREDDR
			or dashring.type == MT_LREDDRDIAG
			or dashring.type == MT_LREDDRVERT) then
				dashring.color = 24
				dashring.prefcolor = dashring.color
				dashring.activecolor = 27
				dashring.redtier = true
			end
				
			local drt = dashring.type
				
			if drt == MT_LGREYDR or drt == MT_LGREYDRDIAG then dashring.info.mass = gh or dashring.info.mass end
			if drt == MT_LGREYDRVERT or drt == MT_LGREYDRDIAG then dashring.info.damage = gv or dashring.info.damage end
				
			if drt == MT_LYELLDR or drt == MT_LYELLDRDIAG then dashring.info.mass = yh or dashring.info.mass end
			if drt == MT_LYELLDRVERT or drt == MT_LYELLDRDIAG then dashring.info.damage = yv or dashring.info.damage end
			
			if drt == MT_LREDDR or drt == MT_LREDDRDIAG then dashring.info.mass = rh or dashring.info.mass end
			if drt == MT_LREDDRVERT or drt == MT_LREDDRDIAG then dashring.info.damage = rv or dashring.info.damage end
				
			if drt == MT_LBLUEDR or drt == MT_LBLUEDRDIAG then dashring.info.mass = bh or dashring.info.mass end
			if drt == MT_LBLUEDRVERT or drt == MT_LBLUEDRDIAG then dashring.info.damage = bv or dashring.info.damage end

			dashring.flags  = $ |MF_NOCLIP|MF_NOCLIPHEIGHT
			searchBlockmap("lines", function(dashring, tline)
				if tline.special == 1024 and not(dashring.spawnpoint.options & MTF_EXTRA) then
					dashring.increasev= 0
					dashring.refline = tline
					dashring.hmove = tline.frontside.textureoffset 
					dashring.hmovepeak = tline.frontside.textureoffset *2
					dashring.hmovespd = tline.frontside.rowoffset / FRACUNIT
					dashring.vmovepeak = tline.backside.textureoffset 
					dashring.vmovespd = tline.backside.rowoffset --/ FRACUNIT
					dashring.o = {x=dashring.x + FixedMul(dashring.hmove/2, cos(dashring.angle + ANGLE_90)),
					y=dashring.y + FixedMul(dashring.hmove/2, sin(dashring.angle + ANGLE_90)), z= dashring.z + (dashring.vmovepeak/2) }
					dashring.moveang = R_PointToAngle2(0, 0, tline.dx, tline.dy)
				end
				
			end, dashring)
		end
	end
	//////////////////////////////////////
	//          MANAGE PLAYERS
	/////////////////////////////////////
	for p in players.iterate do
		if p.DRT == nil then
			p.DRT={vspd = 0,
				  hspd = 0,
				  htspd = 0,
				  vtspd = 0,
				  dashed = false,
				  ang = 0,
				  flags = 0,
				  drc = {x=0,y=0,z=0},
				  drcd = 0,
				  color = 0,
				  lockprevent = 0,
				  driftstore = 0}
			--dont fucking use a local table to do this you idiot
			--unless you like desynchs LMAO
		end
		
		if not p.mo 
		or p.kartstuff[k_squishedtimer] ~= 0 
		or p.playerstate ~= PST_LIVE or
		p.mo.eflags & MFE_SPRUNG
		or p.wall ~= nil or p.LAS and p.LAS.speed > 0 or
		(p.kartstuff[k_spinouttimer] and p.mo.momz ~= 0) 
		or p.spectator 
		or (P_IsObjectOnGround(p.mo) and p.DRT.dashed == false)
		or p.mo.eflags & MFE_JUSTBOUNCEDWALL
		then p.DRT.hspd = 0 p.DRT.vspd = 0 p.DRT.htspd = 0 p.DRT.vtspd = 0   p.DRT.driftstore = 0 p.DRT.lockprevent = 0 end
	
		
		if (p.DRT.hspd > 0 
		and p.DRT.hspd > p.DRT.htspd/2)
		or p.DRT.vspd ~= 0 then
			
			if p.mo then
				p.mo.color = p.DRT.color
				K_SpawnSparkleTrailL(p.mo)
				p.mo.color = p.skincolor
														
				if p.DRT.vspd ~= 0 then
					p.mo.momz = p.DRT.vtspd 
				end
				if p.DRT.hspd ~= 0 
				and p.DRT.vspd == 0 then
					p.mo.momz = 0 
					p.mo.momx = FixedMul(p.DRT.htspd*2,cos( p.DRT.ang)) 
					p.mo.momy = FixedMul(p.DRT.htspd*2,sin( p.DRT.ang)) 
				end
				if p.DRT.hspd ~= 0 
				and p.DRT.vspd ~= 0 then 
					p.mo.momx = FixedMul(p.DRT.htspd,cos( p.DRT.ang)) 
					p.mo.momy = FixedMul(p.DRT.htspd,sin( p.DRT.ang)) 
					p.mo.momz = p.DRT.vtspd 
				end 
				if p.DRT.vspd ~= 0 
				and p.DRT.hspd == 0 then 
					p.mo.momx = 0
					p.mo.momy = 0
				end
			end
		end

		
		p.DRT.dashed = false
		
		if p.DRT.lockprevent > 4*FRACUNIT then
			p.DRT.lockprevent = 0
			p.DRT.hspd = 0
			p.DRT.vspd = 0
			p.DRT.htspd = 0
			p.DRT.vtspd = 0
			if p.mo then
				P_InstaThrust(p.mo, p.mo.angle, 20*FRACUNIT)
			end
		end
		
		--drift sdtore from dash rings
		if p.DRT.driftstore > 0 then
			p.kartstuff[k_driftcharge] = p.DRT.driftstore 
		end
		--cancel this fkag when youre not eing pushed
		
		
		if p.DRT.vspd > 0 then
			p.DRT.vspd = max( 0, $ - (FRACUNIT*42/100))
		end
		--im dumb dont judge me 
		if p.DRT.vspd < 0 then
			p.DRT.vspd = min( 0, $ + (FRACUNIT*42/100))
		end
		p.DRT.hspd = max( 0, $ - (FRACUNIT*42/100))
		if p.DRT.hspd <= p.DRT.htspd/2
		and p.DRT.hspd > 0 then
			--p.mo.flags = $ & ~ MF_NOGRAVITY
			p.DRT.hspd = 0
			p.DRT.htspd = 0
			p.DRT.vspd = 0
			p.DRT.vtspd = 0
			
		end				
	end	
end)


addHook("MobjThinker",function(mo)
	if not mo or mo and not mo.valid
	or not mo.isdashring then return end
	if mo.effecttimer and mo.effecttimer >= 0 then
		--their active effect
		mo.scale = FRACUNIT + (mo.effecttimer/8)
		mo.effecttimer = max(0,$- (FRACUNIT/2))
		mo.color = mo.activecolor
		if mo.effecttimer <=0 then
			mo.color = mo.prefcolor
		end
	end
	if mo.refline then
		--moving dashrings
		mo.increasev = (($ + (mo.vmovespd*32)))--%mo.vmovepeak+1
		mo.hmove = sin(leveltime*(FRACUNIT*(128+(10 *mo.hmovespd))))* (mo.hmovepeak/FRACUNIT)
		mo.vmove = FixedMul(mo.vmovepeak,sin(mo.increasev)) --sin(leveltime*(FRACUNIT*(128+(10 *mo.vmovespd))))* (mo.vmovepeak/FRACUNIT)
		P_TeleportMove(mo, 
			mo.o.x + FixedMul(mo.hmove, cos(mo.moveang)),
			mo.o.y + FixedMul(mo.hmove, sin(mo.moveang)), 
			mo.o.z + mo.vmove)

	end
end, MT_NULL)

local function dashcol(mt, mt2)
	--if not mt
	--or (mt and not mt.valid)
	---or not mt.isdashring then return  end
	
	--if not mt2
	--or (mt2 and not mt2.valid)
	--or not mt2.player 
	--or (mt2.player and not mt2.player.valid)
	--or mt2.player.spectator then return  end
	if not mt.isdashring then return end
	if not mt2.player then return true end
	--if mt2.player.dashringcd > 0 then return true end
	
	local p, dashring = mt2.player, mt
	local hscale = mapobjectscale + (mapobjectscale - p.mo.scale) 
	local vscale = mapobjectscale + (p.mo.scale - mapobjectscale)
	local vertispeed = dashring.info.damage
	local horizspeed = dashring.info.mass
	local finalSpeedH = FixedDiv(horizspeed, hscale)
	local finalSpeedV = FixedDiv(vertispeed, vscale) 
	local finhspeed = FixedMul(finalSpeedH,FRACUNIT*(100+(20*dashring.spawnpoint.extrainfo))/100) 
	local finvspeed = FixedMul(finalSpeedV,FRACUNIT*(100+(20*dashring.spawnpoint.extrainfo))/100) 
	
	--hcange player direction
	if dashring.spawnpoint.options & MTF_AMBUSH then p.mo.angle = dashring.angle end

	--making sure this works well
	--but im sure it shouldnt  cuz 0 * something is 0 LOL
	if dashring.info.damage == 0 then
		finvspeed = 0
	end
	if dashring.info.mass == 0 then
		finhspeed = 0
	end
	
	p.DRT.drc = {x=dashring.x, y=dashring.y, z=dashring.z}
	p.DRT.color = dashring.prefcolor
	p.DRT.hspd = finhspeed
	p.DRT.htspd = finhspeed
	p.DRT.vspd = finvspeed
	p.DRT.ang = dashring.angle
	p.DRT.flags = dashring.flags
	p.DRT.dashed = true
	
	--cant have  pogo springeffect
	p.kartstuff[k_pogospring] = 0
	if p.LAS then
		p.LAS.speed = 0 --no spring effect too
		p.LAS.sprung = false
	end

	if dashring.flags2 & MF2_OBJECTFLIP then p.DRT.vspd = $ *-1 end -- p.DRT.vspd = $ *2  end
	p.DRT.vtspd = p.DRT.vspd 
	p.mo.momz = p.DRT.vspd
	local offy,offx
	
	--diag and hori dash ring teleport you i nfront, taken from hardcode
	offx = FixedMul((mt.radius+ mt2.radius + 1)*2,cos(dashring.angle))
	offy = FixedMul((mt.radius+ mt2.radius + 1)*2,sin(dashring.angle))
		
	if offx > (mt.radius + mt2.radius + 1) then
		offx = mt.radius + mt2.radius + 1
	elseif offx < -(mt.radius + mt2.radius + 1) then
		offx = -(mt.radius + mt2.radius + 1)
	end

	if offy > (mt.radius + mt2.radius + 1) then
		offy = mt.radius + mt2.radius + 1
	elseif offy < -(mt.radius + mt2.radius + 1) then
		offy = -(mt.radius + mt2.radius + 1)
	end
	
	mt.flags = $ & ~MF_SPECIAL
	

	if finhspeed 
	and not finvspeed
	or finvspeed 
	and finhspeed then
		P_TryMove(mt2,mt.x + offx,mt.y + offy,true)
		if mt.spawnpoint.options & MTF_SPECIAL then
			--center vertically
			--also horizontally too
			offx = mt.x+ FixedMul((mt.radius+ mt2.radius + 1)*2,cos(dashring.angle))
			offy = mt.y+ FixedMul((mt.radius+ mt2.radius + 1)*2,sin(dashring.angle))
			P_TryMove(mt2,offx,offy,true)
			if dashring.flags2 & MF2_OBJECTFLIP then
				P_TeleportMove(mt2, mt2.x,mt2.y,mt.z-64*FRACUNIT)
			else
				P_TeleportMove(mt2, mt2.x,mt2.y,mt.z+64*FRACUNIT)
				
			end	
		end
	end
	if finvspeed 
	and not finhspeed
    or finvspeed 
	and finhspeed then
		
		--prevent softlock
		if finvspeed and not finhspeed then
			p.DRT.lockprevent = $ + FRACUNIT
		end
		if finhspeed and finvspeed then
			p.DRT.lockprevent = $ + FRACUNIT/2
		end
		
		if dashring.flags2 & MF2_OBJECTFLIP then
			P_TeleportMove(mt2, mt2.x,mt2.y,mt.z-(mt.height)-1)
		else
			P_TeleportMove(mt2, mt2.x,mt2.y,mt.z+(mt.height)+1)		
		end
		--center horizontally
		if mt.spawnpoint.options & MTF_SPECIAL then
			P_TeleportMove(mt2, mt.x,mt.y,mt2.z)
		end
	end

	S_StartSound(mt, sfx_nbmper) --SWOOOSH
	mt.flags = $ | MF_SPECIAL
	--alow drift store 
	if p.kartstuff[k_driftcharge] then
		p.DRT.driftstore = p.kartstuff[k_driftcharge]
	else
		p.DRT.driftstore = 0
	end
	--mt2.flags = $ |MF_NOGRAVITY --yes
	P_ResetPlayer(mt2.player)
	return true
	
end

addHook("TouchSpecial", dashcol, MT_NULL)

