rawset(_G, "chaosdrives", {version = 2, update = 0, bugfix = 1})

freeslot("sfx_cdpk") --tried to declare this in SOC with no success but it works here!

--console vars
local cd_mode = CV_RegisterVar({
	name = "cd_mode",
	defaultvalue = "Normal",
	flags = CV_NETVAR,
	possiblevalue = {Off = 0, Normal = 1, Remix = 2, PerfectChaos = 3}
})
local cd_want_cuplength = CV_RegisterVar({
	name = "cd_cuplength",
	defaultvalue = 5,
	flags = CV_NETVAR,
	possiblevalue = CV_Natural
})
local cd_want_maxdrives = CV_RegisterVar({
	name = "cd_maxdrives",
	defaultvalue = 9,
	flags = CV_NETVAR,
	possiblevalue = CV_Natural
})
local cd_minimal = CV_RegisterVar({
	name = "cd_minimal",
	defaultvalue = "Off",
	flags = 0,
	possiblevalue = CV_OnOff
})

--gameplay code
chaosdrives.counter = 0
chaosdrives.currentcuplength = cd_want_cuplength.value
chaosdrives.max = cd_want_maxdrives.value
chaosdrives.inRace = false
local hostmod = false
local itemrain = false

local function cd_reward(pmo)
	if not pmo.player.cd_init or not cd_mode.value return end
	--set random here
	local player = pmo.player
	local reward = P_RandomKey(4)
	if reward == 0
		player.cd_run = min($ + 1, chaosdrives.max)
		player.cd_runLast = 0
	elseif reward == 1
		player.cd_swim = min($ + 1, chaosdrives.max)
		player.cd_swimLast = 0
	elseif reward == 2
		player.cd_fly = min($ + 1, chaosdrives.max)
		player.cd_flyLast = 0
	elseif reward == 3
		player.cd_power = min($ + 1, chaosdrives.max)
		player.cd_powerLast = 0
	else -- somebody's messing with things they shouldn't! or maybe i wanted to add extra drive types and never got to it.
		print("chaos drives had an oopsie!")
	end
end

