/*  _________      .__                 ___________      .__  .__                     
 /   _____/ ____ |  | _____ _______  \_   _____/ ____ |  | |__|_____  ______ ____  
 \_____  \ /  _ \|  | \__  \\_  __ \  |    __)__/ ___\|  | |  \____ \/  ___// __ \ 
 /        (  <_> )  |__/ __ \|  | \/  |        \  \___|  |_|  |  |_> >___ \\  ___/ 
/_______  /\____/|____(____  /__|    /_______  /\___  >____/__|   __/____  >\___  >
        \/                 \/                \/     \/        |__|       \/     \/ 
  _________ __            .___.__                                                  
 /   _____//  |_ __ __  __| _/|__| ____  ______                                    
 \_____  \\   __\  |  \/ __ | |  |/  _ \/  ___/                                    
 /        \|  | |  |  / /_/ | |  (  <_> )___ \                                     
/_______  /|__| |____/\____ | |__|\____/____  >                                    
        \/                 \/               \/                                     
__________                                      __                                 
\______   \_______   ____   ______ ____   _____/  |_  ______                       
 |     ___/\_  __ \_/ __ \ /  ___// __ \ /    \   __\/  ___/                       
 |    |     |  | \/\  ___/ \___ \\  ___/|   |  \  |  \___ \                        
 |____|     |__|    \___  >____  >\___  >___|  /__| /____  > /\  /\  /\            
                        \/     \/     \/     \/          \/  \/  \/  \/*/     
//VPhysics lol         
//Mommy sonic colors -- NO (Trevor)
freeslot(
"SKINCOLOR_VIVACITY", "SKINCOLOR_WINE", "SKINCOLOR_SETTING", "SKINCOLOR_GERANIUM", "SKINCOLOR_BLUSH", "SKINCOLOR_TITANIUM", "SKINCOLOR_LIPSTICK", "SKINCOLOR_COTTONCANDY", "SKINCOLOR_WARMBLUE", "SKINCOLOR_GALAXYPINK", "SKINCOLOR_NEONMOSS", "SKINCOLOR_BURNING", "SKINCOLOR_CHOCLATE", "SKINCOLOR_SNOWYPISS", "SKINCOLOR_NEWBEIGE", "SKINCOLOR_GALAXYCYAN", 
"SKINCOLOR_GALAXYRED", "SKINCOLOR_GALAXYORANGE", "SKINCOLOR_GALAXYBROWN", "SKINCOLOR_METALPURPLE", "SKINCOLOR_MASCARA", "SKINCOLOR_CARROT", "SKINCOLOR_ROSEATE", "SKINCOLOR_FUCHSIA"
)
skincolors[SKINCOLOR_VIVACITY] = {
    name = "Vivacity",
    ramp = {0,145,146,148,149,151,151,154,155,168,168,169,169,254,254,31},
    invcolor = SKINCOLOR_ORANGE,
    invshade = 5,
    chatcolor = V_BLUEMAP,
    accessible = true
}
skincolors[SKINCOLOR_WINE] = {
    name = "Wine",
    ramp = {0,200,210,211,34,37,38,40,41,42,44,45,46,47,30,31
},
    invcolor = SKINCOLOR_GREEN,
    invshade = 10,
    chatcolor = V_REDMAP,
    accessible = true
}

  skincolors[SKINCOLOR_SETTING] = {
     name = "Setting",
     ramp = {0,48,49,51,53,55,214,206,185,185,186,186,187,199,29,31},
	 chatcolor = V_ORANGEMAP,
	 invcolor = 4,
	 invcolor = SKINCOLOR_BLUE,
	 accessible = true
 }
 
 skincolors[SKINCOLOR_GERANIUM] = {
    name = "Geranium",
    ramp = {0,3,160,192,193,194,185,185,186,186,186,187,187,254,30,31
},
    invcolor = SKINCOLOR_GOLD,
    invshade = 4,
    chatcolor = V_PURPLEMAP,
    accessible = true
}
skincolors[SKINCOLOR_BLUSH] = {
    name = "Blush",
    ramp = {0,252,200,201,202,202,203,204,205,42,44,45,46,47,30,31
},
    invcolor = SKINCOLOR_AQUA,
    invshade = 1,
    chatcolor = V_PINKMAP,
    accessible = true
}

 skincolors[SKINCOLOR_TITANIUM] = {
     name = "Titanium",
     ramp = {147,148,149,150,152,154,155,155,155,155,168,168,169,253,254,254},
     invcolor = SKINCOLOR_PERIDOT,
     chatcolor = V_BLUEMAP,
	 invshade = 5,
     accessible = true
 }
 
 skincolors[SKINCOLOR_LIPSTICK] = {
     name = "Lipstick",
     ramp = {0,200,210,211,214,38,40,42,45,71,46,47,47,29,30,31},
     invcolor = SKINCOLOR_KETCHUP,
     chatcolor = V_REDMAP,
	 invshade = 1,
     accessible = true
}

skincolors[SKINCOLOR_COTTONCANDY] = {
     name = "Cotton Candy",
     ramp = {0,252,200,201,202,203,204,205,207,44,71,46,47,47,30,31
},
     invcolor = SKINCOLOR_VIOLET,
     chatcolor = V_PURPLEMAP,
	 invshade = 1,
     accessible = true
 }
 
 skincolors[SKINCOLOR_WARMBLUE] = {
     name = "Warm Blue",
     ramp = {0,145,146,148,150,166,185,185,186,186,198,187,199,28,30,31

},
     invcolor = SKINCOLOR_CARBON,
     chatcolor = V_BLUEEMAP,
	 invshade = 1,
     accessible = true
 }
 
  skincolors[SKINCOLOR_GALAXYPINK] = {
     name = "Galaxy Pink",
     ramp = {0,3,201,193,204,205,207,207,186,186,187,187,47,29,30,31


},
     invcolor = SKINCOLOR_FOREST,
     chatcolor = V_PINKMAP,
	 invshade = 1,
     accessible = true
 }
 
   skincolors[SKINCOLOR_NEONMOSS] = {
     name = "Neon Moss",
     ramp = {0,88,96,98,101,125,126,126,127,127,127,139,139,110,111,31


},
     invcolor = SKINCOLOR_VIOLET,
     chatcolor = V_GREENMAP,
	 invshade = 1,
     accessible = true
 }
    skincolors[SKINCOLOR_BURNING] = {
     name = "Burning",
     ramp = {0,48,50,52,67,215,63,63,45,71,46,47,47,29,30,31



},
     invcolor = SKINCOLOR_COBALT,
     chatcolor = V_YELLOWMAP,
	 invshade = 1,
     accessible = true
 }
 
     skincolors[SKINCOLOR_CHOCLATE] = {
     name = "Choclate",
     ramp = {0,4,240,242,246,249,236,239,239,239,29,29,111,30,30,31




},
     invcolor = SKINCOLOR_BLUE,
     chatcolor = V_BROWNMAP,
	 invshade = 1,
     accessible = true
 }
 
     skincolors[SKINCOLOR_SNOWYPISS] = {
     name = "Snow?",
     ramp = {0,0,0,0,1,81,82,64,74,75,76,77,78,236,239,31




},
     invcolor = SKINCOLOR_CARBON,
     chatcolor = V_REDMAP,
	 invshade = 1,
     accessible = true
 }
 
	 skincolors[SKINCOLOR_NEWBEIGE] = {
     name = "New Beige",
     ramp = {0,208,48,216,218,219,221,223,225,228,230,249,251,238,29,31




},
     invcolor = SKINCOLOR_COBALT,
     chatcolor = V_BLACKMAP,
	 invshade = 1,
     accessible = true
 } 
 
 	 skincolors[SKINCOLOR_GALAXYCYAN] = {
     name = "Galaxy Cyan",
     ramp = {0,4,140,141,142,137,143,143,143,138,138,139,139,29,30,31






},
     invcolor = SKINCOLOR_APRICOT,
     chatcolor = V_BLACKMAP,
	 invshade = 1,
     accessible = true
 } 
  	 skincolors[SKINCOLOR_GALAXYRED] = {
     name = "Galaxy Red",
     ramp = {0,3,209,211,212,205,207,42,43,45,71,46,47,47,30,31






},
     invcolor = SKINCOLOR_GREEN,
     chatcolor = V_REDMAP,
	 invshade = 1,
     accessible = true
 } 
   	 skincolors[SKINCOLOR_GALAXYORANGE] = {
     name = "Galaxy Orange",
     ramp = {0,48,218,51,53,67,67,68,69,234,236,238,239,29,30,31






},
     invcolor = SKINCOLOR_BLUE,
     chatcolor = V_ORANGEMAP,
	 invshade = 1,
     accessible = true
 } 
   	 skincolors[SKINCOLOR_GALAXYBROWN] = {
     name = "Galaxy Brown",
     ramp = { 0,4,85,223,67,68,69,69,79,236,238,239,28,29,30,31






},
     invcolor = SKINCOLOR_BLUE,
     chatcolor = V_BLACKMAP,
	 invshade = 1,
     accessible = true
 }  
     skincolors[SKINCOLOR_METALPURPLE] = {
     name = "Metal Purple",
     ramp = {0,160,192,163,164,166,166,167,167,157,158,159,253,254,254,31






},
     invcolor = SKINCOLOR_COBALT,
     chatcolor = V_REDMAP,
	 invshade = 1,
     accessible = true
 }  
     skincolors[SKINCOLOR_MASCARA] = {
     name = "Mascara",
     ramp = {0,209,32,33,35,36,39,207,185,186,186,187,187,199,29,31






},
     invcolor = SKINCOLOR_GREEN,
     chatcolor = V_REDMAP,
	 invshade = 10,
     accessible = true
 }  
 
   skincolors[SKINCOLOR_CARROT] = {
     name = "Carrot",
     ramp = {0,48,217,220,52,55,56,57,58,59,60,61,63,45,71,46},
	 chatcolor = V_ORANGEMAP,
	 invcolor = 4,
	 invcolor = SKINCOLOR_BLUE,
	 accessible = true
 }
 skincolors[SKINCOLOR_ROSEATE] = {
    name = "Roseate",
    ramp = {252,200,200,201,201,202,202,203,206,185,185,186,186,187,254,254 //OLD
},
    invcolor = SKINCOLOR_AQUA,
    invshade = 1,
    chatcolor = V_PINKMAP,
    accessible = true
}
skincolors[SKINCOLOR_FUCHSIA] = {
    name = "Fuchsia",
    ramp = {0,252,176,200,177,201,202,203,205,215,62,63,46,47,29,31 
},
    invcolor = SKINCOLOR_AQUA,
    invshade = 1,
    chatcolor = V_PINKMAP,
    accessible = true
}

//shhh im cool

