freeslot("S_PLAY_OVERDRIVECHARGE",
 "S_PLAY_OVERDRIVEATTACK",
 "S_OVERDRIVEFX",
 "S_OVERDRIVEAURA",
 "SPR2_CHRG", 
 "SPR2_OVRD",
 "SPR_ODFX",
 "SPR_OCFX",
 "MT_OVERDRIVEFX",
 "MT_OVERDRIVEAURA",
 "sfx_movrdr",
 "sfx_mochrg",
 "sfx_moredy",
 "SKINCOLOR_SUPER_TOPAZ1",
 "SKINCOLOR_SUPER_TOPAZ2",
 "SKINCOLOR_SUPER_TOPAZ3",
 "SKINCOLOR_SUPER_TOPAZ4",
 "SKINCOLOR_SUPER_TOPAZ5")
 
skincolors[SKINCOLOR_SUPER_TOPAZ1] = {
    name = "Super Topaz 1",
    ramp = {0,0,0,0,0,80,81,82,72,72,73,73,74,75,76,67},
    invcolor = SKINCOLOR_ORANGE,
    invshade = 9,
    chatcolor = V_BLUEMAP,
    accessible = false
}
skincolors[SKINCOLOR_SUPER_TOPAZ2] = {
    name = "Super Topaz 2",
    ramp = {0,0,0,0,80,81,82,72,73,73,74,74,75,76,67,68},
    invcolor = SKINCOLOR_ORANGE,
    invshade = 9,
    chatcolor = V_BLUEMAP,
    accessible = false
}
skincolors[SKINCOLOR_SUPER_TOPAZ3] = {
    name = "Super Topaz 3",
    ramp = {0,0,0,80,81,82,72,73,74,74,75,76,67,68,69,69},
    invcolor = SKINCOLOR_ORANGE,
    invshade = 9,
    chatcolor = V_BLUEMAP,
    accessible = false
}
skincolors[SKINCOLOR_SUPER_TOPAZ4] = {
    name = "Super Topaz 4",
    ramp = {0,0,80,81,82,72,73,74,74,75,76,67,68,69,70,70},
    invcolor = SKINCOLOR_ORANGE,
    invshade = 9,
    chatcolor = V_BLUEMAP,
    accessible = false
}
skincolors[SKINCOLOR_SUPER_TOPAZ5] = {
    name = "Super Topaz 5",
    ramp = {0,80,81,82,72,73,74,74,75,76,67,68,69,70,70,46},
    invcolor = SKINCOLOR_ORANGE,
    invshade = 9,
    chatcolor = V_BLUEMAP,
    accessible = false
}

local charge = S_PLAY_OVERDRIVECHARGE
states[charge].sprite = SPR_PLAY
states[charge].frame = SPR2_CHRG
states[charge].tics = -1
states[charge].nextstate = S_PLAY_OVERDRIVECHARGE

local overdrive = S_PLAY_OVERDRIVEATTACK
states[overdrive].sprite = SPR_PLAY
states[overdrive].frame = SPR2_OVRD|FF_FULLBRIGHT|FF_ANIMATE
states[overdrive].var1 = 1
states[overdrive].var2 = 1
states[overdrive].tics = -1
states[overdrive].nextstate = S_PLAY_OVERDRIVEATTACK

mobjinfo[MT_OVERDRIVEFX] = {
	spawnstate = S_OVERDRIVEFX,
	spawnhealth = 1,
    deathstate = S_NULL,
	dispoffset = -1,
    speed = FRACUNIT,
    radius = FRACUNIT,
    height = FRACUNIT,
	flags = MF_SCENERY|MF_NOGRAVITY|MF_NOCLIPTHING
}

local effect = S_OVERDRIVEFX
states[effect].sprite = SPR_OCFX
states[effect].frame = FF_FULLBRIGHT|FF_ANIMATE
states[effect].var1 = 6
states[effect].var2 = 1
states[effect].tics = -1
states[effect].nextstate = S_OVERDRIVEFX

