--===========================MAIN THINKERS==============================
--Main gameplay related thinkers. Most of Samus' behaviour is here.
--======================================================================
local SAM = MetroidVanguard
local SamOncePerMap1,SamOncePerMap2 = true,true
local FORCESAMUSSKIN = false

addHook("MapChange", function(gamemap)
	SamOncePerMap1,SamOncePerMap2 = false,false --We're ready once again to use the Spawn functions.
	for z in players.iterate
		if not (z and z.valid) continue end --
		
		if z.sam_saveselect --Obviously don't save in the save menu itself...
			z.sam_dontsave = true
		end
		if z.sam_intoship --Undo these things.
			z.pflags = $ & ~(PF_INVIS|PF_GODMODE|PF_FORCESTRAFE)
		end
		z.samweather = nil
		z.SAM_RevengeBounty,z.SAM_RevengeBountyTime = nil,nil
		if (gametype != GT_COOP)
			z.crystalflashchance = 0 --We don't use this outside of coop
			z.sam_dontsave = true
			z.sam_emeraldflags = 0
			z.sam_saveselected = 0 --Reset all save settings outside coop, please.
			z.sam_saveselect,z.samuschosefile = nil,nil
			z.sam_autotank = nil --Remove bonus items except the Scan Visor at the start of matches
			z.sam_ammodigitizer = 1 --Having the Ammo Digitizer would make this 3. (We use it as a multiplier)
		else
			if z.mo and z.mo.valid
				z.mo.sam_rvzmsg	= nil
			end
			if (z.jointime > 1)
				if z.sam_dontsave
					z.sam_dontsave = false
				else
					z.sam_dosave = true --Gotta do this to update the gamemap properly
				end
				z.sam_changedmap = true
			end
		end
		z.scannedmons,z.scannedplays = nil,nil --No scans at the start of a level, naturally.
	end
end)

local function P_MobjFlip(s) --Preventing MobjFlip crash by overriding the function entirely.
	if s and s.valid and ((s.eflags & MFE_VERTICALFLIP) or (s.flags2 & MF2_OBJECTFLIP))
		return -1 --
	end return 1 --
end

local function StartSamSPBS(s,p)
	if p.samspbschargefull return end --Already boosting!
	
	s.spbssfx = P_SpawnMobj(s.x, s.y, s.z, MT_SAMUSTHOK) --Don't make this a local value.
	s.spbssfx.flags2 = MF2_DONTDRAW s.spbssfx.tics = 90
	S_StartSound(s.spbssfx, sfx_sprnc)

	S_StartSound(s, sfx_sprna)
	s.sam_flashfade = 8
	s.sam_flashfadecolor = SKINCOLOR_SAPPHIRE						
	SamusTutorial(s, "variasuit", true)
	p.charflags = $ & ~SF_NOSKID
	p.runspeed = 2199594
	s.sam_supertilt = 25
	s.sam_afterboost = 7
	s.SAM_StartBooster = 28
	p.samspbschargefull = true
	s.sam_spbsstart = 15
	local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_PBEXPANDI)
	if ghs and ghs.valid
		ghs.color = SKINCOLOR_AZURE
		ghs.scale = s.scale+(5<<16)
		ghs.momx,ghs.momy,ghs.momz = s.momx*10/11,s.momy*10/11,s.momz*10/11
		ghs.scalespeed = $*11
		ghs.destscale = 45<<16
	end

	local ghs = P_SpawnMobjFromMobj(s, 
	FixedMul(120<<16, cos(s.angle)),
	FixedMul(120<<16, sin(s.angle)),
	-5*s.scale, MT_THOK)
	
	ghs.sprite = SPR_MXP4
	ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
	ghs.frame = V|FF_TRANS80
	ghs.blendmode = AST_ADD
	ghs.scale = s.scale/3
	ghs.momx,ghs.momy = s.momx*2/3,s.momy*2/3
	ghs.momz = s.momz+((-9<<16)*P_MobjFlip(ghs))
	ghs.tics,ghs.fuse = 22,11
	ghs.scalespeed = SAM.scaled(ghs, ghs.scalespeed*2)
	ghs.destscale = 99<<16
end

local function PrimeRunPhysics(s, p) --Special physics for Samus.
	if p.noprimerun
		p.noprimerun = $-1 return --
	end
	if (p.pflags & PF_SPINNING) or ((s.flags2 & MF2_TWOD) or twodlevel)
		return --Not now.
	end
	local spbonus = (p.samspbschargefull and (p.speed>20*s.scale)) and 195 or 0 --speedbooster adjustments.
	local forwardmove,sidemove = abs(p.cmd.forwardmove), abs(p.cmd.sidemove)
	p.sam_direct = (forwardmove>sidemove) and forwardmove or sidemove
	p.sam_turnang = (p.cmd.angleturn<<16)+(R_PointToAngle2(0, 0, p.cmd.forwardmove<<16, -(p.cmd.sidemove<<16)))
	
	--Morph Ball physics
	if p.sammorphed
		if s.friction != FRACUNIT
			if not P_IsObjectOnGround(s)
			or (p.sam_direct < 20)
				if s.friction > 62200
					s.friction = 59392
				end
				return --
			end
			local momangle = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)
			local trueturn = (momangle-p.sam_turnang)
			if trueturn != 0
				trueturn = abs($/ANG1)
			end	
			if (trueturn < 80) and (p.speed >= 35<<16)
				s.friction = max(59392, 64930-(trueturn*16))
				s.sam_mbspeedf = true
			elseif (s.friction > 62200)
				s.friction = 59392
			end
		end
		return --Always return here if morphed.
	end
	if not (p.speed > 5*s.scale) or not (p.sam_direct > 3) return end --No need if we're this slow or barely tilting the stick.
	
	local momangle = R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)
	local trueturn = (momangle-p.sam_turnang)
	if trueturn != 0
		trueturn = abs($/ANG1)
		if (trueturn < 7)
			return --If the turning input's not significant, no need for complex physic alterations.
		end
	end
	
	if P_IsObjectOnGround(s) --Grounded.
		
		if (trueturn > 14)
			if (trueturn > 150)
				return --Too much!
			end	
			local premomx,premomy = s.momx,s.momy
			local OGtrueturn = trueturn	
			
			trueturn = min(100, ($*10)/40 )
			
			local moveang = R_PointToDist2(s.x, s.y, s.x+s.momx, s.y+s.momy)
			local xadd = P_ReturnThrustX(s, p.sam_turnang, moveang)+p.cmomx
			local yadd = P_ReturnThrustY(s, p.sam_turnang, moveang)+p.cmomy
			
			if (xadd or yadd)
				P_InstaThrust(s, R_PointToAngle2(s.x-s.momx,s.y-s.momy, s.x+xadd, s.y+yadd), moveang)						
	
				s.momx = FixedMul(s.momx, FixedDiv(trueturn, 100)) + FixedMul(premomx, FixedDiv(100-trueturn, 100))
				s.momy = FixedMul(s.momy, FixedDiv(trueturn, 100)) + FixedMul(premomy, FixedDiv(100-trueturn, 100))
				if (OGtrueturn > 40)
					local TURNv = trueturn*1000
					local TURNh = ((OGtrueturn<70) and 800 or (OGtrueturn<81) and 750 or 600)+spbonus
					local DIV = 2000+(TURNv/TURNh)
					
					s.momy = FixedDiv(FixedMul($, 2000), DIV )
					s.momx = FixedDiv(FixedMul($, 2000), DIV )
				end
			end
		end
		
	else --Air Control!	
		
		trueturn = $*10/100
		
		if (trueturn > 14) return end --Subtleness only here.
		
		local premomx,premomy = s.momx,s.momy
		local moveang = R_PointToDist2(s.x, s.y, s.x+s.momx, s.y+s.momy)
		local xadd = P_ReturnThrustX(s, p.sam_turnang, moveang)+p.cmomx
		local yadd = P_ReturnThrustY(s, p.sam_turnang, moveang)+p.cmomy
	
		if xadd or yadd	
			P_InstaThrust(s, R_PointToAngle2(s.x-s.momx,s.y-s.momy, s.x+xadd, s.y+yadd), moveang)
		
			s.momx = FixedMul(s.momx, FixedDiv(trueturn, 100)) + FixedMul(premomx, FixedDiv(100-trueturn, 100))
			s.momy = FixedMul(s.momy, FixedDiv(trueturn, 100)) + FixedMul(premomy, FixedDiv(100-trueturn, 100))
			local TURNv = trueturn*2
	--		local TURNv = (trueturn*1000)/500
			s.momx = FixedDiv(FixedMul($, 2000), 2000+TURNv)
			s.momy = FixedDiv(FixedMul($, 2000), 2000+TURNv)
		end
	end	
end

--Holding onto that glimmer of hope!
local function CrystalRebirth(s, p) 
	if (leveltime%2==0) and (p.sam_energy < 99+(p.sam_energytanksmax*50))
		p.sam_energy = $+1 --Practically invincible.
	end
	if s.crystalflashanim --Phase 1, the animation
		if p.sammorphed
			SAM.UnMorph(s, true)
		end
		if leveltime % 4 == 0
			S_StartSound(s, sfx_nrga)
			p.sammissiles = $+5
			p.sampw = $+1
			p.samsupermissiles = $+1
			if (s.crystalflashanim > 28)
				local ghs = P_SpawnMobj(
				s.x+((P_RandomRange(FixedMul(-300, s.scale), FixedMul(300, s.scale)))<<16), 
				s.y+((P_RandomRange(FixedMul(-300, s.scale), FixedMul(300, s.scale)))<<16), 
				s.z+((P_RandomRange(FixedMul(300, s.scale), FixedMul(-300, s.scale)))<<16), MT_MSGATHER)
				ghs.scale = (s.scale)/P_RandomRange(1,2)	
				ghs.fuse = P_RandomRange(10,20)
				ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
				ghs.flags = $|MF_SPECIAL|MF_NOBLOCKMAP
				ghs.frame = ($ & ~FF_TRANSMASK)|FF_TRANS50
				ghs.color = SKINCOLOR_PURPLE
				ghs.colorized = true
				P_HomingAttack(ghs, s)
			end
		end

		p.powers[pw_nocontrol] = 2
		s.momx,s.momy = 0,0
		P_SetObjectMomZ(s, 500)
		s.flags = MF_SOLID|MF_SHOOTABLE
		s.state = S_PLAY_FALL
		p.playerstate = PST_LIVE
		p.pflags = $|PF_JUMPED
		
		if (s.crystalflashanim > 120)
			p.camerascale = 2<<16
			s.thesamcam = 1		
			P_SetObjectMomZ(s, 3<<16)
			s.sprite2 = SPR2_DEAD
			s.frame = ($ & ~FF_FRAMEMASK)|C|FF_FULLBRIGHT //|(s.crystalffade)
			if (s.crystalflashanim % 5 == 0)
				s.clight = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_SAMMISSILELIGHT)
				s.clight.crystalflashl = true
				s.clight.scale = s.scale/8
				s.clight.layers = 8
				if s.lastclightc
					s.lastclightc = false
					s.clight.color = SKINCOLOR_SUPERGOLD1
				else
					s.lastclightc = true
					s.clight.color = SKINCOLOR_SUPERRED3			
				end
			end
			
		elseif (s.crystalflashanim > 28)
			p.camerascale = 3<<16
			s.thesamcam = 1				
			if s.crystalflashanim == 60
				s.sprite2 = SPR2_DEAD
				s.frame = ($ & ~(FF_FRAMEMASK|FF_TRANSMASK))|F|FF_FULLBRIGHT|FF_TRANS90
				S_StartSound(s, sfx_cmcha)
				s.crystalffade = FF_TRANS90
			else
				s.sprite2 = SPR2_GLID
				s.frame = ($ & ~FF_FRAMEMASK)|FF_FULLBRIGHT
			end
			
			P_SetObjectMomZ(s, 500)	
			
			s.crystalfroll = $+(ANG1*(s.crystalflashanim/20)) --Do a fancy lil' roll
			s.rollangle = s.crystalfroll
			
			if (s.crystalflashanim % 5 == 0)
				s.clight = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_SAMMISSILELIGHT)
				s.clight.scale = s.scale/7
				s.clight.crystalflashl = true
				s.clight.scalespeed = $/2
				s.clight.layers = 6
				s.lastclightc = (not s.lastclightc) and false or true
				s.clight.color = (s.lastclightc) and SKINCOLOR_SUPERSILVER1 or SKINCOLOR_SUPERRED5
			end
		else
			if (s.crystalflashanim > 20)
				s.rollangle = 0
				s.sprite2 = SPR2_DEAD
				s.frame = D|FF_FULLBRIGHT //|(s.crystalffade)	
			elseif (s.crystalflashanim < 21)		
				if (s.crystalflashanim == 20) --And you're back!
					P_RadiusAttack(s, s, 500<<16)
					if p.sam_spacejumped
						p.sam_spacejumped = false
					end
					s.flags2 = $ & ~MF2_DONTDRAW
					if not p.powers[pw_flashing]
						p.powers[pw_flashing] = 95
					end
					p.camerascale = FRACUNIT
					s.rollangle = 0
					S_StartSound(s, sfx_wvcm2)
					S_StartSound(s, sfx_spcm)			
					A_samquake(s, 70<<16, 23, 1)
					
					local ghs = P_SpawnMobj(s.x, s.y, s.z, MT_PBEXPANDI)
					ghs.scale = $*2
					ghs.scalespeed = $*7
					ghs.destscale = $*55
					
					P_SamFP(p, PAL_RECYCLE, 9)
					s.plexpand3 = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_PBEXPANDW)
					s.plexpand3.scalespeed = $*5
					s.plexpand3.destscale = 99<<16
					s.plexpand3 = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_PBEXPAND)
					s.plexpand3.scalespeed = $*6
					s.plexpand3.destscale = 99<<16					
					s.clight = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_SAMMISSILELIGHT)
					s.clight.layers = 5
					s.clight.crystalflashl = true
					s.clight.color = SKINCOLOR_SUPERSILVER1		
					
				end

				SAM.SpeedBoosterGhosts(s, p, true)	
				A_SAMPARTICLE(s, MT_MPR5, 35, 4, -4, 4, SKINCOLOR_SUPERGOLD2, P_RandomRange(35355, 58355)+40000)
				
				s.sprite2 = SPR2_DEAD
				s.frame = ($ & ~FF_FRAMEMASK)|FF_FULLBRIGHT	
			end
		
		end
		--Crystal Flash, the closest thing to a Super Samus	there is	
		
	else --You've rebirthed! This is where the Crystal Flash state behaviour begins!

		if s.crystalflashftime
			s.crystalflashftime = $-1
			s.crystalflashftimec = 25
			if not s.crystalflashftime
				s.crystalflashftimec = 0
			end
		end
		if p.sammorphed
			SamSpiderCharge(p, s, 103)
			if not s.spiderbanim
				s.spiderbanim = 7
			end
		end
		if s.crystalflashtime == 2288
			SamusMission(s, "\x8E"+"CRYSTAL FLASH ACTIVATED.", nil, nil, 3, 0, false)
			if p.sammorphed
				SAM_CMD(p, "lol", "true", "lol", "lol")
			else
				SAM_CMD(p, "nil", "true", "false", "15")
				S_StartSound(s, sfx_samspa, p)
			end
		end
		if s.crystalflashsymtrns == nil
			s.crystalflashftimec = 0
			s.crystalflashsymtrns = FF_TRANS90
			s.crystalflashsymtrnsd = -1
			s.crystalflashsymcolor = SKINCOLOR_SUPERRED1
		elseif (s.crystalflashsym % 6 == 0)
			if s.crystalflashsymtrns == FF_TRANS40
				s.crystalflashsymcolor = SKINCOLOR_SUPERRED1
				s.crystalflashsymtrnsd = 1
			elseif s.crystalflashsymtrns == FF_TRANS90
				s.crystalflashsymcolor = SKINCOLOR_SUPERRED5
				s.crystalflashsymtrnsd = -1
			end
			s.crystalflashsymcolor = $+s.crystalflashsymtrnsd
			s.crystalflashsymtrns = $+(FRACUNIT*s.crystalflashsymtrnsd)
		end
		if s.crystalflashsym == nil or (s.crystalflashsym > 29) --HUD effects.
			s.crystalflashsym = 0
		else
			s.crystalflashsym = $+1
		end
		local ghs
		if (s.eflags & MFE_JUSTHITFLOOR)
			A_samquake(s, 25<<16, 5, 300<<16)
			S_StartSound(s, sfx_wvbc)
			S_StartSound(s, sfx_rocks1)
			for d = 0,7
				ghs = P_SpawnMobj(
				s.x+FixedMul(25<<16, cos(ANGLE_45*d)), 
				s.y+FixedMul(25<<16, sin(ANGLE_45*d)), 
				s.z, MT_SPINDUST)
				if ghs and ghs.valid
					P_InstaThrust(ghs, ANGLE_45*d, 30<<16)
				end
			end
			for d = 1,20
				local t = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_MINECARTSPARK)
				t.scale = s.scale/15
				t.fuse = 30
				P_InstaThrust(t, P_RandomRange(1,359)*ANG1, P_RandomRange(12,24)<<16)
				t.momx = $+(s.momx*2) t.momy = $+(s.momy*2)
				t.momz = P_RandomRange(4,7)<<16
			end	
		end		
