// Lua code from Jelly Tails and little bit edited for Jelly Sonic
freeslot("SKINCOLOR_JELLYHYPER")
skincolors[SKINCOLOR_JELLYHYPER] = {
	name = "Jelly Sonic Hyper",
	ramp = skincolors[SKINCOLOR_WHITE].ramp,
	invcolor = SKINCOLOR_BLACK,
	chatcolor = V_WHITEMAP,
	invshade = 5,
}
local hyperColors = {
	SKINCOLOR_RUBY,
	SKINCOLOR_SUNSET,
	SKINCOLOR_YELLOW,
	SKINCOLOR_SEAFOAM,
	SKINCOLOR_SKY,
	SKINCOLOR_VAPOR,
	SKINCOLOR_NEON,
}
local function SpawnJellyGoop(p, x, y, z) 
	local o = P_SpawnMobj(x, y, z, MT_JELLYGOOP)
	o.color = p.mo.color
	if p.jellyhyper then o.color = hyperColors[((leveltime % (table.maxn(hyperColors) * 3)) / 3) + 1] end
	if p.mo.eflags & MFE_VERTICALFLIP then
		o.flags2 = o.flags2 | MF2_OBJECTFLIP
	end
	o.scale = p.mo.scale
	return o
end
local jellyStronk = false
local jellyPlayerBounce = true
local jellySpikeNoclip = false
local jellyHyperflash = true
COM_AddCommand("js_stronk", function(p)
	jellyStronk = not jellyStronk
	if jellyStronk then
		print("Jelly Sonic can now push any object")
	else
		print("Jelly Sonic can no longer push any object")
	end
end, COM_ADMIN)
COM_AddCommand("js_playerbounce", function(p)
	jellyPlayerBounce = not jellyPlayerBounce
	if jellyPlayerBounce then
		print("Jelly Sonic can now bounce off of players")
	else
		print("Jelly Sonic can no longer bounce off of players")
	end
end, COM_ADMIN)
CV_RegisterVar({
	name = "js_hyperflash",
	defaultValue = "1",
	flags = CV_CALL,
	PossibleValue = CV_OnOff,
	func = function(cv)
		local val = false
		local v = string.lower(cv.string)
		if v == "on" or v == "true" or v == "1" or v == "yes" then
			val = true
		end
		jellyHyperflash = val
	end
})
addHook("NetVars", function(net)
	jellyStronk = net(jellyStronk)
	jellyPlayerBounce = net(jellyPlayerBounce)
	jellySpikeNoclip = net(jellySpikeNoclip)
end)
local function JellyGoopSplash(p, count, speed, zspeed)
	local step = FixedDiv(FRACUNIT*360, count*FRACUNIT)
	local i = 0
	while i < count do
		local o = SpawnJellyGoop(p, p.mo.x, p.mo.y, p.mo.z)
		P_InstaThrust(o, FixedAngle(i * step), speed)
		o.momz = zspeed
		i = i + 1
	end
end
local function HyperFlash(p, type, duration)
	if not jellyHyperflash then return end
	P_FlashPal(p, type, duration)