local function cd_playerthink(pmo)
	if not cd_mode.value return end
	local player = pmo.player
	local safeoffroad = min(player.kartstuff[k_offroad], FRACUNIT)
	
	if not player.cd_init
		local mostDrives = 0
		for p in players.iterate do
			if p.cd_init == true
				mostDrives = max($, p.cd_run + p.cd_swim + p.cd_fly + p.cd_power)
			end
		end
	
		player.cd_init = true
		player.cd_run = 0
		player.cd_runLast = 35
		player.cd_swim = 0
		player.cd_swimLast = 35
		player.cd_fly = 0
		player.cd_flyLast = 35
		player.cd_power = 0
		player.cd_powerLast = 35
		player.cd_safeHandicap = (player.cd_wantHandicap or 0)
		player.cd_lastItemHeld = KITEM_NONE
		player.cd_boxSafety = 0
		
		--latejoiners roll drives an amount equal to whoever has the most "active" drives, with diminishing returns in the form of you-might-roll-Power-36-times
		local late = 0
		while (late < mostDrives)
			cd_reward(pmo)
			late = $ + 1
		end
	end
	
	if player.playerstate == PST_LIVE
		--normally i only check to see if the player kills a box for compatibility with item rain's stacking mode
		--so here's a hack for smk item panels and other weird modes of getting items.
		if (player.kartstuff[k_itemroulette] and player.kartstuff[k_itemroulette] <= 3) and (player.cd_boxSafety >= TICRATE) and cd_mode.value --for some reason custom item boxes only work with a little bit of leeway.
			cd_reward(pmo)
			player.cd_boxSafety = 0
		end
		
		--chaos drive buffs
		if cd_mode.value > 1
		    -- remix mode calculations start here.
			if cd_mode.value == 3
				player.cd_run, player.cd_swim, player.cd_fly, player.cd_power = 9, 9, 9, 9
			end
			
			-- variables for stat calculations.
			local sp = player.kartspeed
			local spm = min(sp + player.cd_run, 10) - player.cd_safeHandicap
			local ac = 9 - sp
			local acm = min(ac + player.cd_swim, 10) - player.cd_safeHandicap
			local we = player.kartweight
			local wem = min(we + player.cd_power, 10) - player.cd_safeHandicap
			local ha = 9 - we
			local ham = min(ha + player.cd_fly, 10) - player.cd_safeHandicap
			
			-- acceleration.
			local trueaccel = 32 + (4 * ac)
			local desiredaccel = 32 + (4 * acm)
			local acceldiff = FixedDiv(desiredaccel, trueaccel)
			
			-- speed.
			local g_cc = 56320 + (12288 * gamespeed)
			local shiftby = 14
			local truespeed = FixedMul((150 + sp*3)<<shiftby, g_cc)
			local desiredspeed = FixedMul((150 + spm*3)<<shiftby, g_cc)
			local speeddiff = FixedDiv(desiredspeed, truespeed)
				
			-- apply speed/accel modifications.
			player.kartstuff[k_accelboost] = FixedMul($, acceldiff) + (acceldiff-FRACUNIT)
			player.kartstuff[k_boostpower] = FixedMul($, speeddiff) + (speeddiff-FRACUNIT)
			
			-- used for handling calculations.
			local onground = P_IsObjectOnGround(player.mo)
			
			-- for drift handling.
			local function CD_GetKartDriftValue(countersteer, handling)
				if ((player.kartstuff[k_drift] == 0) or (not onground))
					return 0
				elseif (player.kartstuff[k_driftend] != 0)
					return -266*player.kartstuff[k_drift]
				else
					local driftweight = (9-handling)*14
					local basedrift = 83*player.kartstuff[k_drift] - (driftweight - 14)*player.kartstuff[k_drift]/5
					local driftangle = abs((252 - driftweight)*player.kartstuff[k_drift]/5)
					return basedrift + FixedMul(driftangle, countersteer)
				end
			end
			
			-- handling. sweet jesus.
			local turninput = player.cmd.driftturn		
			local function CD_GetKartTurnValue(t, weight)
			
				local p_maxspeed = FixedMul(desiredspeed, 3*FRACUNIT)
				local adjustangle = FixedDiv((p_maxspeed>>FRACBITS) - (player.speed>>FRACBITS), (p_maxspeed>>FRACBITS) + (10-weight))
				
				if (player.kartstuff[k_drift] != 0 and onground)
					if (player.kartstuff[k_driftend] == 0)
						local countersteer = FixedDiv(turninput*FRACUNIT, 800*FRACUNIT)
						t = CD_GetKartDriftValue(countersteer, ham) - CD_GetKartDriftValue(countersteer, ha)
					else
						t = $ + CD_GetKartDriftValue(FRACUNIT, ham) - CD_GetKartDriftValue(FRACUNIT, ha)
					end
				end
				t = FixedMul($, adjustangle)
				if(player.kartstuff[k_invincibilitytimer] or player.kartstuff[k_sneakertimer] or player.kartstuff[k_growshrinktimer] or (HugeQuest and player.huge > 0))
					t = FixedMul($, FixedDiv(5*FRACUNIT, 4*FRACUNIT))
				end
				return t
			end
			local trueturning = CD_GetKartTurnValue(turninput, ha)
			local desiredturning = CD_GetKartTurnValue(turninput, ham)
			local turningdiff = desiredturning - trueturning
			
			if(abs(player.speed) > 0)
				player.cmd.angleturn = $ + (turningdiff<<20)
			end
		else
			-- not remix mode!
			-- calculate acceleration bonus, use k_offroad to scale the bonus.
			local run_calc = max(player.cd_run - player.cd_safeHandicap, -9) * FixedDiv(FRACUNIT - safeoffroad, 20 * FRACUNIT)
			-- drag efficiency as a secondary function for power. use k_bananadrag to scale the bonus. 
			-- under normal circumstances, your speed is reduced to 80% when bananadragging.
			local power_calc = 0
			if player.kartstuff[k_bananadrag] > TICRATE
				power_calc = max(player.cd_power - player.cd_safeHandicap, -9) * FixedDiv(FRACUNIT, 80 * FRACUNIT)
			end
			-- offroad efficiency. having this maximum too low literally brings handicapped players to a dead stop in offroad, so never let the player count as lower than -4 under any circumstances.
			-- under normal circumstances, a player's speed is reduced by 50% in offroad.
			local swim_calc = max(player.cd_swim - player.cd_safeHandicap, -4) * FixedDiv(safeoffroad, 20 * FRACUNIT)
			
			player.kartstuff[k_accelboost] = $ + run_calc
			player.kartstuff[k_boostpower] = $ + max(swim_calc, power_calc)
		end
	end
	
	if player.cd_lastItemHeld == KITEM_NONE and cd_mode.value == 1
		local tempPower = player.cd_power - player.cd_safeHandicap
		if player.kartstuff[k_itemtype] == KITEM_BANANA and player.kartstuff[k_itemamount] <= 10
			player.kartstuff[k_itemamount] = max(1, min(10, $ + tempPower/3))
		elseif player.kartstuff[k_itemtype] == KITEM_ORBINAUT and player.kartstuff[k_itemamount] <= 4
			player.kartstuff[k_itemamount] = max(1, min(4, $ + tempPower/2))
		elseif player.kartstuff[k_itemtype] == KITEM_JAWZ and player.kartstuff[k_itemamount] <= 2
			player.kartstuff[k_itemamount] = max(1, min(2, $ + tempPower/5))
		end
	end
	
	player.cd_runLast = min($ + 1, TICRATE)
	player.cd_swimLast = min($ + 1, TICRATE)
	player.cd_flyLast = min($ + 1, TICRATE)
	player.cd_powerLast = min($ + 1, TICRATE)
	player.cd_boxSafety = min($ + 1, TICRATE)
	player.cd_lastItemHeld = player.kartstuff[k_itemtype]