//		p.sam_shinespark = 3
		if (p.speed == 0)
			ghs = P_SpawnGhostMobj(s)
			ghs.rollangle = s.rollangle
			ghs.tics = 6
			P_SetObjectMomZ(ghs, -2<<16, true)
			ghs.scalespeed = $*P_RandomRange(1,3)
			ghs.destscale = $*5
			ghs.colorized = true
			ghs.blendmode = AST_ADD
			ghs.color = SKINCOLOR_SUPERRED2
		else
			SAM.SpeedBoosterGhosts(s, p, true)
		end
		
		if (s.crystalflashtime % 4 == 0) --Effects	
			local ghs
			local totali = (p.speed > 45<<16) and 3 or (p.speed > 10<<16) and 2 or 1
			local FRAME = A|FF_FULLBRIGHT|FF_TRANS80
			local rngx,rngy,rngz = 0,0,0
			for i = 1,totali
				if i == 2
					rngx,rngy,rngz = -$,-$,-$
				else
					rngx = P_RandomRange(-405,405)<<16 +(s.momx*35)
					rngy = P_RandomRange(-405,405)<<16 +(s.momy*35)
					rngz = P_RandomRange(5,80)<<16 +(s.momz*15)				
				end
				local scale = P_RandomRange(7,12)
				for d = 0,16,3
					ghs = P_SpawnMobj(s.x+rngx, s.y+rngy, s.z+rngz, MT_THOK)
					ghs.scale = s.scale/(scale+d)
					ghs.sprite = SPR_OILF
					ghs.frame = FRAME
					ghs.tics = P_RandomRange(75,150)
					ghs.momz = 2<<16+(d*4096)
					if s.lastclightc
						s.lastclightc = false
					else
						s.lastclightc = true
						ghs.color = SKINCOLOR_SUPERRED2
						ghs.colorized = true
					end
		--			if not p.sammorphed and (SAM_displayplayer(p) and not CV_FindVar("chasecam").value) --Don't bother rendering in first person.
		--				s.ghs.flags2 = $|MF2_DONTDRAW
		--			end
				end
			end
		end
		
		if s.crystalflashtime % 70 == 0
			s.crystalflashftime = 10
			P_RadiusAttack(s, s, 128<<16)
			s.clight = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_SAMMISSILELIGHT)
			s.clight.scale = s.scale/10
			s.clight.crystalflashlt = s
			s.clight.color = SKINCOLOR_SUPERSILVER1
			s.clight.blendmode = AST_ADD
			s.clight.layers = 12
			s.clight.superlayered = true
			S_StartSound(s, sfx_nrga)
			S_StartSound(s, sfx_mbop)
			
			if (p.sam_energy < 99+(p.sam_energytanksmax*50))			
				p.sam_energy = $+10
				p.sammissiles = $+2
			end
			if P_IsObjectOnGround(s)
				for d = 1,16
					local ghs = P_SpawnMobj(
					s.x+FixedMul(25<<16, cos(ANGLE_22h*d)), 
					s.y+FixedMul(25<<16, sin(ANGLE_22h*d)), s.z, MT_SPINDUST)
					if ghs and ghs.valid
						P_InstaThrust(ghs, ANGLE_45*d, 50<<16)
					end
				end
			end
		else
			s.clight = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_SAMMISSILELIGHT)
			if p.sammorphed
				s.clight.scale = s.scale/30
				s.clight.scalespeed = $/3
			else
				s.clight.scale = s.scale/10
			end
			s.clight.crystalflashl = true
			s.clight.crystalflashlt = s
			s.clight.color = SKINCOLOR_SUPERSKY2
			s.clight.layers = 2		
		end
	end
end

local function SamusWeaponReady(s, p)
	local ghs = P_SpawnMobjFromMobj(s, 
	FixedMul(s.radius*5/2, cos(s.angle-ANG2*2)), 
	FixedMul(s.radius*5/2, sin(s.angle-ANG2*2)), 
	s.height*4/11,  MT_SAMCHARGEGFX)
	if ghs and ghs.valid
		ghs.z = $+(FixedMul(FixedMul(50<<16, s.scale), sin(p.aiming)))
		ghs.state = S_SAMCHARGEGFX4
		ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
		ghs.ret2sign = true
		if (leveltime%6==0)
			ghs.spritexscale,ghs.spriteyscale = $*4/3,$*4/3
			ghs.blendmode = AST_ADD
			ghs.color = SKINCOLOR_WHITE
		else
			ghs.color = SKINCOLOR_GREY
		end
		ghs.colorized = true
		ghs.target = s
		return ghs --
	end
end