end
addHook("PlayerSpawn", function(p)
	if p.mo then
		p.hyperTransform = 0
		p.jellyhyper = false
		p.airtime = 0
		p.bouncemomx = 0
		p.bouncemomy = 0
		p.bouncemomz = 0
		p.mo.color = p.skincolor
		p.scalex = FRACUNIT
		p.scaley = FRACUNIT
		p.fallmom = 0
		p.normalspeed = skins[p.mo.skin].normalspeed
		p.jumpfactor = skins[p.mo.skin].jumpfactor
		p.thrustfactor = skins[p.mo.skin].thrustfactor
	end
end)
addHook("PreThinkFrame", function()
	for p in players.iterate() do
		if not p.mo then continue end
		if p.mo.skin ~= "jellysonic" then continue end
	end
end)
addHook("ThinkFrame", function()
	for p in players.iterate() do
		if not p.mo then continue end
		if p.prevskin == "jellysonic" and p.mo.skin ~= "jellysonic" then
			p.mo.spritexscale = FRACUNIT
			p.mo.spriteyscale = FRACUNIT
		end
		p.prevskin = p.mo.skin
		if p.mo.skin ~= "jellysonic" then
			continue
		end
		local gravmul = 1
		if p.mo.eflags & MFE_VERTICALFLIP then
			gravmul = -1
		end
		if gravmul == 1 and p.mo.momz > 0 then
			p.stomp = false
		end
		if gravmul == -1 and p.mo.momz < 0 then
			p.stomp = false
		end
		if p.deadtimer == 1 then
			JellyGoopSplash(p, 32, FRACUNIT*4, FRACUNIT*6*gravmul)
			p.mo.momx = 0
			p.mo.momy = 0
			p.mo.momz = gravmul * FRACUNIT * 15
			P_TeleportMove(p.mo, p.mo.x, p.mo.y, p.mo.z + (FRACUNIT * gravmul))
			p.mo.flags = p.mo.flags & ~MF_NOCLIPHEIGHT
			-- p.mo.flags2 = p.mo.flags2 | MF2_DONTDRAW
			local o = SpawnJellyGoop(p, p.mo.x, p.mo.y, p.mo.z)
			o.spritexscale = FRACUNIT*5
			o.spriteyscale = FRACUNIT*5
			o.momz = FRACUNIT*gravmul*5
		end
		if p.crushedtimer then
			p.crushedtimer = $ - 1
			p.normalspeed = 0
			p.jumpfactor = 0
			p.maxdash = 0
			p.mindash = 0
			p.scalex = FRACUNIT*3
			p.scaley = FRACUNIT/3
			if p.crushedtimer <= 0 then
				p.normalspeed = skins[p.mo.skin].normalspeed
				p.jumpfactor = skins[p.mo.skin].jumpfactor
				p.maxdash = skins[p.mo.skin].maxdash
				p.mindash = skins[p.mo.skin].mindash
			end
		end
		if p.deadtimer > 0 then
			if P_IsObjectOnGround(p.mo) then
				local x = p.mo.spritexscale
				local y = p.mo.spriteyscale
				local targetx = FRACUNIT*5
				local targety = 0
				p.mo.spritexscale = x + (max(min(targetx - x, (FRACUNIT + (abs((targetx - x) * 2))/TICRATE)), -(FRACUNIT + (abs((targetx - x) * 2))/TICRATE)) / 2)
				p.mo.spriteyscale = y + (max(min(targety - y, (FRACUNIT + (abs((targety - y) * 2))/TICRATE)), -(FRACUNIT + (abs((targety - y) * 2))/TICRATE)) / 2)
			end
		end
		if p.mo.state == S_PLAY_PAIN then
			p.paintime = (p.paintime or 0) + 1
			if p.paintime == 1 then
				JellyGoopSplash(p, 8, FRACUNIT*5, FRACUNIT*5 * gravmul)
			end
		else
			p.paintime = 0
		end
		if p.jellyhyper then
			local skin = skins[p.mo.skin]
			p.mo.frame = p.mo.frame | FF_FULLBRIGHT
			p.normalspeed = skin.normalspeed/4*6
			p.mo.color = hyperColors[((leveltime % (table.maxn(hyperColors) * 3)) / 3) + 1]
			p.jumpfactor = skin.jumpfactor/4*6
			p.thrustfactor = skin.thrustfactor/4*6
			if (leveltime + (TICRATE/2)) % TICRATE == 0 then
				p.rings = $ - 1
			end
			if not p.powers[pw_super] or p.mo.health <= 0 then
				p.jellyhyper = false
				p.mo.color = p.skincolor
				p.normalspeed = skin.normalspeed
				p.jumpfactor = skin.jumpfactor
				p.thrustfactor = skin.thrustfactor
				p.mo.frame = p.mo.frame & ~FF_FULLBRIGHT
			end
		end
		if p.mo.health <= 0 then 
			continue 
		end
		if p.hyperTransform then
			p.mo.state = S_PLAY_SUPER_TRANS1 + max(min(((20 - p.hyperTransform) / 2), 5), 0)
			p.mo.momx = 0
			p.mo.momy = 0
			p.mo.momz = 0
			p.cmd.buttons = 0
			p.hyperTransform = $ - 1
			if leveltime % 3 == 0 then
				P_Earthquake(p.mo, p.mo, FRACUNIT*500)
			end
			if p.hyperTransform <= 0 then
				p.jellyhyper = true
			end
			continue
		end
		if p.powers[pw_super] and not p.jellyhyper and not p.hyperTransform and p.rings >= 100 and p.cmd.buttons & BT_CUSTOM1 and p.pflags & PF_JUMPED then
			p.hyperTransform = 20
			HyperFlash(p, PAL_WHITE, p.hyperTransform)
			P_StartQuake(FRACUNIT*10, p.hyperTransform/4*6)
			S_StartSound(nil, sfx_s3k9f)
			continue
		end
		local factor = FRACUNIT + (FixedDiv(abs(p.mo.momz), p.mo.scale) / 50)
		if not p.mobjBounceTimer then p.mobjBounceTimer = 0 end
		if not p.scaley then p.scaley = FRACUNIT end
		if not p.scalex then p.scalex = FRACUNIT end
		local x = p.scalex
		local y = p.scaley
		if not p.scalemomx then p.scalemomx = 0 end
		if not p.scalemomy then p.scalemomy = 0 end
		
		p.scalemomx = FixedMul(p.scalemomx, FRACUNIT/32*30)
		p.scalemomy = FixedMul(p.scalemomy, FRACUNIT/32*30)
		
		p.scalemomx = $ + max(min(FRACUNIT - x, (FRACUNIT/20) + (abs(x)/200)), -((FRACUNIT/20) + (abs(x)/200)))/TICRATE*3
		p.scalemomy = $ + max(min(FRACUNIT - y, (FRACUNIT/20) + (abs(y)/200)), -((FRACUNIT/20) + (abs(y)/200)))/TICRATE*3
		
		p.scalex = $ + p.scalemomx
		p.scaley = $ + p.scalemomy
		
		p.scalex = $ + max(min(FRACUNIT - x, FRACUNIT/200), -FRACUNIT/200)
		p.scaley = $ + max(min(FRACUNIT - y, FRACUNIT/200), -FRACUNIT/200)
		
		p.mo.spritexscale = FixedMul(FixedDiv(FRACUNIT, factor), p.scalex)
		p.mo.spriteyscale = FixedMul(factor, p.scaley)
		
		if p.followmobj then
			local mo = p.followmobj
			mo.spritexscale = p.mo.spritexscale
			mo.spriteyscale = p.mo.spriteyscale
			mo.color = p.mo.color
			if p.mo.frame & FF_FULLBRIGHT then
				mo.frame = mo.frame | FF_FULLBRIGHT
			else
				mo.frame = mo.frame & ~FF_FULLBRIGHT
			end
		end
		if p.powers[pw_carry] then continue end
		if p.mo.sprite2 == SPR2_RUN and P_IsObjectOnGround(p.mo) then
			if leveltime % 5 == 0 then
				JellyGoopSplash(p, 2 + (leveltime%2), FRACUNIT*2, FRACUNIT*5* gravmul)
			end
		end
		p.mo.frame = p.mo.frame | TR_TRANS30
		if p.dashmode > 3*TICRATE then
			if leveltime % 3 == 0 then
				local g = P_SpawnGhostMobj(p.mo)
				g.blendmode = AST_ADD
				g.spritexscale = p.mo.spritexscale
				g.spriteyscale = p.mo.spriteyscale
			end
		end
		if p.followmobj then
			p.followmobj.frame = p.followmobj.frame | TR_TRANS30
		end
		if not P_IsObjectOnGround(p.mo) and p.pflags & PF_JUMPED then
			if p.spintapping and not p.stomp then
				p.stomp = true
				p.mo.momz = FixedMul(-40 * FRACUNIT, p.mo.scale) * gravmul
				p.mo.momx = $ / 2
				p.mo.momy = $ / 2
				p.spintapping = false
				local g = P_SpawnGhostMobj(p.mo)
				g.blendmode = AST_ADD
				g.scale = $ / 2 * 3
			end
		end
		if P_IsObjectOnGround(p.mo) then
			p.wasDashmode = p.dashmode > 3*TICRATE
			p.airtime = 0
			p.stomp = false
			
			-- Broken attempt to make a spamdash
			/*
			if p.mo.state ~= S_PLAY_SPINDASH and p.cmd.buttons & BT_SPIN and P_IsObjectOnGround(p.mo) then
				p.spindashing = true
				p.mo.state = S_PLAY_SPINDASH
				p.dashspeed = max(p.speed, p.mindash)
				p.pflags = p.pflags | PF_STARTDASH
			end
			if p.mo.state == S_PLAY_SPINDASH then
				p.mo.momx = FixedMul(p.mo.momx, FRACUNIT - (FRACUNIT/4))
				p.mo.momy = FixedMul(p.mo.momy, FRACUNIT - (FRACUNIT/4))
				p.pflags = p.pflags | PF_STARTDASH | PF_SPINNING
				if p.dashspeed < p.maxdash then
					p.dashspeed = p.dashspeed + (FRACUNIT*2)
					if p.dashmode > 3*FRACUNIT then
						p.dashspeed = p.dashspeed + (FRACUNIT*1)
					end
				end
			end
			if p.mo.state == S_PLAY_SPINDASH and not (p.cmd.buttons & BT_SPIN) and P_IsObjectOnGround(p.mo) then
				P_InstaThrust(p.mo, p.mo.angle, p.dashspeed)
				p.dashspeed = 0
				p.mo.state = S_PLAY_ROLL
				p.spindashing = false
				p.pflags = p.pflags & ~PF_STARTDASH
				p.pflags = p.pflags | PF_SPINNING
			end
			*/
			
		else
			p.airtime = $ + 1
		end
		if not P_IsObjectOnGround(p.mo) then
			p.fallmom = p.mo.momz
			if p.wasDashmode then
				p.dashmode = (3*TICRATE) + (TICRATE/2)
			end
		end
		if p.powers[pw_justsprung] then
			p.scaley = FRACUNIT + (FRACUNIT/2)
			p.scalex = FRACUNIT - (FRACUNIT/2)
		end
		if p.pflags & PF_STARTJUMP and p.airtime < 2 then
			p.scalex = FRACUNIT + (FRACUNIT/2)
			p.scaley = FRACUNIT - (FRACUNIT/2)
		end
		if p.skidtime > 0 then
			if p.skidtime % 5 == 0 then
				p.scalex = FRACUNIT + (FRACUNIT/4)
				p.scaley = FRACUNIT - (FRACUNIT/4)
				JellyGoopSplash(p, 1 + (leveltime%2), FRACUNIT*3, FRACUNIT*4*gravmul)
			end
		end
		if p.powers[pw_tailsfly] then
			if p.powers[pw_super] then
				p.powers[pw_tailsfly] = 8*TICRATE
			end
			if p.powers[pw_tailsfly] < 3 then
				p.scalex = FRACUNIT + (FRACUNIT/2)
				p.scaley = FRACUNIT - (FRACUNIT/2)
			end
			if p.spintapping then
				p.powers[pw_tailsfly] = 0
				P_DoJump(p, true)
				p.scalex = FRACUNIT + (FRACUNIT/2)
				p.scaley = FRACUNIT - (FRACUNIT/2)
				p.spintapping = false
				local g = P_SpawnGhostMobj(p.mo)
				g.blendmode = AST_ADD
				g.scale = $ / 2 * 3
			end
			local maxfly = 20*FRACUNIT
			if p.mo.eflags & MFE_UNDERWATER then
				maxfly = $ / 2
			end
			if p.cmd.buttons & BT_JUMP then
				if (gravmul == 1 and p.mo.momz < FixedMul(maxfly, p.mo.scale)) or (gravmul == -1 and p.mo.momz > FixedMul(-maxfly, p.mo.scale)) then p.mo.momz = p.mo.momz + FixedMul(FRACUNIT / 2 * gravmul, p.mo.scale) end
			else
				if (gravmul == 1 and p.mo.momz > FixedMul(-maxfly, p.mo.scale)) or (gravmul == -1 and p.mo.momz < FixedMul(maxfly, p.mo.scale)) then p.mo.momz = p.mo.momz - FixedMul(gravmul * FRACUNIT / 2, p.mo.scale) end
			end
		else
			if not P_IsObjectOnGround(p.mo) and not P_PlayerInPain(p) then
				if p.mo.state ~= S_PLAY_JUMP and p.spintapping then
					p.mo.state = S_PLAY_JUMP
					p.pflags = p.pflags | PF_JUMPED
					p.spintapping = false
					S_StartSound(p.mo, sfx_spin)
					local g = P_SpawnGhostMobj(p.mo)
					g.blendmode = AST_ADD
					g.scale = $ / 2 * 3
				end
			end
		end
		if p.mobjBounceTimer > 0 then
			p.mobjBounceTimer = $ - 1
		end
		if not (p.cmd.buttons & BT_USE) then
			p.spintapready = true
			p.spintapping = false
		elseif p.spintapready then
			p.spintapping = true
			p.spintapready = false
		else
			p.spintapping = false
		end
	end
end)
local function doJellyBounce(mo, other)
	local p = mo.player
	if mo.skin ~= "jellysonic" then return end
		if p.mobjBounceTimer > 0 then return end
		local mul = 1
		if p.mo.eflags & MFE_VERTICALFLIP then
			mul = -1
		end
		S_StartSound(p.mo, sfx_s3k7b)
		p.scalex = FRACUNIT + (FRACUNIT/3)
		p.scaley = FRACUNIT - (FRACUNIT/3)
		other.momx = $ + (mo.momx/2)
		other.momy = $ + (mo.momy/2)
		if not (other.flags & MF_PUSHABLE) then other.momz = $ + (mo.momz/2) + (5*FRACUNIT*mul) end
		
		p.bouncemomx = -other.momx
		p.bouncemomy = -other.momy
		if not (other.flags & MF_PUSHABLE) then p.bouncemomz = -other.momz + (10*FRACUNIT*mul) end
		p.mobjBounceTimer = 2
		JellyGoopSplash(p, 4, FRACUNIT*5, FRACUNIT*7*mul)