end

local function cd_racethink()
	if CV_FindVar("hm_scoreboard") and not hostmod --check for hostmod every frame, see if scoreboard is on.
		HM_Scoreboard_AddMod({disp = "Chaos Drives", var = "cd_mode"}) --hostmod manages displaying/hiding this for us.
		hostmod = true
	end
	if itemraindefs and not itemraindefs.sprinkles --check if item rain 
		itemraindefs.sprinkles = {{held = KITEM_NONE, trap = MT_RUNDRIVE, rainmin = 1, rainmax = 1, rainchance = 1, boxmin = 0, boxmax = 0, boxchance = 1},
		{held = KITEM_NONE, trap = MT_SWIMDRIVE, rainmin = 1, rainmax = 1, rainchance = 1, boxmin = 0, boxmax = 0, boxchance = 1},
		{held = KITEM_NONE, trap = MT_FLYDRIVE, rainmin = 1, rainmax = 1, rainchance = 1, boxmin = 0, boxmax = 0, boxchance = 1},
		{held = KITEM_NONE, trap = MT_POWERDRIVE, rainmin = 1, rainmax = 1, rainchance = 1, boxmin = 0, boxmax = 0, boxchance = 1}}
	end
	if not chaosdrives.inRace and leveltime == 1
		chaosdrives.inRace = true
	end
	if chaosdrives.inRace
		for player in players.iterate
		    if (not (player or player.mo))
				continue
			end
			--finally drift stuff
			if (player.kartstuff[k_spinouttimer] == 0 and player.kartstuff[k_jmp] == 1 and P_IsObjectOnGround(player.mo) and player.kartstuff[k_drift] != 0)
				local driftadditivem
				if cd_mode.value > 1
					local ac = 10 - player.kartspeed
					local acm = min(ac + player.cd_swim, 10) - player.cd_safeHandicap
					local we = player.kartweight
					local wem = min(we + player.cd_power, 10) - player.cd_safeHandicap
					
					--calculate how many drift points the player is expected to get (this is the same for everybody regardless of their skin's stats)
					--local driftadditive = 24

					--if (player.kartstuff[k_drift] >= 1)
						--if (player.cmd.driftturn > 0)
							--driftadditive = $ + abs(player.cmd.driftturn)/100
						--elseif (player.cmd.driftturn < 0)
							--driftadditive = $ - abs(player.cmd.driftturn)/75
						--end
					--elseif (player.kartstuff[k_drift] <= -1)
						--if (player.cmd.driftturn < 0)
							--driftadditive = $ + abs(player.cmd.driftturn)/100
						--elseif (player.cmd.driftturn > 0)
							--driftadditive = $ - abs(player.cmd.driftturn)/75
						--end
					--end

					--if (player.kartstuff[k_getsparks] == 0 or (player.kartstuff[k_offroad] and !player.kartstuff[k_invincibilitytimer] and !player.kartstuff[k_hyudorotimer] and !player.kartstuff[k_sneakertimer]))
						--driftadditive = 0
					--end
						
					----calculate drift spark rate, use the difference as a multiplier to finely adjust the player's current drift progress.
					--local truedsr = (26*4 + ((9-ac)*2) + (9 - we))*8
					--local desireddsr = (26*4 + ((9-acm)*2) + (9 - wem))*8
					--local dsrdiff = FixedDiv(truedsr * FRACUNIT, desireddsr * FRACUNIT)
						
					--local driftadditivem = FixedMul(driftadditive * FRACUNIT, dsrdiff)>>(FRACBITS)
					
					--unfortunately k_driftcharge stuff is at such a low scale that multiplying like this just doesn't seem to work. so, instead...
				
					driftadditivem = (((acm-ac)*2) + (wem-we))/2
				elseif cd_mode.value == 1
					driftadditivem = (player.cd_fly - player.cd_safeHandicap)
				end
				if driftadditivem != 0
					local dsone = K_GetKartDriftSparkValue(player)
					local dstwo = dsone * 2
					local dsthree = dstwo * 2
					if ((player.kartstuff[k_driftcharge] < dsone and player.kartstuff[k_driftcharge]+driftadditivem >= dsone)
						or (player.kartstuff[k_driftcharge] < dstwo and player.kartstuff[k_driftcharge]+driftadditivem >= dstwo)
						or (player.kartstuff[k_driftcharge] < dsthree and player.kartstuff[k_driftcharge]+driftadditivem >= dsthree))
						S_StartSoundAtVolume(player.mo, sfx_s3ka2, 192, player);
					end
					player.kartstuff[k_driftcharge] = $ + driftadditivem
				end
			end
		end
	end
end

local function cd_resetcuplength()
	chaosdrives.counter = 0
	chaosdrives.currentcuplength = cd_want_cuplength.value
	chaosdrives.max = cd_want_maxdrives.value
	if cd_mode.value > 0
		chatprint("\x8b[Chaos Drives]\x80 The current Cup has ended! Progress reset.", true)
	end
	local cd_handicaptext = ""
	local cd_firstItem = true
	for p in players.iterate do
		p.cd_init = false
		if p.cd_wantHandicap and p.cd_wantHandicap > 0
			if cd_firstItem
				cd_handicaptext = $ .. p.name .. " (" .. p.cd_wantHandicap .. ")"
				cd_firstItem = false
			else
				cd_handicaptext = $ .. ", " .. p.name .. " (" .. p.cd_wantHandicap .. ")"
			end
		end
	end
	if (not cd_firstItem) and cd_mode.value > 0
		chatprint("\x8b[Chaos Drives]\x80 Handicaps: " .. cd_handicaptext, false)
	end
end

local function cd_interthink()
	if chaosdrives.inRace == false or cd_want_cuplength.value == 999999999 or not cd_mode.value
		return
	end
	if chaosdrives.inRace and chaosdrives.currentcuplength ~= cd_want_cuplength.value
		cd_resetcuplength()
		chaosdrives.inRace = false
	elseif (chaosdrives.counter + 1) < chaosdrives.currentcuplength
		local cd_remaining = chaosdrives.currentcuplength - chaosdrives.counter - 1
		if (cd_remaining) == 1
			chatprint("\x8b[Chaos Drives]\x80 The current Cup will end next course.")
		elseif (cd_remaining) <= 25
			chatprint("\x8b[Chaos Drives]\x80 The current Cup will end in " .. cd_remaining .. " courses.")
		end
		chaosdrives.counter = $ + 1
		chaosdrives.inRace = false
	else
		cd_resetcuplength()
		chaosdrives.inRace = false
	end
end

local function cd_spawndrive(pmo, cdt)
	local thisdrive = P_SpawnMobj(pmo.x, pmo.y, pmo.z, cdt)
	thisdrive.cd_source = pmo
	thisdrive.threshold = pmo.player.laps
	thisdrive.fuse = TICRATE * 120
end

local function cd_hitreward(vic, src, pmo)
	if not cd_mode.value return end
	if not vic or not vic.valid 
		return
	end
	local reward = P_RandomKey(4)
	if reward == 0
		cd_spawndrive(vic.mo, MT_RUNDRIVE)
	elseif reward == 1
		cd_spawndrive(vic.mo, MT_SWIMDRIVE)
	elseif reward == 2
		cd_spawndrive(vic.mo, MT_FLYDRIVE)
	elseif reward == 3
		cd_spawndrive(vic.mo, MT_POWERDRIVE)
	end
end

-- HUD code

hud.add(function(cdhud, player, cam)
	if not player.cd_init or not cd_mode.value return end
	local cd_huds = { cdhud.cachePatch("K_CHDB"), cdhud.cachePatch("K_CHDC"), cdhud.cachePatch("K_CHDD"), cdhud.cachePatch("K_CHDE") }
	
	local baseX = 160
	local baseY = 176
	
	if (splitscreen == 1 and cam.pnum == 1)
		baseY = 76
	elseif (splitscreen >= 2 and cam.pnum == 1)
		baseX = 80
		baseY = 76
	elseif (splitscreen >= 2 and cam.pnum == 2)
		baseX = 240
		baseY = 76
	elseif (splitscreen >= 2 and cam.pnum == 3)
		baseX = 80
		baseY = 176
	elseif (splitscreen >= 2 and cam.pnum == 4)
		baseX = 240
		baseY = 176
	end
	
	local runColor = V_TRANSLUCENT
	if player.cd_runLast % 6 < 3 and player.cd_runLast <= 33
		runColor = V_80TRANS
	end
	
	local swimColor = V_TRANSLUCENT
	if player.cd_swimLast % 6 < 3 and player.cd_swimLast <= 33
		swimColor = V_80TRANS
	end
	
	local flyColor = V_TRANSLUCENT
	if player.cd_flyLast % 6 < 3 and player.cd_flyLast <= 33
		flyColor = V_80TRANS
	end
	
	local powerColor = V_TRANSLUCENT
	if player.cd_powerLast % 6 < 3 and player.cd_powerLast <= 33
		powerColor = V_80TRANS
	end
	
	if cd_minimal.value
		if cd_mode.value != 3
			cdhud.drawString(baseX-24, baseY, player.cd_run - player.cd_safeHandicap, runColor|V_GREENMAP, "center")
			cdhud.drawString(baseX-8, baseY, player.cd_swim - player.cd_safeHandicap, swimColor|V_YELLOWMAP, "center")
			cdhud.drawString(baseX+8, baseY, player.cd_fly - player.cd_safeHandicap, flyColor|V_PURPLEMAP, "center")
			cdhud.drawString(baseX+24, baseY, player.cd_power - player.cd_safeHandicap, powerColor|V_REDMAP, "center")
		end
	else
		if cd_mode.value == 3
			local c = {"\x80", "\x85", "\x87", "\x82", "\x83", "\x84", "\x81", "\x80", "\x85", "\x87", "\x82", "\x83", "\x84", "\x81", "\x80", "\x85", "\x87", "\x82", "\x83", "\x84", "\x81"}
			local d = #c/3
			local g = (leveltime/15) % d + 1
			local t = "PERFECT CHAOS"
			local f = ""
			for x = 1, #t do
				local y = c[g+x]..string.sub(t, x, x)
				f = f..y
			end
			cdhud.drawString(baseX, baseY, f, V_TRANSLUCENT, "center")
		else
			cdhud.draw(baseX-48, baseY, cd_huds[1], runColor)
			cdhud.drawNum(baseX-24, baseY+12, player.cd_run - player.cd_safeHandicap, V_20TRANS)
			
			cdhud.draw(baseX-24, baseY, cd_huds[2], swimColor)
			cdhud.drawNum(baseX, baseY+12, player.cd_swim - player.cd_safeHandicap, V_20TRANS)
			
			cdhud.draw(baseX, baseY, cd_huds[3], flyColor)
			cdhud.drawNum(baseX+24, baseY+12, player.cd_fly - player.cd_safeHandicap, V_20TRANS)
			
			cdhud.draw(baseX+24, baseY, cd_huds[4], powerColor)
			cdhud.drawNum(baseX+48, baseY+12, player.cd_power - player.cd_safeHandicap, V_20TRANS)
		end
	end
end, "game")

-- hooks

addHook("MobjDeath", function(box, pmo, source)
	if box and box.valid and pmo and pmo.valid and pmo == source
		pmo.player.cd_boxSafety = 0
		cd_reward(pmo)
	end
end, MT_RANDOMITEM)

--MobjDamage doesn't seem to work for rewarding on hits, but oh hey, these hooks do!
addHook("PlayerSpin", cd_hitreward, MT_PLAYER)
addHook("PlayerExplode", cd_hitreward, MT_PLAYER)
addHook("PlayerSquish", cd_hitreward, MT_PLAYER)

--initialize stats, and apply bonuses during thinking if possible.
addHook("MobjThinker", cd_playerthink, MT_PLAYER)

--check collision against chaos drives
addHook("MobjMoveCollide", function(pmo, box)
	if box and box.valid and box.type != MT_RUNDRIVE and box.type != MT_SWIMDRIVE and box.type != MT_FLYDRIVE and box.type != MT_POWERDRIVE
		return
	end
	if box and box.valid and pmo.z + pmo.height*2 >= box.z and pmo.z <= box.z + box.height then
		if pmo == box.cd_source and pmo.player.laps <= box.threshold
			return false
		else
			local player = pmo.player
			if box.state == S_RUNDRIVE
				player.cd_run = min($ + 1, chaosdrives.max)
				player.cd_runLast = 0
			elseif box.state == S_SWIMDRIVE
				player.cd_swim = min($ + 1, chaosdrives.max)
				player.cd_swimLast = 0
			elseif box.state == S_FLYDRIVE
				player.cd_fly = min($ + 1, chaosdrives.max)
				player.cd_flyLast = 0
			elseif box.state == S_POWERDRIVE
				player.cd_power = min($ + 1, chaosdrives.max)
				player.cd_powerLast = 0
			end
			if sfx_cdpk -- Hopefully catch cases where there are too many sounds slotted.
				S_StartSoundAtVolume(nil, sfx_cdpk, 191, player) 
			end
			P_KillMobj(box, pmo)
			player.kartstuff[k_driftboost] = $ + TICRATE -- tiny speed boost to reward pickups even at max drives.
			return
		end
	end
end, MT_PLAYER)

--server stuff.
addHook("ThinkFrame", cd_racethink)
addHook("IntermissionThinker", cd_interthink)
addHook("NetVars", function(net) rawset(_G, "chaosdrives", net(_G.chaosdrives)) end)

--console commands
COM_AddCommand("cd_handicap", function(player, num)
	if tonumber(num) or num == "0"
		player.cd_wantHandicap = max(0, min(19, abs(tonumber(num))))
		CONS_Printf(player, "Your handicap will become " .. player.cd_wantHandicap .. " at the earliest opportunity.")
	end
end)
COM_AddCommand("cd_reset", function(player)
	if player == server or IsPlayerAdmin(player)
		cd_resetcuplength()
	else
		CONS_Printf(player, "Who died and made you Chaos Drive god?")
	end
end)

--weight hack for remix mode

local function CD_KartBouncing (mobj1, mobj2, bounce, solid)
	local we1 = mobj1.player.kartweight
	local wem1 = min(we1 + mobj1.player.cd_power, 10) - mobj1.player.cd_safeHandicap
	local we2 = mobj2.player.kartweight
	local wem2 = min(we2 + mobj2.player.cd_power, 10) - mobj2.player.cd_safeHandicap
	
	mobj1.player.kartweight = wem1
	mobj2.player.kartweight = wem2
	K_KartBouncing(mobj1, mobj2, bounce, solid)
	mobj1.player.kartweight = we1
	mobj2.player.kartweight = we2
end

addHook("MobjCollide", function(player, mover)
	if (cd_mode.value < 2) or not(player.player) or not (mover.player)
		return --you're not a player, get outta here.
	elseif (mover.z > player.z + player.height) or (mover.z + mover.height < player.z)
		return
	elseif (player.player.kartstuff[k_squishedtimer]
	or player.player.kartstuff[k_hyudorotimer]
	or player.player.kartstuff[k_justbumped]
	or player.scale > mover.scale + (mapobjectscale/8)
	or mover.player.kartstuff[k_squishedtimer]
	or mover.player.kartstuff[k_hyudorotimer]
	or mover.player.kartstuff[k_justbumped]
	or mover.scale > player.scale + (mapobjectscale/8))
		return
	elseif (G_BattleGametype() and ((player.player.kartstuff[k_bumper] and !mover.player.kartstuff[k_bumper]) or (mover.player.kartstuff[k_bumper] and !player.player.kartstuff[k_bumper])))
		return
	elseif (P_IsObjectOnGround(player) and mover.momz < 0)
		CD_KartBouncing(mover, player, true, false)
		if (G_BattleGametype() and mover.player.kartstuff[k_pogospring])
			K_StealBumper(mover.player, player.player, false)
			K_SpinPlayer(player.player, mover, 0, mover, false)
		end
	elseif (P_IsObjectOnGround(mover) and player.momz < 0)
		CD_KartBouncing(player, mover, true, false)
		if (G_BattleGametype() and player.player.kartstuff[k_pogospring])
			K_StealBumper(player.player, mover.player, false)
			K_SpinPlayer(mover.player, player, 0, player, false)
		end
	else
		CD_KartBouncing(mover, player, false, false)
		if (G_BattleGametype())
			if (player.player.kartstuff[k_sneakertimer] and !(mover.player.kartstuff[k_sneakertimer]) and !(player.player.powers[pw_flashing]))
				K_StealBumper(player.player, mover.player, false)
				K_SpinPlayer(mover.player, player, 0, mover, false)
			else if (mover.player.kartstuff[k_sneakertimer] and !(player.player.kartstuff[k_sneakertimer]) and !(mover.player.powers[pw_flashing]))
				K_StealBumper(mover.player, player.player, false)
				K_SpinPlayer(player.player, mover, 0, player, false)
			end
		end
	end		
end
end, MT_PLAYER)