if (VERSION == 202) and (SUBVERSION < 10)
	local function blackout(v)
		v.drawFill()
		v.drawString(160, 100, ("Get 2.2.10 of srb2 or higher dipshit."),V_REDMAP, "center")
	end
	hud.add(blackout, "title")
	hud.add(blackout, "game")
	error("Fuck you!!!!!!!!", 0)
end

//hi welcome to Vphysics code -Trystan/Hurricane --sex 
-- we will first start off with configurations. Mod creators, if you dont want your character supporting vphysics just make the isvphysics variable 0. Im going to do this for hakune because i said so. Deal with it DaJumpJumpette.
addHook("PlayerThink", function(player)
	if player.mo and player.mo.valid
		if player.mo.isvphysics == nil
			player.mo.isvphysics = 0
		end
	end
end)


freeslot("S_PLAY_SWIP")
freeslot("SPR2_SWIP")
states[S_PLAY_SWIP] = {SPR_PLAY, SPR2_SWIP, 3, nil, 0, 0, S_PLAY_SWIP}

/*freeslot(
"MT_NIGG",
"S_NIGG",
"SPR_FUCK"
)

mobjinfo[MT_NIGG] = {
	doomednum = -1,
	spawnstate = S_NIGG,
	spawnhealth = 1000,
	radius = 48*FRACUNIT,
	height = 64*FRACUNIT,
	flags = MF_NOGRAVITY
}

states[S_NIGG] = {
	sprite = SPR_FUCK,
	frame = A|FF_ANIMATE|FF_FULLBRIGHT|TR_TRANS30,
	tics = 19,
	var1 = 3,
	var2 = 2,
	nextstate = S_NULL
}*/
	