mobjinfo[MT_OVERDRIVEAURA] = {
	spawnstate = S_OVERDRIVEAURA,
	spawnhealth = 1,
    deathstate = S_NULL,
	dispoffset = -1,
    speed = FRACUNIT,
    radius = FRACUNIT,
    height = FRACUNIT,
	flags = MF_SCENERY|MF_NOGRAVITY|MF_NOCLIPTHING
}

local aura = S_OVERDRIVEAURA
states[aura].sprite = SPR_ODFX
states[aura].frame = FF_FULLBRIGHT|FF_ANIMATE
states[aura].var1 = 1
states[aura].var2 = 1
states[aura].tics = -1
states[aura].nextstate = S_OVERDRIVEAURA

sfxinfo[sfx_movrdr].caption = "Overdrive Attack"
sfxinfo[sfx_mochrg].caption = "Overdrive Charging"
sfxinfo[sfx_moredy].caption = "Overdrive Ready"

local function FlipObjectFromObject(mo, master)
  mo.flags2 = ($ & ~MF2_OBJECTFLIP) | (master.flags2 & MF2_OBJECTFLIP)
  mo.eflags = ($ & ~MFE_VERTICALFLIP) | (master.eflags & MFE_VERTICALFLIP)
end

addHook("PlayerThink", function(player)
	if player.mo and player.mo.valid and player.mo.skin == "metalsonic"
		if player.overdrivechargetimer == nil
			player.overdrivechargetimer = 0
		end
		if player.overdrivepulsetimer == nil
			player.overdrivepulsetimer = 0
		end
		if player.dooverdriveattack == nil
			player.dooverdriveattack = false
		end
		if player.overdriveattacktimer == nil
			player.overdriveattacktimer = 0
		end
		if player.odstats == nil
			player.odstats = false
		end
		if player.resetod == nil
			player.resetod = false
		end
		if P_PlayerInPain(player)
		or (player.pflags & PF_SLIDING)
		or player.powers[pw_carry]
		or player.spectator
		or player.playerstate != PST_LIVE
		or not player.mo.health
		or player.panim == PA_PAIN
		or player.iseggrobo
		or (player.dirk_frozen)
		or (player.gotflag or player.gotcrystal)
		or player.powers[pw_nocontrol]
		or player.exiting
			player.resetod = true
		else
			player.resetod = false
		end
		local flip = (P_MobjFlip(player.mo) == 1) and 0 or player.mo.height+(20*FU)
		//Overdrive charge checks
		if P_IsObjectOnGround(player.mo)
		and player.resetod == false
			if player.cmd.buttons & BT_CUSTOM2 -- Is the player holding custom 2?
			and not player.dooverdriveattack
			and not ((player.mo.state == S_PLAY_SPINDASH) or (player.pflags & PF_SPINNING))
				if ((player.overdrivechargetimer < 85) and not (player.powers[pw_sneakers] or player.powers[pw_super])) --Is the charge timer below 85 without shoes/super?
				or ((player.overdrivechargetimer < 50) and (player.powers[pw_sneakers] or player.powers[pw_super]))
					player.overdrivechargetimer = $ + 1
				end
				if player.overdrivechargetimer >= 1
					player.mo.momz = 0
				end
				if not (leveltime & 3)
				and player.overdrivechargetimer >= 2
				and player.mo.state == S_PLAY_OVERDRIVECHARGE
					S_StartSound(player.mo, sfx_s3k5c)
				end
				if not player.c2down
				and ((player.overdrivechargetimer < 85) or ((player.overdrivechargetimer < 50) and (player.powers[pw_sneakers] or player.powers[pw_super])))
				and not player.dooverdriveattack
					player.c2down = true
					player.mo.state = S_PLAY_OVERDRIVECHARGE
					player.mo.momx = FixedMul($, FRACUNIT*88/100)
					player.mo.momy = FixedMul($, FRACUNIT*88/100)
					local effect = P_SpawnMobjFromMobj(player.mo, 0, 0, flip, MT_OVERDRIVEFX)
					effect.source = player.mo
					S_StartSound(player.mo, sfx_mochrg)
				end
				player.pflags = $|PF_STASIS
			else
				player.c2down = false
				if player.mo.state == S_PLAY_OVERDRIVECHARGE
				and (((player.overdrivechargetimer < 85) and not (player.powers[pw_sneakers] or player.powers[pw_super])) or ((player.overdrivechargetimer < 50) and (player.powers[pw_sneakers] or player.powers[pw_super]))) --Why does this conditional need to arbitrarily be a chungus?
					player.mo.state = S_PLAY_STND
					S_StopSoundByID(player.mo, sfx_mochrg)
					S_StartSound(player.mo, sfx_kc65)
					player.overdrivechargetimer = 0
				elseif ((player.overdrivechargetimer >= 85) or ((player.overdrivechargetimer >= 50) and (player.powers[pw_sneakers] or player.powers[pw_super])))
				and player.dooverdriveattack == false
					player.dooverdriveattack = true
					S_StartSound(player.mo, sfx_movrdr)
					player.mo.state = S_PLAY_OVERDRIVEATTACK
					player.charflags = SF_MACHINE|SF_MULTIABILITY|SF_SUPER|SF_RUNONWATER|SF_CANBUSTWALLS
					player.normalspeed = 72*FRACUNIT
					player.jumpfactor = skins[player.mo.skin].jumpfactor*2
					player.charability = CA_NONE
					player.charability2 = CA2_NONE
					if not player.cmd.forwardmove
						player.cmd.forwardmove = 50 
					end
					P_InstaThrust(player.mo, player.mo.angle, 102*FRACUNIT)
					local aura = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z*P_MobjFlip(player.mo), MT_OVERDRIVEAURA)
					aura.scale = player.mo.scale
					aura.source = player.mo
					player.overdrivechargetimer = 0
					player.odstats = true
				end
			end
			if player.c2down == true
			and player.mo.state ~= S_PLAY_OVERDRIVECHARGE
				player.overdrivechargetimer = 0
				player.pflags = $ & ~PF_STASIS
			end
			if player.dooverdriveattack
				if player.overdriveattacktimer < 3
					player.overdriveattacktimer = $ + 1
				end
			end
			if ((player.overdrivechargetimer >= 85) or ((player.overdrivechargetimer >= 50) and (player.powers[pw_sneakers] or player.powers[pw_super])))
				player.overdrivepulsetimer = $ + 1
				player.mo.frame = B|FF_FULLBRIGHT
			end
			if player.overdrivepulsetimer >= 2
				player.overdrivepulsetimer = 0
				player.mo.frame = A
			end
		end
		if not P_IsObjectOnGround(player.mo)
			player.overdrivechargetimer = 0
		end
		if player.dooverdriveattack
			player.mo.state = S_PLAY_OVERDRIVEATTACK
			player.mo.frame = (leveltime % 2)|FF_FULLBRIGHT
		end
		if ((player.overdrivechargetimer == 84) or ((player.overdrivechargetimer == 49) and (player.powers[pw_sneakers] or player.powers[pw_super])))
		and player.mo.state == S_PLAY_OVERDRIVECHARGE
			S_StartSound(player.mo, sfx_moredy)
		end
		if ((player.overdriveattacktimer >= 3) and (player.speed < 15*FRACUNIT))
		or ((player.overdriveattacktimer >= 3) and (player.mo.state ~= S_PLAY_OVERDRIVEATTACK))
			player.overdriveattacktimer = 0
			player.dooverdriveattack = false
			S_StartSound(player.mo, sfx_kc65)
			player.normalspeed = 36*FRACUNIT
			player.jumpfactor = skins[player.mo.skin].jumpfactor
			player.charability = CA_FLOAT
			player.charability2 = CA2_SPINDASH
			player.charflags = SF_MACHINE|SF_MULTIABILITY|SF_SUPER|SF_DASHMODE
			player.mo.state = S_PLAY_WALK
			player.odstats = false
		end
	end
