local globalVars = {
	machSpeed = 0,
	machTimer = 0,
	taunting = false,
	tauntDeb = false,
	tauntTimer = 0,
	tauntTimer2 = 0,
	breakdancing = false,

	grabbing = false,
	grabbingTime = 0,
	hasGrabbedEnemy = false,
	grabDeb = false,
	afterGrabGroundTime = 0,
	zDeb = false,
	spinAfterGrab = false,

	wallrun = false,
	walljumped = false,

	aiTime = 0,
	aiColor = false,

	jumpDeb = true
}

local peppinoVars = {
	chargingSuperJump = false,
	hasSuperJumped = false,
	cancelledSuperJump = false,
	superDebounce = false,
	superFloorDeb = 0,
	superJumpCharge = 0,
}
local noiseVars = {
	pogoStick = false,
	pogoDeb = false,
	prevPogoZ = 0
}
local snickVars = {
	diving = false
}

local function isPTSkin(skin)
	if skin == 'peppino' or skin == 'thenoise' or skin == 'snick' then return true
	else return false end
end

local function copy(obj, seen)
    if type(obj) ~= 'table' then
        return obj 
    end
    if seen and seen[obj] then
        return seen[obj] 
    end
    local s = seen or {}
    local res = setmetatable({}, getmetatable(obj))
    s[obj] = res
    for k, v in pairs(obj) do 
        res[copy(k, s)] = copy(v, s) 
    end
    return res
end --COPIED FROM STACK OVERFLOW LMFAO