addHook("PlayerThink", function(player)
	if player.mo and player.mo.valid
		if player.mo.skin == "hakune" //haha 
		or player.mo.skin == "adventuresonic" //vphysics is weird when hes aroung
			player.mo.isvphysics = 0
		end
		if player.mo.isvphysics == 0 return end
		if (player.pflags & PF_BOUNCING) return end
		if player.mo.isstomping == nil
				player.mo.isstomping1 = 0
			end
			if player.mo.isstomping2 == nil
				player.mo.isstomping = 0
			end
			if not (player.cmd.buttons & BT_SPIN) then //silvervortex reasons
				player.usetapready = true
				player.usetapping = false
			elseif player.usetapready then
				player.usetapping = true
				player.usetapready = false
			else
				player.usetapping = false
			end
			if not (player.cmd.buttons & BT_JUMP) then
				player.jumptapready = true
				player.jumptapping = false
			elseif player.jumptapready then
				player.jumptapping = true
				player.jumptapready = false
			else
				player.jumptapping = false
			end
			if player.mo.doublejump == nil
				player.mo.doublejump = 0
			end
			if player.whattio == nil
				player.whattio = 0
			end
			//entirely scrapped, was too buggy.
			//edit: maybe i can bring this back idk im working on it
			//edit:no wtf this sucks
			/*if (player.pflags & PF_GLIDING) and (player.whattio == 1) return end
			if player.mo.skin == "hakune" return end
			if player.mo.skin == "hurricane" return end
			if player.mo.skin == "knuckles"
			and player.usetapping //more silvervortex reasons
			and not P_IsObjectOnGround(player.mo)
			and (player.pflags & PF_GLIDING)
			and not (player.pflags & PF_THOKKED)
			and not (player.climbing == 1)
				S_StartSound(player.mo, sfx_zoom)
				player.mo.state = S_PLAY_ROLL
				player.pflags = $1 & ~PF_GLIDING
				player.mo.isstomping1 = 1
			end
			if (player.pflags & PF_THOKKED)
			and (player.pflags & PF_GLIDING)
			and player.mo.skin == "knuckles"
				player.pflags = $1 & ~PF_THOKKED
			end
			if player.mo.skin == "knuckles"
			and player.mo.isstomping1 == 1
				P_SetObjectMomZ(player.mo, -FRACUNIT, true)		
			end
			if player.mo.isstomping1 == 1
				local abcdefghi = P_SpawnGhostMobj(player.mo)
				abcdefghi.fuse = 4
			end
			//AAA KNUX 
			if P_IsObjectOnGround(player.mo)
			and player.mo.skin == "knuckles"
			and player.mo.isstomping1 == 1
			and not (player.cmd.buttons & BT_JUMP)
			and not (player.pflags & PF_THOKKED)
				P_SetObjectMomZ(player.mo, 8*FRACUNIT)
				S_StartSound(player.mo, sfx_s3k49)
				P_StartQuake(3*FRACUNIT, 3)
				P_NukeEnemies(player.mo, player.mo, 500*FRACUNIT)
				player.mo.state = S_PLAY_ROLL
				player.mo.isstomping1 = 0
				player.pflags = $|PF_JUMPED|PF_THOKKED
				P_InstaThrust(player.mo, player.mo.angle, player.speed)
				P_Thrust(player.mo, player.mo.angle, 5*FRACUNIT)
			end
			if P_IsObjectOnGround(player.mo)
			and player.mo.skin == "knuckles"
			and player.mo.isstomping1 == 1
			and (player.cmd.buttons & BT_JUMP)
			and not (player.pflags & PF_THOKKED)
				P_SetObjectMomZ(player.mo, 6*FRACUNIT)
				S_StartSound(player.mo, sfx_s3k49)
				P_StartQuake(3*FRACUNIT, 3)
				P_NukeEnemies(player.mo, player.mo, 500*FRACUNIT)
				player.whattio = 1
				player.mo.state = S_PLAY_GLIDE
				player.mo.isstomping1 = 0
				player.pflags = $|PF_GLIDING|PF_THOKKED
				player.pflags = $1 & ~PF_SPINNING
			end
			if player.whattio == 1
				player.pflags = $|PF_THOKKED
			end
			if player.mo.state == S_PLAY_CLIMB
				player.whattio = 0
				player.pflags = $1 & ~PF_THOKKED
			end
			if (player.pflags & PF_GLIDING)
				player.pflags = $1 & ~PF_SPINNING
			end
			if player.mo.state == S_PLAY_GLIDE
			and not (player.cmd.buttons & BT_JUMP)
				player.whattio = 0
			end
			if player.mo.state == S_PLAY_GLIDE_LANDING
				player.whattio = 0
			end
			if P_PlayerInPain(player)
				player.whattio = 0
			end
			if (player.pflags & PF_SPINNING)
			and (player.pflags & PF_GLIDING)
			and player.mo.skin == "knuckles"
				player.pflags = $1 & ~PF_GLIDING
				player.pflags = $1 & ~PF_SPINNING
			end
			if (player.pflags & PF_GLIDING)
			and player.mo.skin == "knuckles"
			and P_IsObjectOnGround(player.mo)
				player.pflags = $1 & ~PF_GLIDING
			end
			if (player.mo.eflags & MFE_GOOWATER)
				player.mo.isstomping1 = 0
			end
			if (player.mo.eflags & MFE_SPRUNG)
				player.mo.isstomping1 = 0
			end
			if P_PlayerInPain(player)
				player.mo.isstomping1 = 0
			end*/
			//knuckles actual ability
			if player.mo.kjv == nil
				player.mo.kjv = 0 //knuckles jump variable
			end
			if player.mo.rt == nil
				player.mo.rt = 14*TICRATE //roll timer
			end
			if player.mo.atc == nil // about to (un)curl
				player.mo.atc = 0
			end
			if player.mo.re == nil
				player.mo.re = 0
			end
			if player.mo.skin == "knuckles"
			and P_IsObjectOnGround(player.mo)
				player.mo.rt = 14*TICRATE
				player.mo.kjv = 0
			end
			if player.mo.skin == "knuckles"
			and player.mo.kjv == 1
				player.mo.rt = $1 - 1*TICRATE
			end
			if (player.pflags & PF_GLIDING)
			and not P_IsObjectOnGround(player.mo)
			and player.mo.skin == "knuckles"
			and player.usetapping
			and not (player.mo.re == 1)
				player.mo.state = S_PLAY_SPRING
				P_SetObjectMomZ(player.mo, 17*FRACUNIT)
				player.mo.kjv = 1
				player.pflags = $ & ~PF_GLIDING
				S_StartSound(player.mo, sfx_jump)
			end
			if player.mo.rt == 0*TICRATE
			and not P_IsObjectOnGround(player.mo)
			and not (player.mo.re == 1)
				player.mo.state = S_PLAY_ROLL
				S_StartSound(player.mo, sfx_spin)
				player.mo.kjv = 0
				player.mo.rt = 14*TICRATE
				player.mo.atc = 1
			end
			if player.mo.state == S_PLAY_ROLL
			and player.mo.skin == "knuckles"
			and player.mo.atc == 1
			and not (player.mo.re == 1)
			and player.usetapping
				P_SetObjectMomZ(player.mo, -20*FRACUNIT)
				P_Thrust(player.mo, player.mo.angle, 15*FRACUNIT)
				S_StartSound(player.mo, sfx_zoom)
				P_SpawnThokMobj(player)
				player.mo.atc = 0
				player.mo.re = 1
			end
			if P_IsObjectOnGround(player.mo)
			or P_PlayerInPain(player)
				player.mo.re = 0
			end
			//knuckles slam
			if player.mo.dashvariable == nil
				player.mo.dashvariable = 7*TICRATE
			end
			if player.mo.ihatehumans == nil
				player.mo.ihatehumans = 0
			end
			if player.mo.sound == nil
				player.mo.sound = 1
			end
			if player.mo.anotherfuckingvariable == nil
				player.mo.anotherfuckingvariable = 0
			end
			if player.mo.sound == 1
			and player.mo.ihatehumans == 1
				player.mo.sound = 0
				S_StartSound(player.mo, sfx_drill1)
			elseif player.mo.sound == 0
			and player.mo.ihatehumans == 0
				player.mo.sound = 1
			end
			if player.mo.ihatehumans == 1
			and not (player.mo.state == S_PLAY_JUMP)
				player.mo.state = S_PLAY_JUMP
			end
			if (player.pflags & PF_GLIDING)
			and not (player.mo.state == S_PLAY_GLIDE)
			and not (player.mo.eflags & MFE_UNDERWATER)
				player.mo.state = S_PLAY_GLIDE
			end
			if (player.pflags & PF_GLIDING)
			and (player.mo.eflags & MFE_UNDERWATER)
			and not (player.mo.state == S_PLAY_SWIM)
				player.mo.state = S_PLAY_SWIM
			end
			if player.usetapping
			and player.mo.skin == "knuckles"
			and (player.pflags & PF_JUMPED)
			and not (player.mo.eflags & MFE_SPRUNG)
			and not (player.pflags & PF_THOKKED)
				player.mo.ihatehumans = 1
			end
			if player.mo.ihatehumans == 1
			and player.mo.skin == "knuckles"
			and not (player.pflags & PF_THOKKED)
			and not (player.mo.eflags & MFE_SPRUNG)
			and not (player.mo.asd == 1)
				player.mo.dashvariable = $1 - 1*TICRATE
				P_SetObjectMomZ(player.mo, (0 + 12*FRACUNIT))
				local ghostyboy = P_SpawnGhostMobj(player.mo)
				ghostyboy.fuse = 4
			end
			if player.mo.asd == nil
				player.mo.asd = 0
			end
			if player.mo.dashvariable < 0
			and not (player.pflags & PF_THOKKED)
			and not (player.pflags & PF_GLIDING)
			and not (player.mo.state == S_PLAY_CLIMB)
			and player.mo.skin == "knuckles"
				player.mo.asd = 1
				player.mo.ihatehumans = 0
			end
			if player.mo.dashvariable < 0
			and (player.pflags & PF_THOKKED)
				player.mo.asd = 0
			end
			if player.mo.dashvariable < 0
			and player.mo.state == S_PLAY_CLIMB
				player.mo.asd = 0
			end
			if player.mo.asd == 1
			and not (player.pflags & PF_THOKKED)
			and not (player.mo.state == S_PLAY_CLIMB)
			and not (player.mo.eflags & MFE_SPRUNG)
				P_SetObjectMomZ(player.mo, -4*FRACUNIT, true)
				player.mo.anotherfuckingvariable = 1
				local ghostyboy2 = P_SpawnGhostMobj(player.mo)
				ghostyboy2.fuse = 4
			end
			if player.mo.asd == 1
			and (player.mo.eflags & MFE_SPRUNG)
				player.mo.momx = $*5/4
				player.mo.momy = $*5/4
				player.mo.momz = $*5/4
				S_StartSound(player.mo, sfx_sprong)
				player.mo.state = S_PLAY_SPRING
				player.mo.anotherfuckingvariable = 0
				player.mo.asd = 0
				player.mo.ihatehumans = 0
				player.mo.dashvariable = 7*TICRATE
			end
			if (player.pflags & PF_GLIDING)
			or (player.mo.state == S_PLAY_CLIMB)
				player.mo.asd = 0
				player.mo.anotherfuckingvariable = 0
				player.mo.ihatehumans = 0
				player.mo.dashvariable = 7*TICRATE
			end
			if P_IsObjectOnGround(player.mo)
				player.mo.dashvariable = 7*TICRATE
				player.mo.ihatehumans = 0
			end
			if player.mo.anotherfuckingvariable == 1
			and P_IsObjectOnGround(player.mo)
			and player.mo.skin == "knuckles"
			and not (player.pflags & PF_THOKKED)
			and not (player.pflags & PF_SPINNING)
			and not (player.pflags & PF_GLIDING)
			and not (player.mo.eflags & MFE_SPRUNG)
				P_SetObjectMomZ(player.mo, 14*FRACUNIT)
				P_NukeEnemies(player.mo, player.mo, 500*FRACUNIT)
				S_StartSound(player.mo, sfx_s3k49)
				P_StartQuake(3*FRACUNIT, 3)
				S_StartSound(player.mo, sfx_crumbl)
				player.mo.state = S_PLAY_SPRING
				player.mo.anotherfuckingvariable = 0
				local ghostyboy3 = P_SpawnGhostMobj(player.mo)
				ghostyboy3.fuse = 4
				player.mo.asd = 0
			end
			if (player.pflags & PF_SPINNING)
			and player.mo.skin == "knuckles"
			and player.mo.anotherfuckingvariable == 1
			and P_IsObjectOnGround(player.mo)
			and not (player.pflags & PF_THOKKED)
			and player.mo.state == S_PLAY_ROLL
			and not (player.pflags & PF_GLIDING)
				P_SetObjectMomZ(player.mo, 8*FRACUNIT)
				P_NukeEnemies(player.mo, player.mo, 500*FRACUNIT)
				S_StartSound(player.mo, sfx_s3k49)
				P_StartQuake(3*FRACUNIT, 3)
				S_StartSound(player.mo, sfx_crumbl)
				player.mo.state = S_PLAY_ROLL
				P_Thrust(player.mo, player.mo.angle, 5*FRACUNIT)
				player.mo.anotherfuckingvariable = 0
				player.pflags = $|PF_THOKKED
				player.mo.asd = 0
			end
			if (player.mo.eflags & MFE_SPRUNG)
				player.mo.anotherfuckingvariable = 0
				player.mo.asd = 0
				player.mo.ihatehumans = 0
			end
			if P_PlayerInPain(player)
				player.mo.anotherfuckingvariable = 0
				player.mo.asd = 0
				player.mo.ihatehumans = 0
			end
			//end of knuckles
			if player.mo.skin == "sonic"
				player.charability = CA_HOMINGTHOK
			end
			if player.mo.variable == nil
				player.mo.variable = 0
			end
			if player.mo.skin == "tails"
			and not (player.powers[pw_tailsfly])
				player.mo.variable = 1
			end
			if player.mo.s == nil
				player.mo.s = 0
			end
			if player.powers[pw_tailsfly] // make it work for swim too
			and player.mo.skin == "tails"
			and player.usetapping
			and player.mo.variable == 1
				P_SetObjectMomZ(player.mo, 18*FRACUNIT)
				P_Thrust(player.mo, player.mo.angle, 5*FRACUNIT)
				P_InstaThrust(player.mo, player.mo.angle, player.speed)
				S_StartSound(player.mo, sfx_s3k51)
				S_StartSound(player.mo, sfx_zoom)
				P_SpawnGhostMobj(player.mo)
				player.mo.variable = 0
				local whitty = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z + player.mo.height, MT_FBOMB) //...And spawn the whitty itself
				whitty.target = player.mo //The bomb can't hurt tilly dog
				P_NukeEnemies(whitty, whitty, 500*FRACUNIT)
				player.mo.s = 1
			end
			if player.mo.s == 1
			and player.usetapping
			and player.mo.variable == 0
			and player.powers[pw_tailsfly] //fix it so it can work for swimming aswell HURRICANE.
			and player.mo.skin == "tails"
				local whitty2 = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z + player.mo.height, MT_FBOMB) //...And spawn the whitty itself
				whitty2.target = player.mo //The bomb can't hurt tilly
				P_InstaThrust(whitty2, player.mo.angle, 0*FRACUNIT)
				S_StartSound(player.mo, sfx_s3k51)
				S_StartSound(player.mo, sfx_zoom)
				P_SpawnGhostMobj(player.mo)
			end
			if not (player.powers[pw_tailsfly])
			and not (player.mo.eflags & MFE_UNDERWATER) 
				player.mo.s = 0
			end
			if not (player.powers[pw_tailsfly])
			and (player.mo.eflags & MFE_UNDERWATER)
				player.mo.s = 0
			end
			if player.mo.grass == nil
				player.mo.grass = 0
			end
			/*if player.mo.meteor == nil
				player.mo.meteor = 0
			end*/
			//tired idiot
			if player.mo.state == S_PLAY_FLY_TIRED
			and player.mo.skin == "tails"
			and player.usetapping
				player.mo.state = S_PLAY_ROLL
				player.pflags = $|PF_JUMPED
				P_SetObjectMomZ(player.mo, 12*FRACUNIT)
				//player.mo.meteor = 1
				player.mo.swipe = 1
				P_Thrust(player.mo, player.mo.angle, 4*FRACUNIT)
				S_StartSound(player.mo, sfx_kc5b)
			end
			/*if player.mo.meteor == 1
				player.mo.grass = $ + ANGLE_45
				player.mo.state = S_PLAY_EDGE
				player.drawangle = player.mo.grass
			end
			if player.mo.meteor == 1
			and (player.mo.eflags & MFE_JUSTHITFLOOR)
				player.mo.meteor = 0
			end
			if player.mo.meteor == 1
			and P_PlayerInPain(player)
				player.mo.meteor = 0
			end
			if player.mo.meteor == 1
			and (player.mo.eflags & MFE_SPRUNG)
				player.mo.meteor = 0
			end*/
			//swipe
			if player.mo.swipe == nil
				player.mo.swipe = 0
			end
			if player.mo.skin == "tails"
			and player.usetapping
			and not (player.pflags & PF_THOKKED)
			and (player.pflags & PF_JUMPED)
				P_SetObjectMomZ(player.mo, 12*FRACUNIT)
				S_StartSound(player.mo, sfx_kc5b)
				P_Thrust(player.mo, player.mo.angle, 4*FRACUNIT)
				player.pflags = $|PF_THOKKED
				player.mo.swipe = 1
				for i = 1, 8
					local curangle = ANG1*45*i
					local dust = P_SpawnMobj(player.mo.x+(18*cos(curangle)), player.mo.y+(18*sin(curangle)), player.mo.z+(4*FRACUNIT), MT_DUST)
					dust.angle = curangle
					P_InstaThrust(dust, dust.angle, 5*FRACUNIT)
					dust.momz = 4*FRACUNIT/2
				end
			end
			if player.mo.swipe == 1
			and (player.mo.eflags & MFE_JUSTHITFLOOR)
				player.mo.swipe = 0
			end
			if player.mo.swipe == 1
			and not (player.mo.eflags & MFE_JUSTHITFLOOR)
			and not (player.mo.eflags & MFE_SPRUNG)
				player.mo.grass = $ + ANGLE_45
				player.mo.state = S_PLAY_EDGE
				player.drawangle = player.mo.grass
			end
			if player.mo.state == S_PLAY_EDGE
			and player.mo.swipe == 1
				if player.mo.momz <= -6*FRACUNIT*P_MobjFlip(player.mo) and (player.cmd.buttons & BT_SPIN)
					P_SetObjectMomZ(player.mo, -6*FRACUNIT, false)
				end
			end
			if player.mo.soundeffectbruh3 == nil
				player.mo.soundeffectbruh3 = 0
			end
			if player.mo.soundeffectbruh3 == 1
				S_StartSound(player.mo, sfx_s3k42)
				player.mo.soundeffectbruh3 = 0
			end
			if player.mo.skin == "tails"
			and player.mo.state == S_PLAY_EDGE
			and player.mo.swipe == 1
			and player.drawangle == ANGLE_45
				S_StartSound(player.mo, sfx_s3k52)
			end
			if player.mo.swipe == 1
			and P_PlayerInPain(player)
				player.mo.swipe = 0
			end
			if P_IsObjectOnGround(player.mo)
			and player.mo.skin == "tails"
				player.pflags = $1 & ~PF_NOJUMPDAMAGE
			end
			if player.mo.swipe == 1
			and (player.mo.eflags & MFE_SPRUNG)
				player.mo.swipe = 0
			end //omg no way cock
			if player.mo.avil == nil
				player.mo.avil = 0
			end
			if player.mo.skin == "tails"
			and player.mo.state == S_PLAY_EDGE
			and player.mo.swipe == 1
			and not (player.mo.avil == 1)
			and player.jumptapping
				P_SetObjectMomZ(player.mo, 10*FRACUNIT)
				local sexslave = P_SpawnGhostMobj(player.mo)
				sexslave.fuse = 6
				S_StartSound(player.mo, sfx_zoom)
				player.mo.state = S_PLAY_SPRING
				player.mo.swipe = 0
				player.mo.avil = 1
				player.pflags = $|PF_NOJUMPDAMAGE
			end
			if player.mo.avil == 1
			and player.mo.skin == "tails"
			and player.usetapping
				player.mo.swipe = 1
				player.pflags = $1 & ~PF_NOJUMPDAMAGE
				player.mo.state = S_PLAY_EDGE
			end
			if player.mo.avil == 1
			and P_PlayerInPain(player)
				player.mo.avil = 0
			end
			if player.mo.avil == 1
			and (player.mo.eflags & MFE_JUSTHITFLOOR)
				player.mo.avil = 0
			end
			if player.mo.avil == 1
			and (player.mo.eflags & MFE_SPRUNG)
				player.mo.avil = 0
			end//HOLY FUCKING COCK
			//hold to fly
			if (player.powers[pw_tailsfly] > 0)
			and (player.cmd.buttons & BT_JUMP)
				player.fly1 = 1
			end
			// shhhh
			if player.mo.skin == "amy"
			and (player.cmd.buttons & BT_CUSTOM1)
			and player.speed == 0*FRACUNIT
				player.mo.state = S_PLAY_GLIDE_LANDING
				player.pflags = $|PF_FULLSTASIS
			end
			//drip drop?
			if player.mo.skin == "sonic"
			and player.usetapping 
			and (player.pflags & PF_JUMPED)
				player.mo.state = S_PLAY_SPINDASH
				player.mo.isstomping2 = 1
				player.charability = CA_NONE
				S_StartSound(player.mo, sfx_spndsh)
				player.pflags = $|PF_THOKKED
				player.pflags = $1 & ~PF_NOJUMPDAMAGE
			end
			if player.mo.isstomping2 == 1
			and player.mo.state == S_PLAY_SPINDASH
				P_SpawnSkidDust(player, 10*FRACUNIT)
			end
			if player.mo.state == S_PLAY_SPRING
				player.mo.isstomping2 = 0
			end
			if player.mo.state == S_PLAY_ROLL
				player.mo.isstomping2 = 0
			end
			if (player.mo.eflags & MFE_SPRUNG)
				player.mo.isstomping2 = 0
			end
			if P_PlayerInPain(player)
				player.mo.isstomping2 = 0
			end
			//drip drop? 2
			if (player.mo.eflags & MFE_JUSTHITFLOOR)
			and player.mo.skin == "sonic"
			and player.mo.isstomping2 == 1
				player.charability = CA_HOMINGTHOK
				P_InstaThrust(player.mo, player.mo.angle, player.speed)
				P_Thrust(player.mo, player.mo.angle, 15*FRACUNIT, false)
				P_SpawnMobj(player.mo.x, player.mo.y - 25*FRACUNIT, player.mo.z, MT_SPINDUST)
				P_SpawnMobj(player.mo.x + 20*FRACUNIT, player.mo.y - 20*FRACUNIT, player.mo.z, MT_SPINDUST)
				S_StartSound(player.mo, sfx_zoom)
				player.mo.isstomping2 = 0
				player.pflags = $1 & ~PF_SPINNING
			end
			if player.mo.isstomping2 == 1
			and player.mo.skin == "sonic"
				player.mo.state = S_PLAY_SPINDASH
			end
			if not (player.cmd.buttons & BT_CUSTOM1) then
				player.custom1tapready = true
				player.custom1tapping = false
			elseif player.custom1tapready then
				player.custom1tapping = true
				player.custom1tapready = false
			else
				player.custom1tapping = false
			end
			if player.mo.throost == nil
				player.mo.throost = 0
			end
			// Falling edge thingy Trevor did for no reason but still added it :sonicsmug:
			if (player.mo.state == S_PLAY_WALK or player.mo.state == S_PLAY_RUN)
			and player.mo.momz > 0
			and not (player.powers[pw_carry] == CR_ROLLOUT)
			and not (player.mo.skin == "metalsonic")
			and not (player.mo.skin == "hexhog")
			and not P_IsObjectOnGround(player.mo)
				player.mo.state = S_PLAY_SPRING
			end
			if (player.mo.state == S_PLAY_WALK or player.mo.state == S_PLAY_RUN)
			and player.mo.momz < 1
			and not (player.powers[pw_carry] == CR_ROLLOUT)
			and not (player.mo.skin == "metalsonic")
			and not (player.mo.skin == "hexhog")
			and not P_IsObjectOnGround(player.mo)
				player.mo.state = S_PLAY_FALL
			end
			// eh, just a little something, cause rafael breaks with momentum homing
			//edit, i dont remember if rafael even has a homing attack anymore so im taking this out
			/*if player.mo.skin == "rafael" 
			and player.mo.state == S_PLAY_SPRING
			and not (player.mo.eflags & MFE_SPRUNG)
				player.mo.state = S_PLAY_CLIMB
			end*/
			if player.mo.skin == "rafael" return
		end
		if player.mo.skin == "amy"
		and player.mo.state == S_PLAY_MELEE_LANDING
		and not (player.cmd.buttons & BT_SPIN)
			player.mo.state = S_PLAY_STND
		end
		if player.mo.justsprung == nil
			player.mo.justsprung = 0
		end
		if (player.mo.eflags & MFE_SPRUNG)
			player.mo.justsprung = 1
		end
		if player.mo.justsprung == 1
		and player.mo.state == S_PLAY_SPRING
		and player.jumptapping
		and not (player.charflags & SF_NOJUMPSPIN)
			player.mo.state = S_PLAY_ROLL
			player.mo.metalabilitytimer = 19*TICRATE
			player.mo.timerthingo = 15*TICRATE
			S_StartSound(player.mo, sfx_spin)
			player.pflags = $|PF_JUMPED
		end
		if player.mo.justsprung == 1
		and (player.charflags & SF_NOJUMPSPIN)
			player.pflags = $ | PF_JUMPED|PF_NOJUMPDAMAGE
		end
		if (player.pflags & PF_THOKKED)
			player.mo.justsprung = 0
		end
		if P_IsObjectOnGround(player.mo)
			player.mo.justsprung = 0
			player.pflags = $1 & ~PF_JUMPED
		end
		if player.mo.justsprung == 1
		and not (player.charflags & SF_NOJUMPSPIN)
		and player.mo.momz == 0
			player.mo.state = S_PLAY_FALL
			player.mo.justsprung = 0
			player.pflags = $1 & ~PF_JUMPED
		end
	end