end)

addHook("MobjThinker", function(mo)
    if not mo.source return end
    mo.lifetime = $ or 0
	mo.angle = mo.source.player.drawangle
	local ghost = P_SpawnGhostMobj(mo)
	ghost.rollangle = mo.rollangle
	ghost.blendmode = AST_ADD
	P_TeleportMove(mo, mo.source.x + mo.lifetime * mo.momx, mo.source.y + mo.lifetime * mo.momy, mo.source.z + 17*FRACUNIT + mo.lifetime * mo.momz)
    mo.lifetime = $ + 1
	if mo.source.player.dooverdriveattack == false
		P_RemoveMobj(mo)
	end
end, MT_OVERDRIVEAURA)

addHook("MobjThinker", function(mo)
    if not mo.source return end
    mo.lifetime = $ or 0
	mo.angle = mo.source.player.drawangle
	mo.rollangle = $ + FixedAngle((FU*360)/9)
	FlipObjectFromObject(mo, mo.source)
	local flip = (P_MobjFlip(mo.source) == 1) and 0 or mo.source.height+(17*FU)
	local z = 17*mo.scale
	if mo.eflags & MFE_VERTICALFLIP
		z = -$ + mo.source.z + mo.source.height - mo.height
	else
		z = $ + mo.source.z
	end
	P_TeleportMove(mo, mo.source.x + mo.lifetime * mo.momx, mo.source.y + mo.lifetime * mo.momy, z + mo.lifetime * mo.momz)
    mo.lifetime = $ + 1
	if not mo.source.player.overdrivechargetimer
	or mo.source.state ~= S_PLAY_OVERDRIVECHARGE
	or not P_IsObjectOnGround(mo.source)
	or mo.source.player.resetod
		P_RemoveMobj(mo)
	end
end, MT_OVERDRIVEFX)