--Glorified PlayerThink hook that's only active with a mobj.
addHook("MobjThinker", function(s) if not (s.valid and s.player) return end local p = s.player
	if p.sams_shotcd == nil or p.sam_energytanksmax == nil
		SamusSetUp(p) --Set up Samus' values. In future projects we'll use tables.
	end
	if not p.samcmult
	or ((p.samcmult == 11 and not p.samchallenger) or (p.samcmult == 7 and not p.buffbottomtier))
		p.samcmult = 8 --Damage multiplier in Match. 8 is 1:1, 11 is about a 30% reduction, 7 is a slight increase.
	end
	if p.sam_joinsync == nil
		SAM.JoinSync(p,s)
	end
	
	if p.samhudmessagetime
		p.samhudmessagetime = $-1
		local MTIME = (p.samhudmessagetime) or 1		
		if not p.samhudmessageoffset
			if MTIME < 30
				p.samhudmessageoffset = 1
			end
			p.samhudmessageoffset = 30
		elseif p.samhudmessageoffset and not ((p.samhudmessageoffset) < 2)
			p.samhudmessageoffset = $-1
		end
		p.samhudmessageflags = 0
		--Let's kill our old elseif chain, we're better than that now.
		if MTIME > 210
			p.samhudmessageflags = min(FF_TRANS90, (MTIME-210)<<16)
		elseif MTIME < 30
			p.samhudmessageflags = max(FF_TRANS10, 9-(MTIME/3)<<16 )
		end	
	elseif p.samhudmessageoffset
		p.samhudmessageoffset = 0
	end
	local ZFLIP = P_MobjFlip(s) --So I don't have to call this accursed function as much.
	
	
	if G_GametypeHasSpectators()	
		SAM.ArenaModes(p,s)
	else --No longer GameTypeHasSpectators
		if p.matchtanks or p.match2tanks
		or (p.cooptanks == nil and p.matchtanks == nil)
			p.sam_energytanksmax = 0
			p.sam_energytanks = 0
			p.matchtanks = false
			p.match2tanks = false
			p.cooptanks = true
		end
		if p.samchallenger
			p.samchallenger = 0
			S_StartSound(nil, sfx_kc59, p)
			CONS_Printf(p, "\x85"+"Turned off challenger mode!")
			if p.samcmult == 11 p.samcmult = 8 end
		end --Spectator check end.
	end
	
	--Cancel scan if...!
	if p.scannedmons and s.sam_scanpowerup and not p.sam_hyperbeampanic
		if p.sam_saveselect
		or not (table.maxn(p.scannedmons)) and not (table.maxn(p.scannedplays))		
			s.samradaranim = 9
			s.samradaranimd = false
			p.scannedmons,p.scannedplays = nil,nil
			S_StopSoundByID(s, sfx_sscan1)
			S_StartSound(s, sfx_samtm7)
			s.sam_scanpowerup = 0
		end
	end
	if p.SAM_warps
		p.samescapehud,p.samescapeseconds,p.samescapemseconds = nil,nil,nil
		if gamemap == 807 or gamemap == 806
			local STARPOST = p.starpostnum or 0
			local WARP = p.SAM_warps
			if WARP.HUD
				WARP.HUD = $-1
			end	
			if WARP.num == nil or (WARP.num < STARPOST)
				if (STARPOST)
					WARP.num = (STARPOST) or 0
					WARP.angle = p.starpostangle
					WARP.x,WARP.y,WARP.z = p.starpostx,p.starposty,p.starpostz
					if multiplayer
						for z in players.iterate
							if z.valid and z != p
								local ZWARP = z.SAM_warps
								local ZWARPnum = (ZWARP and ZWARP.num) and ZWARP.num or 0
								if (ZWARPnum < WARP.num)
									z.SAM_warps = WARP
								end
							end
						end
					end
				end
			elseif WARP.num and (WARP.num > STARPOST) and WARP.x != nil
				WARP.HUD = 3
				if p.sams_c3cd == 50 and (p.cmd.buttons & BT_CUSTOM3) 
				and (p.panim == PA_IDLE) and (p.speed < s.scale)
				and not (p.cmd.buttons & (BT_CUSTOM1|BT_JUMP|BT_SPIN|BT_CUSTOM2|BT_FIRENORMAL|BT_ATTACK))
					s.momx,s.momy,s.momz = 0,0,0
					P_SetOrigin(s, WARP.x<<16, WARP.y<<16, WARP.z<<16)
					s.angle = (WARP.angle != nil) and WARP.angle or s.angle
					P_FlashPal(p, PAL_RECYCLE, 5)
					if WARP.warp == "ACZ4"
					or WARP.warp == "DSZ4" and WARP.angle != ANGLE_90
						SAM_COM_BufInsertText(p, "tunes TNSION")
					end
					S_StartSound(nil, sfx_samtm7,p)
					S_StartSound(nil, sfx_samspa, p)
					p.visorclosein = 15
					p.sams_c3cd = 99<<16
					p.powers[pw_nocontrol] = 20
				end
			end
		end
	elseif p.samescapehud
		p.samescapeseconds = p.samescapehud/35
		p.samescapemseconds = G_TicsToCentiseconds(p.samescapehud)
		if multiplayer or s.health
			p.samescapehud = $-1
		end
		if p.starpostnum or (p.exiting and not multiplayer) or mapheaderinfo[gamemap].lvlttl != "Black Core"
			for ns in players.iterate
				P_SamFP(ns, PAL_RECYCLE, 8)
				ns.samescape = 0
				ns.samescapehud = 0
			end
		end
	end
	if p.samescape --Escape run in Black Core!
		SAM.BlackCoreEscape(p,s)
	end
	--We just spawned! Time to do a whole lot of crap!
	if s.sam_sprst and not (p.powers[pw_carry] == CR_NIGHTSMODE)
		SAM.StartSpawn1(p,s) --Triple spawn functions!
		if not SamOncePerMap2 and (SAMUSCAMPAIGN == true or SAM.HUNTERS(s)) and mapheaderinfo[gamemap]
			SAM.StartMap(p,s)
			SamOncePerMap2 = true
			p.samweather = 0
		end	
		SAM.StartSpawn2(p,s)
		s.sam_sprst = nil
	end

	--Enter zee ship.	
	if (p.sam_st and not p.sam_st.valid)
		p.sam_st = nil
		p.sam_intoship = 0
		if SAM_FirstPerson(p, true)
		--	SamCam(p, camera.chase, nothing)
		--	SAM_CMD(p, PREVCAM, FIRSTPERSON, CAMERAdotCHASE, VISORCLOSEIN)
			SAM_CMD(p, "nil", "lol", "true", "15")		
		--	SamCam(p, false, false)
		else
			SAM_CMD(p, "nil", "true", "false", "15")
		end
		p.samentercam = false
		if (s.flags & MF_NOCLIPHEIGHT) or (p.pflags & PF_INVIS)
			s.flags = $|MF_SHOOTABLE & ~(MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_BOUNCE)
			p.pflags = $ & ~(PF_INVIS|PF_FORCESTRAFE)
		end
		p.sam_exitship = 0
		p.accelstart = skins[s.skin].accelstart
	end
	if p.newsamfile and not p.sam_saveselect
		p.newsamfile = false
	end
	if p.sam_shipjingle
		p.sam_shipjingle = $-1	
		if (p.sam_shipjingle == 165)
			if YouAreSamus(s) and not p.sam_firstperson
				p.sam_prevcam = nil
				p.sam_firstperson = true
				p.visorclosein = 15
				if SAM_displayplayer(p)
					camera.chase = false
				end		
			end
		elseif (p.sam_shipjingle <= 1)
			p.sam_shipjingle = 0
			SAM_COM_BufInsertText(p, "tunes -default")
			P_RestoreMusic(p)
		end
	end
	
	--Show increased numbers for the HUD!
	
	if (p.sammissiles > p.micatchup) 
		p.micatchupflash = 20
		p.micatchupnum = ((p.sammissiles)-(p.micatchup))
	end
	if (p.samsupermissiles > p.smcatchup)
		p.smcatchupflash = 20
		p.smcatchupnum = ((p.samsupermissiles)-(p.smcatchup))
	end
	if (p.sampw > p.pbcatchup)
		p.pbcatchupflash = 20
	end
	if (p.encatchup != nil) and (p.sam_energy < p.encatchup)
		p.encatchupflash = 8
	end
	p.encatchup = p.sam_energy
	p.micatchup = p.sammissiles
	p.smcatchup = p.samsupermissiles
	p.pbcatchup = p.sampw

	SAM.Completion(p,s) --Special function for tracking item rate
	
	if p.samustimeshow
		p.samustimeshow = $-1
	end
	if p.samitemgettimer
		p.samitemgettimer = $-1
	end
	if p.beampain
		p.beampain = $-1
		s.tempsamdye = SKINCOLOR_SUPERSILVER1
		s.tempsamdyetr = FF_TRANS30
	end	
/*	if p.sam_negatewallc
		p.sam_negatewallc = min(5,$-1)
	end */
	
	p.beampulse = p.beampulse and $-1 or 68
	
	if p.sam_darkpz
		if p.sam_darkpz == 1
			SAM_COM_BufInsertText(p, "tunes TNSION")
		else
			SAM_COM_BufInsertText(p, "tunes DARKPZ")
		end
		p.sam_darkpz = nil
	end	
	if p.gltimer --There was a better way, but here we are.
		if (p.gltimer > 75) or (p.gltimer < 19)
			p.gltrans = V_AUTOFADEOUT
		elseif (p.gltimer > 69)
			p.gltrans = FF_TRANS10
		elseif (p.gltimer > 63)
			p.gltrans = FF_TRANS20
		elseif (p.gltimer > 56)
			p.gltrans = FF_TRANS30
		elseif (p.gltimer > 50)
			p.gltrans = FF_TRANS40
		elseif (p.gltimer > 42)
			p.gltrans = FF_TRANS50
		elseif (p.gltimer > 35)
			p.gltrans = FF_TRANS40
		elseif (p.gltimer > 29)
			p.gltrans = FF_TRANS30
		elseif (p.gltimer > 23)
			p.gltrans = FF_TRANS20
		elseif (p.gltimer >= 17)
			p.gltrans = FF_TRANS10
		end
		p.gltimer = $-1
	else
		p.gltimer = 79
	end
	
	//s timers. Work regardless of whether you're Samus.
		
	--[SAMUS DIALOGUE EXAMPLE PART 2] UNCOMMENT THIS AND THE FIRST PART TO ACTIVATE. 
	/*	if s.samusdialogue and s.samusdialogue.customnextboxready
		s.samusdialogue.active = false
			if s.samusdialogue.customnextbox == 3
			SamusDialogue(s, "I will run for president! Residents ", "of space, let us build SamusCare! ", "SAMPRE", 2, 0, nil)
			s.samusdialogue.customnextbox = 4
			elseif s.samusdialogue.customnextbox == 4
			SamusDialogue(s, "It's free healthcare for all! ...unless", "you're a teleporting guard dick. ", "SAMDEF", 2, 0, nil)
			s.samusdialogue.customnextbox = 5
			elseif s.samusdialogue.customnextbox == 5
			s.samusdialogue.noscale = false
			SamusDialogue(s, "Samus...just use the plasma beam. ", nil, "SAMDEF", 1, 0, nil)
			s.samusdialogue.customnextbox = 6
			elseif s.samusdialogue.customnextbox == 6
			s.samusdialogue.noscale = false
				if p.sams_itemcompletion != nil and (p.sams_itemcompletion <= 3) and not p.sam_plasmabeam
				SamusDialogue(s, "Shut up. ", "I'm doing a 3% run. ", "SAMPRE", 2, 0, nil)
				else
				SamusDialogue(s, "Shut up!!", "I'm bad at this, okay?", "SAMSAD", 2, 0, nil)
				end
				s.samusdialogue.customnextbox = 0 //Setting this 0 ends the chain.
			end
		end */
		
	if p.samusmusicadd2
		p.samusmusicadd2 = $-1
		if not p.samusmusicadd2
			p.samusmusicadd2 = nil
		end
	elseif not p.samusmusicadded
		if (p==server) or (p.jointime > 70) --You will WAIT, darn you.
			SAM_COM_BufInsertText(p, "addfile samusmusic.pk3; tunes -none")
			p.samusmusicadded,p.sam_autoaddmusic = true,true
			if p.sam_saveselect
				SAM_COM_BufInsertText(p, "tunes SAMMU1")
				S_ChangeMusic("SAMMU1", true, p, 0, 0, 699, 699)
			else
				P_RestoreMusic(p)
			end
		end
	end	
	if s.sam_difficultymsg
		s.sam_difficultymsg = $-1
		if (s.sam_difficultymsg < 31)
		and (s.sam_difficultymsg % 3 == 0)
			if s.sam_difficultytrns != FF_TRANS90
				s.sam_difficultytrns = $+FRACUNIT
			end
		elseif (s.sam_difficultymsg % 3 == 0)
			if s.sam_difficultytrns != FF_TRANS10
				s.sam_difficultytrns = $-FRACUNIT
			end
		end
	end
	if p.sam_dosave
		if not G_IsSpecialStage(gamemap) and not (gamemap == 812)
		and not (p.powers[pw_carry] == CR_NIGHTSMODE)
			ProfileSamusSave(s, p, p.sam_saveselected, true, false)
		end
		p.sam_dosave = nil
		SetSamusColor(s, p)
	end
	/*
	if not s.sam_waveoverload and (p.cmd.buttons & BT_CUSTOM3)
	InflictWaveOverLoad(s, 55, nil)
	end */
	if s.sam_waveoverload
		SAM.OverLoadStatus(p,s)
	end
	if p.sam_forceanalogoff --These...STUPID....
		p.sam_forceanalogoff = $-1
		if not p.sam_forceanalogoff
			p.pflags = $|PF_ANALOGMODE
		end
	end
	
	if p.sam_forcedirectcharoff
	p.sam_forcedirectcharoff = $-1
		if not p.sam_forcedirectcharoff
		//	p.pflags = $|PF_ANALOGMODE & ~PF_DIRECTIONCHAR
			SAM_COM_BufInsertText(p, "configanalog 1; directionchar 0")
		end
	end
	
	if s.metroidsnack
		s.metroidsnack = $-1
		if not s.metroidsnack
			p.viewrollangle = 0 --reset this
		end
	end
	--Crystal Flash power!
	if s.crystalflashtime
		s.crystalflashtime = $-1
		if not s.crystalflashtime or not YouAreSamus(s)
			s.crystalflashtime,s.crystalflashanim = 0,0
			s.rollangle = 0
			A_samquake(s, 70<<16, 14, 1)
			P_SamFP(p, PAL_RECYCLE, 6)
			S_StartSound(s, sfx_rocks3)
			S_StartSound(s, sfx_wvcm2)
			S_StartSound(s, sfx_samtm7)
			if p.camerascale == 3<<16
				p.camerascale = FRACUNIT
			end
			if s.nocftunechange
				s.nocftunechange = false
			else
				local TEXT = (s.crystalflashtune==2) and "tunes omega" or (s.crystalflashtune) and "tunes darkpz" or "tunes -default"
				for z in players.iterate
					if z and z.valid
						SAM_COM_BufInsertText(z, TEXT)
					end
				end
			end
		else
			CrystalRebirth(s, p)
			if s.crystalflashanim
				s.crystalflashanim = $-1
				p.camerascale = 3<<16
				s.thesamcam = 1
			end				
		end
	end
	
	--Samus' dialogue thinker here.
	if s.samusdialogue and s.samusdialogue.active
		SAM.RunSamusDialogue(s, p)
	end
	if s.samusmission and s.samusmission.active
		SAM.RunSamusMission(s, p)
	end
	if p.samustutorial and p.samustutorial.active
		SAM.RunSamusTutorial(s,p)			
	end
	if p.sam_saveselect
		SAM.RunSamusSaveMenu(s, p)
	end			
	if s.bmreflwarning
		s.bmreflwarning = $-1
	end
	if s.pzpaintime --Cooldown timer for Phazon Damage
		s.pzpaintime = $-1
	end				
	if s.saniccdflinch
		s.saniccdflinch = $-1
	end
	if s.omegarushpanic
		s.omegarushpanic = $-1
	end
	if s.sam_wavestunned
		s.sam_wavestunned = $-1
		if s.sam_wavestunned % 20 == 0
			s.momx,s.momy,s.momz = $*10/15,$*10/15,$*10/13
			A_samquake(s, 50<<16, 7, 1)
			S_StartSound(s, sfx_mtrds)
		end
	end
	if s.sam_systemreboot
		s.sam_systemreboot = $-1
		if s.sam_systemreboot == 3 and not s.myorammer 
			p.viewrollangle = 0
		end
	end
	if s.myorammer --Omega knockback mechanic
		if (p.speed < 16<<16) or P_IsObjectOnGround(s)
			if not s.myowait --Give it an extra tic!
				s.myowait = true
			else
				s.myoangle = 0
				s.rollangle = 0
				p.viewrollangle = 0
				p.powers[pw_flashing] = 0
				p.losstime = 50<<16
				P_DamageMobj(s)
				A_samquake(s, 80<<16, 10, 1)
				P_SamFP(p, PAL_NUKE, 6)
				S_StartSound(s, sfx_bkpoof) S_StartSound(s, sfx_dmpain) S_StartSound(s, sfx_rocks2) S_StartSound(s, sfx_pstop)
				s.myorammer = nil
				s.myowait = nil
			end
			
		else
			if s.myoangle == nil
				s.myoangle = 0
			elseif not p.sam_sensitive
				s.myoangle = $+ANG20
			end
			A_BossScream(s, 0, MT_EXPLODE)
			s.rollangle = s.myoangle
			p.viewrollangle = s.myoangle
		end
	end
	if p.sam_shipready
		p.sam_shipready = max($-1,0)
	end
	if p.sams_c1cdjlg --Button pressed.
		p.sams_c1cdjlg = $-1
	end
	if p.sam_c1ready
		p.sam_c1ready = (not P_IsObjectOnGround(s)) and $-1 or 0
	end
	if p.sam_j1ready
		p.sam_j1ready = (not P_IsObjectOnGround(s)) and $-1 or 0
	end
	if p.sams_c2cdjlg
		p.sams_c2cdjlg = $-1
	end
	if p.sams_normfcdjlg
		p.sams_normfcdjlg = $-1
	end
	if (gametype == GT_COOP) and SAMUSDIFFICULTY == 2
	or p.samdoubleammo and (gametyperules & GTR_RINGSLINGER)
		p.samadrain = 2
	else
		p.samadrain = 1
	end
	
	if p.samhands
		p.samhands = max($-1,0)
	end
	if p.hbimmune and not (p.powers[pw_flashing] and (p.hbimmune < 3))
		p.hbimmune = $-1
	end
	if p.samnoflag
		p.samnoflag = $-1
	end
	if s.thesamcam and not s.crystalflashanim
		p.camerascale = FRACUNIT
		s.thesamcam = 0
	end
	if p.samusnum == nil --Your player number. So I don't have to look it up every single time.
		for i = 0,31
			if p == players[i]
				p.samusnum = i break --
			end
		end
	end
	if p.samnoflagmessage
		p.samnoflagmessage = $-1
		if p.samnoflagmessage == 104
			S_StartSound(s, sfx_s3k80)
			CONS_Printf(p, "\x85"+"Cannot pick up flags for 10 seconds after exiting ship.")
			p.samnoflagmessage = 103
		end
	end	
	local FIREBUTTON = (p.swapfire) and BT_FIRENORMAL or BT_ATTACK
	local NORMALFIRE = (p.swapfire) and BT_ATTACK or BT_FIRENORMAL
	
	if p.sams_supermissileready and not (p.cmd.buttons & FIREBUTTON)
		p.sams_supermissileready = $-1
	end
	if p.sams_powerbombready 
	and not ((p.cmd.buttons & NORMALFIRE) or ((p.cmd.buttons & BT_CUSTOM2) and not p.c1c2disable))
		p.sams_powerbombready = $-1
	end
	if p.sam_hyperbeampanic
		if not p.sam_hyperbeam
			if (leveltime % 3 == 0) --Flash colors
				if p.sam_hyperbeampanic == 84
					p.sam_hyperbeampanic = SKINCOLOR_SUPERRED1
				elseif (p.sam_hyperbeampanic == SKINCOLOR_SUPERRED1)
					p.sam_hyperbeampanic = SKINCOLOR_SUPERSKY5
				elseif (p.sam_hyperbeampanic == SKINCOLOR_SUPERSKY5)
					p.sam_hyperbeampanic = 84
				end
				if not s.sam_scanpowerup
					SAM.DoAreaScan(s, p, hyper, "skipmonitors")
					s.samradaranim = 1
					s.samradaranimd = true
					S_StartSound(s, sfx_sscan2)	
				end
			end
			s.sam_scanpowerup = 3
		else --if p.sam_hyperbeam
			SAM.HyperBeamPassive(p,s, true)
		end
	elseif p.sam_hyperbeam 
		SAM.HyperBeamPassive(p,s)
	end
	
	--Do some button timers.
	if (p.cmd.buttons & BT_JUMP)
		p.sams_jumpcd = ((p.pflags & PF_JUMPED)) and $+1 or $+2
	elseif p.sams_jumpcd
		p.sams_jumpcd = 0
	end
	if p.hyperbrakmsg
		p.hyperbrakmsg = $-1
	end
	if (p.cmd.buttons & BT_CUSTOM1) and not p.c1c2disable
		p.sams_c1cd = $+1
	elseif p.sams_c1cd
		if s.sambsblchargelvl
			s.sambsblchargelvl = 0
		end
		p.sams_c1cdjlg = 2
		p.sams_c1cd = 0
	end
	if (p.cmd.buttons & BT_CUSTOM2) and not p.c1c2disable
		p.sams_c2cd = $+1
	elseif p.sams_c2cd
		p.sams_c2cdjlg = 2
		p.sams_c2cd = 0
	end	
	p.sams_usecd = (p.cmd.buttons & BT_USE) and $+1 or 0
	if (p.cmd.buttons & NORMALFIRE) --These buttons swap based on p.swapfire.
		p.sams_normfcd = $+1
	elseif p.sams_normfcd
		p.sams_normfcdjlg = 2
		p.sams_normfcd = 0
	end
	if (p.cmd.buttons & FIREBUTTON)
		p.sams_firecd = $+1
	elseif p.sams_firecd
		if s.sambsblchargelvl
			s.sambsblchargelvl = 0
		end
		p.sams_firecdjlg = 2
		p.sams_firecd = 0
	end
	if p.sams_weappress 
		if not (p.cmd.buttons & (BT_WEAPONPREV|BT_WEAPONNEXT))
			p.sams_weappress = false
		end
	end
	
	//Plasma Beam Combo, Gattling Vortex!
	if p.exiting
		SAM.Exiting(p,s) --
	elseif s.gattlingvortex
		SAM.PlasmaCombo(p,s) --
	end
	--The Wave Beam Combo! Includes Death Ball bonus similar to Metroid Prime 2: Echoes' multiplayer mode
	if s.wavebuffering
	or (s.crystalflashtime and p.sammorphed)
		SAM.WaveBeamCombo(p,s)
	elseif s.wavebuffering and s.sam_deathball
		s.sam_deathball = false		
	end
	if not SamOncePerMap1
		SAM.SpawnShip(p,s)
		SamOncePerMap1 = true
	end
	if p.shipMSG
		p.shipMSG = $-1
		if not p.shipMSG
			p.shipMSG = nil
		end
	end
	if s.sam_acz4msg
		if s.subsector.sector.tag == 2 or s.subsector.sector == sectors[9]
			if not (p.nosamustutorials)
				SamusMission(s, "\x85"+"Gruesome violence incoming.", "\x85"+"Use \x82"+"samusmatch hidegore"+"\x85 in", "\x85"+"the console to hide scene.", 3, 0, true)
			end
			s.sam_acz4msg = false
		end
	end
	
	SAM.HudPlayerThinker(p,s) --Setup HUD values.
	
	if not (YouAreSamus(s)) --Let's get the non-Samus-specific stuff out of the way first!
		if p.samusenergyhud
			p.samusenergyhud = false
			if not p.sam_specialstage
				p.rings = 1
			end	
		end
		if s.samusscaled --s.otherchar s.NotSamus. Usually right as you switch from Samus to another char.
			p.sams_beamcombocharge = 0
			s.samusscaled = false
			if SAM_FirstPerson(p, true) --Un-first person when another character.
				if not (gametyperules & GTR_FIRSTPERSON)
				--	SamCam(p, opposite of camera.chase, nothing)
				--	SAM_CMD(p, PREVCAM, FIRSTPERSON, CAMERAdotCHASE, VISORCLOSEIN)
					SAM_CMD(p, "nil", "lol", "true", "lol")
				--	SamCam(p, true, true)
				--	p.sam_prevcam = nil
				end
			end
			if (p.samxtralife != nil)
				p.xtralife = p.samxtralife
				p.samxtralife = nil
			end
			p.viewrollangle = 0
			if s.scale > 88000 and s.scale < 92000
				s.scale = FRACUNIT  --If beeg, be NOT beeg
			end
			if s.gravitylights 
				if s.gravitylights.valid --Disable Gravity Suit lights.
					s.gravitylights.state = S_NULL
				end
				s.gravitylights = nil
			end
			if (p.skincolor >= SKINCOLOR_SUPERSILVER1) and (p.skincolor <= SKINCOLOR_SUPERTAN5)
				p.skincolor = SKINCOLOR_BLUE --Fixing a weird bug where you're stuck with colors...
				s.color = SKINCOLOR_BLUE
			end
			SAM.SwitchFromSam(p,s)
		end
		
		--Don't carry morph ball stuff to other characters.
		if p.sammorphed
			p.sammorphed,p.morphanim = false,false
			p.sams_beamcombocharge = 0
			p.viewrollangle = 0
			if s.scale == 42001 --if smol, be not smol
				s.scale = FRACUNIT
			end
			if s.friction == 61777
				s.flags = $ & ~MF_BOUNCE
				s.state = S_PLAY_FALL
			end
		end
		--No switching to other characters in the Hunters gamemode. Play Match for that instead!
		if SAM.HUNTERS(s) or FORCESAMUSSKIN == true
			if not p.powers[pw_carry]
				s.momx,s.momy = 0,0
				s.state = S_PLAY_STND
				p.pflags = $ & ~(PF_JUMPED|PF_STARTJUMP|PF_SPINNING|PF_STARTDASH|PF_THOKKED|PF_NOJUMPDAMAGE)
			end
			R_SetPlayerSkin(p, "samus")
			s.skin = "samus"
			SAM_COM_BufInsertText(p, "skin samus")
			if not p.weapondelay
				P_SamFP(p, PAL_NUKE, 4)
				S_StartSound(nil, sfx_samspa, p)
				if SAM.HUNTERS(s) 
					CONS_Printf(p, "\x85"+"Hunters is a Samus-focused gamemode. Character crossplay is available in Match!")
				else
					CONS_Printf(p, "\x85"+"The server has set forceskin to"+"\x82 Samus")
				end
			end
			p.powers[pw_nocontrol],p.weapondelay,p.tossdelay = 9,9,9
		end
		return --We're done at this rate.
	end
	--From now on, if YouAreSamus(s) is active
	
	if not s.health 
		SAM.SamusIsFuckingDead(p,s) --NOOOOOOOOOOOOOOOOOOOOOOOOOOOooooooooooooo
			
	elseif (p.powers[pw_carry] != CR_NIGHTSMODE) --Main code begins here.
	
		--THIS IS WHERE THE ACTION BEGINS. s.skin == "samus" is not a thing, btw, use YouAreSamus.
		--MAIN SKIN CHECK. Main s.skin check. skincheck. 
		SAM.SamusTimers(p,s, ZFLIP)
		
		p.weapondelay = 9
		p.currentweapon = 0
		p.samusenergyhud = true
		if P_IsObjectOnGround(s)
			local SPINPAD = s.samspinpad or 0
			if P_PlayerTouchingSectorSpecial(p, 3, 6)
			or P_PlayerTouchingSectorSpecial(p, 3, 5)
				if (SPINPAD < 42)
					if P_PlayerTouchingSectorSpecial(p, 3, 5) and not p.sammorphed
						s.samspinpadconfirmed = 12
						s.samspeedpad = 12
					else
						s.samspinpad = 50
					end
					p.bsblboost = 0
				end
			end	
		end
		

		if p.runspeed != 2199594
			p.charflags = $ & ~SF_NOSKID 
			p.runspeed = 2199594
		end SAM.GRPcd(p, s)
		
		p.sammissilesmax = min($, 250)
		p.sammissiles = min($, p.sammissilesmax)
		
		p.samsupermissilesmax = min($,50)
		p.samsupermissiles = min($, p.samsupermissilesmax)
		
		p.sampwmax = min($, 30)
		p.sampw = min($, p.sampwmax)
		
		--Last missile changes.
		if s.sam_geton 
			s.sam_geton = $-1
		end		
		
		if (leveltime % 25 == 0)
			if (gametype == GT_COOP) and (netgame)
				local STARPOST, ENERGY = p.starpostnum or 0,p.sam_energy or 0
				if (s.SAM_starpost != STARPOST) and (ENERGY < 50) and s.SAM_starpost != nil
					p.sam_energy = 50
					S_StartSound(nil, sfx_nrga, p)
				end
				s.SAM_starpost = STARPOST
			end
			s.missiletrns = s.missiletrns and min(FF_TRANS50, $+FRACUNIT) or FF_TRANS10
			s.supermissiletrns = s.supermissiletrns and min(FF_TRANS50, $+FRACUNIT) or FF_TRANS10
			s.pwbtrns = s.pwbtrns and min(FF_TRANS50, $+FRACUNIT) or FF_TRANS10
		else
			if s.samlastmissiles == nil or s.samlastmissiles != p.sammissiles
				s.missiletrns = 0
			end
			if s.samlastsupers == nil or s.samlastsupers != p.samsupermissiles
				s.supermissiletrns = 0
			end
			if s.samlastpw == nil or  s.samlastpw != p.sampw
				s.pwbtrns = 0
			end
		end
		
		s.samlastmissiles = p.sammissiles
		s.samlastsupers = p.samsupermissiles
		s.samlastpw = p.sampw
		
		if p.sam_autotank
			if (p.sam_energy < p.sam_autotank)
			and not p.sam_intoship and not p.sam_saveselect
				s.sam_autotimer = s.sam_autotimer and $+1 or 1
				if (s.sam_autotimer > 40)
					p.sam_energy = $+1 --auto restore energy with an autotank
					s.sam_autotimer = 0
				end
			end
		end
		
		if p.samnetrestart
			S_StartSound(s, sfx_samjin)
			S_StartSound(s, sfx_samspa)
			p.samnetrestart = 0
		end
		--Switch skins between Power Suit Samus and Varia/Gravity Suit Samus whenever!
		if not p.sam_gravitysuit
			if s.skin == "samus"
				SAM_COM_BufInsertText(p, "skin samus; skin basesamus")		
				R_SetPlayerSkin(p, "basesamus")
				s.skin = "basesamus"
			end
		elseif s.skin == "basesamus" --Switch skins!
			SAM_COM_BufInsertText(p, "skin basesamus; skin samus")	
			R_SetPlayerSkin(p, "samus")
			s.skin = "samus"
		end

		//Check the lightning in your sector.			

		if s.bcz4prep and (gamemap == 26) and mapheaderinfo[gamemap].lvlttl == "Black Core"
			if s.bcz4prep
				p.sambeamlight = FF_TRANS70 --Don't be this utterly dark, pls.
				if p.sam_fullypoweredsuit  and SAMUSCAMPAIGN == true
					G_SetCustomExitVars(28) --Get prepped to go to the TRUE Final Boss.
				end
			end
		else	
			if (p.pflags & PF_SLIDING) and not p.sammorphed
				s.state = S_PLAY_FALL
			end
			if s.subsector and s.subsector.sector
				local SEC =	s.subsector.sector
				if p.sam_firstperson
					SAM.ApplyBeamLight(p,s)
				end
				if s.dsz2msgprep
					if SEC.tag == 403 or SEC.sector == sectors[1866]	
						SamusMission(s, "\x80  Hold\x82 CUSTOM1\x80 or\x82 FIRE", "\x80 while in Morph Ball to", "\x80      spin in place", 3, 0, true)
						s.dsz2msgprep = false
					end
				elseif s.sam_rvzmsg
					if SEC.tag == 55 or SEC.sector == sectors[145]
						SamusMission(s, "\x84"+"UNIQUE ARTIFACT SIGNATURE", "\x84     DETECTED IN ZONE", nil, 3, 0, false)
						s.sam_rvzmsg = false
					end
				end
			end
		end

		if s.samhudgimmick or (p.dialog == true)
			p.sams_mshotcd,p.sams_morphcd,p.sams_shotcd = 3,3,3
		else
			if p.sammorphed and p.sam_spiderball
				SAM.SpiderBallAbility(p,s) --
			end
			if p.sams_beamcombocharge --Animation and prep system for charging your Beam Combos.
				SAM.BeamComboCharge(p,s) --
			end
		end

		if (p.cmd.buttons & BT_WEAPONMASK)
			if (p.cmd.buttons & BT_WEAPONMASK) != 7
			and not p.holdingswitch and not p.sam_beamswitch and not p.sams_chargetime
			and not p.powers[pw_nocontrol]
				p.sam_wantstoswitch = (p.cmd.buttons & BT_WEAPONMASK)
				p.sams_c2cd = 0
				p.sams_firecd = 0
				p.sams_normfcd = 0
				p.sams_powerbombready = 0
				p.sams_supermissileready = 0
				p.sams_mshotcd = 10
				A_SAMBEAMSWITCH(p)
				p.holdingswitch = true
			end
		elseif p.holdingswitch
			p.holdingswitch = false
		end
		if (gametype == GT_COOP)
			if not p.sam_fullypoweredsuit
				if p.sams_itemcompletion and (p.sams_itemcompletion >= 100)
				and not p.exiting and not p.sam_saveselect and (leveltime > 3)
					p.sam_fullypoweredsuit = true
					p.sam_fpsmsg = 370
				end
			elseif p.sam_fpsmsg and not p.exiting and not p.sam_saveselect and (leveltime > 3)
				p.sam_fpsmsg = max($-1,0)
				if (p.sam_fpsmsg == 293)
					S_StartSound(nil, sfx_samusp)
					print("\x83 "+p.name+"\x83 obtained their\x82 fully powered suit")
					for z in players.iterate
						if not z.nosammusic
						SAM_COM_BufInsertText(z, "tunes -none") 
						end
					end
				end
				if (p.sam_fpsmsg < 293)
					A_SAMPARTICLE(s, MT_MPR1, 50, 1, 1, 5, SKINCOLOR_MAGENTA, 40000, true)
					A_SAMPARTICLE(s, MT_MPR1, 30, 1, 1, 6, SKINCOLOR_ORANGE, 25000, true)
				end
				if p.sam_fpsmsg == 1
					for z in players.iterate
						if not z.nosammusic
							SAM_COM_BufInsertText(z, "tunes SAMUSP 0 1.25") 
						end
					end
					CONS_Printf(p, "\x82 -Ammo and Energy completely refilled!")
					A_samquake(s, 11<<16, 50, 1000<<16)
					P_SamFP(p, PAL_MIXUP, 10)
					p.sam_energy = 99+(p.sam_energytanksmax*50)
					p.sam_hyperbeamammo = 99
					p.sammissiles = p.sammissilesmax
					p.sampw = p.sampwmax
					p.samsupermissiles = p.samsupermissilesmax
					p.sam_shinespark = 80
					p.sam_spacejumped = false
					s.pwbomb = P_SpawnMobj(s.x, s.y, s.z, MT_SAMPOWERBOMB)
					s.pwbomb.target = s
					s.pwbomb.gravitysuitjustgot = true
					S_StartSound(s, sfx_pwbmb)
					if (p.cmd.buttons & BT_CUSTOM1) and not p.c1c2disable 
					or p.autospeedbooster
						if not p.samspbschargefull and (p.cmd.sidemove or p.cmd.forwardmove)
							p.runspeed = 2199594
							StartSamSPBS(s,p)
						end
					end
					p.sam_fpsmsg = 0
				end
			end
		else --not coop.
		
			if (All7Emeralds(p.powers[pw_emeralds])) 
			or G_GametypeHasSpectators() and (
			s.samemeralds == 7 
			or p.powers[pw_emeralds]==0 and p.powers[pw_invulnerability]==700 and p.powers[pw_sneakers]==700
			)
				if not p.exiting and not p.sam_saveselect
					p.powers[pw_emeralds] = 0
					s.samemeralds = 0
					
					if not p.sam_hyperbeam
						S_StartSound(nil, sfx_mtnk)
						S_StartSound(nil, sfx_s3k9f)
						p.sam_hyperbeam = true SamusTutorial(s, "hyperbeam")
						p.sam_hyperbeamammo = 0
						p.samitemgettimer = 83
						p.samitemcolor = SKINCOLOR_CLOUDY
						if p.samchallenger and (p.samchallenger > 3)
							p.samitemgetname = "True Hyper Beam"
							p.samitemscale = 102000
						else
							p.samitemgetname = "Hyper Beam"
							p.samitemscale = 88000
						end
						
						if G_GametypeHasSpectators()
							p.powers[pw_invulnerability] = 0 //Don't let 2.2 screw over the Hyper Beam mechanic in match....
							p.powers[pw_sneakers] = 0
							P_RestoreMusic(p)
							P_StartQuake(11<<16, 28)
							local MISSILES = (p.sammissilesmax) or 0
							if p.samchallenger and (p.samchallenger > 3)
								if (MISSILES < 30)				
									p.sammissilesmax = 30
								end
								if not p.sammissiles or (p.sammissiles < 30)				
									p.sammissiles = 30
								end
								p.samqchallenger = true
								print("\x85 =!!Emergency!!= The fully powered Hyper Beam has been captured! Stop "+p.name+"\x85 at all costs!")
							else
								print("\x85 =!!Emergency!!= The Hyper Beam has been captured! Stop "+p.name+"\x85 immediately!")
							end
							
							p.sam_energy = 99+(p.sam_energytanksmax*50)
							if (p.sam_energytanksmax > p.sam_energytanksstart) --Convert extra e-tanks into hyperbeam ammo
								p.sam_hyperbeamammo = 30+((p.sam_energytanksmax-p.sam_energytanksstart)*10)
							else
								p.sam_hyperbeamammo = 30
							end
							p.sam_energytanksmax = 2
							p.sam_energy = 199
							p.sam_energytanks = p.sam_energytanksmax
							
							for z in players.iterate
								z.sam_hyperbeampanic = 84
								if not z.sam_hyperbeam
									if z.mo
										SAM.DoAreaScan(z.mo, z, nil, "skipmonitors")
									end
									z.samhudmessage1 = "\x80"+p.name+"\x81 captured the Hyper Beam! Kill them"
									z.samhudmessage2 = "before they gather more ammo and destroy everyone!"
								else
								
									z.mo.sam_scanpowerup = 0
									z.scannedmons,z.scannedplays = nil,nil
									z.samhudmessage1 = "\x81"+"You are hunted!\x82 Use the Hyper Beam to wreak"
									z.samhudmessage2 = "\x82"+"as much havoc as possible before dying!"
								end
								z.samhudmessagetime = 230
								P_SamFP(z, PAL_NUKE, 12)
								if not z.nosammusic
									SAM_COM_BufInsertText(z, "tunes -none; tunes SAMUSH")
								end
							end
							
						else
							P_SamFP(p, PAL_MIXUP, 10)
							CONS_Printf(p, "\x82You've obtained the Hyper Beam! Charge it with energy to unleash the ultimate weapon!")
						end
					elseif p.sam_hyperbeam and not p.sam_saveselect
						P_SamFP(p, PAL_MIXUP, 9)
						S_StartSound(s, sfx_mtnk)
						p.sam_hyperbeamammo = 99
						p.sam_energy = 99+(p.sam_energytanksmax*50)
						CONS_Printf(p, "\x82"+"Hyper Beam ammo maxed out!")
					end
				end
			end
		end
		
		if (s.scale <= FRACUNIT+5500) and (s.scale >= FRACUNIT-5500)
		and (s.destscale <= FRACUNIT+5500) and (s.destscale >= FRACUNIT-5500)

		or s.scale == 42001 and not p.sammorphed
		
			if not (p.powers[pw_carry] == CR_ZOOMTUBE)
			/*	if not s.samusscaled
					if SAM_FirstPerson(p, true) --remember between levels what your FPS preference was.
						if not twodlevel and not (s.flags2 & MF2_TWOD)
						--	SamCam(p, opposite of camera.chase, nothing)
						--	SAM_CMD(p, PREVCAM, FIRSTPERSON, CAMERAdotCHASE, VISORCLOSEIN)
							SAM_CMD(p, "nil", "true", "true", "15")
						--	SamCam(p, false, false)
						end
					else
						SAM_CMD(p, "nil", "false", "true", "lol")
					end
				end */			
				s.scale,s.destscale = 90000,90000
				p.visorclosein = 15
			
				SamusTutorial(s, "beams")
				SamusTutorial(s, "monitorhunt")
				SamusTutorial(s, "lockon")	
			
				if leveltime and p.jointime and not p.powers[pw_carry]
					if not S_SoundPlaying(s, sfx_samspa)
						S_StartSound(s, sfx_samspa, p)
					end
					if not s.samusjustspawned and not s.samusscaled
						p.sam_firstperson = true
						p.sam_prevcam = nil
						if SAM_displayplayer(p) and camera
							camera.chase = false
						end
					end
				end
				s.samusscaled,s.samusjustspawned = true,true
				if p.powers[pw_shield] and (p.powers[pw_shield] != 37|SH_PROTECTFIRE|SH_PROTECTSPIKE|SH_PROTECTWATER)
					p.powers[pw_shield] = SH_NONE
				end
			end
		end
		if p.rings
			if p.samxtralife == nil or not p.xtralife
				p.samxtralife = p.xtralife
				p.xtralife = 9
			end
			if s.saminfhealth
				p.sam_energy = $+1
			end
			if s.samusjustspawned or p.rings == 1
				p.rings = 2
				s.samusjustspawned = false
				s.prevsamhealth = p.rings
				if (p.sam_energy > 1) and P_IsObjectOnGround(s)
					if P_PlayerTouchingSectorSpecial(p, 1, 10)
					or P_PlayerTouchingSectorSpecial(p, 1, 9) 
						p.sam_energy = $-1
						p.sam_energyflash = 1
					end
				end
			else
				if s.prevsamhealth and p.rings
				and not (s.prevsamhealth == p.rings)
					if (p.rings != (s.prevsamhealth+100)) --1-ups from score do not heal you.
						GiveSamusEnergy(p, p.rings-s.prevsamhealth, 1)
					end
				end
				s.prevsamhealth = p.rings
			end
			if (p.rings > 9850) --What are we doing??
				p.rings = 8001
				s.prevsamhealth = p.rings
			end
		end
		if p.objectplacer
			p.sams_shotcd,p.sams_mshotcd = 3,3
		end	
		if p.sam_energy != nil
			SAM.EnergySystem(p,s) --
		end

		if All7Emeralds(emeralds) and not p.sam_hyperbeam 
		and not p.exiting and not p.sam_saveselect
		and not G_GametypeHasSpectators()
			P_SamFP(p, PAL_MIXUP, 10)
			S_StartSound(s, sfx_spwup)
			CONS_Printf(p, "\x82You've obtained the Hyper Beam! Charge it with energy to unleash the ultimate weapon!")
			p.sam_hyperbeam = true SamusTutorial(s, "hyperbeam")
			p.sam_hyperbeamammo = 0
			p.samitemgettimer = 83
			p.samitemcolor = SKINCOLOR_CLOUDY
			p.samitemgetname = "Hyper Beam"
			p.samitemscale = 88000
		end
		if s.samemwarning and ((not s.samemeralds) or (s.samemeralds < 5))
			s.samemwarning = $-1
		end
		if not p.samcheat or (p.samcheat < 9)
			SAM.SPCheatKit(p,s)
			p.samcheat = p.samcheat and $+1 or 1 --Cannot activate the cheat from here on out.
		end
		SAM.PowerUpConvert(p,s) --Convert picked up weapon rings and shields!
		
		if (s.eflags & MFE_UNDERWATER) --You're wearing a spacesuit. Of course you're not drowning.
			p.powers[pw_underwater] = 990
		end
		if not p.samushasatimer --And spacetime isn't used for Metal Sonic races, you're immune to space suffocation too.
			p.powers[pw_spacetime] = 0
		end
		if (s.state == S_PLAY_PAIN) and not (p.pflags & PF_SLIDING)
			p.sams_shotcd = 2
			p.sams_mshotcd = 2
			p.sam_shinespark = 0
			p.sam_shinesparkfly = 0
			p.sam_shinesparkstop = 0
		elseif s.samslopespin 
			if(p.pflags & PF_SPINNING)
				p.pflags = $ & ~PF_SPINNING
				if p.panim == PA_ROLL
					s.state = S_PLAY_FALL
				end
			end
		elseif not p.sammorphed 
			if (s.state == S_PLAY_SPINDASH)
			or ((p.powers[pw_carry] == CR_ZOOMTUBE) or (p.powers[pw_carry] == CR_MACESPIN)) and not p.sam_screwattacking
				if not p.sams_notyet and not (s.sprite == SPR_ZSSA)		
					SamMorphSwitch(p, s)
					S_StartSound(s, sfx_smorph)
					CancelScrewAttack(s,p)
				end
			end
			local USECD = (p.sams_usecd) or 0
			if (p.cmd.buttons & BT_USE) and not (USECD > 1)
			and not p.sam_shipready 
			and not p.sams_beamcombocharge 
			and not s.samhudgimmick
			and not (s.sprite == SPR_ZSSA)
				local GROUNDED = (P_IsObjectOnGround(s))
				if (
					GROUNDED
				or (p.pflags & PF_JUMPED)
				or (p.panim == PA_WALK or p.panim == PA_RUN) and not GROUNDED
				or (s.state == S_PLAY_SPRING or s.state == S_PLAY_FALL) and not GROUNDED and not (p.pflags & PF_JUMPED)
				)
				
				and not p.sams_morphcd
				and not p.exiting
				and (p.powers[pw_carry]==CR_BRAKGOOP or not (p.powers[pw_nocontrol] or p.powers[pw_carry])) --You CAN morph in Brak goo.
				and s.scale == 90000 --Sorry, this gets too complicated with varying sizes.
				
					SamMorphSwitch(p, s)
					S_StartSound(s, sfx_smorph)
					
					--This is the manual morph ball switch, so add more stuff!
					s.morphtrailwait = 7					
					
					p.samspbschargefull = false
					p.samspbscharge,p.sams_morphcd = 0,35
					s.momx,s.momy,s.momz = $*5/6,$*5/6,$*5/6
					p.pflags = $ & ~ PF_STARTJUMP
					p.sams_c2cd = 0
					s.scale = 42001	
					
					if (s.state == S_PLAY_SPRING) and (s.momz*ZFLIP > 0)
					and not GROUNDED and not (p.pflags & PF_JUMPED)
						s.momz = $*4/5
					end	
					if s.metroidsnack --Don't escape TOO easily
						s.momx,s.momy = $/5,$/5
					end
					
					--Multibomb technique if morphing with a charged beam!
					if (p.sams_chargetime > 41) and p.sam_bombs
						S_StartSound(s, sfx_smobo)
						local ghs = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_PBEXPAND)
						ghs.scale = s.scale*2
						ghs.tics = $+3
						ghs.scalespeed = $*4 ghs.destscale = 99<<16
						ghs.color = SKINCOLOR_SUPERGOLD2
						ghs.colorized = true
						ghs.blendmode = AST_ADD
						p.camerascale = 196071
						s.thesamcam = 1
						for d = 1,8 --Even I couldn't stand the old code for this one...
							ghs = P_SpawnMobj(
							s.x+FixedMul(-140<<16, cos(s.angle+(ANGLE_45*d))), 
							s.y+FixedMul(-140<<16, sin (s.angle+(ANGLE_45*d))), 
							s.z+FixedMul(FRACUNIT*20, (ZFLIP*s.scale)), MT_SAMMORPHBOMB)
							if ghs and ghs.valid
								ghs.flags = $|MF_GRENADEBOUNCE|MF_BOUNCE & ~MF_NOGRAVITY
								ghs.target = s
								ghs.momz = $-3<<16+(s.momz/2)
								ghs.momx = $+(s.momx/2) ghs.momy = $+(s.momy/2)
								P_Thrust(ghs, s.angle+(ANGLE_45*d), -6<<16)
								if (ghs.floorz > s.floorz+140<<16) --Oh, geez, don't clip up there.
									ghs.state = S_NULL
								end
							end
							ghs = P_SpawnMobj(
							s.x+FixedMul(-80<<16, cos(ANGLE_45*d)),
							s.y+FixedMul(-80<<16, sin (ANGLE_45*d)),
							s.z+FixedMul(FRACUNIT*20, (ZFLIP*s.scale)), MT_THOK)
							ghs.sprite = SPR_MBOM	
							ghs.frame = A|FF_TRANS60|FF_FULLBRIGHT
							ghs.destscale = 99<<16
						end
					end
				elseif not p.sam_screwattacking and not p.sam_shinesparkfly
					S_StartSound(s, sfx_sdenid)
				end
			end
		end
		if (p.pflags & PF_ANALOGMODE) and P_IsObjectOnGround(s)
			s.wallnopejump = 2
		end
		if (p.cmd.buttons & BT_JUMP)
		and (p.panim == PA_FALL and (p.sam_spacejump and p.sam_spacejumped or not p.sam_spacejump)
		or (P_PlayerInPain(p) and not p.sam_spacejump)
		or p.sammorphed and p.sam_highjump and not s.spiderballing)
			s.sam_bufferjump = s.sam_bufferjump and $+1 or 1
		elseif s.sam_bufferjump
			s.sam_bufferjump = 0
		end
		
		--========================
		--MAIN MORPH BALL CODE
		--========================

		if p.sammorphed --if p.sam_morphed is wrong.
			SAM.MorphBall(p,s) --ALL of that in 1 function? More likely than you think.
			if not (p.pflags & PF_SPINNING)
				PrimeRunPhysics(s, p)
			end
		else --if not p.sammorphed
		
			--beam code HUD stuff.
			SAM.ArmCannon(p,s) --
			p.samybeam = max($,0) 
			
			--Visor transition reset
			
			if p.visorclosein
				p.samvisoraimytrue1 = 0
				p.samvisoraimytrue2 = 0
				p.samvisoraimxtrue = 0
				p.samvisordropdist = 0
				p.samvisordropdist2 = 0
				p.samangshift = 0
				s.sam_beamroll = 0
				s.samvisordrop = 0
				s.lastsamusangle = s.angle		
			else
				SAM.ArmCannon2(p,s) --Part 2. Includes visor stuff.	
			end
			PrimeRunPhysics(s, p)

			--Frame jump system, aka coyote time frames. Metroid Prime Hunters had something like this too.
			--Also adds fall "damage". Deals no actual damage, but stuns.

			if not P_IsObjectOnGround(s)
				--Spacejump when running off a ledge like in Hunters?
				--Careful with stuff like this....
				if (p.cmd.buttons & BT_JUMP)
				and (p.sams_jumpcd == 1 or not p.sams_jumpcd)
					if p.sam_spacejump and not p.sam_spacejumped
					and not (p.pflags & (PF_JUMPED|PF_STARTJUMP|PF_SPINNING|PF_SLIDING|PF_JUMPSTASIS))
					and ((p.panim <= PA_DASH) or (p.panim == PA_FALL))
					and not (s.eflags & (MFE_SPRUNG|MFE_APPLYPMOMZ|MFE_GOOWATER))
					and not p.sam_framejump
					and not p.sam_screwattacking
					and not p.sam_shinespark
					and not p.powers[pw_carry]
					and not p.exiting 
					and not p.beampain
					and not p.sam_shinesparkfly
					and not s.crystalflashanim
					and not p.sam_intoship	
						p.pflags = $|PF_JUMPED & ~(PF_JUMPDOWN|PF_STARTJUMP)
					end
				end
				
				if (s.momz*ZFLIP < s.scale*2)
				and not (twodlevel or (s.flags2 & MF2_TWOD)) 
				and not (s.eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))
					local FALLDMG = (s.momz*ZFLIP)/s.scale
					s.sam_falldmg = s.sam_falldmg and $+FALLDMG or FALLDMG 
				elseif s.sam_falldmg
					s.sam_falldmg = 0
				end
				if p.sam_framejump
					p.sam_framejump = $-1
					if (p.cmd.buttons & BT_JUMP) and (p.sams_jumpcd <= 2)
						if ((p.panim == PA_WALK) or (p.panim == PA_RUN) or (p.panim == PA_FALL))
						and not (p.pflags & (PF_JUMPED|PF_SPINNING|PF_THOKKED))
						and not (s.eflags & MFE_SPRUNG)
						and not p.powers[pw_carry]
							P_DoJump(p, true)
							p.pflags = $ & ~(PF_SPINNING|PF_THOKKED|PF_STARTDASH)
							p.sam_framejump = 0
						end
					end
				end
			else
				if s.sam_falldmg and (s.sam_falldmg < -920) --OHW, MY KNEES
					if not p.sam_screwattacking					
						if not (p.samspbschargefull and (p.speed > 20*s.scale))	
							s.momx,s.momy = $/4,$/4
							p.visorclosein = 16
							if (p.powers[pw_nocontrol] < 11)
								p.powers[pw_nocontrol] = 11
							end
						else --Speedbooster landing
							p.visorclosein = 9
							s.momx,s.momy = $*2/3,$*2/3
						end

						p.beampain = 6
						S_StartSound(s, sfx_samfld)
						P_SamFP(p, PAL_NUKE, 2)
						P_NukeEnemies(s, s, 0)
						A_samquake(s, 55<<16, 12, 60<<16)
						S_StartSound(s, sfx_sballf)
						
						local ANG,ghs = (leveltime%3==0) and s.angle+ANGLE_22h or (leveltime%2==0) and s.angle+ANG10 or s.angle
						for d = -4,3
							ghs = P_SpawnMobjFromMobj(s, 0,0,0, MT_PARTICLE)
							P_Thrust(ghs, ANG, 11<<16) 
							ghs.fuse = 10
							ANG = $+ANGLE_45
						end
					end
				elseif s.sam_bufferjump
					if (s.sam_bufferjump < 6) and (p.cmd.buttons & BT_JUMP) and (p.pflags & PF_JUMPDOWN)
					and not p.powers[pw_carry] and not (p.pflags & PF_JUMPED)
						 p.pflags = $ & ~PF_JUMPDOWN
					end
					s.sam_bufferjump = 0
				end
				s.sam_falldmg = 0
				p.sam_framejump = 5
			end				
		end
		
		--Morph Ball Check is now gone.

		if not p.sam_beamswitch
			if (p.cmd.buttons & (BT_WEAPONNEXT|BT_WEAPONPREV)) and not p.sams_weappress
			and not p.powers[pw_nocontrol] and not p.sams_chargetime
				p.sams_c2cd,p.sams_firecd,p.sams_normfcd,p.sams_powerbombready,p.sams_supermissileready = 0,0,0,0,0
				p.sams_mshotcd = 10
				A_SAMBEAMSWITCH(p)
			end
			if not p.sam_beamswitch
				if s.crystalflashtime
					p.sam_beamcolor = SKINCOLOR_SUPERSKY1
				elseif p.sam_powerbeamequip
					if p.sam_powerbeammeltdown
						p.sam_beamcolor = SKINCOLOR_BLACK
					elseif (gametyperules & GTR_RINGSLINGER) and (leveltime < 3150)
					and not p.sam_powerbeamcombo and G_GametypeHasSpectators()
						p.sam_beamcolor = SKINCOLOR_PINK
					else
						p.sam_beamcolor = SKINCOLOR_POWERBEAM
					end
				elseif p.sam_spazerbeamequip
					p.sam_beamcolor = p.sam_spazerbeammeltdown and SKINCOLOR_BLACK or SKINCOLOR_GREEN
				elseif p.sam_wavebeamequip
					p.sam_beamcolor = p.sam_wavebeammeltdown and SKINCOLOR_BLACK or SKINCOLOR_MAGENTA
				elseif p.sam_icebeamequip
					p.sam_beamcolor = p.sam_icebeammeltdown and SKINCOLOR_BLACK or SKINCOLOR_SKY
				elseif p.sam_plasmabeamequip
					p.sam_beamcolor = p.sam_plasmabeammeltdown and SKINCOLOR_BLACK or SKINCOLOR_RED
				elseif p.sam_hyperbeamequip
					p.sam_beamcolor = SKINCOLOR_WHITE
				end
			end
		end
		
		//Here are the new Beam Combos!
		if (p.sams_chargetime > 41) and not p.sams_shotcd 
			local MISSILES = (p.sammissiles or 0)*p.samadrain
			local FIRECD = p.sams_firecd or 0
			if (p.cmd.buttons & FIREBUTTON) and (MISSILES >= 5) and FIRECD and (FIRECD < 5)
				if not p.powers[pw_nocontrol]
				and not p.exiting 
				and not p.sammorphed
				and p.sam_chargebeam
				
					if p.sam_powerbeamequip and p.sam_powerbeamcombo and (MISSILES >= 10)
					or p.sam_spazerbeamequip and p.sam_spazerbeamcombo and (MISSILES >= 15)
					or p.sam_wavebeamequip and p.sam_wavebeamcombo and (MISSILES >= 15)
					or p.sam_icebeamequip and p.sam_icebeamcombo and (MISSILES >= 15)
					or p.sam_plasmabeamequip and p.sam_plasmabeamcombo and (MISSILES >= 5) 
					
						if G_GametypeHasSpectators() and not p.sam_wavebeamequip --This one be stealthy.
							print(p.name+"\x85"+" is charging a beam combo!")
							for z in players.iterate
								if z.mo and (z.mo != s) and z.mo.health --Show where it's coming from!
									z.mo.sam_combowarn = 40
									z.mo.sam_combowarntarget = s
									z.mo.sam_combowarnang = R_PointToAngle2(z.mo.x, z.mo.y, s.x, s.y)
								end
							end
						end
						p.sams_shotcd,p.sams_mshotcd,p.sams_chargetimecd = 35,35,35
						p.sams_chargetime = 0
						S_StartSound(s, sfx_cmcha)
						p.sams_beamcombocharge = 1
						
					elseif not (FIRECD > 2)
					
						p.sams_firecd = 10
						if not S_SoundPlaying(s, sfx_sdenid)
							S_StartSound(s, sfx_sdenid)
						end
					end
				end
			end
		end
		
		SAM.TryBeamShot(p,s) --Gonna fire?
		if not p.sammorphed
			if p.sam_highjump
				SAM.HighJumpAbility(p, s) --
			end
			local MISSILES = p.sammissiles or 0
			local SUPERS = p.samsupermissiles or 0	
			local CHARGE = p.sams_chargetime or 0
			if p.sams_firecdjlg
				if not p.sams_mshotcd and not p.powers[pw_nocontrol] and not p.exiting 
				and not (CHARGE > 10)
					if not p.sams_supermissileready and (MISSILES >= 1*p.samadrain)
						MISSILES = $*p.samadrain
						local ENERGY = (p.sam_energy) or 0
						local HAMMO = (p.sam_hyperbeamammo) or 0
						
						if p.samchallenger and p.sam_hyperbeamequip and (p.samchallenger > 3) --The ultimate Weapon!
						and ( (MISSILES >= 10*p.samadrain) and (HAMMO >= 15*p.samadrain)
						or (ENERGY > 25) and G_GametypeHasSpectators() )
						and not p.gotflag 
						and not (p.sam_restricthyper and not p.hypernetgo) 
						and not p.sams_beamcombocharge
							p.sams_shotcd = 22
							p.sams_mshotcd = 22
							S_StartSound(s, sfx_cmcha)
							p.sams_beamcombocharge = 14
						else
							p.sammissiles = max($-1*p.samadrain, 0)
							SamusBeamFire(s, MT_SAMMISSILE)
							S_StartSound(s, sfx_mssh2)
							S_StartSound(s, sfx_mssh2)
							s.MissileAmmoDrain = 3
							if not s.crystalflashtime
								SamusTutorial(s, "missiles", true)
								p.sams_shotcd = (p.sam_icebeamequip) and 13 or 14
								p.sams_mshotcd = 23
							else
								p.sams_shotcd = 4
								p.sams_mshotcd = 4
							end
						end
	
					elseif p.sams_supermissileready and (SUPERS >= 1*p.samadrain) 
	
						p.sams_shotcd = 20
						p.sams_mshotcd = 40
						p.samsupermissiles = $-1*p.samadrain
						s.SuperAmmoDrain = 4
						A_samquake(s, 10<<16, 5, 3500<<16)
						SamusTutorial(s, "supermissiles", true)
						SamusBeamFire(s, MT_SAMSUPERMISSILE)
						S_StartSound(s, sfx_smsh)
						S_StartSound(s, sfx_smsh)
					else
						if not p.samhudmessagetime and (p.samadrain and (p.samadrain > 1))
							p.samhudmessagetime = 35
							p.samhudmessage1 = "\x85"+"Double Ammo is on. You'll need twice the ammunition."
							p.samhudmessage2 = nil
						end
						S_StartSound(s, sfx_sdenid)
						p.sams_mshotcd = 12
						p.sams_shotcd = 4
					end
				end
			end
			if (p.cmd.buttons & FIREBUTTON)
				if(p.sams_firecd or 0) > 25
				and (SUPERS >= p.samadrain)
				and not p.sams_supermissileready
				and not p.sams_firecdjlg
				and not p.sams_shotcd 
				and not p.sams_mshotcd
				and not (CHARGE > 10)
				
					if not p.powers[pw_nocontrol] and not p.exiting
						p.sams_supermissileready = 2 --Initial effect.
						S_StartSound(s, sfx_mread)
						local ghs = SamusWeaponReady(s, p)
						if ghs and ghs.valid
							ghs.dontstateme = true
							ghs.color = SKINCOLOR_WHITE
							ghs.sprite = SPR_MBOM
							ghs.frame = R|FF_TRANS90
							ghs.blendmode = AST_ADD
							ghs.tics = 99 ghs.fuse = 8
							ghs.scale = $/5 ghs.scalespeed = $*2
							ghs.destscale = $*99
						end
					end
				end
			end
			
			--Charge Beam charging up!	
			if ( (p.cmd.buttons & BT_CUSTOM2) and not p.c1c2disable and p.sams_c2cd and (p.sams_c2cd > 17)
			
			or (p.cmd.buttons & NORMALFIRE) and p.sams_normfcd and (p.sams_normfcd > 17)
			
			or (CHARGE > 4) 
			and ( p.sam_walljumping and p.sam_walljumpsound or s.sam_ldclmb and (s.sam_ldclmb > 20) )
			
			)
			
			and p.sam_chargebeam
			and not p.sams_shotcd
		--	and not (p.sam_walljumpsound and (p.sam_walljumpsound > 2)) 
			and not p.exiting
			and not p.sams_chargetimecd
			and not p.sam_hyperbeamequip
			
				p.sams_chargetime = $+1
				s.sam_stopmult = 2
				if (p.sams_chargetime > 9) and not s.sams_chargedrawcd
					if (leveltime%2)
						if p.sams_chargetime == 40
							p.sams_firecd = 0
							SamusTutorial(s, "chargebeam", true)
						end						
						if SAM.AttractPickUps(s, 1800<<16, 1)
							s.sams_chargedrawcd = 0
						else
							s.sams_chargedrawcd = 9 --Save resources, pls.
						end
					end
				elseif s.sams_chargedrawcd
					s.sams_chargedrawcd = $-1
				end
				if p.sams_chargetime == 1
					S_StopSoundByID(s, sfx_pbcha)
					S_StartSound(s, sfx_pbcha) --Initial charging sound!
				elseif (p.sams_chargetime%2==0)
					local ZHEIGHT = (s.eflags & MFE_VERTICALFLIP) and (s.height*4/11) or (s.height*2/3)
					local RAD = s.radius*8/3
					local ANG = s.angle-(ANG2*8)
					local DIV = max(17, 50-p.sams_chargetime)
					
					local ghs = P_SpawnMobj(s.x+FixedMul(RAD, cos(ANG)), s.y+FixedMul(RAD, sin(ANG)),s.z+ZHEIGHT, MT_SAMCHARGEGFX)
					ghs.z = $+(FixedMul(FixedMul(50<<16, s.scale), sin(p.aiming)))
					ghs.scale = s.scale/(P_RandomRange((DIV/2)+1,DIV) )
					ghs.ChargeGFX = true
					if p.sam_powerbeamequip
						if (gametyperules & GTR_RINGSLINGER) and (leveltime < 3150)
						and not p.sam_powerbeamcombo and G_GametypeHasSpectators()
							ghs.color = SKINCOLOR_PINK
						else
							ghs.color = SKINCOLOR_VARIASUIT
						end
					else
						ghs.color = p.sam_beamcolor
					end
					ghs.momx,ghs.momy = s.momx*2/3,s.momy*2/3
					ghs.eflags = s.eflags
					ghs.blendmode = AST_ADD
					ghs.target = s
					
					if (p.sams_chargetime > 37)
						if not (s.flags2 & MF2_DONTDRAW) and not (p.samspbschargefull and (p.speed > 20<<16))
							local ghs = SAM.SpeedBoosterGhosts(s, p, "dontsave") --Spawn a flashing overlay!
							if ghs and ghs.valid
								if ghs.sprite == SPR_SAMU and s.skin == "basesamus" --Use the correct one, though!
									if (ghs.frame & FF_FRAMEMASK) == A
										ghs.frame = ($ & ~FF_FRAMEMASK)|F
									end
								end
								ghs.skin = s.skin
								ghs.color,ghs.colorized = p.sam_beamcolor,true
								ghs.fuse,ghs.tics = 2,2
								ghs.frame = ($ & ~FF_TRANSMASK)|FF_TRANS70
							end
						end
						if p.sams_chargetime>=50
							if (p.sams_chargetime % 50 == 0)
							or not S_SoundPlaying(s, sfx_pbchao)
								S_StopSoundByID(s, sfx_pbchao)
								S_StartSound(s, sfx_pbchao)
							end
						end
					end
				end
			elseif p.sams_chargetime
				p.sams_chargetime = 0
				p.sams_chargetimecd = 26
				S_StopSoundByID(s, sfx_pbcha)
				S_StopSoundByID(s, sfx_pbchao)
			end				
		else--if p.sammorphed
			if p.sams_chargetime
				p.sams_chargetime = 0
				p.sams_chargetimecd = 26
				S_StopSoundByID(s, sfx_pbcha)
				S_StopSoundByID(s, sfx_pbchao)
			end					
			if (p.sampw or 0) >= p.samadrain 
				if (p.cmd.buttons & BT_CUSTOM2) and not p.c1c2disable and (p.sams_c2cd or 0) > 24
				or (p.cmd.buttons & NORMALFIRE) and p.sams_normfcd and (p.sams_normfcd or 0) > 24
					if not p.sams_morphcd and not p.sams_powerbombready 
					and not p.powers[pw_nocontrol] and not p.exiting
						p.sams_powerbombready = 2
						S_StartSound(s, sfx_mread)
						local ghs = P_SpawnMobjFromMobj(s, 0, 0, s.height, MT_THOK)
						ghs.color = SKINCOLOR_CRIMSON
						ghs.sprite = SPR_MBOM
						ghs.frame = R|FF_TRANS60|FF_FULLBRIGHT
						ghs.blendmode = AST_ADD
						ghs.fuse = 9 ghs.tics = 99
						ghs.scalespeed = $*4 ghs.destscale = $*99
						ghs.momx = s.momx ghs.momy = s.momy
						P_SetObjectMomZ(ghs, FRACUNIT*11)
						ghs.momz = $+s.momz
					end
				end
			end
			if p.sams_powerbombready and p.sampw
				if not (s.samret2fire and s.samret2fire.valid)
					s.samret2fire = P_SpawnMobjFromMobj(s,
					FixedMul(s.radius*5/2, cos(s.angle-ANG2*2)),
					FixedMul(s.radius*5/2, sin(s.angle-ANG2*2)),
					s.height/10, MT_SAMCHARGEGFX) local ghs = s.samret2fire
					ghs.state = S_SAMCHARGEGFX4
					ghs.sprite = SPR_MPR9
					ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
					ghs.frame = Z|FF_TRANS30
					ghs.tics = 12
					ghs.scale = $*10/9
					ghs.destscale = $*6
					ghs.color = SKINCOLOR_SUPERGOLD4
					ghs.ret2bomb = true
					ghs.target = s
				end
				
				local rng = P_RandomRange(-50,50)
				local ghs = P_SpawnMobjFromMobj(s,
				rng<<16,
				P_RandomRange(-50,50)<<16,
				8<<16, MT_SAMWINDLINE)
				ghs.scale = 35000+(rng*310)
				if leveltime % 2 == 0
					P_SetObjectMomZ(ghs, 20*ghs.scale)
					ghs.flags2 = $|MF2_SHADOW
					ghs.momx,ghs.momy = s.momx,s.momy
				else
					ghs.momx,ghs.momy = s.momx/2,s.momy/2
					P_SetObjectMomZ(ghs, 16*ghs.scale+(rng*500))
				end
				ghs.rollangle = ANGLE_90
				ghs.blendmode = AST_ADD
				ghs.destscale = $*99
				ghs.fuse = (51+rng)/17
				
				
				local pcolor = SKINCOLOR_EMERALD					
				if p.samvisorcolor and p.sam_gravitysuit == 2
					pcolor = p.samvisorcolor
				end	
			end
		end
		if p.sams_supermissileready and not (s.samret2fire and s.samret2fire.valid)
			local ghs = SamusWeaponReady(s, p)
			if ghs and ghs.valid
				s.samret2fire = ghs
				ghs.sprite = SPR_MPR9
				ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
				ghs.frame = Z|FF_TRANS30
				ghs.tics = 12
				ghs.scale = s.scale/3
				ghs.destscale = $*5
				ghs.target = s
			end
		end

		if p.sam_gravitysuit
			local FORCECOLOR = p.forceskincolor2		
			if p.sam_gravitysuit == 2
				p.gravityrd = (SAMUSDIFFICULTY==2) and 6 or 10
			else
				p.gravityrd = (SAMUSDIFFICULTY==2) and 5 or 8 --defense values. Higher number = More Defense.
			end				
			if s.exposedtime
				s.exposedtime = 0
			end
			if not p.sam_gravitysuitjustgot
				SetSamusColor(s, p)					
			elseif not p.sam_saveselect
				if not S_SoundPlaying(s, sfx_ssuitu)
					S_StartSound(s, sfx_ssuitu)
				end
				if p.sam_gravitysuitjustgot == 1
					s.pwbomb = P_SpawnMobj(s.x, s.y, s.z, MT_SAMPOWERBOMB) --Create a big boom!
					s.pwbomb.target = s
					s.pwbomb.eflags = s.eflags
					s.pwbomb.gravitysuitjustgot = true
					S_StartSound(s, sfx_pwbmb)
				end
				p.sam_gravitysuitjustgot = $-1
				local pcolor = SKINCOLOR_VARIASUIT
				if (p.sam_gravitysuit == 1)
					A_SAMPARTICLE(s, MT_MPR1, 25, 2, 2, 3, SKINCOLOR_ORANGE, 40000, true)
				else
					A_SAMPARTICLE(s, MT_MPR1, 25, 2, 2, 3, SKINCOLOR_MAGENTA, 40000, true)
					pcolor = p.samvisorcolor
				end
				if P_IsObjectOnGround(s) or (s.z < (s.z+s.floorz)+50<<16) --So shiny, wow!
					for d = 1,8
						local ghs = SamShinySplat(s, pcolor, 2)
						ghs.scale = $*5
						ghs.momx,ghs.momy = s.momx*8/7,s.momy*8/7
						ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
						ghs.sprite = SPR_BBTR
						ghs.frame = C|FF_TRANS20
						ghs.flags2 = $|MF2_SPLAT
						ghs.rollangle = (leveltime*ANG10)+(ANGLE_45*d)
					end
				end					
			end
		else
			p.gravityrd = (SAMUSDIFFICULTY==2) and 4 or 7 --defense values
			if s.burnuptime and (s.burnuptime%34==0) --Mod support.
				p.rings = max(1, $-s.prevringlost)
				s.prevringlost = $+2
				if p.sam_energy
					p.sam_energy = max($-5,0)
				else
					P_DamageMobj(s)
				end
			end
		end
		--Set Samus' color according to her suit.
		local FORCECOLOR = (p.sam_gravitysuit==1) and p.forceskincolor2 or (p.sam_gravitysuit) and p.forceskincolor3 or p.forceskincolor1
		if (FORCECOLOR) and s.color == p.skincolor
			if FORCECOLOR != p.skincolor
			and not p.sam_screwattacking and not p.sam_gravitysuitjustgot
			and not G_GametypeHasTeams()
				s.color = FORCECOLOR
			end
		end	
		
		--if NOT p.sammorphed
		if not p.sammorphed
		
			p.sampers = 1
			SAM.ScrewAttackAbility(p,s, ZFLIP)
			
			--LOCK ON CODE
			SAM.LockOnAbility(p,s)
			
			if p.sam_screwattacking and (s.state == S_PLAY_WALK)
				CancelScrewAttack(s,p)
			end
			if (p.pflags & PF_JUMPED) --Walljump check
			and ((p.cmd.buttons & BT_JUMP) and not (p.sams_jumpcd > 2))
			and not (s.sam_ldclmb and s.sam_ldclmb > 18)
				samwallcheck(s,p)
			end
			if p.speed >= 38<<16 and not s.morphedmachactive
				s.smmachball = p.speed
			end

			if p.samspbs
			and (p.autospeedbooster or (p.cmd.buttons & BT_CUSTOM1) and not p.c1c2disable) 
			and not p.gotflag
				if (
				(p.speed > 24*s.scale) 
				and not ((s.eflags & MFE_UNDERWATER) and p.sam_gravitysuit != 2)
				
				or (twodlevel or (s.flags2 & MF2_TWOD)) and (p.speed > 13*s.scale)
				and not ((s.eflags & MFE_UNDERWATER) and p.sam_gravitysuit != 2)
				)
				and not p.powers[pw_carry]
					p.samspbscharge = $+1
					if s.samspinpadconfirmed and not p.sampbschargefull and not p.sammorphed and not s.samspinpad
						p.samspbscharge = 140
						StartSamSPBS(s,p)
					elseif (s.wavebuffering or s.crystalflashtime) and (p.samspbscharge < 50)
						p.samspbscharge = 50						
					end
					if (p.samspbscharge > 70) and (p.samspbscharge < 138)
						local ghs
						local ZHEIGHT = (s.eflags & MFE_VERTICALFLIP) and FixedMul(s.height/52, s.scale) or
						s.scale == 90000 and FixedMul(s.height*20/29, s.scale) or (s.height*20/21)
						local ANG2 = ANG1*12
						for i = -1,1,2
							ghs = P_SpawnMobj(
							s.x+FixedMul(-25<<16, cos(s.angle + ANG2*i )), 
							s.y+FixedMul(-25<<16, sin(s.angle + ANG2*i )),
							s.z+ZHEIGHT, MT_SAMCHARGEGFX)
							if ghs and ghs.valid
								ghs.scale = s.scale/P_RandomRange(10,20)
								ghs.color = SKINCOLOR_SKY
								ghs.momx,ghs.momy = s.momx/2,s.momy/2
							end
						end
					end
				elseif not s.samspinpadconfirmed
					if p.sampbschargefull or (p.samspbscharge > 139)
						local forwardmove = abs(p.cmd.forwardmove)
						local sidemove = abs(p.cmd.sidemove)
						local direct = (forwardmove>sidemove) and forwardmove or sidemove --Decide how hard we're pressing the stick! From 0 to 50!
						if (direct > 10) 
						or (p.pflags & PF_JUMPED) and not p.autospeedbooster
							s.sam_afterboost = 7
							if not p.autospeedbooster
								s.sam_spbshack = 11 --And again alternate controls screw my life.
							end
							if (p.pflags & PF_JUMPED)
								local PLUS = (not p.autospeedbooster and not (p.cmd.buttons & BT_CUSTOM1)) and 1 or 3
								p.sam_spbsgrace = p.sam_spbsgrace and $+PLUS or PLUS
							else
								p.sam_spbsgrace = p.sam_spbsgrace and $+8 or 8
							end
						else
							p.sam_spbsgrace = p.sam_spbsgrace and $+8 or 8							
						end
						if (p.sam_spbsgrace > 15)
							p.samspbscharge = 0
							p.sampbschargefull = false
							p.sam_spbsgrace = 0
						end				
					else
						p.samspbscharge = 0
						p.sampbschargefull = false
					end
				end

				if not p.samspbschargefull
					if s.sam_unstuck
						if P_IsObjectOnGround(s)
							p.accelstart = 175
							p.thrustfactor = 7
						else
							p.accelstart = 192
							p.thrustfactor = ((s.eflags & MFE_UNDERWATER) and p.sam_gravitysuit==2) and 13 or 11
						end
						s.sam_unstuck = $-1
					elseif (s.eflags & MFE_UNDERWATER) and p.sam_gravitysuit == 2
						p.normalspeed = 62<<16
						p.accelstart = (p.sam_spacejumpedboost) and 192 or 175
						p.thrustfactor = (p.sam_spacejumpedboost) and 12 or 7				
					elseif not (s.eflags & MFE_UNDERWATER)
						p.normalspeed = 32<<16
						p.accelstart = (p.sam_spacejumpedboost) and 192 or 150
						p.thrustfactor = (p.sam_spacejumpedboost) and 11 or 5
					else
						p.normalspeed = skins[s.skin].normalspeed
						p.thrustfactor = (p.sam_spacejumpedboost) and 11 or skins[s.skin].thrustfactor
						p.accelstart = (p.sam_spacejumpedboost) and 192 or skins[s.skin].accelstart
					end
				elseif p.samspbschargefull and (p.samspbscharge > 70)
					if not p.sammorphed and not s.morphedmachactive
						s.smmachball = p.speed
						s.smmachballspbs = true
					end
					if not p.autospeedbooster
						s.sam_spbshack = 11 --waa8
					end
					if P_IsObjectOnGround(s) or p.sam_walljumping
						if (s.SAM_StartBooster or 0)<16
							s.SAM_StartBooster = 16
						end
					end					
					if s.SAM_StartBooster
						local MINZ = (P_IsObjectOnGround(s)) and 0 or -77*ZFLIP
						local RNG1 = P_RandomRange(30, 250)
						local AIMPLUS = p.aiming/50
						local ADDSCALE = (s.SAM_StartBooster>16) and s.SAM_StartBooster*3000 or 0
						SAM.SpeedBoosterWindLines(s, RNG1*s.scale, 
						{XY = P_RandomRange(50, 190,s)*s.scale, EZ = P_RandomRange(94*ZFLIP,MINZ)*s.scale+AIMPLUS},
						(ADDSCALE) and FF_TRANS50 or (leveltime%2) and FF_TRANS60 or FF_TRANS70, 90000+(RNG1*750)+ADDSCALE,
						(RNG1/14)+5, (leveltime%3==0) and SKINCOLOR_SUPERSKY5 or SKINCOLOR_SILVER)
					end
					
					s.sam_afterboost = 7
					SAM.SpeedBoosterGhosts(s, p)
					
					if s.speedghost
						s.tempsamdye = s.speedghost.color
						s.tempsamdyetr = FF_TRANS70
					end
					
					if s.morphedmachactive --morphine
						p.normalspeed = s.morphedmachspeed*14/9
						p.thrustfactor = 13
					else
						if not (p.pflags & PF_ANALOGMODE)
							p.powers[pw_noautobrake] = 3
						end
						if ((s.eflags & MFE_UNDERWATER) and p.sam_gravitysuit == 2) and not p.powers[pw_flashing]
							p.normalspeed = 88<<16
							p.accelstart = 192
							p.thrustfactor = (p.sam_spacejumpedboost) and 13 or 9
						elseif (s.eflags & MFE_UNDERWATER) or (p.powers[pw_flashing] and not s.samspinpadconfirmed)
							p.samspbscharge = 0
							p.sampbschargefull = false
							s.momx,s.momy = $/2,$/2
						else
							p.normalspeed = 43<<16
							p.accelstart = 192
							p.thrustfactor = (p.sam_spacejumpedboost) and 11 or 6
						end
					end	
					SAM.CheckForShineSpark(s, p) --Check for Shinespark potential!
				end

				if (p.samspbscharge > 70)
					if (p.samspbscharge == 71)
						s.spbssfx = P_SpawnMobj(s.x, s.y, s.z, MT_THOK) --Don't make this a local value.
						s.spbssfx.flags2 = $|MF2_DONTDRAW
						s.spbssfx.tics = 90
						S_StartSound(s.spbssfx, sfx_sprnc)
						p.samspbscharge = 86
					end
					if (p.samspbscharge > 130) and not p.samspbschargefull
						P_SamFP(p, PAL_RECYCLE, 2)
						StartSamSPBS(s,p) --Local function referal
					end
					if s.spbssfx and s.spbssfx.valid
						P_MoveOrigin(s.spbssfx, s.x, s.y, s.z+s.height/2)
					end
				elseif s.spbssfx and s.spbssfx.valid
					s.spbssfx.state = S_NULL
				end
			elseif ((s.eflags & MFE_UNDERWATER) and p.sam_gravitysuit == 2)
				p.normalspeed = 45<<16
				if p.sam_spacejumpedboost
					p.thrustfactor = 12
					p.accelstart = 192
				else
					p.thrustfactor = 6
					p.accelstart = 143
				end
				if p.samspbscharge
					p.samspbschargefull = false
					p.samspbscharge = 0
				end
			else
				p.normalspeed = skins[s.skin].normalspeed
				if p.sam_spacejumpedboost
					p.thrustfactor = 11
					p.accelstart = 192
				else
					p.thrustfactor = skins[s.skin].thrustfactor
					p.accelstart = skins[s.skin].accelstart
				end
				if p.samspbscharge
					p.samspbschargefull = false
					p.samspbscharge = 0
				end
			end


			if p.sam_spacejump and ((p.cmd.buttons & BT_JUMP) and not (p.sams_jumpcd > 2))
				if P_PlayerInPain(p) and not s.spazershocked
					P_SetObjectMomZ(s, (s.eflags & MFE_UNDERWATER) and 5<<16 or 11<<16)
					p.sam_spacejumped = true
					p.pflags = $|PF_JUMPED
					p.sam_spacejumpedboost = 12
					s.state = S_PLAY_FALL
					S_StartSound(s, sfx_sjmp)
				end
					
			end
			if p.sam_spacejumped
				if p.sam_spacejumpedboost
					local ghs
					local rng = P_RandomRange(10,20)
					local FLIPZ = (s.eflags & MFE_VERTICALFLIP) and FixedMul(s.height/52, s.scale) or s.height			
					for i = -1,1,2
						ghs = P_SpawnMobj(
						s.x+FixedMul( -25<<16, cos(s.angle+(ANG1*12*i)) ), 
						s.y+FixedMul( -25<<16, sin(s.angle+(ANG1*12*i)) ), 
						s.z+FLIPZ, MT_SAMCHARGEGFX)
						ghs.scale = s.scale/rng
						ghs.color = SKINCOLOR_SKY
						ghs.momx,ghs.momy = s.momx/2,s.momy/2			
					end
				end
				if P_IsObjectOnGround(s) or p.powers[pw_carry] or (s.eflags & MFE_JUSTHITFLOOR)
					p.sam_spacejumped = false
				end
			end
			if (p.powers[pw_carry] == CR_ZOOMTUBE)
				if (p.pflags & PF_SPINNING) and not (s.sprite == SPR_ZSSA)
					SamMorphSwitch(p, s)
					S_StartSound(s, sfx_smorph)
					S_StartSound(s, sfx_zoom)
				end
			end


		elseif p.sammorphed and p.sambsbl and not p.gotflag
			if ( 
			(p.cmd.buttons & BT_CUSTOM1) and not p.c1c2disable and p.sams_c1cd and p.sams_c1cd>10 or 
			(p.cmd.buttons & FIREBUTTON) and p.sams_firecd and p.sams_firecd>10 
			)
			and not p.sams_shotcd and not p.powers[pw_nocontrol] and not p.exiting
			or p.realtime==0 and (gametype == GT_RACE or gametype == GT_COMPETITION)
			
				if (gametype == GT_RACE or gametype == GT_COMPETITION)
				and not p.powers[pw_nocontrol] and (p.realtime < 9) --Instant charge in races!
					if (p.cmd.buttons & BT_CUSTOM1) 
						p.sams_c1cd = 500
						p.sambsblchargefull = true
					elseif (p.cmd.buttons & FIREBUTTON)
						p.sams_firecd = 500
						p.sambsblchargefull = true
					end
				end
				if s.sambsblchargelvl == 16
					for i = 1,5
						A_SAMPARTICLE(s, MT_MPR1, 3+i, 8, -i, i, SKINCOLOR_SUPERGOLD1-1+i, 25000)
					end						
				end
				s.sambsblchargelvl = s.sambsblchargelvl and $+1 or 1
				s.bsblglowticket = 2
				
			elseif p.sambsblchargefull and not p.sams_c1cdjlg and not p.sams_firecdjlg
				p.sambsblchargefull = false
				s.sambsblchargelvl = 0
			end
			
			if (p.sams_c1cdjlg or p.sams_firecdjlg) and p.sambsblchargefull
			and not p.sams_shotcd and not p.powers[pw_nocontrol] and not p.exiting
			and not (p.powers[pw_carry] == CR_ZOOMTUBE)
				if (p.pflags & PF_DIRECTIONCHAR)
					p.drawangle = s.angle
				end
				p.sams_c1cdjlg = 0
				p.sams_firecdjlg = 0
				S_StartSound(s, sfx_zoom)
				s.bsblboostcspeed = p.speed
				P_InstaThrust(s, s.angle, 75<<16)
				p.bsblboostangle = s.angle
				p.bsblboost = 9
				p.bsblboostattack = 18
				p.cmd.forwardmove = 1
				if s.samslopespin
					s.samslopespin = 1
				end
				if (twodlevel or (s.flags2 & MF2_TWOD)) and s.z == s.floorz
					s.z = s.z+FRACUNIT
				end
			end
			if p.bsblboostattack
				SAM.AttractPickUps(s, 400<<16, 3)
				p.charflags = $|SF_RUNONWATER
				P_SpawnPlayerMissile(s, MT_SAMMONBREAKER)
			elseif (p.charflags & SF_RUNONWATER) and not s.samspinpad
				p.charflags = $ & ~SF_RUNONWATER
			end		
			if p.bsblboost and p.bsblboostangle and not (p.powers[pw_flashing] == 9) 
				s.flags = $ & !MF_BOUNCE
				if (p.powers[pw_carry] == CR_BRAKGOOP)
					p.powers[pw_carry] = 0 --ignore this stuff.
					p.powers[pw_nocontrol] = 0			
				elseif (p.powers[pw_carry] == CR_ZOOMTUBE)
					p.bsblboost = 0 return --
				end
				if (s.eflags & MFE_UNDERWATER) and p.sam_gravitysuit != 2
					P_InstaThrust(s, p.bsblboostangle, 45<<16)
				else
					P_InstaThrust(s, p.bsblboostangle, max(75<<16, (s.bsblboostcspeed) or 0) )
				end
				local ghs = P_SpawnMobjFromMobj(s, s.momx, s.momy, s.momz, MT_THOK)
				ghs.angle = p.bsblboostangle //R_PointToAngle2(s.x, s.y, s.x+s.momx, s.y+s.momy)
				ghs.sprite = SPR_BBTR
				ghs.blendmode = AST_ADD
				ghs.colorized = true
				if leveltime % 2 == 0
					ghs.color = SKINCOLOR_SUPERGOLD3
					ghs.scale = $*12/14
					ghs.tics = 2
					ghs.frame = A|FF_FULLBRIGHT|FF_TRANS70
				else
					ghs.color = SKINCOLOR_SUPERORANGE5
					ghs.scale = $*12/15
					ghs.tics = 9
					ghs.fuse = 6
					ghs.frame = A|FF_FULLBRIGHT|FF_TRANS40
				end
				p.sams_c1cd = 0
				p.sams_firecd = 0
				if not ((p.pflags & PF_STARTJUMP) and (p.pflags & PF_JUMPED) 
				and (s.momz*ZFLIP > 0) and (p.cmd.buttons & BT_JUMP))
					P_SetObjectMomZ(s, -FRACUNIT, true)
				end
			end
		end
		SAM.ShineSparkAbility(p,s, ZFLIP)
		if p.powers[pw_carry] == CR_DUSTDEVIL
			s.samdustdevil = true //SRB2 doesn't properly scale tornado jumps, alongside many other things. Gotta do it manually.
		else
			if s.samdustdevil
				if not P_IsObjectOnGround(s) and not p.sammorphed
					p.pflags = $|PF_JUMPED
					P_SetObjectMomZ(s, 3<<16, true)
					if (p.cmd.forwardmove) or (p.cmd.sidemove) -- Allow a bit more speed build up too.
					s.momx = $*10/9 s.momy = $*10/9
					end				
				end
				s.samdustdevil = false
			end
			
			--Adjust thrustfactor on slopes so you don't get easily stuck on them like hedgehogs. Samus was around when traction was invented.
			if s.standingslope and (p.speed <= 5<<16) and P_IsObjectOnGround(s)
				if (abs(s.standingslope.zdelta) > 26000)
				and (p.cmd.forwardmove or p.cmd.sidemove) 
				and not p.sammorphed and (p.thrustfactor < 11)
				and P_IsObjectOnGround(s)
					p.thrustfactor = (abs(s.standingslope.zdelta) > 60000) and 15 or 11
				end
			end				
		end				
		--Recreate the Mach/Mock Ball from Super Metroid! Morphine!
		SAM.MachBallExploit(p,s)
		if p.sam_power_grip	
			SAM.PowerGripAbility(p,s, ZFLIP)
		end
		
		--We'll have to make a manual system nowadays to see if players changed their chasecam every frame.
		if SAM_displayplayer(p)
			local CHASECAM = CV_FindVar("chasecam").value --third person is 1, first person is 0
			if CHASECAM != nil and camera
				if p.sammorphed or s.sam_screwattackfling --Main times when we want to stay in 3rd person unless the player switches manually.		
				or twodlevel or (s.flags2 & MF2_TWOD) or p.threedimensionalexplosion	
					if p.sam_prevcam != CHASECAM and p.sam_prevcam != nil
					or ((s.flags & MF2_TWOD) or (twodlevel)) and camera and camera.chase != true
						SAM_CMD(p, "nil", p.sam_firstperson and "true" or "false", "true", "lol")
					end
				else
					if p.sam_prevcam == nil --Wait 1 frame before deciding what camera to switch to.
						--	SamCam(p, camera.chase, nothing)
						--	SAM_CMD(p, PREVCAM, FIRSTPERSON, CAMERAdotCHASE, VISORCLOSEIN)
						if p.sam_firstperson
							if CHASECAM == 1 --Manually switch out of first person!
								SAM_CMD(p, "nil", "false", "true", "lol")
							end
						elseif CHASECAM == 0 --Manually switch into first person
							SAM_CMD(p, "nil", "true", "false", "15")
						end
					else
						if p.sam_prevcam != CHASECAM --Do we need to change camera??
							if CHASECAM == 0 
								if p.sam_prevcam != 0
									SAM_CMD(p, "nil", "false", "true", "15")
								end
							elseif p.sam_prevcam == 0
								SAM_CMD(p, "nil", "false", "true", "lol")
							end
						elseif not p.sam_prevcam != nil // CHASECAM
							SAM_CMD(p, "nil", p.sam_firstperson and "true" or "false", "lol", "lol")
						end
					end
				end
			end
		end
		
		if p.sam_spacejumpedsound
			p.sam_spacejumpedsound = $-1
			if p.sam_spacejumpedsound == 1 and not p.sam_walljumpsound
				S_StartSound(s, sfx_sjmp)
			end
		elseif p.sugoigolfmode and (gametype == GT_COOP)
			p.pflags = $|PF_JUMPSTASIS
			p.charability2 = CA2_SPINDASH
		end
		if (p.cmd.buttons & BT_CUSTOM3)
			p.sams_c3cd = p.sams_c3cd and $+1 or 1
		else
			p.sams_c3cd = 0
		end
	end	