end)

addHook("MobjDeath", function(target, inflictor, source)
    if source and source.player
    and (target.flags & (MF_ENEMY|MF_BOSS|MF_MONITOR))
		if source.skin == "tails"
			if source.player.mo.state == S_PLAY_EDGE
			and source.player.mo.swipe == 1
			and (source.player.cmd.buttons & BT_SPIN)
				P_SetObjectMomZ(source.player.mo, 10*FRACUNIT, true)
				source.player.mo.avil = 0
			end
		end
    end
end) 

addHook("PlayerThink", function(player) 
	//hom hom
	if player.justhom == nil
		player.justhom = 0
	end
	if player.homing
		player.fangbang = true
	end
	if (player.charflags & SF_NOJUMPSPIN)
	and not P_IsObjectOnGround(player.mo)
	and not P_PlayerInPain(player)
	and not (player.pflags & PF_BOUNCING)
		player.pflags = $|PF_JUMPED|PF_NOJUMPDAMAGE
	end
	if P_LookForEnemies(player,true,false)
	and not (player.homing)
	and player.mo.skin == "sonic"
		player.pflags = $ & ~PF_NOJUMPDAMAGE
		player.cool = {x = player.mo.momx, y = player.mo.momy, z = player.mo.momz}
	end
	if player.fangbang == true and not player.homing
	and player.mo.skin == "sonic"
	and (player.pflags & PF_JUMPDOWN)
	and not (player.mo.eflags & MFE_SPRUNG)
	and not P_PlayerInPain(player)
	or player.fangbang == true and not player.homing
	and player.mo.skin == "adventuresonic"
	and (player.pflags & PF_JUMPDOWN)
	and not (player.mo.eflags & MFE_SPRUNG)
	and not P_PlayerInPain(player)
		player.pflags = $|PF_JUMPED
		P_InstaThrust(player.mo, player.mo.angle, FixedHypot(player.cool.x, player.cool.y))
		P_Thrust(player.mo, player.mo.angle, 20*FRACUNIT)
		player.fangbang = false
		player.pflags = $ & ~PF_NOJUMPDAMAGE
		P_SetObjectMomZ(player.mo, 10*FRACUNIT, false)
		player.mo.state = S_PLAY_JUMP
		player.mo.aliv = 1
		S_StartSound(player.mo, sfx_zoom)
	end
	if P_PlayerInPain(player)
		player.fangbang = false
	end
	if (player.mo.eflags & MFE_SPRUNG)
		player.fangbang = false
	end
	if player.mo.skin == "sonic"
	and P_IsObjectOnGround(player.mo)
		player.pflags = $ & ~PF_NOJUMPDAMAGE
	end
	if player.fangbang == true and not player.homing
	and player.mo.skin == "sonic"
	and not (player.pflags & PF_JUMPDOWN)
	and not (player.mo.eflags & MFE_SPRUNG)
	and not P_PlayerInPain(player)
	or player.fangbang == true and not player.homing
	and player.mo.skin == "adventuresonic"
	and not (player.pflags & PF_JUMPDOWN)
	and not (player.mo.eflags & MFE_SPRUNG)
	and not P_PlayerInPain(player)
		player.pflags = $ & ~PF_NOJUMPDAMAGE
		player.pflags = $|PF_JUMPED
		player.fangbang = false
		P_SetObjectMomZ(player.mo, 15*FRACUNIT, false)
		P_InstaThrust(player.mo, player.mo.angle, 10*FRACUNIT)
	end
	if player.dashmode > 3*TICRATE
	and not P_IsObjectOnGround(player.mo)
		player.dashmode = 110
	end
	if player.fangbang == true and not (player.homing)
	and P_IsObjectOnGround(player.mo)
		player.mo.state = S_PLAY_ROLL
		player.pflags = $|PF_SPINNING
		player.fangbang = false
		player.homing = false
	end
	if (player.mo.eflags & MFE_SPRUNG)
		player.mo.popjump = 0
	end
	if P_PlayerInPain(player)
		player.mo.popjump = 0
	end
end)