-- randomizer code for taunt, by Clairebun
local function L_Choose(...)
	local args = {...}
	local choice = P_RandomRange(1,#args)
	return args[choice]
end

-- momz launch code thats gravity and water safe, also by Clairebun
local function L_ZLaunch(mo,thrust,relative)
	if mo.eflags&MFE_UNDERWATER then
		thrust = $*3/5
	end
	P_SetObjectMomZ(mo,thrust,relative)
end

-- wall run code taken from the srb2 wad archive, only modified slightly to make it more pt like
-- the creator of this is unknown
local function doboing(mobj, line)
	if not mobj.player or not mobj.player.valid then
		return
	end

	local whichside = P_PointOnLineSide(mobj.x, mobj.y, line)

	local climbangle = R_PointToAngle2(line.v1.x, line.v1.y, line.v2.x, line.v2.y)
	local climbline = climbangle

	if (whichside) then // on second side?
		climbline = $+ ANGLE_180
	end

	climbangle = $+ (ANGLE_90 * (whichside and -1 or 1))

	mobj.player.pt.wallrunLine = line
	mobj.player.pt.wallrun = true
	mobj.player.peppino.cancelledSuperJump = false
	mobj.angle = climbangle
	mobj.momx = 0
	mobj.momy = 0
	L_ZLaunch(mobj,mobj.player.normalspeed/2,false)
	if (mobj.player.cmd.buttons & BT_JUMP) and mobj.player.pt.jumpDeb then
		local speed = mobj.player.normalspeed/FRACUNIT
		mobj.angle = climbangle + ANGLE_180
		mobj.momx = speed*cos(mobj.angle)
		mobj.momy = speed*sin(mobj.angle)
		L_ZLaunch(mobj,7*FRACUNIT,false)
		mobj.player.pt.wallrun = false
		mobj.player.pt.wallrunLine = nil
		mobj.player.pflags = $|PF_JUMPED
		mobj.player.pt.jumpDeb = false
	elseif not (mobj.player.cmd.buttons & BT_JUMP) and not mobj.player.pt.jumpDeb then
		mobj.player.pt.jumpDeb = true
	end
end
local function boingy(mobj, line)
    local cursec = line.frontsector
    if mobj.subsector.sector == cursec then cursec = line.backsector end

    if not cursec then
				doboing(mobj, line)
      	return true
    end
	
    local fheight = cursec.floorheight
    local cheight = cursec.ceilingheight

    if cursec.f_slope then
        fheight = P_GetZAt(cursec.f_slope, mobj.x + mobj.momx, mobj.y + mobj.momy)
    end
    if cursec.c_slope then
        cheight = P_GetZAt(cursec.c_slope, mobj.x + mobj.momx, mobj.y + mobj.momy)
    end

    mobj.curline = line

    if (mobj.z + mobj.height/2 < fheight or mobj.z + mobj.height/2 > cheight) then
				doboing(mobj, line)
        return true
    else
        for rov in cursec.ffloors() do
            if rov.flags & FF_SOLID then
                if (mobj.z + mobj.height/2 > rov.bottomheight and mobj.z + mobj.height/2 < rov.topheight) then
										doboing(mobj, line)
                    return true
                end
            end
        end
    end
    return false
end

-- code stole from pizza tower after images, by luigi budd
-- used with permission
local function PTAfterImage(p)
	local chasecam = CV_FindVar("chasecam")
	local afteri = P_SpawnGhostMobj(p.mo)
	if p.pt.aiColor == false then
		afteri.color = SKINCOLOR_AIREALLYRED
	elseif p.pt.aiColor == true then
		afteri.color = SKINCOLOR_AIREALLYGREEN
	end
	afteri.colorized = true
	afteri.frame = FF_FULLBRIGHT|p.mo.frame|TR_TRANS10
	afteri.fuse = 14
	
	//should you be out of my face?
	if chasecam.value then
		afteri.flags2 = $ & ~MF2_DONTDRAW
	else
		afteri.flags2 = $ | MF2_DONTDRAW
	end

	p.pt.aiColor = not p.pt.aiColor
end

local function returnMachSpeed(machSpeed, skin)
	if machSpeed == 1 then
		if skin ~= 'snick' then
			return 47 * FRACUNIT
		else
			return 53*FRACUNIT,75*FRACUNIT
		end
	elseif machSpeed == 2 then
		if skin ~= 'snick'
			return 58 * FRACUNIT
		else
			return 65*FRACUNIT,90*FRACUNIT
		end
	end
end -- Self explaniatory.

local function PlayerVars(player)
	player.pt = copy(globalVars)
	player.peppino = copy(peppinoVars)
	player.noise = copy(noiseVars)
	player.snick = copy(snickVars)
end
addHook('PlayerSpawn', PlayerVars)

local function MachSpeed(player)
	local mo = player.mo
	if player.speed >= player.runspeed and player.pt.machSpeed < 2 then -- Check if we are running and not in mach 2
		-- Keep decreasing the timer
		player.pt.machTimer = $-1
		if player.pt.machTimer <= 0 then -- If it hit 0, Increase the mach if it isnt already 2
			S_StartSound(mo, sfx_cdfm40)
			player.pt.machSpeed = $+1
			player.pt.machTimer = 135 -- We will leave the value at this due to us already setting its default value when we defined it on PlayerSpawn.
			if mo.skin ~= 'snick' then
				local ns,as = returnMachSpeed(player.pt.machSpeed, mo.skin)
				player.normalspeed = ns
			else
				local ns,as = returnMachSpeed(player.pt.machSpeed, mo.skin)
				player.normalspeed = ns
				player.actionspd = as
			end
		end
	elseif not player.pt.wallrun and player.speed < player.runspeed then
		player.pt.machTimer = 30 -- If we aren't in mach speed, Put the timer to 30.
		if player.pt.machSpeed > 0 then
			if mo.skin ~= 'snick' then
				player.normalspeed = 32*FRACUNIT
			else
				player.normalspeed = 36*FRACUNIT
				player.actionspd = 60*FRACUNIT
			end
			player.pt.machSpeed = 0
		end
	end
end

local function SuperJump(player)
	local mo = player.mo
	if (gametyperules & GTR_RACE) and leveltime < 4 * TICRATE then return end
	if (player.cmd.buttons & BT_CUSTOM1) and not player.pt.grabbing and not player.peppino.hasGrabbedEnemy and not player.peppino.superDebounce and not player.exiting then
		if P_IsObjectOnGround(mo) then
			player.peppino.chargingSuperJump = true
		end
		player.peppino.superDebounce = true
	elseif (not (player.cmd.buttons & BT_CUSTOM1) and player.peppino.superDebounce) or player.exiting then
		if P_IsObjectOnGround(mo) then
			player.peppino.chargingSuperJump = false
		end
		player.peppino.superDebounce = false
	end

	if (player.peppino.hasSuperJumped) then
		player.pflags = $|PF_FULLSTASIS
	end

	if (player.peppino.chargingSuperJump) then
		player.pflags = $|PF_FULLSTASIS
		player.peppino.superJumpCharge = $+1
		if player.peppino.superJumpCharge % 6 == 0 then
			S_StartSound(mo,sfx_spndsh)
		end
		if player.peppino.superJumpCharge >= 40 then
			L_ZLaunch(mo, player.peppino.superJumpCharge*FRACUNIT, false)
			S_StartSound(mo, sfx_zoom)
			player.peppino.hasSuperJumped = true
			player.peppino.superJumpCharge = 0
			player.peppino.chargingSuperJump = false
		end
	elseif not player.peppino.chargingSuperJump and player.peppino.superJumpCharge > 0 then
		L_ZLaunch(mo, player.peppino.superJumpCharge*FRACUNIT, false)
		S_StartSound(mo, sfx_zoom)
		player.peppino.hasSuperJumped = true
		player.peppino.superJumpCharge = 0
		player.peppino.chargingSuperJump = false
	end

	if player.peppino.hasSuperJumped then
		if (player.cmd.buttons & BT_SPIN) then
			mo.momx = (returnMachSpeed(player.pt.machSpeed)/FRACUNIT)*cos(mo.angle)
			mo.momy = (returnMachSpeed(player.pt.machSpeed)/FRACUNIT)*sin(mo.angle)
			L_ZLaunch(mo, 8*FRACUNIT, false)
			player.peppino.hasSuperJumped = false
			S_StartSound(mo, sfx_thok)
			S_StartSound(mo, sfx_phalol)
			player.peppino.superFloorDeb = 0
			player.peppino.cancelledSuperJump = true
			return
		end
		player.peppino.superFloorDeb = $+1

		if player.peppino.superFloorDeb > 4 then
			if P_IsObjectOnGround(mo) then
				player.peppino.superFloorDeb = 0
				player.peppino.hasSuperJumped = false
			end
		end

		if player.peppino.chargingSuperJump and not P_IsObjectOnGround(mo) then
			player.peppino.superJumpCharge = 0
			player.peppino.chargingSuperJump = false
		end
	end
end

local function Grab(player)
	local mo = player.mo
	if (gametyperules & GTR_RACE) and leveltime < 4 * TICRATE then return end
	if (player.cmd.buttons & BT_SPIN) and not player.pt.grabDeb and not player.pt.hasGrabbedEnemy and not player.pt.grabbing and not player.pt.spinAfterGrab and not player.exiting then
		player.pt.grabbing = true
		player.pt.grabDeb = true
	elseif (not (player.cmd.buttons & BT_SPIN) and player.pt.grabDeb) or player.exiting then
		player.pt.grabDeb = false
	end

	if player.pt.grabbing then
		mo.momx = 47*cos(mo.angle)
		mo.momy = 47*sin(mo.angle)
		if not player.pt.zDeb then
			player.pt.zDeb = true
			mo.momz = 0
			S_StartSound(mo, sfx_s23c)
		end

		if (player.cmd.buttons & BT_SPIN) and not player.pt.grabDeb then
			player.pt.grabbing = false
			player.pt.zDeb = false
			player.pt.grabbingTime = 0
			player.pflags = $|PF_SPINNING
			player.pt.spinAfterGrab = true
			mo.state = S_PLAY_ROLL
			S_StartSound(mo, sfx_spin)
		end

		player.pt.grabbingTime = $+1
		if player.pt.grabbingTime >= 22 then
			player.pt.grabbing = false
			player.pt.grabbingTime = 0
			player.pt.zDeb = false
			player.pt.machSpeed = 1
			player.pt.machTimer = 135
			player.normalspeed = returnMachSpeed(player.pt.machSpeed)
		end
	end
	if player.pt.hasGrabbedEnemy then
		if mo.state ~= S_PLAY_PEPPINO_PUNCH then
			mo.state = S_PLAY_PEPPINO_PUNCH
		end
	end
	if player.pt.hasGrabbedEnemy then
		player.pt.afterGrabGroundTime = $+1
		if player.pt.afterGrabGroundTime >= 4 and P_IsObjectOnGround(mo) then
			player.pt.hasGrabbedEnemy = false
			player.pt.afterGrabGroundTime = 0
		end
	end
	if not (player.pflags & PF_SPINNING) and player.pt.spinAfterGrab then
		player.pt.spinAfterGrab = false
	end
end

local function Taunt(player)
	local mo = player.mo
	if (player.cmd.buttons & BT_CUSTOM2) and not player.pt.tauntDeb then
		if not player.pt.taunting then
			player.pt.taunting = true
			player.pt.prevState = mo.state
			player.pt.prevMoms = {mo.momx, mo.momy, mo.momz}
			player.pt.lastPFlags = player.pflags
			S_StartSound(mo, sfx_mytaun)
		end
		player.pt.tauntDeb = true
	elseif not (player.cmd.buttons & BT_CUSTOM2) and player.pt.tauntDeb then
		player.pt.tauntDeb = false
	end

	if (player.cmd.buttons & BT_CUSTOM2) then
		player.pt.tauntTimer = $+1
	else
		player.pt.tauntTimer = 0
		if player.pt.breakdancing then player.pt.breakdancing = false end
	end
	if player.pt.taunting then
		player.pt.tauntTimer2 = $+1
		mo.momx = 0
		mo.momy = 0
		mo.momz = 0
		if player.pt.tauntingState == nil then
			if mo.skin == 'peppino' or mo.skin == 'thenoise' then
				player.pt.tauntingState = L_Choose(
					S_PLAY_PEPPINO_TAUNT1,
					S_PLAY_PEPPINO_TAUNT2,
					S_PLAY_PEPPINO_TAUNT3,
					S_PLAY_PEPPINO_TAUNT4,
					S_PLAY_PEPPINO_TAUNT5,
					S_PLAY_PEPPINO_TAUNT6,
					S_PLAY_PEPPINO_TAUNT7,
					S_PLAY_PEPPINO_TAUNT8,
					S_PLAY_PEPPINO_TAUNT9,
					S_PLAY_PEPPINO_TAUNT10
				)
			elseif mo.skin == 'snick' then
				player.pt.tauntingState = L_Choose(
					S_PLAY_PEPPINO_TAUNT1,
					S_PLAY_PEPPINO_TAUNT2,
					S_PLAY_PEPPINO_TAUNT3,
					S_PLAY_PEPPINO_TAUNT4
				)
			end
		end

		if mo.state ~= player.pt.tauntingState then
			mo.state = player.pt.tauntingState
		end
		if player.pt.tauntTimer2 >= 12 then
			mo.momx = player.pt.prevMoms[1]
			mo.momy = player.pt.prevMoms[2]
			mo.momz = player.pt.prevMoms[3]
			mo.state = player.pt.prevState
			player.pflags = player.pt.lastPFlags
			player.pt.taunting = false
			player.pt.tauntTimer2 = 0
			player.pt.tauntingState = nil
		end
	end

	if player.pt.tauntTimer > 20 and player.speed == 0 and mo.momz == 0 then
		player.pt.breakdancing = true
	end

	if player.pt.breakdancing then
		if mo.state ~= S_PLAY_PEPPINO_BREAKDANCE then
			mo.state = S_PLAY_PEPPINO_BREAKDANCE
		end
		player.pflags = $|PF_FULLSTASIS
	else
		if mo.state == S_PLAY_PEPPINO_BREAKDANCE then
			mo.state = S_PLAY_STND
		end
	end
end

local function PogoStick(player)
	local mo = player.mo
	if (player.cmd.buttons & BT_CUSTOM1) and not player.noise.pogoStick and not P_IsObjectOnGround(mo) then
		player.noise.pogoStick = true
	elseif not (player.cmd.buttons & BT_CUSTOM1) and player.noise.pogoStick then
		player.noise.pogoStick = false
	end

	if P_IsObjectOnGround(mo) and player.noise.pogoStick then
		if player.noise.prevPogoZ > -(4*P_MobjFlip(mo))*FRACUNIT then player.noise.prevPogoZ = -(4*P_MobjFlip(mo))*FRACUNIT end
		if player.noise.pogoDeb then
			S_StartSound(mo, sfx_s3k87)
			player.noise.pogoDeb = false
		end
		mo.momz = -player.noise.prevPogoZ
	elseif not P_IsObjectOnGround(mo) and player.noise.pogoStick then
		player.noise.pogoDeb = true
		player.noise.prevPogoZ = mo.momz
	end
end

local function Dive(player)
	if (player.cmd.buttons & BT_CUSTOM1) and not P_IsObjectOnGround(player.mo) and player.pt.machSpeed > 0 and not player.snick.diving then
		player.snick.diving = true
		S_StartSound(player.mo, sfx_zoom)
	elseif (not (player.cmd.buttons & BT_CUSTOM1) or P_IsObjectOnGround(player.mo)) and player.snick.diving then
		player.snick.diving = false
	end

	if player.snick.diving then
		local speed = player.normalspeed/FRACUNIT
		player.mo.momx = speed*cos(player.mo.angle)
		player.mo.momy = speed*sin(player.mo.angle)
		L_ZLaunch(player.mo, -(speed*FRACUNIT)/2)
	end
end

local function AnimationHandler(player)
	local state = nil
	local mo = player.mo

	if not (player.pflags & PF_SPINNING) and mo.skin ~= 'snick' then
		if player.pt.machSpeed == 0 and player.speed >= player.runspeed and not P_IsObjectOnGround(mo) and player.pflags & PF_JUMPED then state = S_PLAY_PEPPINO_SECJUMP end
		if player.pt.machSpeed == 1 and not player.pt.hasGrabbedEnemy then state = S_PLAY_PEPPINO_MACH3 end
		if player.pt.machSpeed == 2 and not player.hasGrabbedEnemy then state = S_PLAY_PEPPINO_MACH4 end
	elseif not (player.pflags & PF_SPINNING) and mo.skin == 'snick' then
		if player.pt.machSpeed == 1 then state = S_PLAY_PEPPINO_MACH3 end
		if player.pt.machSpeed == 2 then state = S_PLAY_PEPPINO_MACH4 end
		if player.pt.machSpeed > 0 and not P_IsObjectOnGround(mo) and player.pflags & PF_JUMPED then state = S_PLAY_ROLL end
	end
	if mo.skin == 'peppino' then
		if player.peppino.chargingSuperJump then state = S_PLAY_PEPPINO_SJWAIT end
		if player.peppino.hasSuperJumped then state = S_PLAY_PEPPINO_SUPERJUMP end
		if player.peppino.cancelledSuperJump then state = S_PLAY_PEPPINO_LUNGE end
	elseif mo.skin == 'thenoise' then
		if player.noise.pogoStick then state = S_PLAY_PEPPINO_SJWAIT end
	elseif mo.skin == 'snick'
		if player.snick.diving then state = S_PLAY_PEPPINO_SJWAIT end
	end
	if player.pt.grabbing then state = S_PLAY_PEPPINO_GRAB end
	if player.pt.hasGrabbedEnemy then state = S_PLAY_PEPPINO_PUNCH end
	if player.pt.wallrun then state = S_PLAY_PEPPINO_CLIMBWALL end
	return state
end

local function PeppinoThink(player)
	if not player.mo then return end
	if not player.mo.valid then return end
	local mo = player.mo
	if not isPTSkin(mo.skin) then return end
	if player.playerstate == PST_DEAD or P_PlayerInPain(player) then
		PlayerVars(player)
		return
	end
	local mo = player.mo
	if gametyperules & GTR_RACE then
		if leveltime < 4 * TICRATE then return end
	end

	if not (player.peppino.hasSuperJumped or player.peppino.chargingSuperJump or player.peppino.cancelledSuperJump or player.pt.grabbing or player.pt.hasGrabbedEnemy or player.pt.taunting) then
		MachSpeed(player)
	end

	if mo.skin == 'peppino' and player.pt.machSpeed > 0 and not player.pt.taunting and not player.pt.breakdancing and not player.pt.wallrun then
		SuperJump(player)
	end

	if mo.skin == 'thenoise' and not (player.pt.taunting and player.pt.breakdancing and player.pt.grabbing and player.pt.hasGrabbedEnemy) then
		PogoStick(player)
	end

	if mo.skin ~= 'snick' and not (player.peppino.hasSuperJumped or player.peppino.chargingSuperJump or player.peppino.cancelledSuperJump or player.pt.taunting or player.pt.breakdancing or player.pt.wallrun) then
		Grab(player)
	end

	if mo.skin == 'snick' then
		Dive(player)
	end

	if (player.speed >= player.runspeed or player.pt.wallrun) and player.pt.machSpeed > 0 then
		player.pt.aiTime = $+1

		if player.pt.aiTime > 4 then
			player.pt.aiTime = 0
			PTAfterImage(player)
		end
	end

	if mo.skin == 'snick' and player.pflags & PF_THOKKED and player.pt.machSpeed == 0 then
		player.pt.machSpeed = 1
		player.pt.machTimer = 135
		local ns,as = returnMachSpeed(player.pt.machSpeed, mo.skin)
		player.normalspeed = ns
		player.actionspd = as
	end

	if player.pt.walljumped and P_IsObjectOnGround(mo) then
		player.pt.walljumped = false
	end

	if not player.pt.wallrun then
		Taunt(player)
	end

	--[[ also part of old wallrun code
	else
		mo.momx = 0
		mo.momy = 0
		P_SetObjectMomZ(mo, player.normalspeed/2)

		if (player.cmd.buttons & BT_JUMP) then
			player.pt.walljumped = true
			player.pt.wallrun = false
			P_InstaThrust(mo, mo.angle, 32*FRACUNIT/-2)
			mo.angle = R_PointToAngle2(0, 0, mo.momx, mo.momy)
			player.pt.machSpeed = 0
			player.pt.machTimer = 30
			L_ZLaunch(mo,8*FRACUNIT,false)
			player.normalspeed = 32*FRACUNIT
			P_DoJump(player)
		end

		if PTR_GlideClimbTraverse(mo,player.pt.wallRunLine) then
			local real,ang = PTR_GlideClimbTraverse(mo,player.pt.wallRunLine)
			if not P_IsClimbingValid(player,ang) then
				player.pt.wallrun = false
				mo.momx = (player.normalspeed/FRACUNIT)*cos(mo.angle)
				mo.momy = (player.normalspeed/FRACUNIT)*sin(mo.angle)
				mo.momz = 0
			end
		else
			player.pt.wallrun = false
			mo.momx = (player.normalspeed/FRACUNIT)*cos(mo.angle)
			mo.momy = (player.normalspeed/FRACUNIT)*sin(mo.angle)
			mo.momz = 0
		end
	end]]--

	if not player.pt.taunting and not player.pt.breakdancing then
		local state = AnimationHandler(player)
		if state ~= nil then
			if mo.state ~= state then mo.state = state end
		end
	
		if player.speed < player.runspeed and (mo.state == S_PLAY_PEPPINO_MACH3 or mo.state == S_PLAY_PEPPINO_MACH4) then
			mo.state = S_PLAY_RUN
		end

		if player.peppino.cancelledSuperJump and P_IsObjectOnGround(mo) then
			player.peppino.cancelledSuperJump = false
		end
	
		if (mo.state == S_PLAY_PEPPINO_LUNGE and P_IsObjectOnGround(mo)) then
			mo.state = S_PLAY_WALK
		end

		if (mo.skin == 'snick' and mo.state == S_PLAY_RUN) or mo.state == S_PLAY_PEPPINO_MACH3 or mo.state == S_PLAY_PEPPINO_MACH4 or mo.state == S_PLAY_PEPPINO_SECJUMP then
			player.charflags = $|SF_RUNONWATER|SF_CANBUSTWALLS
		else
			player.charflags = $ & ~SF_RUNONWATER
			player.charflags = $ & ~SF_CANBUSTWALLS
		end

		if (mo.state == S_PLAY_PEPPINO_SJWAIT and not P_IsObjectOnGround(mo)) then
			player.pt.chargingSuperJump = false
			player.pt.superJumpCharge = 0
			player.state = S_PLAY_WALK
		end

		if (mo.state == S_PLAY_PEPPINO_CLIMBWALL and P_IsObjectOnGround(mo)) then
			mo.state = S_PLAY_RUN
		end
	end
end
addHook('PlayerThink', PeppinoThink)

rawset(_G, 'L_ZCollide', function(mo1,mo2)
	if mo1.z > mo2.height+mo2.z then return false end
	if mo2.z > mo1.height+mo1.z then return false end
	return true
end)

addHook('PlayerCanDamage', function(player, mo2)
	local mo = player.mo
	if not isPTSkin(mo.skin) then return end
	if (mo2.flags & MF_ENEMY) or (mo2.flags & MF_BOSS) or (mo2.flags & MF_MONITOR) then
		if not L_ZCollide(player.mo, mo2) then return end
		if player.pt.grabbing then
			L_ZLaunch(mo, 4*FRACUNIT)
			player.pt.hasGrabbedEnemy = true
			player.pt.grabbing = false
			player.pt.zDeb = false
			player.pt.grabbingTime = 0
			player.pt.machSpeed = 2
			player.normalspeed = returnMachSpeed(player.pt.machSpeed)
			return true
		end
		if player.pt.machSpeed > 0 and not (player.peppino.chargingSuperJump and player.peppino.hasSuperJumped and player.peppino.cancelledSuperJump) then
			return true
		end
	end
end)

addHook('PlayerThink', function(player)
	if player.mo and player.mo.valid then
		if player.pt.wallrun and player.pt.wallrunLine then
			if not boingy(player.mo, player.pt.wallrunLine) then
				player.pt.wallrun = false
				player.pt.wallrunLine = nil
				player.mo.momx = (player.normalspeed/FRACUNIT)*cos(player.mo.angle)
				player.mo.momy = (player.normalspeed/FRACUNIT)*sin(player.mo.angle)
				player.mo.momz = 0
			end
		end
	end
end)

addHook("MobjLineCollide", function(mo, line)
	if not isPTSkin(mo.skin) then return end
	if (mo.player.cmd.buttons & BT_CUSTOM3) and not mo.player.peppino.chargingSuperJump and not mo.player.peppino.hasSuperJumped and not mo.player.noise.pogoStick and not mo.player.pt.grabbing and not mo.player.pt.hasGrabbedEnemy and not mo.player.snick.diving then
		boingy(mo, line)
	end
end, MT_PLAYER)

--[[ scrapped but more new wall run code
-- this worked but also stopped ur air momentum if your not moving directly towards the wall lmfao
addHook('MobjMoveBlocked', function(mo, mobj, line)
	if not isPTSkin(mo.skin) then return end
	if (mo.player.cmd.buttons & BT_CUSTOM3) and not mo.player.peppino.chargingSuperJump and not mo.player.peppino.hasSuperJumped and not mo.player.noise.pogoStick and not mo.player.pt.grabbing and not mo.player.pt.hasGrabbedEnemy and not mo.player.snick.diving then
		mo.player.cancelledSuperJump = false
		mo.player.pt.wallrun = true
		mo.player.pt.wallrunTime = 0
	end
end, MT_PLAYER)--]]

--[[ scrapped wall run code, it always made thebplayer float on fences/shoet walls or just abput any wall
code by BuggietheBug and Pacola
addHook("MobjMoveBlocked", function(mo,mobj,line)
	if not isPTSkin(mo.skin) then return end
	if line and line.valid then
		if PTR_GlideClimbTraverse(mo,line) and mo.player and mo.player.valid then
			local real,ang = PTR_GlideClimbTraverse(mo,line)
				if (P_IsClimbingValid(mo.player,ang) or (mobj and mobj.valid)) then
					if (mo.player.cmd.buttons & BT_CUSTOM3) and not mo.player.pt.wallrun and not mo.player.pt.grabbing and not mo.player.pt.hasGrabbedEnemy and not mo.player.peppino.chargingSuperJump and not mo.player.peppino.hasSuperJumped and not mo.player.peppino.cancelledSuperJump and not mo.player.noise.pogoStick and not (mo.player.pflags & PF_SPINNING) then
						mo.player.pt.wallRunLine = line
						mo.player.pt.wallrun = true
					end
				else
					mo.player.pt.wallrun = false
			end
		else
			mo.player.pt.wallrun = false
		end
	end
end,MT_PLAYER) ]]--

addHook('AbilitySpecial', function(player)
	if not player.mo then return end
	if player.mo.skin == 'snick' then
		if player.pt.wallrun then return true end
	end
end)

addHook('MobjDeath', function(target, inflictor, source)
	if source == nil or target == nil then return end
	if source.player and source.skin == 'peppino' and target.flags & MF_MONITOR then
		S_StartSound(source, sfx_myvoce)
		return
	end
end)