-- Bikemod by RetroStation, inspired by minenice's Inside Drift

if not BikeMod then rawset(_G, "BikeMod", {}) else return end

local bikemod_enabled = CV_RegisterVar({
	name = "bikemod_enabled",
	defaultvalue = -1,
	flags = 0,
	PossibleValue = {Default = -1, Off = 0, On = 1}
})

BikeMod.Characters ={}
BikeMod.AddBike = function (...)
	local packedargs = {...}
	
	for k,v in ipairs(packedargs)
		if type(v.skin) ~= "string" then
			print ("ERROR: Invalid skin parameter - must be a string.")
			return
		end
		
		BikeMod.Characters[packedargs[k].skin] = {registered = true}
		print("Successfully registered "..packedargs[k].skin.." to BikeMod!")
	end
end



local id_outtable = { -- Outside Drift Angles
	[1] = 60, -- 94
	[2] = 78, -- 115
	[3] = 96, -- 136
	[4] = 114, -- 157
	[5] = 132, -- 178
	[6] = 150, -- 199
	[7] = 168, -- 220
	[8] = 186, -- 241
	[9] = 204 -- 262
}

local id_intable = { -- Inside Drift Angles
	[1] = 108, -- 84
	[2] = 102, -- 80
	[3] = 96, -- 77
	[4] = 90, -- 73
	[5] = 84, -- 70
	[6] = 78, -- 66
	[7] = 72, -- 63
	[8] = 66, -- 59
	[9] = 60  -- 56
}


-- Inside Drift in MKWii is busted, and this mod aims to normalize the mechanic.
-- Instead of applying a set amount of momentum during drifts, I instead decided 
-- to apply momentum proportionate to a character's Spark Rate. Additionally, 
-- the above tables' keys correspond to weight, making character support 
-- universal while also making this compatible with Hostmod's Restat. All 
-- applied momentum during drifts respects friction, or lack thereof, so you 
-- won't be gaining ludicrous amounts of speed if you decided to lean outward on 
-- an icy drift turn.

addHook("MobjThinker", function(mo)
	if FZeroKart and FZeroKart.Active.value then return end
	if (mo.player and mo.valid and ((BikeMod.Characters[mo.skin] and bikemod_enabled.value == -1) or bikemod_enabled.value == 1))
	and leveltime >= 236 then
		local p = mo.player
		local iangle = id_intable[p.kartweight]
		local oangle = id_outtable[p.kartweight]
		local pks = p.kartstuff
		local turnvalue = FixedDiv(p.cmd.angleturn*FRACUNIT, 800*FRACUNIT)
	
		--if leveltime%(5*TICRATE) == 0 then
			--print(K_GetKartDriftSparkValue(p))
			--print(FRACUNIT)
			--print((FRACUNIT + (30*FRACUNIT/32)))
		--end
		
		--pks[k_driftcharge] = min ($, K_GetKartDriftSparkValue(p))
		--pks[k_speedboost] = max($, (3*FRACUNIT)/20) -- +15%

		pks[k_accelboost] = max($, FRACUNIT/2) -- +50%
		
		-- Getting hit as a bike results in increased spinout. Amount of 
		-- extra spinout scales with spark rate as well, so god help you if you 
		-- get hit as Flicky.

		
		if pks[k_spinouttimer] then
			if p.indspin
				--print("Get fucked.")
				--if P_IsObjectOnGround(mo)
					--K_DropItems(p)
				--end
				pks[k_spinouttimer] = ($+1)+(K_GetKartDriftSparkValue(p)/100) -- Scales with spark rate
				p.indspin = false
			elseif p.indboom
				--print("Get fucked.")
				pks[k_spinouttimer] = ($+1)+(K_GetKartDriftSparkValue(p)/100)
				mo.momz = $*21/20
				p.indboom = false
			end
			--print(pks[k_spinouttimer])
		end
		

		if p.kartstuff[k_drift] > 0 then -- Left Drift
			if p.speed >= 10*mo.scale
			and P_IsObjectOnGround(mo)
			and not (p.pflags & PF_TIMEOVER) then
				if p.cmd.driftturn < 0 then
					P_Thrust(mo, mo.angle - oangle*ANG1, FixedMul(p.speed/23, ((K_GetKartDriftSparkValue(p))*65) - mo.friction))
				elseif p.cmd.driftturn >= 0 then
					P_Thrust(mo, mo.angle + iangle*ANG1, FixedMul(p.speed/18, ((K_GetKartDriftSparkValue(p))*75) - mo.friction))
					if p.speed < 29*mo.scale and p.speed >= 22*mo.scale and (p.cmd.buttons & BT_ACCELERATE) and not (p.cmd.buttons & BT_BRAKE) and not p.kartstuff[k_offroad] then
						P_Thrust(mo, mo.angle, 2*mo.scale/3)
					end
				end
			end
		elseif p.kartstuff[k_drift] < 0 then -- Right Drift
			if p.speed >= 10*mo.scale
			and P_IsObjectOnGround(mo)
			and not (p.pflags & PF_TIMEOVER) then
				if p.cmd.driftturn > 0 then
					P_Thrust(mo, mo.angle + oangle*ANG1, FixedMul(p.speed/23, ((K_GetKartDriftSparkValue(p))*65) - mo.friction))
				elseif p.cmd.driftturn <= 0 then
					P_Thrust(mo, mo.angle - iangle*ANG1, FixedMul(p.speed/18, ((K_GetKartDriftSparkValue(p))*75) - mo.friction))
					if p.speed < 29*mo.scale and p.speed >= 22*mo.scale and (p.cmd.buttons & BT_ACCELERATE) and not (p.cmd.buttons & BT_BRAKE) and not p.kartstuff[k_offroad] then
						P_Thrust(mo, mo.angle, 2*mo.scale/3)
					end
				end
			end
		end
		
		-- Without this, Bike sliptiding would be useless since it would default 
		-- to Kart's default sliptide turning radius, which is actually larger 
		-- than Bike's drift radius. Thank you Ridge Turnpike for making me 
		-- realize this.
		if pks[k_aizdriftstrat] and not pks[k_drift]
			if pks[k_aizdriftstrat] > 0 then -- Left Sliptide
				P_Thrust(mo, mo.angle + iangle*ANG1, FixedMul(p.speed/30, (FRACUNIT) - mo.friction))
			elseif pks[k_aizdriftstrat] < 0 -- Right Sliptide
				P_Thrust(mo, mo.angle - iangle*ANG1, FixedMul(p.speed/30, (FRACUNIT) - mo.friction))
			end
		end
	end
end, MT_PLAYER)


addHook("PlayerSpin", function(p, inf, source)
	if not (((inf and inf.valid) or (source and source.valid)) and ((BikeMod.Characters[p.mo.skin] and bikemod_enabled.value == -1) or bikemod_enabled.value == 1)) then return end
	p.indspin = true
end)
addHook("PlayerExplode", function(p, inf, source)
	if not (inf and inf.valid and ((BikeMod.Characters[p.mo.skin] and bikemod_enabled.value == -1) or bikemod_enabled.value == 1)) then return end
	p.indboom = true
end)

BikeMod.Init = true -- Do NOT run this a second time.