//Momentum COCK //svae
addHook("PlayerThink", function(player)
	if player.mo and player.mo.valid
	if player.mo.skin == "hakune" return end
	if not (player.mo.doublejump == 1) return end // vphymom command stuff
	if player.speed < player.normalspeed return end //no op speed with this line, remove it and i will personally find your address and my war crime rate will go high.
		if (player.cmd.forwardmove) or (player.cmd.sidemove)
		and	player.normalspeed < player.speed
			player.mo.friction = FRACUNIT
		else
			player.mo.friction = 29*FRACUNIT/32
		end
		if player.speed > 65*FRACUNIT
		and player.mo.state == S_PLAY_RUN
		and not (player.pflags & PF_BOUNCING)
		and P_IsObjectOnGround(player.mo)
		and not (player.mo.eflags & MFE_UNDERWATER)
			P_SpawnSkidDust(player, 10*FRACUNIT)
			local vphyrundust = P_SpawnMobj(player.mo.x, player.mo.y,
			player.mo.z + ((player.mo.eflags & MFE_VERTICALFLIP)/MFE_VERTICALFLIP * (player.mo.height - mobjinfo[MT_SPINDUST].height)),
			MT_SPINDUST)
			P_InstaThrust(vphyrundust, player.mo.angle+(P_RandomRange(-ANG30/FRACUNIT, ANG30/FRACUNIT)*FRACUNIT), FixedMul(-player.dashspeed/12-1*FRACUNIT-P_RandomByte()<<11, player.mo.scale))
			P_TryMove(vphyrundust, vphyrundust.x+vphyrundust.momx, vphyrundust.y+vphyrundust.momy, true)
			P_SetObjectMomZ(vphyrundust, 8*FRACUNIT, true)
			vphyrundust.fuse = 6	
		end
		if player.speed > 65*FRACUNIT
		and player.mo.state == S_PLAY_RUN
		and P_IsObjectOnGround(player.mo)
		and (player.mo.eflags & MFE_UNDERWATER)
		and not (player.pflags & PF_BOUNCING)
			P_SpawnSkidDust(player, 10*FRACUNIT)
			local vphyrundust2 = P_SpawnMobj(player.mo.x, player.mo.y,
			player.mo.z + ((player.mo.eflags & MFE_VERTICALFLIP)/MFE_VERTICALFLIP * (player.mo.height - mobjinfo[MT_MEDIUMBUBBLE].height)),
			MT_MEDIUMBUBBLE)
			P_InstaThrust(vphyrundust2, player.mo.angle+(P_RandomRange(-ANG30/FRACUNIT, ANG30/FRACUNIT)*FRACUNIT), FixedMul(-player.dashspeed/12-1*FRACUNIT-P_RandomByte()<<11, player.mo.scale))
			P_TryMove(vphyrundust2, vphyrundust2.x+vphyrundust2.momx, vphyrundust2.y+vphyrundust2.momy, true)
			P_SetObjectMomZ(vphyrundust2, 8*FRACUNIT, true)
			vphyrundust2.fuse = 6	
		end
		if player.speed > 65*FRACUNIT
		and not (player.pflags & PF_BOUNCING)
			player.charflags = $|SF_RUNONWATER
		else
			player.charflags = $1 & ~SF_RUNONWATER
		end
	end
end)
//spike break with enough speed
local function Break_shit (plr, thing)
	-- copied from p_map.c PIT_CheckThing
	if (thing.type == MT_SPIKE
	or thing.type == MT_WALLSPIKE)
	then
		if (thing.flags & MF_SOLID) and ((thing.type == MT_SPIKE) or (thing.type == MT_WALLSPIKE))
		then
			S_StartSound(plr, thing.info.deathsound)
		end
		for iter in thing.subsector.sector.thinglist()
		do
			-- this is a fucked formatting
			if (
				iter.type == thing.type and
				iter.health > 0 and
				( iter.flags & MF_SOLID ) and
				(iter == thing or
				P_AproxDistance(P_AproxDistance(
				thing.x - iter.x, thing.y - iter.y),
				thing.z - iter.z) < 56*thing.scale))
			then
				P_KillMobj(iter, plr, tmthing, 0)
			end
		end
		return 2
		elseif (( thing.flags & MF_MONITOR ))
		then
		if (P_DamageMobj(thing, tmthing, tmthing, 1, 0))
		then
			return 2
		end
	end
end

addHook ("MobjMoveCollide", function (plr, thing)
	if plr.player ~= nil and plr.player.speed > 65*FRACUNIT
		if (thing.type == MT_SPIKE
		or thing.type == MT_WALLSPIKE)
			if (plr.z + plr.height < thing.z) 
			or (plr.z > thing.z + thing.height)
				return false
			else
				return Break_shit(plr, thing)
			end
		end
	end
end)

addHook ("MobjMoveCollide", function (plr, thing)
	if plr.player ~= nil and plr.player.mo.state == S_PLAY_FLIA
		if (thing.type == MT_SPIKE
		or thing.type == MT_WALLSPIKE)
			if (plr.z + plr.height < thing.z) 
			or (plr.z > thing.z + thing.height)
				return false
			else
				return Break_shit(plr, thing)
			end
		end
	end
end)

addHook("PlayerThink", function(player) //a bunch of variables and other stuff
	if player.mo and player.mo.valid 
		if player.mo.isvphysics == 0 return end
		if player.mo.mommyou == nil
			player.mo.mommyou = 0
		end
		if player.mo.aliv == nil
			player.mo.aliv = 0
		end
		if not (player.cmd.buttons & BT_JUMP) then
			player.jtr = true
			player.jt = false
		elseif player.jtr then
			player.jt = true
			player.jtr = false
		else
			player.jt = false
		end
		if player.mo.mommyou == 1
		and player.mo.momz > 0
			local ghost = P_SpawnGhostMobj(player.mo)
			ghost.fuse = 4
		end
		if P_IsObjectOnGround(player.mo)
			player.mo.mommyou = 0
		end
		if (player.pflags & PF_THOKKED)
		and player.mo.skin == "sonic"
		or (player.pflags & PF_THOKKED)
		and player.mo.skin == "fang"
		and not (player.pflags & PF_BOUNCING) 
			player.mo.mommyou = 1
		end
		if player.mo.alivv == nil
			player.mo.alivv = 10*TICRATE
		end
		if P_IsObjectOnGround(player.mo)
			player.mo.alivv = 10*TICRATE
			player.mo.aliv = 0
		end
		if player.mo.skin == "sonic"
		and player.mo.aliv == 1
		and not (player.homing)
		and not (player.fangbang == 1)
		or player.mo.skin == "fang"
		and player.mo.aliv == 1
			player.mo.alivv = $1 - 1*TICRATE
		end
		if player.mo.skin == "sonic"
		and player.mo.alivv == 0*TICRATE
		and not (player.homing)
		and not (player.fangbang == 1)
		or player.mo.skin == "fang"
		and player.mo.alivv == 0*TICRATE
			player.mo.state = S_PLAY_SPRING
			player.mo.aliv = 0
			S_StartSound(player.mo, sfx_s3k42)
			player.pflags = $1|PF_NOJUMPDAMAGE
			player.mo.alivv = 10*TICRATE
		end
		if player.mo.skin == "sonic"
		and player.mo.aliv == 0
		and P_IsObjectOnGround(player.mo)
			player.pflags = $1 & ~PF_NOJUMPDAMAGE
		end
	end
end)

addHook("AbilitySpecial", function(player)
	if player.mo.isvphysics == 0 return end
	if player.mo.skin == "sonic"
	and not (player.pflags & PF_THOKKED)
	and not P_LookForEnemies(player,true,false)
		P_SetObjectMomZ(player.mo, 10*FRACUNIT)
		P_InstaThrust(player.mo, player.mo.angle, player.speed)
		P_Thrust(player.mo, player.mo.angle, 15*FRACUNIT)
		S_StartSound(player.mo, sfx_thok)
		S_StartSound(player.mo, sfx_zoom)
		P_SpawnThokMobj(player)
		player.mo.aliv = 1
		player.mo.state = S_PLAY_JUMP
		player.pflags = $1|PF_THOKKED
		player.pflags = $1 & ~PF_NOJUMPDAMAGE
	end
end)

freeslot("sfx_bonk", "sfx_aois")

//amy sheet
freeslot("S_PLAY_FLIA")
freeslot("SPR2_FLIA")
states[S_PLAY_FLIA] = {SPR_PLAY, SPR2_FLIA, 3, nil, 0, 0, S_PLAY_FLIA}