addHook("PlayerCanDamage", function(player, mobj)
	if player.mo and player.mo.valid and player.mo.skin == "metalsonic"
		if player.mo.state == S_PLAY_OVERDRIVECHARGE
		and P_IsObjectOnGround(player.mo)
			P_DamageMobj(mobj, player.mo, source, 1, damagetype)
			return true
		elseif player.dooverdriveattack
		or player.powers[pw_super]
			P_DamageMobj(mobj, player.mo, source, 2, damagetype)
			return true
		end
	end
end)

addHook("ShouldDamage", function(target, inflictor, source, damage, damagetype)
    if target and target.valid and target.skin == "metalsonic"
    and (target.player.dooverdriveattack)
	and not (damagetype & DMG_DEATHMASK)
        return false
    end
end, MT_PLAYER)

addHook("MobjCollide", function(spike, plmo)
    if not (plmo and plmo.valid and plmo.skin == "metalsonic") then return end
    if plmo.type ~= MT_PLAYER then return end
    if plmo.z + plmo.height < spike.z or spike.z + spike.height < plmo.z then return end
    local player = plmo.player
    if player.dooverdriveattack then
        P_KillMobj(spike, plmo, plmo)
    end
end, MT_SPIKE)

addHook("MobjCollide", function(spike, plmo)
    if not (plmo and plmo.valid and plmo.skin == "metalsonic") then return end
    if plmo.type ~= MT_PLAYER then return end
    if (plmo.z > spike.z+spike.height*4) or (spike.z > plmo.z+plmo.height*2) then return end
    local player = plmo.player
	if player.dooverdriveattack then
        P_KillMobj(spike, plmo, plmo)
    end
end, MT_WALLSPIKE)

addHook("MobjDamage", function(plmo, instakill, source, damage, killtype)
	if not (plmo and plmo.valid and plmo.skin == "metalsonic") then return end
    if plmo.type ~= MT_PLAYER then return end
	if plmo.state == S_PLAY_OVERDRIVEATTACK and killtype & DMG_DEATHMASK
		plmo.state = S_PLAY_DEAD
	end
end)

addHook("PlayerSpawn", function(player)
	if player.mo and player.mo.valid and player.mo.skin == "metalsonic"
		player.overdrivechargetimer = 0
		player.overdrivepulsetimer = 0
		player.dooverdriveattack = false
		player.overdriveattacktimer = 0
		if player.odstats == true
			player.normalspeed = 36*FRACUNIT
			player.jumpfactor = skins[player.mo.skin].jumpfactor
			player.charability = CA_FLOAT
			player.charability2 = CA2_SPINDASH
			player.charflags = SF_MACHINE|SF_MULTIABILITY|SF_SUPER|SF_DASHMODE
			player.odstats = false
		end
	end
end)