end
addHook("MobjMoveCollide", function(mo, other)
	local p = mo.player
	if other.type == MT_RING or other.type == MT_STARPOST or other.flags & MF_SPRING then return end
	if mo.skin ~= "jellysonic" then return end
	if p.mo.eflags & MFE_VERTICALFLIP then
		if (mo.z < (other.z - other.height) or (mo.z > other.z)) then return end
	else
		if (mo.z > (other.z + other.height) or (mo.z < other.z)) then return end
	end
	if other.type == MT_PLAYER and other.player.powers[pw_carry] then return end
	if other.type == MT_PLAYER and not jellyPlayerBounce then return end
	if (other.type == MT_SPIKE or other.type == MT_WALLSPIKE) and jellySpikeNoclip then
		p.scalex = FRACUNIT - (FRACUNIT/8)
		p.scaley = FRACUNIT + (FRACUNIT/8)
		return false
	end
	if (abs(mo.momx) + abs(mo.momy) + abs(mo.momz)) < FRACUNIT * 5 then return end
	local gravmul = 1
	if p.mo.eflags & MFE_VERTICALFLIP then
		gravmul = -1
	end
	if not (other.flags & MF_ENEMY) and not (other.flags & MF_MONITOR) and not (other.type == MT_PLAYER) and not (other.flags & MF_PUSHABLE) and not jellyStronk then 
		if other.flags & MF_SOLID then
			p.bouncemomx = -mo.momx/2
			p.bouncemomy = -mo.momy/2
			p.scalex = FRACUNIT / 2
			p.scaley = FRACUNIT - (FRACUNIT/4)
			S_StartSound(p.mo, sfx_s3k7b)
			JellyGoopSplash(p, 4, FRACUNIT*5, FRACUNIT*7*gravmul)
		end
		return 
	end
	if other.flags & MF_ENEMY and P_PlayerCanDamage(p, other) then
		return
	end
	if p.powers[pw_flashing] then return end
	if other.type == MT_PLAYER then
		other.player.mobjBounceTimer = 5
	end
	S_StartSoundAtVolume(p.mo, sfx_ghit, 127)
	doJellyBounce(mo, other)
end, MT_PLAYER)
addHook("ShieldSpecial", function(p)
	if p.mo.skin ~= "jellysonic" then return end
	if p.powers[pw_shield] & SH_PROTECTWATER or p.powers[pw_shield] & SH_PROTECTELECTRIC or p.powers[pw_shield] & SH_FORCE or p.powers[pw_shield] & SH_WHIRLWIND then return true end
	
end)
addHook("PostThinkFrame", function()
	for p in players.iterate() do
		if not p.mo then continue end
		if p.mo.skin ~= "jellysonic" then
			continue
		end
		if p.mo.health <= 0 then continue end
		p.mo.momx = (p.bouncemomx or p.mo.momx)
		p.bouncemomx = 0
		
		p.mo.momy = (p.bouncemomy or p.mo.momy)
		p.bouncemomy = 0
		
		p.mo.momz = (p.bouncemomz or p.mo.momz)
		p.bouncemomz = 0
		if p.spintimer then
			p.spintimer = $ - 1
			if not p.spintimer then
				p.pflags = p.pflags | PF_SPINNING
				p.mo.state = S_PLAY_ROLL
			end
		end
		if P_IsObjectOnGround(p.mo) then
				if p.fallmom then
				local factor = FRACUNIT + (abs(FixedDiv(p.fallmom, p.mo.scale))/25)
				if factor > (FRACUNIT) + (FRACUNIT/8*7) then
					p.mo.momz = -(p.fallmom/8) * 4
					if p.mo.eflags & MFE_UNDERWATER then
						p.mo.momz = $ / 2
					end
					local g = P_SpawnGhostMobj(p.mo)
					g.blendmode = AST_ADD
					g.scale = $ / 2 * 3
					p.mo.state = S_PLAY_JUMP
					if p.powers[pw_shield] & SH_PROTECTFIRE and p.powers[pw_shield] & SH_PROTECTWATER then
						P_ElementalFire(p, true)
					end
					if p.powers[pw_shield] == SH_BUBBLEWRAP then
						p.mo.momz = -(p.fallmom/8) * 6
					end
					p.pflags = (p.pflags | PF_JUMPED) & ~PF_SPINNING
					S_StartSound(p.mo, sfx_s3k44)
					if p.jellyhyper then
						HyperFlash(p, PAL_WHITE, 5)
					end
				end
				if factor > FRACUNIT + (FRACUNIT/16) then
					S_StartSoundAtVolume(p.mo, sfx_ghit, max(min(FixedMul(factor-FRACUNIT, FRACUNIT*255)/FRACUNIT, 255), 0))
					if p.jellyhyper then
						P_Earthquake(p.mo, p.mo, FixedMul(FRACUNIT*500, factor - FRACUNIT))
					end
				end
				if factor > FRACUNIT/16*25 then
					JellyGoopSplash(p, 8, abs(p.fallmom) / 6, -p.fallmom/2)
				end
				local o = SpawnJellyGoop(p, p.mo.x, p.mo.y, p.mo.z)
				o.momz = -p.fallmom/4
				o.momx = p.mo.momx/4
				o.momy = p.mo.momy/4
				p.scalex = FixedMul(FRACUNIT, factor)
				p.scaley = FixedDiv(FRACUNIT, factor)
				if (abs(p.fallmom) > 200*FRACUNIT) then
					JellyGoopSplash(p, 16, abs(p.fallmom) / 6, -p.fallmom/2)
					p.scalex = FRACUNIT*4
					p.scaley = FRACUNIT/4
					P_DamageMobj(p.mo, nil, nil, 1, DMG_INSTAKILL)
				end
				p.fallmom = 0
			end
		end
		p.mo.frame = p.mo.frame | TR_TRANS30
		if p.followmobj then
			p.followmobj.frame = p.followmobj.frame | TR_TRANS30
		end
	end
end)
addHook("MobjMoveBlocked", function(mo)
	local p = mo.player
	if mo.skin ~= "jellysonic" then return end
	local factor = FRACUNIT + (FixedDiv((abs(mo.momx) + abs(mo.momy)), p.mo.scale)/100)
	--if p.pflags & PF_SPINNING then
	--	factor = FixedMul(factor, FRACUNIT + (FRACUNIT/4))
	--end
	local gravmul = 1
	if p.mo.eflags & MFE_VERTICALFLIP then
		gravmul = -1
	end
	if factor > FRACUNIT + (FRACUNIT/4) then
		local wasSpinning = false
		if p.pflags & PF_SPINNING then
			p.pflags = p.pflags & ~PF_SPINNING
			wasSpinning = true
		end
		factor = min(factor, FRACUNIT*2)
		--mo.momx = FixedMul(-mo.momx, factor - FRACUNIT)
		--mo.momy = FixedMul(-mo.momy, factor - FRACUNIT)
		if not P_IsObjectOnGround(mo) and not p.powers[pw_tailsfly] then
			mo.state = S_PLAY_JUMP
			p.pflags = p.pflags | PF_JUMPED
		end
		P_BounceMove(p.mo)
		JellyGoopSplash(p, 4, FRACUNIT*5, FRACUNIT*7*gravmul)
		S_StartSound(p.mo, sfx_s3k7b)
		if wasSpinning then
			p.spintimer = 2
			--p.pflags = p.pflags | PF_SPINNING
		end
	end
	if factor > (FRACUNIT/16*17) then
		S_StartSoundAtVolume(p.mo, sfx_ghit, max(min(FixedMul(factor-FRACUNIT, FRACUNIT*255)/FRACUNIT, 255), 0))
	end
	p.scalex = FixedMul(FRACUNIT, factor)
	p.scaley = FixedDiv(FRACUNIT, factor)
end, MT_PLAYER)

addHook("PlayerHeight", function(p)
	if p.mo.skin ~= "jellysonic" then return end
	--print((p.mo.ceilingz - p.mo.floorz)/FRACUNIT + "")
	if (p.mo.ceilingz - p.mo.floorz) < FixedMul(skins[p.mo.skin].height, FRACUNIT/32*38) then
		local h = (p.mo.ceilingz - p.mo.floorz)/32*20
		p.scaley = FixedDiv(h, FixedMul(skins[p.mo.skin].height, p.mo.scale))
		if h < FRACUNIT*4 or p.crushedtimer then
			h = 0
			p.crushedtimer = 10
		end
		return h
	end
end)