addHook("PlayerThink", function(player)
    if player.mo and player.mo.valid
		if player.mo.isvphysics == 0 return end
		if player.mo.supermerio == nil
			player.mo.supermerio = 0
		end
		if not (player.cmd.buttons & BT_SPIN) then //silvervortex reasons
			player.utr = true
			player.ut = false
		elseif player.utr then
			player.ut = true
			player.utr = false
		else
			player.ut = false
		end
		if player.mo.ameeabilitytimer == nil
			player.mo.ameeabilitytimer = 15*TICRATE
		end
		if player.mo.soundeffectbruh2 == nil
		    player.mo.soundeffectbruh2 = 0
		end
		if player.mo.uh == nil
			player.mo.uh = 0
		end
		if player.mo.gwak == nil
			player.mo.gwak = 0
		end
		if player.ut
		and not P_PlayerInPain(player)
		and P_IsObjectOnGround(player.mo)
		and not (player.pflags & PF_THOKKED)
		and player.mo.skin == "amy"
			player.mo.supermerio = 1
			player.mo.soundeffectbruh2 = 1
		end
		if player.mo.soundeffectbruh2 == 1
			S_StartSound(player.mo, sfx_s3k42)
			player.mo.soundeffectbruh2 = 0
		end
		if player.mo.skin == "amy"
		and not (player.mo.supermerio == 1)
		and P_IsObjectOnGround(player.mo)
			player.mo.ameeabilitytimer = 15*TICRATE
			player.mo.supermerio = 0
		end
		if player.mo.skin == "amy"
		and player.mo.supermerio == 1
			player.mo.ameeabilitytimer = $1 - 1*TICRATE
		end
		if player.mo.state == S_PLAY_FLIA
		and P_IsObjectOnGround(player.mo)
			P_SpawnSkidDust(player, 10*FRACUNIT)
		end
		if not (player.pflags & PF_THOKKED)
		and player.mo.ameeabilitytimer == 0*TICRATE
			player.mo.supermerio = 0
			player.mo.state = S_PLAY_MELEE
			S_StartSound(player.mo, sfx_s3k42)
			player.mo.uh = 1
			P_SetObjectMomZ(player.mo, 4*FRACUNIT)
			player.pflags = $|PF_THOKKED
		end
		if player.mo.uh == 1
		and P_IsObjectOnGround(player.mo)
		and not (player.mo.state == S_PLAY_MELEE)
			player.mo.state = S_PLAY_MELEE_LANDING
			S_StartSound(player.mo, sfx_s3k8b)
		end
		if player.mo.skin == "amy"
		and P_IsObjectOnGround(player.mo)
			player.charability2 = CA2_NONE
		end
		if player.mo.skin == "amy"
		and not P_IsObjectOnGround(player.mo)
			player.charability2 = CA2_MELEE
		end
		if player.mo.uh == 1
		and player.mo.skin == "amy"
		and player.mo.state == S_PLAY_MELEE_LANDING
		and (player.cmd.buttons & BT_SPIN)
			P_SetObjectMomZ(player.mo, 16*FRACUNIT)
			P_InstaThrust(player.mo, player.mo.angle, player.speed)
			player.mo.state = S_PLAY_TWINSPIN
			player.mo.uh = 0
			player.mo.ameeabilitytimer = 15*TICRATE
			player.mo.gwak = 1
		elseif player.mo.uh == 1
		and not (player.cmd.buttons & BT_SPIN)
			player.mo.uh = 0
			player.mo.ameeabilitytimer = 15*TICRATE
		end
		if player.mo.gwak == 1
		and P_IsObjectOnGround(player.mo)
			player.mo.gwak = 0
		end
		if player.mo.supermerio == 1
		and not P_PlayerInPain(player)
		and (player.cmd.buttons & BT_SPIN)
			P_Thrust(player.mo, player.mo.angle, 1*FRACUNIT)
		end
		if player.mo.supermerio == 1
		and not (player.cmd.buttons & BT_SPIN)
			player.mo.ameeabilitytimer = 0*TICRATE
			player.mo.supermerio = 0
			player.mo.state = S_PLAY_MELEE
			S_StartSound(player.mo, sfx_s3k42)
			player.mo.uh = 1
			P_SetObjectMomZ(player.mo, 4*FRACUNIT)
			player.pflags = $|PF_THOKKED
		end
		if player.mo.supermerio == 1
			player.mo.soundeffectbruh2 = 0
		end
		if P_PlayerInPain(player)
			player.mo.supermerio = 0
		end
		if (player.mo.eflags & MFE_SPRUNG)
			player.mo.ameeabilitytimer = 15*TICRATE
		end
		if player.mo.skin == "amy"
			player.charflags = $|SF_NOSHIELDABILITY
		end
		if player.mo.state == S_PLAY_TWINSPIN
		and player.mo.skin == "amy"
			player.pflags = $|PF_THOKKED
		end
		if player.mo.supermerio == 1
			player.mo.state = S_PLAY_FLIA
		end
		if player.mo.supermerio == 1
		and not P_IsObjectOnGround(player.mo)
			P_SetObjectMomZ(player.mo, -5*FRACUNIT)
		end
		if player.nodont == nil
			player.nodont = false
		end
		if player.yesdont == nil
			player.yesdont = false
		end
		if player.mo.skin == "amy"
		and not (player.mo.state == S_PLAY_FLIA)
		and not (player.mo.state == S_PLAY_TWINSPIN)
			player.pflags = $|PF_NOJUMPDAMAGE
        end
    end
end)
//amy jump!!!!!!!!!
addHook("AbilitySpecial", function(player)
	if player.mo.skin == "amy"
	and (player.pflags & PF_JUMPED)
	and not (player.pflags & PF_THOKKED)
		P_SetObjectMomZ(player.mo, 15*FRACUNIT)
		player.mo.state = S_PLAY_TWINSPIN
		S_StartSound(player.mo, sfx_s3k42)
		player.pflags = $|PF_THOKKED
		for i = 1, 8
			local curangle = ANG1*45*i
			local dust = P_SpawnMobj(player.mo.x+(18*cos(curangle)), player.mo.y+(18*sin(curangle)), player.mo.z+(4*FRACUNIT), MT_DUST)
			dust.angle = curangle
			P_InstaThrust(dust, dust.angle, 5*FRACUNIT)
			dust.momz = 4*FRACUNIT/2
		end
	end
end)
//amy smashes!!!! your parents!!!!!
addHook("SpinSpecial", function(player)
	if (player.mo.supermerio == 1) return end
	if player.mo.skin == "amy"
	and (player.pflags & PF_JUMPED)
	and not (player.pflags & PF_THOKKED)
		player.yesdont = true
	end
end)

addHook("PlayerThink", function(player)
	if player.mo.skin == "amy"
	and (player.pflags & PF_JUMPED)
	and player.yesdont == true
		P_SetObjectMomZ(player.mo, -1*FRACUNIT, true)
		player.mo.state = S_PLAY_FLIA
		player.nodont = true
	end
	if player.nodont == true
	and (player.mo.eflags & MFE_JUSTHITFLOOR)
	and not (player.mo.eflags & MFE_SPRUNG)
		P_SetObjectMomZ(player.mo, 13*FRACUNIT)
		P_NukeEnemies(player.mo, player.mo, 350*FRACUNIT)
		P_Thrust(player.mo, player.mo.angle, 8*FRACUNIT)
		P_InstaThrust(player.mo, player.mo.angle, player.speed)
		player.mo.state = S_PLAY_TWINSPIN
		S_StartSound(player.mo, sfx_s3k9e)
		player.nodont = false
		player.yesdont = false
	end
	if player.nodont == true
	and (player.mo.eflags & MFE_SPRUNG)
		player.nodont = false
		player.yesdont = false
		player.mo.momx = $*5/4
		player.mo.momy = $*5/4
		player.mo.momz = $*5/4
		S_StartSound(player.mo, sfx_sprong)
		player.mo.state = S_PLAY_SPRING
	end
	if player.mo.skin == "amy"
		player.charability = 0
	end
	if not S_SoundPlaying(player.mo, sfx_s3k42)
	and player.mo.state == S_PLAY_FLIA
	and player.mo.skin == "amy"
		S_StartSound(player.mo, sfx_s3k42)
	end
	if (player.mo.eflags & MFE_GOOWATER)
	and player.yesdont == true
	and player.nodont == true
		player.yesdont = false
		player.nodont = false
		player.mo.state = S_PLAY_FALL
	end
	if P_PlayerInPain(player)
	and player.yesdont == true
	and player.nodont == true
		player.yesdont = false	
		player.nodont = false
		player.mo.state = S_PLAY_PAIN
	end
end)

--General setup for bustable block checking and busting
local function CheckAndCrumble(mo, sec)
  for fof in sec.ffloors()
    if not (fof.flags & FF_EXISTS) continue end -- Does it exist?
    if not (fof.flags & FF_BUSTUP) continue end -- Is it bustable?
    
    if mo.z + mo.height < fof.bottomheight continue end -- Are we too low?
    if mo.z > fof.topheight continue end -- Are we too high?
    if mo.skin == "amy"
    and mo.state == S_PLAY_FLIA
		EV_CrumbleChain(fof) -- Crumble
	end
  end
end

addHook("ThinkFrame", do
	for player in players.iterate
		if player.speed > 65*FRACUNIT
			player.charflags = $|SF_CANBUSTWALLS
			A_BossScream(player.mo, 0, 	MT_BOXSPARKLE)
		else
			local p = player.mo
			player.charflags = skins[player.mo.skin].flags
		end
	end
end)

addHook("PlayerThink", function(player)
  if not player.mo return end
  if player.mo.skin != "amy" return end

  CheckAndCrumble(player.mo, player.mo.subsector.sector)
end)

addHook("MobjLineCollide", function(mo, line)
  if not mo.player return end
  if mo.skin != "amy" return end

  for _, sec in ipairs({line.frontsector, line.backsector})
    CheckAndCrumble(mo, sec)
  end
end, MT_PLAYER)
//Istg if you touch this im going to beat you till you cannot breathe anymore. Jk pls dont report me i swear
//nah but fr vphysics is reusable take any shit you need
/*--General setup for bustable block checking and busting SPEED
local function CheckAndCrumble(mo, sec)
  for fof in sec.ffloors()
    if not (fof.flags & FF_EXISTS) continue end -- Does it exist?
    if not (fof.flags & FF_BUSTUP) continue end -- Is it bustable?
    
    if mo.z + mo.height < fof.bottomheight continue end -- Are we too low?
    if mo.z > fof.topheight continue end -- Are we too high?
    if mo.player.speed > 65*FRACUNIT //i fucking hate capybaras bro
	and mo.state == S_PLAY_RUN
		EV_CrumbleChain(fof) -- Crumble
	end
  end
end

addHook("PlayerThink", function(player)
  if not player.mo return end
  if player.speed > 65*FRACUNIT return end

  CheckAndCrumble(player.mo, player.mo.subsector.sector)
end)

addHook("MobjLineCollide", function(mo, line)
  if not mo.player return end
  if mo.player.speed > 65*FRACUNIT return end
  
  for _, sec in ipairs({line.frontsector, line.backsector})
    CheckAndCrumble(mo, sec)
  end
end, MT_PLAYER)*/

addHook("PlayerCanDamage", function(player)
	if player.mo.state == S_PLAY_FLIA
		return true
	end
end)

addHook("PlayerCanDamage", function(player)
	if player.speed > 65*FRACUNIT
		return true
	end
end)

//a
addHook("AbilitySpecial", function(player)
	if player.mo.isvphysics == 0 return end
	if player.mo.skin == "metalsonic"
	and (player.pflags & PF_JUMPED)
	and not (player.pflags & PF_THOKKED)
		player.mo.garbage = 1
		player.mo.soundeffectbruh = 1
		player.pflags = $|PF_NOJUMPDAMAGE
	end
end)

//Command/I/O stuff
local function writeCvar(file, vphysics)
    if player == consoleplayer then
        local file = io.openlocal("client/vphysics.dat")
        io.openlocal("client/vphysics.dat", "r")
        file:close()// funni line
    end
end

local function readCvar(file, vphysics)
    local value = file:read("*l")
    if file then
        COM_BufInsertText(consoleplayer, vphysics .. ' "' .. value .. '"')
    else
        print(vphysics.." not found.")
    end
end

local function saveConfig(vphysics)
    -- Open the file ("w" means we will write data to it)
    local file = io.openlocal(vphysics, "vphymom")

    writeCvar(file, "vphymom")
        
    file:close() -- We're done, close the file now
end

COM_AddCommand("vphymom", function(player, arg1)
  local file = io.openlocal("client/vphysics.dat", "w")
    if arg1 == "1" or arg1 == "on" or arg1 == "yes"
        if not player.mo then return end
        player.mo.doublejump = 1
    file:write("vphymom 1")
        CONS_Printf(player, "Momentum has been enabled")
    elseif arg1 == "0" or arg1 == "off" or arg1 == "no"
        player.mo.doublejump = 0
    file:write("vphymom 0")
        CONS_Printf(player, "Momentum has been disabled.")
    elseif not (arg1 == "1" or arg1 == "on" or arg1 == "yes")
	and not (arg1 == "0" or arg1 == "off" or arg1 == "no")     
        print("The fuck was that lmao put a valid one.")
    file:close()
    end
end)

addHook("PlayerSpawn", function(player)
    if player.mo and player.mo.valid
		local file = io.openlocal("client/vphysics.dat", "r")
		COM_BufInsertText(player, file:read("*l"))
		file:close()
    end
end)