end, MT_PLAYER)


COM_AddCommand("ForceSamusSkin", function(p)
	FORCESAMUSSKIN = (not FORCESAMUSSKIN)
	print("\x82"+"FORCESAMUSSKIN\x80 has been set to\x87 "+FORCESAMUSSKIN)
end, COM_ADMIN)
COM_AddCommand("SamusNetSaves", function(p)
	SAMUSNETSAVES = (not SAMUSNETSAVES)
	print("\x82"+"SAMUSNETSAVES\x80 has been set to\x87 "+SAMUSNETSAVES)
end, COM_ADMIN)
COM_AddCommand("SamusCampaign", function(p)
	SAMUSCAMPAIGN = (not SAMUSCAMPAIGN)
	print("\x82"+"SAMUSCAMPAIGN\x80 has been set to\x87 "+SAMUSCAMPAIGN)
end, COM_ADMIN)
COM_AddCommand("MetroidSkins", function(p)
	METROIDSKINS = (not METROIDSKINS)
	print("\x82"+"METROIDSKINS\x80 have been set to\x87 "+METROIDSKINS)
end, COM_ADMIN)

COM_AddCommand("SamusDifficulty", function(p, var1)
	if not tostring(var1) return end --
	var1 = string.lower(tostring(var1))
	
	if var1 == "fusion" or var1 == "fusionmode" or var1 == "fusiondifficulty" 
	or var1 == "hard" or var1 == "hardmode" or var1 == "survival" or var1 == "2"
		SAMUSDIFFICULTY = 2
		print("\x82"+"SAMUSDIFFICULTY\x80 has been set to\x81 Fusion Mode")
	elseif var1 == "hyper" or var1 == "hypermode" or var1 == "hyperdifficulty"
	or var1 == "normal" or var1 == "normalmode" or var1 == "on" or var1 == "1"
		SAMUSDIFFICULTY = 1
		print("\x82"+"SAMUSDIFFICULTY\x80 has been set to\x84 Hyper Mode")
	elseif var1 == "zero" or var1 == "zeromissionmode" or var1 == "zeromission"
	or var1 == "zerodifficulty" or var1 == "zeromissiondifficulty" or var1 == "zeromode" 
	or var1 == "easy" or var1 == "easymode" or var1 == "off" or var1 == "0"
		SAMUSDIFFICULTY = 0
		print("\x82"+"SAMUSDIFFICULTY\x80 has been set to\x83 Zero Mission")
	end
end, COM_ADMIN)

addHook("NetVars", function(network) --It's not SRB2 2.1 anymore, let's give this another shot!
	FORCESAMUSSKIN = network($)
	SamOncePerMap1 = network($)
	SamOncePerMap2 = network($)
	METROIDSKINS = network($)
	SAMUSNETSAVES = network($)
	SAMUSCAMPAIGN = network($)
	SAMUSDIFFICULTY = network($)
end)