addHook("PlayerSpawn", function(player)
	if player.mo and player.mo.valid
		player.mo.isvphysics = 1
	end
end)
addHook("PlayerCanDamage", function(player)
	if player.mo.isvphysics == 0 return end
	if player.mo.skin == "sonic"
	and player.mo.state == S_PLAY_ROLL
		return true
	end
end)

--we gotta, number one victory royale yeah fortnite we bout to get down (get down) ten kills on the board right now, just wiped out tomato town.... my friend just got downed, i revived him now were heading southbound, now were in the plesant park, streets, look at the map go to the marked sheet. Take me to your xbox to play fortnite today. you can take me to moisty mires, but not loot lake. I'd really love to....chug jug with you. we can be pro fortnite gamers...........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
//wtf
//The Fang Ability (This took so momming long.) -Hurricane
addHook("PlayerThink", function(player)
	if player.mo and player.mo.valid
		if player.mo.isvphysics == 0 return end
		if player.mo.popjump == nil
			player.mo.popjump = 0
		end
		if player.mo.skin == "fang"
		and player.usetapping
		and not P_IsObjectOnGround(player.mo)
		and not (player.mo.state == S_PLAY_ROLL)
			player.popjampuu = P_LookForEnemies(player, true, true)
			if player.popjampuu 
			and (player.popjampuu.flags & (MF_ENEMY|MF_BOSS|MF_MONITOR))
			and player.mo.skin == "fang"
				P_SpawnMissile(player.mo, player.popjampuu, MT_CORK)
				P_InstaThrust(player.mo, player.mo.angle, player.speed)
				P_Thrust(player.mo, player.mo.angle, 5*FRACUNIT)
				P_SetObjectMomZ(player.mo, 13*FRACUNIT)
				S_StartSound(player.mo, sfx_corkp)
				player.mo.state = S_PLAY_ROLL
				player.pflags = $|PF_THOKKED
				player.mo.popjump = 0
				player.mo.aliv = 1
			end
			if player.mo.popjump == 1
			and P_IsObjectOnGround(player.mo)
				player.mo.popjump = 0
			end
		end
	end
end)

// now the new part (thanks mr.board for suggesting this to me :>)
//edit: NO NEW PART
//edit: YES NEW PART
addHook("PlayerThink", function(player)
	if player.mo.valid and player.mo.skin == "fang" 
	and (player.pflags & PF_BOUNCING)
	and (player.cmd.buttons & BT_SPIN) then
		P_SetObjectMomZ(player.mo, 13*FRACUNIT)
		P_InstaThrust(player.mo, player.mo.angle, player.speed)
		player.mo.state = S_PLAY_ROLL
		player.mo.aliv = 1
		S_StartSound(player.mo, sfx_zoom)
		player.pflags = $ & ~PF_BOUNCING
	end
	if player.mo.skin == "fang"
		player.popjampuu2 = P_LookForEnemies(player, true, true)
		if player.popjampuu2
		and player.mo.skin == "fang"
		and not (P_IsObjectOnGround(player.mo))
		and not (player.mo.state == S_PLAY_FIRE)
			if (player.popjampuu2.flags & (MF_ENEMY|MF_BOSS|MF_MONITOR))
				P_SpawnLockOn(player, player.popjampuu2, S_LOCKON3)
			end
		end
    end
end)		

addHook("PlayerThink", function(player)
	if player.mo and player.mo.valid
		if player.chargedash == nil
			player.chargedash = 0
		end
		if (player.mo.garbage == 1) return end
		if player.mo.skin == "metalsonic"
		and not (player.chargedash == 1)
			player.prevmom = {x = player.mo.momx, y = player.mo.momy, z = player.mo.momz}
		end
		if not (player.cmd.buttons & BT_SPIN)
		and player.chargedash == 1
		and not (player.mo.garbage == 1)
		and not (player.dashmode > 3*TICRATE)
			P_InstaThrust(player.mo, player.mo.angle, FixedHypot(player.prevmom.x, player.prevmom.y))
			P_Thrust(player.mo, player.mo.angle, 15*FRACUNIT)
			S_StartSound(player.mo, sfx_zoom)
			player.chargedash = 0
			player.mo.state = S_PLAY_ROLL
			P_SpawnThokMobj(player)
			player.pflags = $1|PF_THOKKED
		end
		if not (player.cmd.buttons & BT_SPIN)
		and player.chargedash == 1
		and not (player.mo.garbage == 1)
		and (player.dashmode > 3*TICRATE)
			P_InstaThrust(player.mo, player.mo.angle, FixedHypot(player.prevmom.x, player.prevmom.y))
			P_Thrust(player.mo, player.mo.angle, 15*FRACUNIT)
			S_StartSound(player.mo, sfx_zoom)
			player.chargedash = 0
			player.mo.state = S_PLAY_DASH
			P_SpawnThokMobj(player)
			player.pflags = $1|PF_THOKKED
		end
		if not (player.cmd.buttons & BT_SPIN)
		and player.chargedash == 1
		and not (player.mo.garbage == 1)
			P_InstaThrust(player.mo, player.mo.angle, FixedHypot(player.prevmom.x, player.prevmom.y))
			P_Thrust(player.mo, player.mo.angle, 15*FRACUNIT)
			S_StartSound(player.mo, sfx_zoom)
			player.chargedash = 0
			player.mo.state = S_PLAY_ROLL
			P_SpawnThokMobj(player)
			player.pflags = $1|PF_THOKKED
		end
		if (player.cmd.buttons & BT_SPIN)
		and not (player.cmd.buttons & BT_JUMP)
		and player.mo.skin == "metalsonic"
		and not (player.mo.garbage == 1)
		and not (player.pflags & PF_THOKKED)
		and (player.pflags & PF_JUMPED)
			player.chargedash = 1
		end
		if (player.cmd.buttons & BT_SPIN)
		and player.chargedash == 1
		and not (player.mo.garbage == 1)
		and (player.speed > 1*FRACUNIT)
		and not (player.speed < 0*FRACUNIT)
			P_SetObjectMomZ(player.mo, 0*FRACUNIT)
			P_Thrust(player.mo, R_PointToAngle2(0, 0, player.mo.momx, player.mo.momy), -3*FRACUNIT)
			player.mo.state = S_PLAY_GLIDE_LANDING
			local suprfunnimario = P_SpawnGhostMobj(player.mo)
			suprfunnimario.fuse = 4
		end
		if (player.cmd.buttons & BT_SPIN)
		and player.chargedash == 1
		and not (player.mo.garbage == 1)
		and (player.speed < 1*FRACUNIT)
		and not (player.speed > 1*FRACUNIT)
			P_SetObjectMomZ(player.mo, 0*FRACUNIT)
			P_InstaThrust(player.mo, R_PointToAngle2(0, 0, player.mo.momx, player.mo.momy), 0*FRACUNIT)
			player.mo.state = S_PLAY_GLIDE_LANDING
			local imgonnakms = P_SpawnGhostMobj(player.mo)
			imgonnakms.fuse = 4
		end
		if player.chargedash == 1
		and P_IsObjectOnGround(player.mo)
			player.chargedash = 0
			player.pflags = $1|PF_SPINNING
			player.mo.state = S_PLAY_ROLL
			S_StartSound(player.mo, sfx_spin)
		end
		if player.chargedash == 1
		and P_PlayerInPain(player)
			player.chargedash = 0
		end
	end
end)

//I dont know why i put this over here..
addHook("PlayerThink", function(player)
    if player.mo and player.mo.valid
		if player.mo.isvphysics == 0 return end
		if player.mo.garbage == nil
			player.mo.garbage = 0
		end
		if player.mo.metalabilitytimer == nil
			player.mo.metalabilitytimer = 25*TICRATE
		end
		if player.mo.soundeffectbruh == nil
		    player.mo.soundeffectbruh = 0
		end
		if player.mo.soundeffectbruh == 1
			S_StartSound(player.mo, sfx_bkpoof)
			player.mo.soundeffectbruh = 0
		end
		if player.mo.skin == "metalsonic"
		and P_IsObjectOnGround(player.mo)
			player.mo.metalabilitytimer = 25*TICRATE
			player.mo.garbage = 0
		end
		if player.mo.skin == "metalsonic"
		and player.mo.garbage == 1
			player.mo.metalabilitytimer = $1 - 1*TICRATE
		end
		if not (player.pflags & PF_THOKKED)
		and player.mo.metalabilitytimer == 0*TICRATE
			player.mo.garbage = 0
			player.mo.state = S_PLAY_SPRING
			player.pflags = $|PF_THOKKED
			player.mo.metalabilitytimer = 25*TICRATE
		end
		if player.mo.garbage == 1
		and not P_PlayerInPain(player)
		and (player.cmd.buttons & BT_JUMP)
			P_SetObjectMomZ(player.mo, 9*FRACUNIT)
			player.mo.state = S_PLAY_WALK
			local amoggy = P_SpawnGhostMobj(player.mo)
			amoggy.fuse = 4
		end
		if player.mo.garbage == 1
		and not (player.cmd.buttons & BT_JUMP)
			player.mo.garbage = 0
			player.mo.state = S_PLAY_SPRING
		end
		if player.mo.skin == "metalsonic"
		and P_IsObjectOnGround(player.mo)
		and player.mo.garbage == 1
			player.mo.garbage = 0
			player.mo.state = S_PLAY_STND
		end
		if player.mo.skin == "metalsonic"
			player.charability = 0
		end
		if player.mo.garbage == 1
			player.mo.soundeffectbruh = 0
		end
		if (player.mo.eflags & MFE_SPRUNG)
			player.mo.garbage = 0
		end
		if P_PlayerInPain(player)
			player.mo.garbage = 0
		end
		if (player.cmd.buttons & BT_JUMP)
		and player.mo.garbage == 1 //jumpy
		and player.chargedash == 1 //chargy
			player.chargedash = 0 // no chargy
		end
		if (player.cmd.buttons & BT_SPIN)
		and player.mo.garbage == 1 //jumpy
		and player.chargedash == 1 //chargy
			player.mo.garbage = 0 // no jumpy
		end
		if P_PlayerInPain(player)
			local redneck = P_SpawnGhostMobj(player.mo)
			redneck.fuse = 4
		end
    end
end)

addHook("MobjDamage", function(player, inf, src, dmg, dmgtype)
	if player.isvphysics == 0 return end
	if player.player.mo.skin == "adventuresonic" return end
	if (player.player.rings == 0) return end
	if not player.player.donotloop then
		local moms = {x=player.momx,y=player.momy,z=player.momz}    
		player.player.donotloop = true -- Make sure this doesn't happen multiple times
		P_DamageMobj(player) -- Damage player with this info
		P_Thrust(player, player.angle, -25*FRACUNIT)
		player.player.donotloop = false -- ok
		
		-- Player in pain
		-- Restore previous momentum
		player.momx = moms.x
		player.momy = moms.y
	return true
	end
end, MT_PLAYER)

--General setup for bustable block checking and busting
local function CheckAndCrumble2(mo, sec)
  for fof in sec.ffloors()
    if not (fof.flags & FF_EXISTS) continue end -- Does it exist?
    if not (fof.flags & FF_BUSTUP) continue end -- Is it bustable?
    
    if mo.z + mo.height < fof.bottomheight continue end -- Are we too low?
    if mo.z > fof.topheight continue end -- Are we too high?
    if mo.skin == "knuckles"
    and mo.state == S_PLAY_JUMP
		EV_CrumbleChain(fof) -- Crumble
	end
  end
end

addHook("PlayerThink", function(player)
  if not player.mo return end
  if player.mo.skin != "knuckles" return end

  CheckAndCrumble2(player.mo, player.mo.subsector.sector)
end)

addHook("MobjLineCollide", function(mo, line)
  if not mo.player return end
  if mo.skin != "knuckles" return end

  for _, sec in ipairs({line.frontsector, line.backsector})
    CheckAndCrumble2(mo, sec)
  end
end, MT_PLAYER)

freeslot("SPR2_FUNI", "S_PLAY_FUNNI")
states[S_PLAY_FUNNI] = {
        sprite = SPR_PLAY,
        frame = SPR2_FUNI,
        tics = 70,
		nextstate = S_PLAY_STND
}

addHook("PlayerThink", function(player)
	if player.mo and player.mo.valid
		if not (player.cmd.buttons & BT_CUSTOM1) then
			player.c1tapready = true
			player.c1tapping = false
		elseif player.c1tapready then
			player.c1tapping = true
			player.c1tapready = false
		else
			player.c1tapping = false
		end
		if player.mo.skin == "fang"
		and player.c1tapping
		and P_IsObjectOnGround(player.mo)
			player.mo.state = S_PLAY_FUNNI
			player.pflags = $|PF_FULLSTASIS
		end
		if player.mo.state == S_PLAY_FUNNI
		and player.mo.skin == "fang"
			player.mo.frame = FF_ANIMATE | (((70 - player.mo.tics)/5) % 2)
			player.pflags = $|PF_FULLSTASIS
		end
	end
end)
//mommy sonic
addHook("ThinkFrame", do
	for player in players.iterate
		if player.mo.skin == "mosonic"
			player.charability2 = CA2_NONE
		end
		if not (player.mo and player.mo.valid and player.mo.skin == "mosonic") return end
		if player.cum == nil
			player.cum = 0
		end
		if player.topspin == nil
			player.topspin = 0
		end
		if player.mo.skin == "mosonic"
		and (player.cmd.buttons & BT_SPIN)
			player.mo.state = S_PLAY_STND
			player.camangle = player.cmd.angleturn<<16 + R_PointToAngle2(0, 0, player.cmd.forwardmove*FRACUNIT, -player.cmd.sidemove<<16)
			P_Thrust(player.mo, player.camangle, 1*FRACUNIT)
			player.topspin = 1
		end
		if player.speed > 0
		and player.mo.skin == "mosonic"
			player.drawangle = player.cum
			player.cum = $ + ANGLE_45
		end
		if player.topspin == 1
		and P_IsObjectOnGround(player.mo)
			local vphyrundust = P_SpawnMobj(player.mo.x, player.mo.y,
			player.mo.z + ((player.mo.eflags & MFE_VERTICALFLIP)/MFE_VERTICALFLIP * (player.mo.height - mobjinfo[MT_SPINDUST].height)),
			MT_SPINDUST)
			P_InstaThrust(vphyrundust, player.mo.angle+(P_RandomRange(-ANG30/FRACUNIT, ANG30/FRACUNIT)*FRACUNIT), FixedMul(-player.dashspeed/12-1*FRACUNIT-P_RandomByte()<<11, player.mo.scale))
			P_TryMove(vphyrundust, vphyrundust.x+vphyrundust.momx, vphyrundust.y+vphyrundust.momy, true)
			P_SetObjectMomZ(vphyrundust, 8*FRACUNIT, true)
			vphyrundust.fuse = 6
		end
		if not (player.cmd.buttons & BT_SPIN)
		and player.mo.skin == "mosonic"
			player.topspin = 0	
		end
		if player.topspin == 1
			A_BossScream(player.mo, 0, 	MT_BOXSPARKLE)
		end
		if player.topspin == 0
		and player.mo.skin == "mosonic"
			player.acceleration = 0*FRACUNIT
			player.normalspeed = 0*FRACUNIT
		end
		if player.jumptapping
		and P_IsObjectOnGround(player.mo)
			P_SetObjectMomZ(player.mo, 12*FRACUNIT)
			player.pflags = $|PF_JUMPED
		end
		if P_PlayerInPain(player)
		and player.mo.skin == "mosonic"
			S_StartSound(player.mo, sfx_aois)
			P_KillMobj(player.mo)
		end
		if player.mo.skin == "mosonic"
		and player.topspin == 1
		and player.drawangle == ANGLE_45
			S_StartSound(player.mo, sfx_s3k42)
		end
	end
end)

addHook("PlayerCanDamage", function(player)
	if player.topspin == 1
		return true
	end
end)

//Fang momentum renewal by CobaltBW //save2
addHook("PlayerThink", function(player)
	if player.charability == CA_BOUNCE then
	//Create bounce history
		if player.bouncyboing == nil then
			player.bouncyboing = false
		end
		if player.pflags&PF_BOUNCING and not(player.bouncyboing) //Activate bounce
		or (not(player.pflags&PF_BOUNCING) and player.pflags&PF_THOKKED and player.bouncyboing) and not (player.cmd.buttons & BT_JUMP)//Deactivate bounce
			local pmo = player.mo
            local scale = pmo.scale //Normalspeed calculations are affected by scale
            local pmom = FixedDiv(FixedHypot(player.rmomx,player.rmomy),scale) //Current speed, scaled for normalspeed calculations
            local momangle = R_PointToAngle2(0,0,player.rmomx,player.rmomy)
            local mom = FixedHypot(pmo.momx,pmo.momy)
            local aup = FixedMul(P_ReturnThrustX(nil,momangle,pmom),scale)
            local aside = FixedMul(P_ReturnThrustY(nil,momangle,pmom),scale)    
			local grounded = P_IsObjectOnGround(pmo)
			pmo.momx = FixedMul(P_ReturnThrustX(nil,momangle,pmom),scale)
			pmo.momy = FixedMul(P_ReturnThrustY(nil,momangle,pmom),scale)
			pmo.momz = $*1
		end
		player.bouncyboing = (player.pflags&PF_BOUNCING > 0)
	end
	if (player.pflags & PF_BOUNCING) 
	and (player.cmd.buttons & BT_JUMP)
		return
	end
	local pmo = player.mo
	player.waterlast = (pmo.eflags&MFE_UNDERWATER > 0)
	player.dashlast = (player.pflags&PF_STARTDASH > 0)
end)

//remaking fang popgun because the vanilla one sucks ass (or cock idk)
addHook("ThinkFrame", do
	for player in players.iterate
		if not (player.mo.skin and player.mo.valid and player.mo.skin == "fang") return end
		if player.mo.skin == "fang"
			player.charability2 = CA2_NONE
		end
		if player.shot == nil
			player.shot = 0
		end
		if player.gwakky == nil
			player.gwakky = 0
		end
		if player.mo.state == S_PLAY_WALK 
		or player.mo.state == S_PLAY_RUN  
		or player.mo.state == S_PLAY_STND 
		or player.mo.state == S_PLAY_WAIT 
		or player.mo.state == S_PLAY_FIRE 
		or player.mo.state == S_PLAY_FIRE_FINISH
			player.shooty = P_LookForEnemies(player, true, true)
		end
		if player.shooty
		and player.shooty.valid
		and (player.shooty.flags & (MF_ENEMY|MF_BOSS|MF_MONITOR))
		and player.usetapping
		and not (player.mo.popjump == 1)
		and P_IsObjectOnGround(player.mo)
		and not (player.pflags & PF_THOKKED)
			P_SpawnMissile(player.mo, player.shooty, MT_CORK)
			player.mo.state = S_PLAY_FIRE
			S_StartSound(player.mo, sfx_corkp)
			P_SetObjectMomZ(player.mo, 4*FRACUNIT)
			player.pflags = $|PF_THOKKED
			player.shot = 1
		end
		if player.usetapping
		and not (player.shooty)
		and not (player.mo.popjump == 1)
		and P_IsObjectOnGround(player.mo)
		and not (player.pflags & PF_THOKKED)
			player.mo.state = S_PLAY_FIRE
			S_StartSound(player.mo, sfx_corkp)
			P_SetObjectMomZ(player.mo, 4*FRACUNIT)
			player.pflags = $|PF_THOKKED
			P_SPMAngle(player.mo, MT_CORK, player.mo.angle)
		end
		/*if player.gwakky == 1
		and P_IsObjectOnGround(player.mo)
		and player.speed > 0*FRACUNIT
			player.mo.state = S_PLAY_STND
			player.gwakky = 0
			local pmo = player.mo
            local scale = pmo.scale //Normalspeed calculations are affected by scale
            local pmom = FixedDiv(FixedHypot(player.rmomx,player.rmomy),scale) //Current speed, scaled for normalspeed calculations
            local momangle = R_PointToAngle2(0,0,player.rmomx,player.rmomy)
            local mom = FixedHypot(pmo.momx,pmo.momy)
            local aup = FixedMul(P_ReturnThrustX(nil,momangle,pmom),scale)
            local aside = FixedMul(P_ReturnThrustY(nil,momangle,pmom),scale)    
			pmo.momx = FixedMul(P_ReturnThrustX(nil,momangle,pmom),scale)
			pmo.momy = FixedMul(P_ReturnThrustY(nil,momangle,pmom),scale)
			pmo.momz = $*1
		end*/
		if player.shooty
		and player.shooty.valid
		and (player.shooty.flags & (MF_ENEMY|MF_BOSS|MF_MONITOR))
		and P_IsObjectOnGround(player.mo)
			P_SpawnLockOn(player, player.shooty, S_LOCKON1)
		end
		//fang is so fucking retarded i hate fang so much (jk fang is my favorite vphysics character)
		if player.mo.skin == "fang"
			player.charflags = $|SF_NOJUMPDAMAGE
		end
	end
end)

addHook("ThinkFrame", do
    for player in players.iterate
        if not (player and player.mo and player.mo.valid and player.exiting and (gametyperules & GTR_FRIENDLY)) 
            return
        end
        player.shieldkeep = player.powers[pw_shield]
    end
end)

addHook("PlayerSpawn", function(player)
    if not (gametyperules & GTR_FRIENDLY) return end    
    if (player.shieldkeep == nil) return end
    if (player and player.mo and player.mo.valid)
        P_SwitchShield(player, player.shieldkeep)
        P_SpawnShieldOrb(player)
        player.shieldkeep = nil
    end
end)