--=========================ENEMY SYSTEMS + HUD AID====================================
--Hooks for enemy damage, Hypermode/Fusion mode enemies, custom bosses, 
--and general Samus-specific enemy reactions are mostly clumped here. 
--At the end I put HUD and MENU related hooks to declutter the SAVF_HUD thinker a bit
--====================================================================================
local SAM = MetroidVanguard
local HOST = (SAM) and SAM.HOST

local SamOncePerMap5 = true
addHook("MapChange", function(gamemap)
	SamOncePerMap5 = false
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

SAM.SetHyperMode = function(p, m, allversion) 
	if CBW_Chaos and (gametype == GT_CHAOS) or not m.valid return end --
	
	if SAMUSDIFFICULTY != 0
		if allversion == nil 
		or m.flags != nil and ((m.flags & (MF_ENEMY|MF_BOSS)) or (m.type == MT_EGGGUARD) or (m.type == MT_MINUS))
			local t = m.smontracker
			
			if not m.thebabyspawn
			and not (t and t.valid and (t.bolter or t.floater or t.machinegunner or t.rammer or t.flamer or t.leecher))
				
				if m.type == MT_SPINCUSHION
					if (m.scale < 2<<16+25005)
						m.scale = 2<<16+25005
					end
				end
				if m.type == MT_YELLOWSHELL or m.type == MT_SPRINGSHELL or m.type == MT_GFZFISH or m.type == MT_BUGGLE
				or m.type == MT_EGGGUARD or m.type == MT_GSNAPPER or m.type == MT_HANGSTER
					if not (m.FoeTracked and m.FoeTracked.valid)
						m.smontracker = P_SpawnMobj(m.x, m.y, m.z, MT_SFOETRACKER)
						m.smontracker.bolter = true
					end
				end			
				if m.type == MT_REDCRAWLA or m.type == MT_VULTURE or m.type == MT_UNIDUS or m.type == MT_POINTY
					if not (m.FoeTracked and m.FoeTracked.valid)
						m.smontracker = P_SpawnMobj(m.x, m.y, m.z, MT_SFOETRACKER)
						m.smontracker.floater = true
					end
				end		
				if m.type == MT_SNAILER or m.type == MT_CRAWLACOMMANDER or m.type == MT_POPUPTURRET or m.type == MT_JETTGUNNER
				or m.type == MT_DRAGONBOMBER or m.type == MT_CACOLANTERN
					if not (m.FoeTracked and m.FoeTracked.valid)
						m.smontracker = P_SpawnMobj(m.x, m.y, m.z, MT_SFOETRACKER)
						m.smontracker.machinegunner = true
					end
				end		
				if m.type == MT_FACESTABBER  or m.type == MT_REDBUZZ or m.type == MT_JETTBOMBER or m.type == MT_GSNAPPER 
				or m.type == MT_SKIM or m.type == MT_JETJAW
					if not (m.FoeTracked and m.FoeTracked.valid) 
						m.smontracker = P_SpawnMobj(m.x, m.y, m.z, MT_SFOETRACKER)
						m.smontracker.target = m
						m.smontracker.rammer = true
					end
				end	
				if m.type == MT_BLUECRAWLA or m.type == MT_MINUS or m.type == MT_ROBOHOOD or m.type == MT_POPHAT
				or m.type == MT_PYREFLY
					if not (m.FoeTracked and m.FoeTracked.valid) 
						m.smontracker = P_SpawnMobj(m.x, m.y, m.z, MT_SFOETRACKER)
						m.smontracker.flamer = true
					end
				end	
				
				if m.type == MT_PTERABYTE or m.type == MT_CANARIVORE or m.type == MT_CRUSHSTACEAN
				or m.type == MT_BANPYURA or m.type == MT_JETJAW
					m.smontracker2 = P_SpawnMobj(m.x, m.y, m.z, MT_SMONTRACKER) --MT_SMONTRACKER for this!!
					m.smontracker2.thebaby = true --Dem memes, tho
					m.smontracker2.target = m --Also, note that this is tracker2!
				end
				if m.type == MT_GOLDBUZZ
					if not (m.FoeTracked and m.FoeTracked.valid) 	
						m.smontracker = P_SpawnMobj(m.x, m.y, m.z, MT_SFOETRACKER)
						m.smontracker.leecher = true
					end
				end
				if m.type == MT_PENGUINATOR or m.type == MT_HIVEELEMENTAL or m.type == MT_BUMBLEBORE or m.type == MT_SPINBOBERT
					if not (m.FoeTracked and m.FoeTracked.valid)
						m.smontracker = P_SpawnMobj(m.x, m.y, m.z, MT_SFOETRACKER)
						m.smontracker.thetank = true
					end
				end
				
				if m.smontracker
					m.smontracker.target = m
				end
				if m.montargetedyet and not allversion --Someone purposely wants this re-activated, so....
					m.montargetedyet = false
				end
			end
		end
	end
end

--For starting Hyper Mode. Set allmobs to 7 to check all mobs in the map! Set bosscheck to check for boss
rawset(_G, "ActivateHyperMode", function(p, allmobs, bosscheck, force)
	if (gamemap == 806)
		for z in players.iterate
			z.spawnsship = false
			if z.mo
				z.mo.sam_sprstship = false
			end
		end	return --
	end
	if allmobs == 7 --Is it 7? Then update ALL mobjs!
		if (force or not SamOncePerMap5)
			for m in mobjs.iterate(mobjs)  
			
				SAM.SetHyperMode(p, m, true)
				
				if bosscheck and p.mo and m.valid and 
				( (m.type == MT_SAMUSSHIP) or (m.flags & MF_BOSS) or (m.type == MT_METALSONIC_RACE) )
					local s = p.mo
				
					if YouAreSamus(s)
						m.smontracker = P_SpawnMobj(m.x, m.y, m.z, (m.flags & MF_BOSS) and MT_SFOETRACKER or MT_SMONTRACKER)
						m.smontracker.target = m
					end
					if (m.type == MT_SAMUSSHIP) or ( (FixedHypot(m.x-s.x, m.y-s.y)) <= 6000<<16)
						for z in players.iterate
							z.spawnsship = false
							z.sam_restricthyper = ((netgame) and (m.flags & MF_BOSS)) and m or nil
							if z.mo
								z.mo.sam_sprstship = false
							end
						end
					end
				end
			end
			SamOncePerMap5 = true
		end
	elseif allmobs and allmobs.valid --Update an individual mobj of your choosing.	
		SAM.SetHyperMode(p, allmobs)
	end
end)

rawset(_G, "samcriticalfx", function(s, ANG, i) --Mobj, angle to face, inflictor push(for screw attack/shinespark/etc) 
	if ANG != nil
		ANG = $+ANGLE_90
	elseif s.target and s.target.valid
		ANG = R_PointToAngle2(s.x, s.y, s.target.x, s.target.y)+ANGLE_90 
	else
		ANG = s.angle+ANGLE_90
	end local ghs
	for d = 1,16
		ghs = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_SONIC3KBOSSEXPLODE)
		ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
		ghs.blendmode = AST_ADD
		ghs.color,ghs.colorized = P_RandomRange(SKINCOLOR_SUPERSILVER1, SKINCOLOR_SUPERGOLD3), true
		ghs.flags = $|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOBLOCKMAP|MF_NOCLIPTHING
		ghs.flags2 = $|MF2_SHADOW
		P_InstaThrust(ghs, ANG+(ANGLE_180*d), 2*s.scale*d)	
		P_SetObjectMomZ(ghs, (d>8) and -s.scale*d or 2*s.scale*d)
		ghs.scale = s.scale*2 --Do BEFORE the scale adjustments.
		ghs.tics = 1
		if i
			ghs.momx,ghs.momy = $+i.momx,$+i.momy
		end
	end
	ghs = P_SpawnMobjFromMobj(s,0,0,0,MT_THOK) --Sound object.
	ghs.tics,ghs.fuse = 44,44 ghs.flags2 = MF2_DONTDRAW 
	S_StartSound(ghs, sfx_smcrit)
end)

addHook("MobjThinker", function(s)
	if s.valid and s.target and s.target.frozenmobj and s.health
		P_KillMobj(s)
	end
end, MT_UNIBALL)
addHook("MobjThinker", function(s)
	if s.valid and s.target and s.target.frozenmobj and s.health
		P_KillMobj(s)
	end
end, MT_POINTYBALL)

addHook("MobjThinker", function(s)
	if s.valid and s.health and (s.flags & MF_NOGRAVITY) and s.tracer
		if s.ogzsam == nil
			s.ogzsam = s.z
		end
		if s.ogzsam and not s.spazershocked
			if not (s.eflags & MFE_VERTICALFLIP) 
				if (s.z < s.ogzsam-(5<<16))
					s.z = $+55355
				end
			elseif (s.z > s.ogzsam+(5<<16))
				s.z = $-55355
			end
		end
	end
end, MT_EGGMOBILE2)
		
--Global spawn hook. Careful here.
addHook("MobjSpawn", function(m) --All enemy spawns gain an HP & weakness system for Samus
	if m.valid and (m.flags & (MF_ENEMY|MF_BOSS))
		A_SAMUSMOBHP(m) --
	end
end)
addHook("MobjSpawn", function(m) A_SAMUSMOBHP(m) end, MT_MINUS)
addHook("MobjSpawn", function(m) A_SAMUSMOBHP(m) end, MT_EGGSHIELD)
addHook("MobjSpawn", function(m) A_SAMUSMOBHP(m) end, MT_EGGGUARD)
addHook("MobjSpawn", function(m) A_SAMUSMOBHP(m) end, MT_DETON)

--While it's a player spawn hook, do it anyway!
/*addHook("PlayerSpawn", function(p)
	if SAMUSDIFFICULTY != 0
		if (gametype != GT_MATCH) and (gametype != GT_CTF)
		and not (SAM.HUNTERS(s))
			local STARTENEMIES = true
			if not (netgame) and (gametype == GT_COOP)
				if p.samuschosefile == nil or p.sam_saveselect
					if p.mo and YouAreSamus(p.mo)
						STARTENEMIES = false
					end
				end
			end
			if STARTENEMIES != false
				for m in mobjs.iterate(mobjs)
					if m and m.valid and m.flags != nil
						if (m.flags & (MF_ENEMY|MF_BOSS))
						or (m.type == MT_DETON)
						or (m.type == MT_EGGSHIELD) 
						or (m.type == MT_EGGGUARD)
						or (m.type == MT_MINUS)
							A_SAMUSMOBHP(m, p) --p is the player, m are mobjs in this case
						end
					end
				end
			end
		end
	end
end) */

//Pickup drop RNG when enemies die by Samus' hand, or by your multiplayer comrades.
local function SAM_EnemyDies(m,i,so,p) if not (m and m.valid) return end --
	if p and p.valid or (multiplayer)
	
		if not (i and (i.type == MT_HBSHOT)) --Downside from HyperBeam? No pickups!
		and not (i and i.hypered and (i.type == MT_SPAZERSHOCK)) --HyperBeam uses MT_SPAZERSHOCK with mo.hypered for AoE.
		and not (m.type == MT_PZBOSS)
		
			local samRNG = P_RandomRange(1, 200)
			local FLOAT = m.height*2/3*P_MobjFlip(m)
			
			local MISSILES = (p and p.sammissilesmax) or 0
			local SUPERS = (p and p.samsupermissilesmax) or 0
			local PWBOMBS,PW = (p and p.sampwmax) or 0,PW
			local ETANKS = (p and p.sam_energytanksmax) or 0 
			local ENERGY = (p and p.sam_energy) or 0

			if p and p.mo and p.mo.crystalflashtime --Crystal Flash lets Samus harvest even more from enemies than usual!
				if not P_RandomRange(0,9) 
					P_SpawnMobj(m.x, m.y, m.z+(FLOAT*3/2), MT_PBOM)
				else
					P_SpawnMobj(m.x, m.y+50<<16, m.z+(FLOAT*3/2), MT_SPKU)
					P_SpawnMobj(m.x-50<<16, m.y+50<<16, m.z+(FLOAT*2/3), MT_BMPKU)
				end			
				P_ResetScore(p) --Don't have infinite score from this BS, tho'. Dying wasn't exactly deserving of that.
			end
			
			--NOTE: Fix holdon later, it stays untouchable forever atm.		
			if m.dropmonforsam and not m.brakandco --This is given by the MapLoad hook when monitor variety is low!
			and (samRNG < 30) //Drop monitor loot from regular foes in stingy-asf levels
				local TYPE = nil
				if (samRNG < 2)
					TYPE = MT_INVULN_BOX
				elseif (samRNG < 4)
					TYPE = MT_ARMAGEDDON_BOX
				elseif (samRNG < 6)
					TYPE = MT_PITY_BOX
				elseif (samRNG < 8)
					TYPE = MT_ELEMENTAL_BOX
				elseif (samRNG < 11)
					TYPE = MT_WHIRLWIND_BOX
				elseif (samRNG < 14)
					TYPE = MT_FORCE_BOX
				elseif (samRNG < 17)
					TYPE = MT_ATTRACT_BOX
				elseif (samRNG < 21)
					TYPE = MT_SNEAKERS_BOX
				elseif (samRNG < 24) --Raising probability since 1-up monitors are becoming less common in new-age levels.
					TYPE = MT_1UP_BOX
				else
					TYPE = MT_SCORE1K_BOX
				end
				if TYPE != nil
					m.droppedsammon = P_SpawnMobj(m.x,m.y,m.z, TYPE)
					if m.droppedsammon and m.droppedsammon.valid 
					--	m.droppedsammon.holdontime = 5
						m.droppedsammon.ogmonitor = m
					--	m.droppedsammon.holdon = true
					--	m.droppedsammon.samgotme = 0
					--	m.droppedsammon.samgotmehost = false
					end
				end
			elseif (samRNG < 28)
				m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+FLOAT, (samRNG<23) and MT_NRGA or MT_NRGB)
			elseif p
				local MAXE = 99 + (ETANKS or 0)*50
				if (samRNG < 43)
					if (MISSILES > 50) and not SUPERS
						m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z, MT_STNK)
					else
						m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+FLOAT,((samRNG<41) or SUPERS==0) and MT_MPKU or MT_SPKU)
					end
				elseif (samRNG == 43)
					m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+FLOAT, (p.sampwmax) and MT_PBOM or MT_MPKU)
				elseif (samRNG < 46) // Pity Missile Tank
					if (MISSILES < 15)
						m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z, MT_MTNK)
					end
				elseif (samRNG < 49) // Pity Space Jump
					if (MISSILES > 40) and (SUPERS > 2) and not p.sam_spacejump
						m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z, MT_SJMP)
					end
				elseif (samRNG < 53) // Pity ChargeBeam
					if (MISSILES > 15) and SUPERS and not p.sam_chargebeam
						if p.sam_icebeam
						or p.sam_wavebeam and p.sam_spazerbeam
							m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z, MT_CHBM)
						end
					end
				elseif (samRNG < 110) // Mercy energy drop B
					if (ENERGY < max(40, MAXE/5) )
						m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+FLOAT, MT_NRGB)
					end
				elseif (samRNG < 141) // Mercy energy drop D, because C does not exist.
					if (ENERGY < max(40, MAXE/7) )
						m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+FLOAT, MT_NRGD) 
					end
				elseif (samRNG < 160) // Mercy missile drops
					if MISSILES and (p.sammissiles < max(8, MISSILES/2) )
						m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+FLOAT, MT_MPKU)
					elseif (ENERGY < max(40, MAXE/5) )
						m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+FLOAT, MT_NRGA)
					end
				elseif (samRNG < 190) // Mercy big missile drops
					if MISSILES and (p.sammissiles < MISSILES/3)
						m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+FLOAT, MT_BMPKU)
					elseif (ENERGY < max(40, MAXE/5) )
						m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+FLOAT, MT_NRGA)
					end
				elseif (samRNG < 199) // Mercy super missile drops
					if SUPERS and (p.samsupermissiles < max(2, (SUPERS/3)-1))
						m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+FLOAT, MT_SPKU)
					end
				else // Mercy powerbomb drops	
					if PW and (p.sampw < max(2,PW/2) )
						m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+FLOAT, MT_PBOM)
					end
				end
			end
			
			if m and m.valid 					
				if m.thetank and (samRNG < 180) --These drop extra goodies! Lucky you.
					local TTYPE = (samRNG < 160) and MT_SPKU or MT_PBOM
					if (samRNG < 120)
						TTYPE = (samRNG < 50) and MT_BMPKU or MT_NRGD
					end
					m.droppedsamitem = P_SpawnMobj(m.x, m.y, m.z+FLOAT, TTYPE)
				end
				if (m.eflags & MFE_VERTICALFLIP) or (m.flags2 & MF2_OBJECTFLIP)
					if m.droppedsamitem and m.droppedsamitem.valid
						m.droppedsamitem.eflags = $|MFE_VERTICALFLIP
						m.droppedsamitem.flags2 = $|MF2_OBJECTFLIP
					end
					if m.droppedsammon and m.droppedsammon.valid
						m.droppedsammon.eflags = $|MFE_VERTICALFLIP	
						m.droppedsammon.flags2 = $|MF2_OBJECTFLIP
					end
				end
			end
		end
		if p and p.valid
			if i and i.valid
				if (i.type == MT_PBSHOT) --Gain 3x Crystal Flash gauge for powerbeam kills
					p.crystalflashchance = p.crystalflashchance and $+3 or 3
				elseif not i.hypered and not (i.type == MT_HBSHOT) --Anything but the Hyper Beam gives you Crystal Flash gauge.
					p.crystalflashchance = p.crystalflashchance and $+1 or 1
				end
			end
			if m.brakandco --Don't gain infinite score off these guys!
				p.score = max($-100, 100)
				P_ResetScore(p) return --
			end	
			
			--Now gather info for our Gunship's scanbook!
			
			local SPRITE
			if m.info --Their sprite iiiis....?
				if m.info.missilestate
					SPRITE = states[m.info.missilestate] and states[m.info.missilestate].sprite
				elseif m.info.spawnstate
					SPRITE = states[m.info.spawnstate] and states[m.info.spawnstate].sprite
				end
			end
			
			--If it's not the same as what we already have, then let's go!
			if (SPRITE)
			and not ((p.mobjscan1 == SPRITE) or (p.mobjscan2 == SPRITE) or (p.mobjscan3 == SPRITE))
			
				--Shift these into the next slots.
				p.mobjscan3 = p.mobjscan2
				p.mobjscan3weak = p.mobjscan2weak
				p.mobjscan3resist = p.mobjscan2resist
				p.mobjscan3missileresist = p.mobjscan2missileresist
				
				p.mobjscan2 = p.mobjscan1 
				p.mobjscan2weak = p.mobjscan1weak
				p.mobjscan2resist = p.mobjscan1resist
				p.mobjscan2missileresist = p.mobjscan1missileresist	
										
				--Now setup scan1 with any data we can get!
				local WEAK = (m.spazweak) and "WEAPSPBM" or (m.waveweak) and "WEAPWVBM" or 
				(m.iceweak) and "WEAPICBM" or (m.plasmaweak) and "WEAPPLBM" or nil
	
				local RESIST = (m.spazresist) and "WEAPSPBM" or (m.waveresist) and "WEAPWVBM" or 
				(m.iceresist) and "WEAPICBM" or (m.plasmaresist) and "WEAPPLBM" or nil
				
				p.mobjscan1 = SPRITE // print("Scanned enemy graphic[MINUSso]: "+(sprnames[m.sprite])+"A1")
				p.mobjscan1weak = WEAK --Enemy weakness!
				p.mobjscan1resist = RESIST --Enemy is resistant to...
				p.mobjscan1missileresist = (m.missileresist) and "MPKUA0" or nil 
			end
		end
	end
end

--Global Mobjdeath hook. Risky, risky.
addHook("MobjDeath", function(m, i, so)
	if not m.valid or m.flags == nil or not (m.flags & (MF_ENEMY|MF_BOSS|MF_MONITOR))
		return --
	end
	--Pick any one of them, I don't really care.
	local p = (so and so.valid and YouAreSamus(so)) and so.player or (i and i.valid and YouAreSamus(i)) and i.player
	
	if (m.flags & MF_BOSS)
		if not (m.type == MT_PZBOSS)
		and (netgame or (so and YouAreSamus(so)))
			if mobjinfo[m.type].doomednum == 2119 and mobjinfo[m.type].speed == 5 //Dark Knight fix
				for sector in sectors.iterate
					sector.special = 8192
				end
			end
			if not m.superbraksmetal
				for z in players.iterate
					if not netgame or z.speedrunoverride
						z.samustimeshow = 245
					end
				end
			end
			local samusrnd = P_RandomRange(1, 100)
			
			--Spawn these on ALL bosses.
			local ghs = P_SpawnMobj(m.x+(20<<16)+(samusrnd<<16), m.y+(samusrnd<<16), m.z+(samusrnd<<16/3), MT_NRGA)
			ghs = P_SpawnMobj(m.x-(samusrnd<<16), m.y-(samusrnd<<16), m.z, MT_SPKU)
			ghs = P_SpawnMobj(m.x, m.y-(samusrnd<<16), m.z+(samusrnd<<16/2), MT_NRGB)
			ghs = P_SpawnMobj(m.x+(samusrnd<<16), m.y+(33<<16), m.z+(samusrnd<<16/4), MT_BMPKU)
			ghs = P_SpawnMobj(m.x, m.y, m.floorz+(33<<16), MT_EXPLODE)
			ghs = P_SpawnMobj(m.x, m.y, m.floorz, MT_EXPLODE)
			S_StartSound(m, sfx_s3k44)	
			--Just Metal Sonic exclusive.
			if (m.type == MT_METALSONIC_BATTLE) or (m.type == MT_CYBRAKDEMON)
				for i = -1,1,2
					ghs = P_SpawnMobjFromMobj(m, 0,0,(samusrnd<<16/3), MT_NRGD)
					if ghs and ghs.valid
						P_TryMove(ghs, 
						ghs.x+FixedMul( ((66<<16)+(samusrnd<<16))*i, cos(m.angle)),
						ghs.x+FixedMul( ((66<<16)+(samusrnd<<16))*i, sin(m.angle)), true)
					end
				end
				if (m.type == MT_CYBRAKDEMON)
					return --You're done.
				end
			end
			local samRNG = P_RandomRange(1, 200)
			local FLOORZ = (m.floorz) or m.z+1
			local MISSILES = (p and p.sammissilesmax) or 0
			local SUPERS = (p and p.samsupermissilesmax) or 0
			local PWBOMBS,PW = (p and p.sampwmax) or 0,PW
			local ETANKS = (p and p.sam_energytanksmax) or 0 
			local ENERGY = (p and p.sam_energy) or 0
			local ITEMRATE = (p and ITEMRATE) or 0
			
			--What item do you need? Let's give you a good reward.
			if (MISSILES>100) and (SUPERS<10)
				ghs = P_SpawnMobj(m.x, m.y, FLOORZ, MT_STNK)
			elseif (SUPERS>9) and (PWBOMBS<5)
				ghs = P_SpawnMobj(m.x, m.y, FLOORZ, MT_PTNK)
			elseif (ITEMRATE >= 90) and not p.sam_screwattack
				ghs = P_SpawnMobj(m.x, m.y, m.z, MT_SATK)
			elseif (ITEMRATE >= 94) and not (p.sam_gravitysuit==2)
				ghs = P_SpawnMobj(m.x, m.y, m.z, MT_GVST)
			elseif (ITEMRATE >= 98) and not (ETANKS>=12)
				ghs = P_SpawnMobj(m.x, m.y, FLOORZ, MT_ENGTNK)
			elseif (samusrnd < 15)
				ghs = P_SpawnMobj(m.x, m.y, FLOORZ, (not (p and p.sam_bombs)) and MT_MHBM or MT_MTNK)
			elseif (samusrnd < 30)
				ghs = P_SpawnMobj(m.x, m.y, FLOORZ, (not (p and p.sam_chargebeam)) and MT_CHBM or MT_MTNK)
			elseif (samusrnd < 50)
				ghs = P_SpawnMobj(m.x, m.y, m.z+1, (not (p and p.sam_gravitysuit)) and MT_VRST or MT_STNK)
			elseif (samusrnd < 70)
				ghs = P_SpawnMobj(m.x, m.y, FLOORZ, MT_MTNK)
			elseif (samusrnd < 80)
				ghs = P_SpawnMobj(m.x, m.y, FLOORZ, MT_WVBM)
			elseif (samusrnd < 90)
				ghs = P_SpawnMobj(m.x, m.y, FLOORZ, MT_SPBM)
			elseif (samusrnd < 95)
				ghs = P_SpawnMobj(m.x, m.y, FLOORZ, MT_SPBL)
			elseif (samusrnd < 100)
				ghs = P_SpawnMobj(m.x, m.y, FLOORZ, MT_STNK)
			else --if (samusrnd == 100)
				ghs = P_SpawnMobj(m.x, m.y, FLOORZ, MT_PTNK)
			end
		end
	elseif (m.flags & MF_ENEMY) --Add enemy to the gunship's log.
		SAM_EnemyDies(m,i,so,p) --
		
	elseif (m.flags & MF_MONITOR)
	
		if (netgame or splitscreen)	
		and (gametype == GT_COOP)
		and not (m.fuse==1)

			local p = (so and so.valid) and so.player or (i and i.valid) and i.player
			
			if not p
			or (m.type == MT_EGGMAN_BOX) or (m.type == MT_EGGMAN_GOLDBOX)
			or (mobjinfo[m.type].doomednum == 429)
				return --
			end
			if m.SAM_coopboxrespawn == nil SAM.ApplyMonitorSettings(m) end --Apply quickly, then.
				
			local CRESPAWN = (m.SAM_coopboxrespawn!= nil) and m.SAM_coopboxrespawn or 2			
			if p and YouAreSamus(p.mo)
				return true --
				
			/*	if m.gotplayers
					for i,z in pairs(m.gotplayers)
						if (p == z)
							return true --You already got that, you greedy shit.
						end
					end	
				end	
				
				m.smontracker = P_SpawnMobj(m.x, m.y, m.z, MT_SMONTRACKER)
				local TRACK = m.smontracker
				if TRACK and TRACK.valid
					TRACK.mymon = m.type
					if p.samusnum != nil
						if p.samusnumdecided and CRESPAWN == 2
							m.samgotme = (m.samgotme) or 0
							if p==players[0]
								m.samgotmehost = true
								TRACK.gotmestoragehost = true
							elseif m.samgotmehost
								TRACK.gotmestoragehost = true
							else
								TRACK.gotmestorage = (p==players[0] or m.samgotmehost) and true or m.samgotme
							end
							TRACK.gotmestorage = $|p.samusnum
							m.samgotme = $|p.samusnum
						end
					end
					TRACK.tics = (CRESPAWN==2) and 20 or 1020
					TRACK.pp = m.eflags
					TRACK.pp2 = m.flags2
					m.flags2 = $|MF2_DONTDRAW
				end */
				
			elseif (CRESPAWN == 2) and p and p.mo.skin and not YouAreSamus(p.mo)
			
				if not m.gotplayers
					m.gotplayers = {}
				else
					for i,z in pairs(m.gotplayers)
						if (p == z)
							return true --You already got that, you greedy shit!
						end
					end	
				end
				table.insert(m.gotplayers, p) 
				
				--Give the player their desired thing this way without deleting the original monitor.
				local MONSPAWN = P_SpawnMobjFromMobj(m, 0,0,0, m.type)
				MONSPAWN.fuse,MONSPAWN.tics = 1,1
				MONSPAWN.flags2 = $|MF2_DONTDRAW|MF2_DONTRESPAWN --MF2_DONTRESPAWN is crucial here.
				P_DamageMobj(MONSPAWN, p.mo, p.mo)
				if MONSPAWN and MONSPAWN.valid
					MONSPAWN.flags = $|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOBLOCKMAP & ~(MF_SHOOTABLE|MF_SOLID)
					MONSPAWN.fuse,MONSPAWN.tics = 1,1 --Disappear after this no matter what.
					MONSPAWN.state = S_NULL 
				end
				
				--Spawn an item here too, why not.
				m.samspawnitem = P_SpawnMobj(m.x, m.y, m.z, MT_SAMSPAWNITEM)
				m.samspawnitem.chozobox = m
				m.flags = $|MF_NOCLIP & ~(MF_SHOOTABLE|MF_SOLID)
				m.flags2 = $|MF2_DONTDRAW				
				m.samspawnitem.tracer = (so) and so or i
				
				if ((m.type >= MT_PITY_GOLDBOX) and (m.type <= MT_THUNDERCOIN_GOLDBOX)) and not (m.type == MT_GRAVITY_GOLDBOX) 
					m.samspawnitem.goldlaststate = m.state
					m.state,m.tics = S_THOK,-1
				end
				m.flags = $|MF_NOCLIP & ~(MF_SHOOTABLE|MF_SOLID)
				m.flags2 = $|MF2_DONTDRAW
			
				--Open Box effect
				local brng = P_RandomRange(1,360)
				S_StartSound(m, sfx_cdfm50)
				local MVISUALS = (METROIDSKINS)
				for d = 1,3 --Debris.
					local ghs = P_SpawnMobjFromMobj(m, d,d,d, MT_THOK)
					ghs.sprite = SPR_MXP4
					ghs.tics = 10
					ghs.color = m.color				
					ghs.frame = (MVISUALS) and T or U
					ghs.rollangle = brng+((ANG1*69)*d)+ANGLE_45
					ghs.flags = MF_BOUNCE|MF_GRENADEBOUNCE|MF_NOCLIPTHING
					ghs.flags2 = $ & ~MF2_DONTDRAW
					ghs.momx = $+(p.mo.momx/20)
					ghs.momy = $+(p.mo.momy/20)					
					P_InstaThrust(ghs, brng+((ANG1*110)*d), 8*m.scale+(2*d<<16))
					P_SetObjectMomZ(ghs, (4<<16)+(2*d<<16))
				end
				return true --
			end
		end
	end
end)
addHook("MobjDeath", function(m, i, so)
	local p = (so and so.valid and YouAreSamus(so)) and so.player or (i and i.valid and YouAreSamus(i)) and i.player
	SAM_EnemyDies(m,i,so,p) --
end, MT_EGGGUARD)
addHook("MobjDeath", function(m, i, so) if not m.valid or m.flags == nil return end --
	local p = (so and so.valid and YouAreSamus(so)) and so.player or (i and i.valid and YouAreSamus(i)) and i.player
	SAM_EnemyDies(m,i,so,p) --
end, MT_MINUS)

addHook("MobjRemoved", function(m)
	if m and m.valid and not P_RandomRange(0,2)
		P_SpawnMobj(m.x, m.y, m.z+m.height/2, (not P_RandomRange(0,2)) and MT_SPKU or MT_BMPKU)
	end
end, MT_TNTBARREL)

addHook("ShouldDamage", function(s, i, so)
	if s.valid and ((s.state == S_TNTBARREL_FLYING)	or s.tntdelayexp or (s.flags == MF_NOBLOCKMAP))	
		if so and YouAreSamus(so) or i and i.samusshot
			return false --
		end
	end
end, MT_TNTBARREL)

addHook("MobjThinker", function(m) if not (m.valid and m.samreflector) return end local t = m.target
	if not (t and t.valid)
		m.state = S_NULL return --
	elseif not t.samreflecttime
		t.samreflecttime = nil
		m.state = S_NULL return --
	end 
	local s = m
	if s.AppearShield == nil 
		s.AppearShield = 18
		s.blendmode = AST_ADD
		s.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
		s.dispoffset = 99
	end
	if not (t.type == MT_EGGMOBILE4)
		if s.AppearShield
			s.AppearShield = max($-1,0)	
			if s.AppearShield
				s.color = SKINCOLOR_SUPERPURPLE5- ( max(0, min(4, s.AppearShield/3)) )
				s.colorized = true
				A_SAMPARTICLE(s, MT_MPR1, 11, 3, 2, 15, SKINCOLOR_SUPERPURPLE4, 35000, true)
				A_SAMPARTICLE(s, MT_MPR1, 15, 5, 1, 9, SKINCOLOR_AQUA, 29000, true)			
				if s.AppearShield % 3 == 0
					local ghs = P_SpawnMobjFromMobj(t,0,0,t.height/3, MT_SAMUSZAP)
					ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
					ghs.blendmode = AST_ADD
					ghs.color = SKINCOLOR_SUPERSKY5
					ghs.morning,ghs.fuse = 4,12
				end
			else
				s.color = 0
				s.colorized = false
				s.blendmode = AST_TRANSLUCENT
			end
		elseif (t.samreflecttime < 11)
			s.spritexscale,s.spriteyscale = $+2500,$+2500
			s.color = SKINCOLOR_RED
			s.colorized = true
			s.blendmode = AST_ADD
			if (t.samreflecttime < 6)
				s.flags2 = $|MF2_SHADOW
			end
		end
	end
	t.samreflecttime = max($-1,0)
	m.momx,m.momy,m.momz = t.momx,t.momy,t.momz
	P_MoveOrigin(m, t.x, t.y, t.z-t.height/4)
end, MT_MSSHIELD_FRONT)

--Global MobjDamage Hook. Again, be careful here!
addHook("MobjDamage", function(m, i, so, dmg) if not m.valid return end --
	if m.thetank --Special enemy type!
	
		if m.health and (m.health > 1) 
		
		and not (i and 
		(i.type == MT_HBSHOT) or (i.type == MT_ICCHARGECOMBO) or (i.type == MT_SPCHARGECOMBO)
		or i.player and not YouAreSamus(i)
		or not dmg and (dmg > 1)
		)
		and not (so and so.player and so.player.hypermysticsonic)
		
			if i and i.player and not YouAreSamus(i) --Samus melee'd you?
				i.momx,i.momy = -$,-$
				i.momz = -$+ (4<<16*P_MobjFlip(i))
				i.state = S_PLAY_SPRING
				i.player.pflags = $ & ~(PF_SPINNING|PF_JUMPED)
				if not i.player.powers[pw_flashing]
					i.player.powers[pw_flashing] = 24
				end
			end
		
			for d = 1,5 --to encourage players to use more varied weaponry. 
				if (d%2)
					m.moseyflash = P_SpawnMobjFromMobj(m,0,0,m.height/2, MT_SONIC3KBOSSEXPLODE)
					S_StartSound(m, sfx_cybdth)
				else
					S_StartSound(m, sfx_dmpain)
					m.moseyflash = P_SpawnMobjFromMobj(m,0,0,m.height/2, MT_SMOKE)
				end
				m.moseyflash.destscale = m.scale*3
				m.moseyflash.momx = SAM.RNG(-8, 8,m)*m.scale
				m.moseyflash.momy = P_RandomRange(8, -8)*m.scale
				P_SetObjectMomZ(m.moseyflash, SAM.RNG(1, 3,m)<<16 )
			end
			m.moseyflash = P_SpawnMobj(m.x, m.y, m.z, MT_SMONTRACKER)
			m.moseyflash.target = m
			m.moseyflash.flashingt = 30
			m.samusHP,m.samusHPmax = 7,7
			m.health = $-1
			if i and (i.flags & MF_MISSILE) and i.health
				P_ExplodeMissile(i)
			end
			return true --
		elseif i 
			if (i.type == MT_HBSHOT) or (i.type == MT_ICCHARGECOMBO) or (i.type == MT_SPCHARGECOMBO)
				m.health = max($,1) //You're not surviving these!
			end
		end
	elseif (m.flags & MF_BOSS) and so and YouAreSamus(so)
		local p = so.player
		
		if m.health and (m.health > 1)
		and not (m.type == MT_METALSONIC_BATTLE)
		and not (m.type == MT_PZBOSS)
		and p
			--Shall we make custom boss counters to make life harder for Samus?
			if not (p.bsblboostattack or p.sam_screwattacking or p.sam_shinesparkfly or so.sam_deathball)
			and not ((gamemap == 40) and m.floorz == -1024<<16)
				if (m.type == MT_FANG) --Special treatment for a little shit we don't even fight....
					for d = 0,3
						m.fbomb = P_SpawnMissile(m, m.target or m, MT_FBOMB)
						if m.fbomb and m.fbomb.valid
							if d == 0 //Lay a big scary trap.
								P_SpawnMobj(m.x, m.y, m.z, MT_EXPLODE)
								m.fbomb.momx = FRACUNIT/100 m.fbomb.momy = 0 m.fbomb.momz = FRACUNIT/100
								m.fbomb.z = m.fbomb.floorz+FRACUNIT
								m.fbomb.destscale = m.scale*2
								m.fbomb.flags = $|MF_NOGRAVITY
								m.fbomb.kamibomb = true
							else
								m.fbomb.momz = 6<<16+(d*3<<16)
								P_InstaThrust(m.fbomb, R_PointToAngle2(m.x, m.y, so.x, so.y), 8<<16*d)
							end
							m.fbomb.fuse = 900
						end
					end
				else
					local ghs
					local sambossrng = P_RandomRange(1, 5)
					if (sambossrng < 3) or (i.type == MT_HBSHOT) or m.superbrak or not netgame
						
						--GFX
						A_SAMPARTICLE(m, MT_MPR1, 11, 6, -6, 15, SKINCOLOR_FLAME, 55000, true)
						A_SAMPARTICLE(m, MT_MPR1, 15, 9, -5, 9, SKINCOLOR_SKY, 49000, true)	
						
						ghs = P_SpawnMobjFromMobj(m, 0, 0, 0, MT_THOK)
						ghs.sprite = SPR_MXP4
						ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
						ghs.blendmode = AST_ADD
						ghs.frame = W|FF_TRANS10
						ghs.tics,ghs.fuse = 39,14
						ghs.color,ghs.colorized = SKINCOLOR_SKY,true
						ghs.scalespeed = 98000
						ghs.destscale = 99<<16
						ghs.dispoffset = 8	
							
						if (m.type == MT_EGGMOBILE4) --Counter attack!
						or (m.type == MT_EGGMOBILE3) 
						or (m.type == MT_EGGMOBILE2) and (m.health < 4)
							for i = -1,1,1
								ghs = P_SpawnXYZMissile(m, so, MT_ENERGYBALL, m.x+(260<<16*i), m.y+(260<<16*i), m.z+((i==0) and 210<<16 or 160<<16) )
								ghs.flags = $|MF_MISSILE & ~MF_PAIN
								ghs.samcounter = so
							end
							if (m.type == MT_EGGMOBILE3) and (m.health > 4)
							or (m.type == MT_EGGMOBILE4) and (m.health > 2)
							or (m.type == MT_EGGMOBILE2) --and (m.health < 4)
								if (m.EggShield and m.EggShield.valid)
									m.EggShield.state = S_NULL 
								end
								ghs = P_SpawnMissile(m, so, MT_MSSHIELD_FRONT)
								ghs.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIP
								ghs.target = m
								S_StartSound(m, sfx_s3k40)
								ghs.samreflector = true
								ghs.scale = m.height/34
								m.samreflecttime = (m.type == MT_EGGMOBILE4) and 200 or 100
								m.EggShield = ghs
							end
						else --Weaker counter.			
							ghs = P_SpawnMissile(m, so, MT_ENERGYBALL)
							if ghs and ghs.valid
								ghs.flags = MF_NOGRAVITY|MF_MISSILE & ~MF_PAIN
								ghs.samcounter = so
								if ghs and ghs.valid and not p.cvirgin --Slow down to let them learn the pattern.
									ghs.momx,ghs.momy,ghs.momz = $/2,$/2,$/2
									p.cvirgin = true
								end						
							end
							if m.superbrak and ghs and ghs.valid
								ghs.momx,ghs.momy,ghs.momz = $/3,$/3,$/3
							end
						end
					else			
						ghs = P_SpawnMissile(m, so, MT_MSSHIELD_FRONT)
						ghs.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIP
						ghs.target = m
						S_StartSound(m, sfx_s3k40)
						ghs.samreflector = true
						ghs.scale = m.height/34
						m.samreflecttime = ((m.type == MT_EGGMOBILE4) or (m.type == MT_EGGMOBILE3)) and 220 or 110
						m.EggShield = ghs
					end
					return false --
				end
			end
		end
	end
end)

addHook("MobjThinker", function(s) if not s.valid return end --
	if (s.health > 3)
	 	if (s.state < S_EGGMOBILE4_RAISE1)
			if not s.samreflecttime or (s.samreflecttime < 5)
				if s.EggShield and s.EggShield.valid
					s.EggShield.state = S_NULL
				end
				s.mmmmm = P_SpawnMissile(s, s, MT_MSSHIELD_FRONT)
				s.mmmmm.flags = $|MF_NOCLIPHEIGHT|MF_NOCLIP
				s.mmmmm.target = s
				s.mmmmm.samreflector = true
				s.mmmmm.scale = s.height/34
				s.EggShield = s.mmmmm
				s.samreflecttime = 122
			end
		elseif s.samreflecttime
			s.samreflecttime = 0
			if s.mmmmm and s.mmmmm.valid
				P_KillMobj(s.mmmmm)
			end
		end
	elseif (s.health <= 0) or (s.z < s.floorz-2000<<16)
		if not s.Manual --Sigh.
			if s.EggShield and s.EggShield.valid
				s.EggShield.state = S_NULL
			end
			s.Manual = true
			A_Fall(s,0,0)
			A_BossScream(s,0,0)
			A_BossDeath(s,0,0)
		end
	end
end, MT_EGGMOBILE4)

rawset(_G, "NoPushList", function (m)
	if not ((m.flags & MF_BOSS) and not ((m.type == MT_EGGMOBILE) or (m.type == MT_CYBRAKDEMON)))
	and not (m.type == MT_SNAILER) and not (m.type == MT_GFZFISH) and not (m.type == MT_POPUPTURRET)
	and not (m.type == MT_CANARIVORE) and not m.nosamuspushpls //Give an enemy NoSamusPushpls to become immune to pushing
		return false --
	else
		return true --
	end
end)

local function CritGhost(m, color)
	local ghs = P_SpawnGhostMobj(m)
	ghs.destscale = 99<<16
	ghs.scalespeed = $*3
	ghs.color = color
	ghs.colorized = true
	ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
	ghs.blendmode = AST_ADD
end

addHook("ShouldDamage", function(m, i, so)
	if not (i or so) return end 
	if (m.flags & MF_MONITOR) --Damnit, monitors, don't die to Samus' projectiles.
		if so and so.player --Or let projectile characters like Fang screw everything over either...
			if not (m.type == MT_EGGMAN_BOX)
			and not (m.type == MT_EGGMAN_GOLDBOX)
				if YouAreSamus(so)
					return false --Samus never technically damages boxes. Only the systematic drops
				elseif so.skin == "duke" --Duke does Duke things
					return --
				elseif not (G_GametypeHasSpectators()) and m.gotplayers --Check if the player got the box before
					for i,z in pairs(m.gotplayers)
						if (so.player == z)
							return false --greedy.
						end
					end
				end
			end
		end	
	elseif m.samreflecttime 
		if i and YouAreSamus(i)
		or so and YouAreSamus(so)
		or i and i.sambossreflect
			if not (i and i.player and (i.player.sam_screwattacking or i.player.sam_shinesparkfly or i.player.bsblboostattack or i.sam_deathball))
				return false --
			end
		end	
	elseif (m.flags & (MF_ENEMY|MF_BOSS)) 
		if i
			if m.missileresist and (i.type == MT_SAMMISSILE)
				if (so and so.player and YouAreSamus(so))
					so.player.sam_resisthud = 18
				end
				return false --
			elseif m.iceresist and (i.type == MT_ICSHOT)
				if (so and so.player and YouAreSamus(so))
					so.player.sam_resisthud = 18
				end
				return false --
			end
		
			if (m.flags & MF_ENEMY)
				if (i.type == MT_SPCHARGECOMBO)
					return false --
				elseif ( ((i.type == MT_SMONTRACKER) or (i.type == MT_SFOETRACKER)) and i.target and (i.target.flags & MF_ENEMY)) or i.craymobfire
					return false --
				end
				if m.dodgeret
				and (m.health and (i.flags & MF_MISSILE) and ((m.flags & MF_NOGRAVITY) or (P_IsObjectOnGround(m) and not (m.flags & MF_NOGRAVITY))) )
			
 				and not (i.type == MT_SAMSUPERMISSILE or i.type == MT_SAMPOWERBOMB or i.type == MT_HBSHOT or (i.type == MT_WVSHOT and m.waveweak)) 
				and not (m.eflags & MFE_SPRUNG)
					P_SpawnMobj(m.x, m.y, m.z, MT_EXPLODE)
					if not (m.target and m.target.valid and m.target.health) and i.target and i.target.player
						m.target = i.target
						A_FaceTarget(m)
					end
					if not (m.flags & MF_NOGRAVITY)
						P_SetObjectMomZ(m, 5<<16, true)
					end
					if P_RandomRange(0,1) == 1
						P_InstaThrust(m, m.angle+ANGLE_90, 12<<16)
					else
						P_InstaThrust(m, m.angle-ANGLE_90, 12<<16)
					end
					if (m.type == MT_REDBUZZ)
						P_SpawnGhostMobj(m)
						m.z = $+120<<16		
						S_StartSound(m, sfx_s3k41)
						A_SAMUSEXPLOSIONS(m, 22, MT_IVSP, false, 4000)
						A_SAMUSEXPLOSIONS(m, 16, MT_SUPERSPARK, false, 2200)
					end
					m.dodgecd = 75
					m.dodgeret = false
					if i.valid and i.health and (i.flags & MF_MISSILE)
						P_ExplodeMissile(i)
					end
				return false
 				end	
			end
		end
	end
	
--Part two of the ShouldDamage hook	
	if m.samusHP and i and m.health and not (m.flags & MF2_FRET)
		if (so and so.player and YouAreSamus(so))
			so.player.sam_hitmult = 0
			so.player.sam_hithud = 18
			if not (m.type == MT_PZBOSS or m.type == MT_METROIDPART)
				if (i.type == MT_HBSHOT)
				or (i.type == MT_SPAZERSHOCK) and (m.hypered or i.hypered)
					so.player.sam_hitmult = 6
				elseif m.superbrak and i and ((i.type == MT_SPAZERSHOCK or i.type == MT_SPCHARGECOMBO) and not m.hypered)
					so.player.sam_hitmult = 4
				elseif (i.type == MT_SAMSUPERMISSILE or (i.type == MT_SPAZERSHOCK and not m.hypered)
				or (i.player and (i.sam_deathball or i.player.sam_screwattacking or i.player.sam_shinesparkfly))
				or i.type == MT_SPCHARGECOMBO)
					so.player.sam_hitmult = 2
				elseif ((i.type == MT_SAMMORPHPBOMB) or (i.type == MT_SAMPOWERBOMB))
					if not i.phase
					so.player.sam_hitmult = 3
					end
				end
			end
		end
		if (i.type == MT_PBSHOT)
			if not (m.flags2 & MF2_FRET)
				if so and so.player --Nothing resists the power beam, but it does take longer to chew through.
					if SAMUSDIFFICULTY != 2
						if not m.powerbeamsamusHP
							m.powerbeamsamusHP = m.powerbeamsamusHP and $+1 or 1
						else
							m.samusHP = $-1
						end
					else
						if not (m.powerbeamsamusHP and m.powerbeamsamusHP >= 3) --Fusion Mode wants you to play smarter than this.
							m.powerbeamsamusHP = m.powerbeamsamusHP and $+1 or 1
						else
							m.samusHP = $-1
						end				
					end
				else
					m.samusHP = $-1
				end
				if m.samusHP
					S_StartSound(m, sfx_dmpain)
					if not NoPushList(m)
						P_Thrust(m, i.angle, 3<<16)
					end
				end
			end
		elseif (i.type == MT_SPSHOT)
			if m.spazweak
				m.samusHP = $-8
				CritGhost(m, SKINCOLOR_EMERALD)
				if so and so.valid
					samcriticalfx(m, R_PointToAngle2(m.x, m.y, so.x, so.y))
				else
					samcriticalfx(m)
				end
				S_StartSound(m, sfx_s3k81)
				A_SAMUSEXPLOSIONS(m, 4, MT_MPR4, false, 2000, SKINCOLOR_EMERALD)
				A_SAMUSEXPLOSIONS(m, 10, MT_MPR4, false, 1500, SKINCOLOR_GREEN)
				A_SAMUSEXPLOSIONS(m, 12, MT_SMOKE, false, 9000, SKINCOLOR_BLACK)
				A_SAMUSEXPLOSIONS(m, 7, MT_MPR1, false, 1000, SKINCOLOR_YELLOW)
				if (so and so.player and YouAreSamus(so))
					so.player.sam_crithud = 18
				end
			elseif m.spazresist
				m.samusHP = $-1
				if (so and so.player and YouAreSamus(so))
					so.player.sam_resisthud = 18
				end
			else
				m.samusHP = $-2
			end
			if m.samusHP and (m.samusHP > 0)
				S_StartSound(m, sfx_dmpain)
				if not NoPushList(m)
					P_Thrust(m, i.angle, 13<<16)
					if not (m.flags & MF_BOSS) and not m.spazresist
						if m.wavestunner and m.wavestunner.valid and m.wavestunner.spazerstunner
							m.wavestunner.state = S_NULL --Remove the last one
						end
						m.wavestunner = P_SpawnMobj(m.x, m.y, m.z+m.height/2, MT_WAVESTUNNER)
						m.wavestunner.target = m
						m.wavestunner.spazerstunner = 18
						m.wavestunner.spazerstunang = i.angle
						P_SpawnGhostMobj(m)
					end				
				end
			end
		elseif (i.type == MT_WVSHOT)
			if i.charged
				return --
			end
			if m.waveweak
				CritGhost(m, SKINCOLOR_SUPERGOLD2)
				if so and so.valid
					samcriticalfx(m, R_PointToAngle2(m.x, m.y, so.x, so.y))
				else
					samcriticalfx(m)
				end
				m.samusHP = $-8
				S_StartSound(m, sfx_s3k81)
				A_SAMUSEXPLOSIONS(m, 11, MT_SMOKE, false, 1000, SKINCOLOR_BLACK)
				A_SAMUSEXPLOSIONS(m, 7, MT_MPR1, false, 1000, SKINCOLOR_YELLOW)
				if (so and so.player and YouAreSamus(so))
					so.player.sam_crithud = 18
				end
			elseif m.waveresist
				m.samusHP = $-1
				if (so and so.player and YouAreSamus(so))
					so.player.sam_resisthud = 18
				end
			else
				m.samusHP = $-2
			end
			if m.samusHP and (m.samusHP > 0)
				S_StartSound(m, sfx_dmpain)
				if not (m.flags & MF_BOSS) and not m.waveresist
					m.wavestunner = P_SpawnMobj(m.x, m.y, m.z+m.height/2, MT_WAVESTUNNER)
					m.wavestunner.target = m
					P_InstaThrust(m, 0, 0)
				end
			end
		elseif (i.type == MT_ICSHOT)
			if m.iceweak
				CritGhost(m, SKINCOLOR_ICY)
				m.samusHP = $-9
				S_StartSound(m, sfx_s3k81)
				if so and so.valid
					samcriticalfx(m, R_PointToAngle2(m.x, m.y, so.x, so.y))
				else
					samcriticalfx(m)
				end
				A_SAMUSEXPLOSIONS(m, 7, MT_MPR8, false, 1000, SKINCOLOR_SKY)
				A_SAMUSEXPLOSIONS(m, 4, MT_MPR8, false, 2000, SKINCOLOR_WHITE)
				A_SAMUSEXPLOSIONS(m, 12, MT_SMOKE, false, 1000, SKINCOLOR_BLACK)
				A_SAMUSEXPLOSIONS(m, 8, MT_MPR1, false, 1200, SKINCOLOR_YELLOW)
				if (so and so.player and YouAreSamus(so))
						so.player.sam_crithud = 18
				end
			elseif m.iceresist
				m.samusHP = $-1
				if (so and so.player and YouAreSamus(so))
					so.player.sam_resisthud = 18
				end
			else
				m.samusHP = $-3
			end
			if m.samusHP and (m.samusHP > 0)
				S_StartSound(m, sfx_dmpain)
				if not NoPushList(m)
					P_Thrust(m, i.angle, 3<<16)
				end
			end
		elseif (i.type == MT_PLSHOT)
			if i.gattlingvortex
				if m.type == MT_METROIDPART
					m.samusHP = $-5 --Not as effective against a certain Metroid boss
				else
					m.samusHP = $-12
				end
			elseif m.plasmaweak
				CritGhost(m, SKINCOLOR_CARBON)
				if so and so.valid
					samcriticalfx(m, R_PointToAngle2(m.x, m.y, so.x, so.y))
				else
					samcriticalfx(m)
				end
				m.samusHP = $-11
				A_SAMUSEXPLOSIONS(m, 14, MT_SMOKE, false, 1000, SKINCOLOR_BLACK)
				A_SAMUSEXPLOSIONS(m, 10, MT_MPR5, false, 90000, SKINCOLOR_RED, "nii")
				A_SAMUSEXPLOSIONS(m, 7, MT_MPR1, false, 1000, SKINCOLOR_YELLOW)
				S_StartSound(m, sfx_s3k81)
				if (so and so.player and YouAreSamus(so))
					so.player.sam_crithud = 18
				end
			elseif m.plasmaresist
				m.samusHP = $-1
				if (so and so.player and YouAreSamus(so))
					so.player.sam_resisthud = 18
				end
			else
				if m and (m.type <= MT_GFZFISH)
				and (so and so.player and YouAreSamus(so) and SAMUSDIFFICULTY != 2)
					m.samusHP = 0 --instakill from Plasma Shots
				else
					m.samusHP = $-4
				end
			end
			if m.samusHP and (m.samusHP > 0)
				S_StartSound(m, sfx_dmpain)
				if not NoPushList(m)
					P_Thrust(m, i.angle, 25<<16)
					P_SetObjectMomZ(m, 4<<16, true)
				end
				P_ExplodeMissile(i)
			end
		else
			return --Don't continue if it's none of these.
		end

		if m.samusHP and (m.flags & (MF_ENEMY|MF_BOSS)) and m.health
			m.moseyflash = P_SpawnMobj(m.x, m.y, m.z+m.height/2, MT_SMOKE)
			m.moseyflash.scale = m.scale
			m.moseyflash.eflags = m.eflags
			m.moseyflash.destscale = m.scale*3
			m.moseyflash.momx = (P_RandomRange(-3, 3)<<16)
			m.moseyflash.momy = (P_RandomRange(-3, 3)<<16)
			P_SetObjectMomZ(m.moseyflash, (P_RandomRange(1, 3)<<16))
			if ((m.type == MT_METROIDPART) and m.omega)
				m.omega.painfyellow = 7 --Use your own script.
				if i 
					if i.target and i.target.player and i.target.health
						m.omega.target = i.target --Switch target
					end
					if(i.type == MT_SAMMISSILE) and (m.samusHP > 5) --Make missiles extra effective
						m.samusHP = 5
					end
				end
			elseif (m.type == MT_PZBOSS)
				m.painfyellow = 7 --Use your own script.
				if i and i.target and i.target.player and i.target.health
					m.target = i.target --Switch target
				end	
			else
				m.moseyflash = P_SpawnMobj(m.x, m.y, m.z, MT_SMONTRACKER)
				m.moseyflash.target = m
				m.moseyflash.flashingt = 6
				if not m.target and (m.flags & MF_ENEMY)
					if i and i.target and i.target.valid and i.target.health and not (m.type == MT_GFZFISH)
						m.angle =  R_PointToAngle2(m.x, m.y, i.target.x, i.target.y)
					end
				end
			end
		end

		if m.valid and (m.samusHP <= 0)
			if m.health
				if (m.type == MT_CYBRAKDEMON) or m.superstrongfoe
					m.samusHP = 9 m.samusHPmax = 9
					if i and (i.type == MT_PLSHOT)
						P_ExplodeMissile(i)
					end			
				elseif (m.flags & MF_BOSS) and not (m.type == MT_METALSONIC_BATTLE)
					m.samusHP = 6 m.samusHPmax = 6
					if i and (i.type == MT_PLSHOT)
						P_ExplodeMissile(i)
					end
				else
					m.samusHP = 4 m.samusHPmax = 4
				end
			end
			return --
		else
			return false --
		end	
	end
end)

--Drriiiip. No, not the swag in Samus' wardrobe, just water splashing on her visor. 
--Time to make this organized tables instead of 5 million mobj_t variables.
local function DripThinker(p,s)
	if s.VisorDrip == nil --Main VisorDrip Timer and color.
		s.VisorDrip = {timer = 0, color = SKINCOLOR_AZURE}
	end
	local DRIP = s.VisorDrip --Uppercase DRIP will be the main timer table.

	--Determine if our visor is wet or not!
	if (not DRIP.timer or DRIP.timer == 35)
	and not p.sammorphed 
		local COLOR
		if (s.eflags & MFE_UNDERWATER) --Of course you'd get it wet underwater. 
			DRIP.timer = 175
			if (s.eflags & (MFE_GOOWATER|MFE_TOUCHLAVA))
				COLOR = (s.eflags & MFE_TOUCHLAVA) and SKINCOLOR_RED or SKINCOLOR_MAGENTA
			else
				COLOR = SKINCOLOR_AZURE
			end
		else --In the rain!
			local SEC = s.subsector and s.subsector.sector
			if SEC and (SEC.ceilingpic == "F_SKY1" or not SEC.ceilingpic) --Is it raining and are we outside?
				if (globalweather == PRECIP_STORM) or (globalweather == PRECIP_RAIN) or (globalweather == PRECIP_STORM_NOSTRIKES)
				or (curWeather == PRECIP_STORM) or (curWeather == PRECIP_RAIN) or (curWeather == PRECIP_STORM_NOSTRIKES)
					local AIMLVL = max(-999, 1250-(FixedInt(p.speed)*160) )
					if (p.aiming > AIMLVL<<16) --Are we looking up far enough to get our visor wet?
						local BELOWFOF = false --We're not taking shelter under a FOF either?
						for fof in SEC.ffloors()
							if fof and (fof.flags & FF_EXISTS) and (s.z+s.height <= fof.bottomheight)
								if (fof.flags & (FF_BLOCKPLAYER|FF_BLOCKOTHERS))
								and not (fof.flags & (FF_REVERSEPLATFORM|FF_SWIMMABLE|FF_QUICKSAND))
									BELOWFOF = true break --
								end
							end
						end
						if BELOWFOF == false ---Then congrats, you're wet.
							DRIP.timer = (p.speed > 40<<16) and 135 or 165
							COLOR = SKINCOLOR_AZURE
						end
					end
				end
			end
		end
		if COLOR != nil
			DRIP.color = COLOR
		end
		DRIP.timer = max($-1,5) --Only check every 5 tics for performance's sake.
	end
	if not DRIP.timer
		s.VisorDrips = nil return false --
	else
		DRIP.timer = p.sammorphed and 0 or max($-((p.speed>50<<16) and 2 or 1),0)
		if (DRIP.timer > 5)
			if s.VisorDrips == nil --Individual drips! Note the s.
				s.VisorDrips = {}
			end
			for i = 1,14
				if not (s.VisorDrips[i] and s.VisorDrips[i].timer) --Set up the individual drip table incase it's expired or non-existent.
					local timeRNG = P_RandomRange(75-i, 200+i)
					local TRANSRNG = P_RandomRange(2,6)-1
					local EXTRA = (i)*5
					
					s.VisorDrips[i] = {
					timer = timeRNG, --How long the drip persists for.
					START = timeRNG,
					GRAPHIC = (leveltime%2) and (d%2) or P_RandomRange(0,1),
					SCALE = P_RandomRange(9500+i, 40000+i),
					SPEED = P_RandomRange(1,10),
					Xc = P_RandomRange(-20+EXTRA, 240+EXTRA), --Xcoordinates. They don't necessarily need to be on-screen.
					Yc = P_RandomRange(-15+(EXTRA/3), 210+(EXTRA/2) ),
					TRANS = TRANSRNG, --Translucency value to start off with.
					STARTTRANS = 9,
					BLEND = AST_TRANSLUCENT }
				end
				local drip = s.VisorDrips[i] --lowercase for individual drips!
				if drip 
					drip.timer = $-1
					if (drip.timer < 1)
						s.VisorDrips[i] = nil			
					elseif (drip.timer%2==0)
						if (drip.timer%drip.SPEED==0)
							drip.Yc = $+1 --Slide down on the visor.
						end
						drip.STARTTRANS = $-1
						drip.SCALE = (drip.SCALE>12500) and $-(drip.SPEED*8) or max($-drip.SPEED,2000) --get smaller overtime.
						if (DRIP.timer < 15) or (drip.timer < 9) --Last moments before non-existence! Fade out!
							drip.TRANS = min($+1,9)
						else
							local ADD = (drip.timer%(drip.START/11)==0)
							if DRIP.color == SKINCOLOR_RED
								drip.BLEND = AST_ADD
								if ADD
									drip.TRANS = min($+1,6)
								end
							else
								drip.BLEND = AST_TRANSLUCENT
								if ADD
									drip.TRANS = min($+1,9)
								end
							end
						end
					end
				end
			end
		end
	end
end

local T10,T20,T30,T40,T50,T60,T70,T80,T90 =
65536,131072,196608,262144,327680,393216,458752,524288,589824

local function SAM_ItemDeleteHUD(p,s)
	if p.samitemdelete == 1
		if p.sam_bombs
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
				p.sam_bombs = false
				S_StartSound(s, sfx_doord2)
				P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
				S_StartSound(s, sfx_ssmenb)
				p.samitemdelete = 2
			end
		else
			p.samitemdelete = 2
		end
	elseif p.samitemdelete == 2
		if p.sammissilesmax
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
				p.sammissilesmax = 0
				S_StartSound(s, sfx_doord2)
				P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
				S_StartSound(s, sfx_ssmenb)
				p.samitemdelete = 3
			end
		else
			p.samitemdelete = 3
		end
	elseif p.samitemdelete == 3
		if p.samsupermissilesmax
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.samsupermissilesmax = 0
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 4
			end
		else
			p.samitemdelete = 4
		end
	elseif p.samitemdelete == 4
		if p.sampwmax
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sampwmax = 0
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 5
			end
		else
			p.samitemdelete = 5
		end
	elseif p.samitemdelete == 5
		if p.sam_chargebeam
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sam_chargebeam = false
			p.sam_powerbeamcombo = false
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 6
			end
		else
			p.samitemdelete = 6
		end
	elseif p.samitemdelete == 6
		if p.sam_spazerbeam
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sam_spazerbeam = false
			p.sam_spazerbeamcombo = false
			SamResetBeam(p)
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 7
			end
		else
			p.samitemdelete = 7
		end
	elseif p.samitemdelete == 7
		if p.sam_wavebeam
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sam_wavebeam = false
			p.sam_wavebeamcombo = false
			SamResetBeam(p)
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 8
			end
		else
			p.samitemdelete = 8
		end
	elseif p.samitemdelete == 8
		if p.sam_icebeam
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sam_icebeam = false
			p.sam_icebeamcombo = false
			SamResetBeam(p)
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 9
			end
		else
			p.samitemdelete = 9
		end
	elseif p.samitemdelete == 9
		if p.sam_plasmabeam
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sam_plasmabeam = false
			p.sam_plasmabeamcombo = false
			SamResetBeam(p)
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 10
			end
		else
			p.samitemdelete = 10
		end
	elseif p.samitemdelete == 10
		if p.sambsbl
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sambsbl = false
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 11
			end
		else
			p.samitemdelete = 11
		end
	elseif p.samitemdelete == 11
		if p.sam_spiderball
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sam_spiderball = false
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 12
			end
		else
			p.samitemdelete = 12
		end
	elseif p.samitemdelete == 12
		if p.sam_highjump
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sam_highjump = false
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 13
			end
		else
			p.samitemdelete = 13
		end
	elseif p.samitemdelete == 13
		if p.sam_spacejump
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
				p.sam_spacejump = false
				S_StartSound(s, sfx_doord2)
				P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
				S_StartSound(s, sfx_ssmenb)
				p.samitemdelete = 14
			end
		else
			p.samitemdelete = 14
		end
	elseif p.samitemdelete == 14
		if p.sam_screwattack
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sam_screwattack = false
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 15
			end
		else
			p.samitemdelete = 15
		end
	elseif p.samitemdelete == 15
		if p.sam_gravitysuit and p.sam_gravitysuit != 1
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sam_gravitysuit = 1
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			SetSamusColor(s, p) 
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 16
			end
		else
			p.samitemdelete = 16
		end
	elseif p.samitemdelete == 16
		if p.sam_gravitysuit and p.sam_gravitysuit == 1
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sam_gravitysuit = 0
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			SetSamusColor(s, p) 
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 17
			end
		else
			p.samitemdelete = 17
		end
	elseif p.samitemdelete == 17
		if p.samspbs
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.samspbs = false
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 18
			end
		else
			p.samitemdelete = 18
		end
	elseif p.samitemdelete == 18
		if p.sam_energytanksmax
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
			p.sam_energytanksmax = 0
			S_StartSound(s, sfx_doord2)
			P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
			S_StartSound(s, sfx_ssmenb)
			p.samitemdelete = 19
			end
		else
			p.samitemdelete = 19
		end
	elseif p.samitemdelete == 19
		if p.sam_power_grip
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
				p.sam_power_grip = false
				S_StartSound(s, sfx_doord2)
				P_SamFP(p, 3, PAL_NUKE)
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
				S_StartSound(s, sfx_ssmenb)
				p.samitemdelete = 20
			end
		else
			p.samitemdelete = 20
		end					
	elseif p.samitemdelete >= 20
		if p.sam_hyperbeam //Don't want random people removing coop emeralds in netgames.
			if (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
				p.sam_hyperbeam = false
				S_StartSound(s, sfx_doord2)
				SamResetBeam(p)
				p.ssmenudrop = 0
				p.samitemdelete = 0
				p.ssmenusub = 2
				p.ssmenusubpage = 1
				P_SamFP(p, 3, PAL_NUKE)
				if not netgame
					emeralds = 0
				end
			elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
				S_StartSound(s, sfx_ssmenb)
				SamResetBeam(p)
				p.ssmenudrop = 0
				p.samitemdelete = 0
				p.ssmenusub = 2
				p.ssmenusubpage = 1
			end
		else
			S_StartSound(s, sfx_ssmenb)
			SamResetBeam(p)
			p.ssmenudrop = 0
			p.samitemdelete = 0
			p.ssmenusub = 2
			p.ssmenusubpage = 1
		end
	end
end

--The part when you're inside the ship.
local function GunShipMenu(p,s)
	s.flags2 = $|MF2_DONTDRAW
	p.powers[pw_nocontrol] = 0

	if G_GametypeHasSpectators()
		if p.score
			if not p.shipscorelose
				if (p.score > 50)
					P_AddPlayerScore(p, -50)
				else 
					p.score = 0
				end
				p.shipscorelose = 175
				S_StartSound(s, sfx_ssmenb)
			else
				p.shipscorelose = $-1
			end
		end
	end
	
	--Turn the stars into a simple table.
	if s.starSAM == nil
		s.starSAM = {}
	end
	for i = 1,9
		local STAR = s.starSAM[i]
		if STAR == nil
			s.starSAM[i] = {} 
			STAR = s.starSAM[i]
			if i==1		STAR.x,STAR.y = 40,65 --Deliberately NOT RNG!
			elseif i==2 STAR.x,STAR.y = 100,120
			elseif i==3	STAR.x,STAR.y = 293,41
			elseif i==4 STAR.x,STAR.y = 152,8
			elseif i==5 STAR.x,STAR.y = 161,173
			elseif i==6	STAR.x,STAR.y = 66,151
			elseif i==7 STAR.x,STAR.y = 25,96
			elseif i==8 STAR.x,STAR.y = 244,100
			elseif i==9 STAR.x,STAR.y = 190,139 end
		else
			STAR.x,STAR.y = $-1,$-1
			if (STAR.x < 25) STAR.x = 296 end 
			if (STAR.y < 6) STAR.y = 188 end
		end
	end
	local ADMIN = (IsPlayerAdmin(p) or (p == server)) and true or false
	if (isdedicatedserver) and not (ADMIN)
		local TOTAL = 0
		for z in players.iterate
			if z.valid TOTAL = $+1
				if (z == server) or (IsPlayerAdmin(z))
					TOTAL = 99 break --
				end 
			end
		end if (TOTAL<2) ADMIN = true end
	end	
	local MTILT = 22 --How far you should tilt the stick.

		//Main Menu
		   if p.ssmenusub == 1
			if p.ssmenu1 == 1  //Equipment
				if (p.cmd.forwardmove > MTILT) and not p.ssmenuup
					p.ssmenu1 = 5
					S_StartSound(s, sfx_ssmenm)
				elseif (p.cmd.forwardmove < -MTILT) and not p.ssmenudown
					p.ssmenu1 = 2
					S_StartSound(s, sfx_ssmenm)
				elseif (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
					S_StartSound(s, sfx_ssmenc)
					p.ssmenusub = 2
					p.ssmenusubpage = 1
					p.ssmenu1 = 1
					p.ssmenudrop = 0
				end
			elseif p.ssmenu1 == 2  //Controls and Options
				if (p.cmd.forwardmove > MTILT) and not p.ssmenuup
					p.ssmenu1 = 1
					S_StartSound(s, sfx_ssmenm)
				elseif (p.cmd.forwardmove < -MTILT) and not p.ssmenudown
					p.ssmenu1 = 3
					S_StartSound(s, sfx_ssmenm)
				elseif (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
					S_StartSound(s, sfx_ssmenc)
					p.ssmenusub = 3
					p.ssmenusubpage = 1
					p.ssmenu1 = 1
					p.ssmenudrop = 0
				end
			elseif p.ssmenu1 == 3 //Match/CTF
				if (p.cmd.forwardmove > MTILT) and not p.ssmenuup
					p.ssmenu1 = 2
					S_StartSound(s, sfx_ssmenm)
				elseif (p.cmd.forwardmove < -MTILT) and not p.ssmenudown
					p.ssmenu1 = 4
					S_StartSound(s, sfx_ssmenm)
				elseif (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
					S_StartSound(s, sfx_ssmenc)
					p.ssmenusub = 4
					p.ssmenusubpage = 1
					p.ssmenu1 = 1
					p.ssmenudrop = 0
				end
			elseif p.ssmenu1 == 4 //Secret Data
				if (p.cmd.forwardmove > MTILT) and not p.ssmenuup
					p.ssmenu1 = 3
					S_StartSound(s, sfx_ssmenm)
				elseif (p.cmd.forwardmove < -MTILT) and not p.ssmenudown
					p.ssmenu1 = 5
					S_StartSound(s, sfx_ssmenm)
				elseif (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
					S_StartSound(s, sfx_ssmenc)
					p.ssmenusub = 5
					p.ssmenusubpage = 1
					p.ssmenu1 = 1
					p.ssmenudrop = 0
				end
			elseif p.ssmenu1 == 5 //Exit Ship
				if (p.cmd.forwardmove > MTILT) and not p.ssmenuup
					p.ssmenu1 = 4
					S_StartSound(s, sfx_ssmenm)
				elseif (p.cmd.forwardmove < -MTILT) and not p.ssmenudown
					p.ssmenu1 = 1
					S_StartSound(s, sfx_ssmenm)
				elseif (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
					ConfigSamusSave(s, p, true, false)
					AdminSamusSave(p, true, false)
					p.sam_intoship = 0
					p.sam_exitship = 70
					s.friction = 59392
					S_StartSound(s, sfx_ssmenc)
					if (YouAreSamus(s)) 
						if (p.sam_st.scale > 95355)
							S_StopMusic(p)
							p.sam_shipjingle = 210
							S_StartSound(s, sfx_samjin)
							s.scale = 90000
						else
							S_StartSound(s, sfx_mario9)
							P_RestoreMusic(p)
							s.scale = 10000
							s.destscale = 90000
						end
					end
					s.flags2 = $ & ~MF2_DONTDRAW
					if (gametype == GT_CTF)
						s.player.samnoflag = 350
					end
					p.pflags = $ & ~(PF_INVIS|PF_GODMODE)
					p.sams_morphcd,p.sams_notyet,p.sams_jumpcd,p.sams_shotcd,p.powers[pw_nocontrol] = 50,50,50,50,50
				end
			end
		   elseif p.ssmenusub == 2 //Equipment Section.
		  	if p.ssmenusubpage
		  		if (p.cmd.sidemove < -MTILT) and not p.ssmenuleft and (p.ssmenusubpage <= 1)
					p.ssmenusubpage = 26
					S_StartSound(s, sfx_ssmenm)
					p.ssmenudrop = 0
		  		elseif (p.cmd.sidemove > MTILT) and not p.ssmenuright and (p.ssmenusubpage >= 26)
					p.ssmenusubpage = 1
					S_StartSound(s, sfx_ssmenm)
					p.ssmenudrop = 0	
				elseif (p.cmd.sidemove > MTILT) and not p.ssmenuright
					p.ssmenusubpage = $+1
					S_StartSound(s, sfx_ssmenm)
					p.ssmenudrop = 0
				elseif (p.cmd.sidemove < -MTILT) and not p.ssmenuleft
					p.ssmenusubpage = $-1
					S_StartSound(s, sfx_ssmenm)
					p.ssmenudrop = 0

				elseif (p.cmd.buttons & BT_JUMP) and p.ssmenudrop and not p.ssmenujump
				and p.ssmenusubpage == 1
					p.ssmenudrop = 0 
					p.ssmenusub = 77
					p.samitemdelete = 1
					S_StartSound(s, sfx_ssmenc)

				elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
					S_StartSound(s, sfx_ssmenb)
					p.ssmenu1 = 1
					p.ssmenusub = 1
					p.ssmenusubpage = 1
					p.ssmenudrop = 0
				elseif (p.cmd.forwardmove < 0) and not p.ssmenudown and not p.ssmenudrop
				and p.ssmenusubpage == 1
					p.ssmenudrop = 1 
					S_StartSound(s, sfx_ssmenm)
				elseif (p.cmd.forwardmove > 0) and not p.ssmenuup and p.ssmenudrop
					p.ssmenudrop = 0
					S_StartSound(s, sfx_ssmenm)
				end
		  	end

		   elseif p.ssmenusub == 3 //Controls and Options!

		  	if p.ssmenusubpage

				if p.samvisorcolor == nil
					p.samvisorcolor = 5
				end

		  		if (p.cmd.forwardmove > MTILT) and not p.ssmenuup and not (p.ssmenusubpage < 1) and not (p.ssmenusubpage == 500)
					if (p.ssmenusubpage == 1)
						p.ssmenusubpage = 22
					else
						p.ssmenusubpage = $-1
					end
					S_StartSound(s, sfx_ssmenm)
					p.ssmenudrop = 0
		  		elseif (p.cmd.forwardmove < -MTILT) and not p.ssmenudown
				and not ((p.ssmenusubpage > 22) and (p.ssmenusubpage <= 499)) and not (p.ssmenusubpage >= 503)
					if (p.ssmenusubpage == 22)
						p.ssmenusubpage = 1
					else
						p.ssmenusubpage = $+1
					end
					S_StartSound(s, sfx_ssmenm)
					p.ssmenudrop = 0
				elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse and not (p.ssmenusubpage >= 500)
					S_StartSound(s, sfx_ssmenb)
					p.ssmenu1 = 2
					p.ssmenusub = 1
					p.ssmenusubpage = 1
					p.ssmenudrop = 0
				elseif (p.cmd.sidemove < -MTILT) and not p.ssmenuleft and (p.ssmenudrop or (p.ssmenusubpage == 5) or (p.ssmenusubpage >= 500))
					if p.ssmenusubpage == 22 --Filler
						--
					elseif p.ssmenusubpage == 5 
						if (p.samvisorcolor > 1)
							p.samvisorcolor = $-1
							S_StartSound(s, sfx_ssmens)
							if p.samvisorcolor == SKINCOLOR_EMERALD
								p.samvisorcolor = $-1
							end
						end
		  			elseif p.ssmenusubpage == 500 //Custom Suit1
						if (p.customsuitc1 > 1)
							p.customsuitc1 = $-1
							S_StartSound(s, sfx_ssmens)
						end
		  			elseif p.ssmenusubpage == 501 //Custom Suit2
						if (p.customsuitc2 > 1)
							p.customsuitc2 = $-1
							S_StartSound(s, sfx_ssmens)
						end
		  			elseif p.ssmenusubpage == 502 //Custom Suit3
						if (p.customsuitc3 > 1)
							p.customsuitc3 = $-1
							S_StartSound(s, sfx_ssmens)
						end
					else
						S_StartSound(s, sfx_ssmens)
						p.ssmenudrop = $-1
					end
				elseif (p.cmd.sidemove > MTILT) and not p.ssmenuright
		  			if p.ssmenusubpage == 500 //Custom Suit1
						if (p.customsuitc1 < (#skincolors - 1))
							p.customsuitc1 = $+1
							S_StartSound(s, sfx_ssmens)
						end
		  			elseif p.ssmenusubpage == 501 //Custom Suit2
						if (p.customsuitc2 < (#skincolors - 1))
							p.customsuitc2 = $+1
							S_StartSound(s, sfx_ssmens)
						end
		  			elseif p.ssmenusubpage == 502 //Custom Suit3
						if (p.customsuitc3 < (#skincolors - 1))
							p.customsuitc3 = $+1
							S_StartSound(s, sfx_ssmens)
						end
					elseif p.ssmenusubpage == 22 --filler
						--
		  			elseif p.ssmenusubpage == 5 //Gravity Lights
						if p.ssmenusubpage == 5 and (p.samvisorcolor < (#skincolors - 1))
							p.samvisorcolor = $+1
							S_StartSound(s, sfx_ssmens)
							if p.samvisorcolor == SKINCOLOR_EMERALD
								p.samvisorcolor = $+1
							end
						end
		  			elseif not (p.ssmenusubpage == 4 or p.ssmenusubpage == 5 or p.ssmenusubpage == 13 or p.ssmenusubpage == 21) and p.ssmenudrop == 0 //Autospeed, BeamSwap, Tokens, and 5=Starter
						S_StartSound(s, sfx_ssmens)
						p.ssmenudrop = $+1
		  			elseif (p.ssmenusubpage == 4 or p.ssmenusubpage == 14 or p.ssmenusubpage == 8 or p.ssmenusubpage == 13 or p.ssmenusubpage == 17 or p.ssmenusubpage == 20 or p.ssmenusubpage == 21) and p.ssmenudrop < 2 // Difficulty
						S_StartSound(s, sfx_ssmens)
						p.ssmenudrop = $+1
		  			end
				elseif (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
		  			if p.ssmenusubpage == 503
					
						SetSamusColor(s, p)
						local MAXCOLOR = SKINCOLOR_SUPERSILVER1
						p.forceskincolor1 = (p.customsuitc1 >= MAXCOLOR) and p.customsuitc1 or 0
						p.forceskincolor2 = (p.customsuitc1 >= MAXCOLOR) and p.customsuitc2 or 0
						p.forceskincolor3 = (p.customsuitc1 >= MAXCOLOR) and p.customsuitc3 or 0

						CONS_Printf(p, "\x83"+"Custom Suit color schemes set!")
						S_StartSound(s, sfx_ssmeno)
						p.ssmenu1 = 2
						p.ssmenusub = 3
						p.ssmenusubpage = 3
						p.ssmenudrop = 0

		  			elseif p.ssmenusubpage == 1
					S_StartSound(s, sfx_ssmeno)
						if p.ssmenudrop
							CONS_Printf(p, "\x85"+"Auto Speed Boost toggled off")
							p.autospeedbooster = 0
						else
							CONS_Printf(p, "\x82"+"Auto Speed Boost toggled on")
							p.autospeedbooster = 1
						end
		  			elseif p.ssmenusubpage == 2
					S_StartSound(s, sfx_ssmeno)
						if not p.ssmenudrop
							CONS_Printf(p, "\x82"+"Fire buttons swapped! Fire missiles with NORMALFIRE, shoot beams with FIRE!")
							p.swapfire = 1
						else
							CONS_Printf(p, "\x85"+"Fire buttons reverted to normal! Fire missiles with FIRE, shoot beams with NORMALFIRE!")
							p.swapfire = 0
						end
		  			elseif p.ssmenusubpage == 3
						S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
		  						if not p.customsuitc1
									p.customsuitc1 = SKINCOLOR_POWERSUIT
								end
								if not p.customsuitc2
									p.customsuitc2 = SKINCOLOR_VARIASUIT
								end
								if not p.customsuitc3
									p.customsuitc3 = SKINCOLOR_GRAVITYSUIT
								end

								p.ssmenusubpage = 500
								p.ssmenudrop = 0
							else
								CONS_Printf(p, "\x82"+"Suit colors set to steady. You'll remain whatever color you pick regardless of suit.")
								p.customsuitc1 = 0
								p.customsuitc2 = 0
								p.customsuitc3 = 0
								p.skincolor = SKINCOLOR_ORANGE
								s.color = SKINCOLOR_ORANGE
							end
		  			elseif p.ssmenusubpage == 4
						if not (gametype == GT_COOP)
						
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed in COOP/Single Player")
						
						elseif not (ADMIN)
						
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
								SAMUSDIFFICULTY = 0
								print("\x83"+"Normal difficulty activated! Enemies behave similar to vanilla SRB2, except for specific weaknesses, resistances, and boss counterattacks.")
							elseif p.ssmenudrop == 1
								SAMUSDIFFICULTY = 1
								print("\x87"+"Hypermode activated! Enemies and bosses are now far tougher and have extra abilities!")
							else
								SAMUSDIFFICULTY = 2
								print("\x89"+"Fusion Mode activated! Enemies are even more resilient, defense is lower, tanks grant no health/ammo, weapons drain 2x ammo, and it's tougher to recover. This is the ultimate survival mode!")
							end
		  					for z in players.iterate
								z.pflags = $ & ~(PF_INVIS|PF_GODMODE|PF_FORCESTRAFE)
		  					end								
							G_SetCustomExitVars(SAM_map(nil), 1)
							G_ExitLevel()
						end
		  			elseif p.ssmenusubpage == 6 //NoGunShipSpawn
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else 
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
							print("\x82"+"Samus' gunship will now appear upon player spawns.")
		  						for ns in players.iterate
		  						ns.nogunshipspawn = false
		  						end
							else
							print("\x85"+"Samus' gunship will no longer spawn. To reset this action later, use the console command: \x83SPAWNGUNSHIP")
		  						for ns in players.iterate
		  						ns.nogunshipspawn = true
		  						end
							end
						end
		  			elseif p.ssmenusubpage == 7 //sam_netsaves
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
								print("\x82"+"Joining Samus players must start off with fresh or no saves!")
								SAMUSNETSAVES = false
							else
								print("\x82"+"Joining Samus players will be able to use their existing savefiles!")
		  						SAMUSNETSAVES = true
							end
						end
		  			elseif p.ssmenusubpage == 8 //Scroll-Swap
						S_StartSound(s, sfx_ssmeno)
						if not p.ssmenudrop
							p.sam_scrollswap = true
							CONS_Printf(p, "\x83"+"Scroll Swap active. Weapon Previous is Weapon Next and vice versa.")
						else
							p.sam_scrollswap = false
							CONS_Printf(p, "\x84"+"Scroll Swap de-activated.")
						end
		  			elseif p.ssmenusubpage == 9 //Tutorials
						S_StartSound(s, sfx_ssmeno)
						if not p.ssmenudrop
							CONS_Printf(p, "\x83"+"Tutorials re-activated.")
							p.nosamustutorials = false
							p.samustutorial = nil
						else
							CONS_Printf(p, "\x85"+"Tutorials de-activated.")
		  					p.nosamustutorials = true
							p.samustutorial = nil
						end
		  			elseif p.ssmenusubpage == 10 //Boss NetWeap
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
								print("\x82"+"The Ultimate Weapon is now unrestricted vs bosses.")
		  						for ns in players.iterate
									ns.hypernetgo  = true
		  						end
							else
								print("\x85"+"The Ultimate Weapon is now restricted vs bosses.")
		  						for ns in players.iterate
									ns.hypernetgo = false
		  						end
							end
						end
		  			elseif p.ssmenusubpage == 11 //Morph Ball interactions
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
								print("\x83"+"Physical Morph Ball player interactions in coop/race turned on.")
		  						for ns in players.iterate
									ns.morphcoop = false
		  						end
							else
								print("\x85"+"Physical Morph Ball player Interactions in coop/race turned off.")
		  						for ns in players.iterate
									ns.morphcoop = true
		  						end
							end
						end
		  			elseif p.ssmenusubpage == 12 //Metroid Item Skins
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
								METROIDSKINS = true
								print("\x83"+"Objects like rings, starposts, and most monitors will now spawn with Metroid skins!")
							else
								print("\x84"+"Metroid skins turned off! Objects will now spawn with their default SRB2 looks!")
		  						METROIDSKINS = false
							end
						end
		  			elseif p.ssmenusubpage == 13 //Token Style
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
								print("\x82"+"Token style switched to No-Damage challenge for Samus players.")
		  						for ns in players.iterate
									ns.tokensrb2style = 0
		  						end
							elseif p.ssmenudrop == 1
								print("\x82"+"Token style switched to No-Damage challenge for all characters.")
		  						for ns in players.iterate
									ns.tokensrb2style = 1
		  						end
							else
								print("\x85"+"Token style switched to original behaviour for Samus players.")
		  						for ns in players.iterate
									ns.tokensrb2style = 2
		  						end
							end
						end
		  			elseif p.ssmenusubpage == 14 //Coop Boxes
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						elseif not (netgame or multiplayer)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"Can only change this setting in multiplayer games.")
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
								print("\x83"+"Monitors can now only be opened once per Hunter in coop, and respawn quickly.")
		  						for ns in players.iterate
									ns.coopboxrespawn = 2
		  						end
							elseif p.ssmenudrop == 1
								print("\x82"+"Monitors now respawn in about 30 seconds without limitations in coop.")
		  						for ns in players.iterate
									ns.coopboxrespawn = 1
		  						end
							else
								print("\x85"+"Monitors now use the default SRB2 coop respawn behaviour.")
		  						for ns in players.iterate
									ns.coopboxrespawn = 0
		  						end
							end
						end
					elseif p.ssmenusubpage == 15 // World Events
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
								SAMUSCAMPAIGN = true
								print("\x83"+"World Events have been turned on. Stages may be altered to suit Samus' Campaign.")
							else
								print("\x83"+"World Events have been turned off. Stages will look and act like vanilla SRB2.")
		  						SAMUSCAMPAIGN = false
							end
						end
					elseif p.ssmenusubpage == 16 // Visor Edges
						S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
							CONS_Printf(p, "\x83"+"First person visor edges re-activated.")
		  						p.sam_visorhidden = false
							else
							CONS_Printf(p, "\x85"+"First person visor edges are now hidden.")
								p.sam_visorhidden = true
							end
					elseif p.ssmenusubpage == 17 // Lock-On. C1+C3, C3, or Off.
						S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
							CONS_Printf(p, "\x83"+"The Lock-On can be activated with Custom 1 or Custom 3.")
		  						p.sam_lockonpower = 1
							
							elseif p.ssmenudrop == 1
							CONS_Printf(p, "\x84"+"The Lock-On can be activated with Custom 3.")
		  						p.sam_lockonpower = 2
								
							else
							CONS_Printf(p, "\x87"+"The Lock-On will be inaccessible. Using the mouse to aim is recommended.")
								p.sam_lockonpower = 0
								if p.mo
								SamusTutorial(p.mo, "lockon", true)
								end
							end
					elseif p.ssmenusubpage == 18 // Toggle Lock
						S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
							CONS_Printf(p, "\x83"+"The Lock-On will stay active until you let go off the button.")
		  						p.sam_lockontoggle = false	
							else
							CONS_Printf(p, "\x84"+"The Lock-On will stay active until you tap the button again.")
								p.sam_lockontoggle = true
							end
					elseif p.ssmenusubpage == 19 // No Monitor Lock
						S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
							CONS_Printf(p, "\x82"+"Monitors can be locked onto once close enough.")
		  						p.sam_lockonnomon = false
							else
							CONS_Printf(p, "\x87"+"Monitors are no longer targets for the lock-on.")
								p.sam_lockonnomon = true
							end
					elseif p.ssmenusubpage == 20 // AutoScan
						S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
							CONS_Printf(p, "\x83"+"The scan visor activates automatically when idling. Custom1 or TossFlag activate it manually.")
		  						p.sam_noautoscan = 0
							elseif p.ssmenudrop == 1
							CONS_Printf(p, "\x84"+"The scan visor activates only on a press of Custom1 or Toss Flag.")
								p.sam_noautoscan = 1								
							else
							CONS_Printf(p, "\x87"+"The scan visor activates only on a press of Toss Flag.")
								p.sam_noautoscan = 2
							end
					elseif p.ssmenusubpage == 21 // Screen Tilt
						S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
								CONS_Printf(p, "\x83"+"Samus' cannon and view now adjust to her movement")
		  						p.sam_noscreentilt = 0
							elseif p.ssmenudrop == 1
								CONS_Printf(p, "\x84"+"The camera no longer rolls with your arm cannon movement.")
								p.sam_noscreentilt = 1								
							else
								CONS_Printf(p, "\x87"+"Neither your camera nor your arm cannon will tilt with movement.")
								p.sam_noscreentilt = 2
							end
					elseif p.ssmenusubpage == 22 --First Time Menu setup.
						S_StartSound(s, sfx_ssmeno)
						if io and (p == consoleplayer)
						local file = io.openlocal("client/MetroidVanguard/firstsetup.dat", "w+")
							file:write("RESET "+tostring(21473636))
							file:close()
							CONS_Printf(p, "\x83"+"FIRST-TIME SETUP MENU WILL NOW RETURN UPON GAME RESTART.")
						end
		  			end
				end
		  	end

		   elseif p.ssmenusub == 4 //Match and CTF settings

		  	if p.ssmenusubpage

		  		if (p.cmd.forwardmove > MTILT) and not p.ssmenuup and not (p.ssmenusubpage < 1)
					if (p.ssmenusubpage == 1)
						p.ssmenusubpage = 11
					else
						p.ssmenusubpage = $-1
					end
					S_StartSound(s, sfx_ssmenm)
					p.ssmenudrop = 0
		  		elseif (p.cmd.forwardmove < -MTILT) and not p.ssmenudown and not (p.ssmenusubpage > 11)
					if (p.ssmenusubpage == 11)
						p.ssmenusubpage = 1
					else
						p.ssmenusubpage = $+1
					end
					S_StartSound(s, sfx_ssmenm)
					p.ssmenudrop = 0
				elseif (p.cmd.buttons & BT_USE) and not p.ssmenuuse
					S_StartSound(s, sfx_ssmenb)
					p.ssmenu1 = 3
					p.ssmenusub = 1
					p.ssmenusubpage = 1
					p.ssmenudrop = 0
				elseif (p.cmd.sidemove < -MTILT) and not p.ssmenuleft and (p.ssmenudrop or ((p.ssmenusubpage == 4) or (p.ssmenusubpage == 11)))
					if p.ssmenusubpage == 4
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							if p.ssmenusubpage == 4 and (p.sam_energytanksstart >= 1)
							S_StartSound(s, sfx_ssmens)
								for ns in players.iterate
									if ns.sam_energytanksstart != nil
									ns.sam_energytanksstart = $-1
										if (ns.sam_energytanksstart < 0)
										ns.sam_energytanksstart = 0
										end
									end
								end
							end
						end
		  			elseif p.ssmenusubpage == 11 //Respawn Timer
						if not (ADMIN)
						S_StartSound(s, sfx_sdenid)
						CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							if not p.sam_respawnboxer
								p.sam_respawnboxer = 30
							end							
							if p.ssmenusubpage == 11
								if (p.sam_respawnboxer > 1)
									p.sam_respawnboxer = $-1
									S_StartSound(s, sfx_ssmens)
									for ns in players.iterate
										ns.sam_respawnboxer = p.sam_respawnboxer
									end
								end
							end
						end
					else
					S_StartSound(s, sfx_ssmens)
					p.ssmenudrop = $-1
					end
				elseif (p.cmd.sidemove > MTILT) and not p.ssmenuright
		  			if p.ssmenusubpage == 4 //Energy Tanks
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							if p.ssmenusubpage == 4 and (p.sam_energytanksstart < 12)
							S_StartSound(s, sfx_ssmens)
								for ns in players.iterate
									if ns.sam_energytanksstart != nil
									ns.sam_energytanksstart = $+1
										if (ns.sam_energytanksstart > 12)
										ns.sam_energytanksstart = 12
										end
									end
								end
							end
						end
		  			elseif p.ssmenusubpage == 11 //Respawn Timer
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							if not p.sam_respawnboxer or (p.sam_respawnboxer > 30)
								p.sam_respawnboxer = 30
							end
							if p.ssmenusubpage == 11	
								if (p.sam_respawnboxer < 30)
									S_StartSound(s, sfx_ssmens)
									p.sam_respawnboxer = $+1
									if (p.sam_respawnboxer > 30)
										p.sam_respawnboxer = 30
									end					
									for ns in players.iterate --sync up, boys.								
										ns.sam_respawnboxer = p.sam_respawnboxer
									end
								end
							end
						end
		  			elseif (p.ssmenusubpage == 3 or p.ssmenusubpage == 5 or p.ssmenusubpage == 1 or p.ssmenusubpage >= 7) and p.ssmenudrop == 0 // Beamcombo, Challenger, etc.
						S_StartSound(s, sfx_ssmens)
						p.ssmenudrop = $+1
		  			elseif (p.ssmenusubpage == 2) and p.ssmenudrop < 5 //Starting Kit options
						S_StartSound(s, sfx_ssmens)
						p.ssmenudrop = $+1
		  			elseif p.ssmenusubpage == 6 and p.ssmenudrop < 2 // Hunters allowed
						S_StartSound(s, sfx_ssmens)
						p.ssmenudrop = $+1
		  			end
				elseif (p.cmd.buttons & BT_JUMP) and not p.ssmenujump
		  			if p.ssmenusubpage == 1
						if not G_GametypeHasSpectators()
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed in battle gametypes")
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
								CONS_Printf(p, "\x82"+"Challenger mode activated! Deal 30% less damage to players. Can you still win?")
		  						if not p.samchallenger
									p.samchallenger = 1
		  						end
							else
								CONS_Printf(p, "\x85"+"Challenger mode deactivated. Any potential rewards are also withdrawn.")
								p.samchallenger = 0
							end
						end
		  			elseif p.ssmenusubpage == 2
						S_StartSound(s, sfx_ssmeno)
						if not (IsPlayerAdmin(p) or (p == server))
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							if not p.ssmenudrop
								print("\x83"+"Default starter kit set\x82 for Match/CTF gametypes. Start fresh every match!")
								for ns in players.iterate
								ns.samusmatch = 0
								end
							elseif p.ssmenudrop == 1
								print("\x86"+"Basics starter kit set\x82 for Match/CTF gametypes. Start with a reasonable arsenal.")
								for ns in players.iterate
								ns.samusmatch = 5
								end
							elseif p.ssmenudrop == 2
								print("\x84"+"Morph Ball starter kit\x82 set for Match/CTF gametypes. Start with your fully powered Morph Ball!")
								for ns in players.iterate
								ns.samusmatch = 4
								end
							elseif p.ssmenudrop == 3
								print("\x84"+"FPS Starter kits set for \x82 for Match/CTF gametypes! Start with all beams and the spacejump!")
								for ns in players.iterate
								ns.samusmatch = 9
								end
							elseif p.ssmenudrop == 4
								print("\x87"+"Starting kits removed\x82 for Match/CTF gametypes! You keep everything you collect even through stage switches.")
								for ns in players.iterate
								ns.samusmatch = 1
								end
							elseif p.ssmenudrop == 5
								print("\x86"+"Ultimate starter kit\x82 set for Match/CTF gametypes. Start with all items except Beam Combos!")
								for ns in players.iterate
								ns.samusmatch = 2
								end
							end
						end
		  			elseif p.ssmenusubpage == 3 // Beam Combo setting
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
								print("\x82"+"Beam combos can now be earned again by picking up the same beam twice.")
		  						for ns in players.iterate
									ns.sam_beamcombosrestrict = false
		  						end
							else
								print("\x85"+"Beam combos can no longer be obtained in Match/CTF gametypes.")
		  						for ns in players.iterate
									ns.sam_beamcombosrestrict = true
		  						end
							end
						end
		  			elseif p.ssmenusubpage == 5 // Double Ammo setting
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
							print("\x84"+"Ammo drain set to double. All actions require 2x the usual ammo.")
		  						for ns in players.iterate
		  						ns.samdoubleammo = true
		  						end
							elseif p.ssmenudrop
							print("\x83"+"Double ammo drain turned off. Weapons only require the usual amount of ammo to deploy.")
		  						for ns in players.iterate
		  						ns.samdoubleammo = nil
		  						end
							end
						end
		  			elseif p.ssmenusubpage == 6 // What character is allowed?
						if not (IsPlayerAdmin(p) or (p == server))
						S_StartSound(s, sfx_sdenid)
						CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
							print("\x83"+"Character setting set to CrossPlay. Any character can fight in matches.")
		  						for ns in players.iterate
		  						ns.sammatchchars = 0
		  						end
							elseif p.ssmenudrop == 1
							print("\x82"+"Character setting set to Hunters. Matches become Metroid-styled games using Samus.")
		  						for ns in players.iterate
		  						ns.sammatchchars = 1
		  						end
							elseif p.ssmenudrop >= 2
							print("\x84"+"Character setting set to Sonic characters. Any character except for Samus is allowed in Matches.")
		  						for ns in players.iterate
		  						ns.sammatchchars = 2
		  						end
							end
						end
		  			elseif p.ssmenusubpage == 7 // Monitors: SRB2 Or Samus?
						if not (ADMIN)
						S_StartSound(s, sfx_sdenid)
						CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else
							S_StartSound(s, sfx_ssmeno)
							if not p.ssmenudrop
							print("\x83"+"Monitors will now spawn in matches using Samus' algorithm for optimal balance.")
		  						for ns in players.iterate
		  						ns.sammatchmonitors = false
		  						end
							else--if p.ssmenudrop
							print("\x85"+"Monitors will now spawn in matches using SRB2's default settings.")
		  						for ns in players.iterate
		  						ns.sammatchmonitors = true
		  						end
							end
						end
		  			elseif p.ssmenusubpage == 8
						S_StartSound(s, sfx_ssmeno)
						if not p.ssmenudrop
							CONS_Printf(p, "\x83"+"Music triggered by Samus specific-events will now play for you.")
		  					p.nosammusic = false
						else--if p.ssmenudrop
							CONS_Printf(p, "\x85"+"Music triggered by Samus specific-events will no longer play for you.")
		  					p.nosammusic = true
						end
		  			elseif p.ssmenusubpage == 9 //Disable Super Missiles and Power Bombs
						S_StartSound(s, sfx_ssmeno)
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else							
							if not p.ssmenudrop
		  						for ns in players.iterate
								CONS_Printf(ns, "\x83"+"Power Bomb Tanks and Super Missile Tanks are restored to proper behaviour.")
		  						ns.nosuperpowert = false
		  						end
							else--if p.ssmenudrop
		  						for ns in players.iterate
								CONS_Printf(ns, "\x85"+"Power Bomb Tanks and Super Missile Tanks now only give normal munitions in match modes")
		  						ns.nosuperpowert = true
		  						end
							end
						end
		  			elseif p.ssmenusubpage == 10 // Turn Monitors into ammo spawns.
						S_StartSound(s, sfx_ssmeno)
						if not (ADMIN)
						S_StartSound(s, sfx_sdenid)
						CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else							
							if not p.ssmenudrop
		  						for ns in players.iterate
								CONS_Printf(ns, "\x82"+"Ammo spawns are now turned into monitors again.")
		  						ns.boxammospawns = false
		  						end
							else--if p.ssmenudrop
		  						for ns in players.iterate
								CONS_Printf(ns, "\x84"+"Monitors will now spawn as ammo instead.")
		  						ns.boxammospawns = true
		  						end
							end
						end
		  			elseif p.ssmenusubpage == 11 // Set Box respawn timer
						S_StartSound(s, sfx_ssmeno)
						if not (ADMIN)
							S_StartSound(s, sfx_sdenid)
							CONS_Printf(p, "\x85"+"This setting can only be changed by an admin.")
						else							
							if not p.ssmenudrop
		  						for ns in players.iterate
									CONS_Printf(ns, "\x82"+"Ammo spawns are now turned into monitors again.")
									ns.boxammospawns = nil
		  						end
							else--if p.ssmenudrop
		  						for ns in players.iterate
									CONS_Printf(ns, "\x84"+"Monitors will now spawn as ammo instead.")
									ns.boxammospawns = true
		  						end
							end
						end
		  			end
		  		end
		  	end


		elseif p.ssmenusub == 5 //Data Section.
		
		  	if p.ssmenusubpage
				if (p.cmd.buttons & BT_USE) and not p.ssmenuuse
					S_StartSound(s, sfx_ssmenb)
					p.ssmenu1 = 4
					p.ssmenusub = 1
					p.ssmenusubpage = 1
					p.ssmenudrop = 0	
				elseif abs(p.cmd.sidemove) > MTILT
					if (p.cmd.sidemove < -MTILT) 
						if not p.ssmenuleft 
							if (p.ssmenusubpage <= 1)
								p.ssmenusubpage = 20
							else
								p.ssmenusubpage = $-1
							end
							S_StartSound(s, sfx_ssmenm)
						end
					elseif not p.ssmenuright
						if (p.ssmenusubpage >= 20)
							p.ssmenusubpage = 1
						else
							p.ssmenusubpage = $+1
						end
						S_StartSound(s, sfx_ssmenm) 
					end
				end
		  	end

		elseif p.ssmenusub == 77 //Item Deletion Section
			if p.samitemdelete
				SAM_ItemDeleteHUD(p,sT)
			end
	end
		   
	//Keep these below the menu Lua or it'll break.
	p.ssmenuleft = (p.cmd.sidemove < -MTILT) and true or false
	p.ssmenuright = (p.cmd.sidemove > MTILT) and true or false
	p.ssmenuup = (p.cmd.forwardmove > MTILT) and true or false
	p.ssmenudown = (p.cmd.forwardmove < -MTILT) and true or false
	p.ssmenujump = (p.cmd.buttons & BT_JUMP) and true or false
	p.ssmenuuse = (p.cmd.buttons & BT_USE) and true or false
end

local function EnterGunShip(p,s)
--	SAM_CMD(p, PREVCAM, FIRSTPERSON, CAMERAdotCHASE, VISORCLOSEIN)
	SAM_CMD(p, "lol", "lol", "true", "lol")
	p.sam_shipjingle = 0
	if p.sam_hyperbeam and G_GametypeHasSpectators()
		p.sam_hyperbeam = false
		p.sam_energytanksmax = p.sam_energytanksstart
		SamResetBeam(p)
		if p.sam_hyperbeampanic 
			for z in players.iterate
				if not z.nosammusic
					SAM_COM_BufInsertText(z, "tunes -default")
				end
				z.sam_hyperbeampanic = 0
			end
		end
	end
	if YouAreSamus(s)
		p.samspbschargefull = false
		p.sam_spacejumped = false
		p.samspbscharge = 0
		p.bsblboost = 0
		p.bsblboostattack = 0
		p.sams_morphcd = 2
		p.sambsblchargefull = false
		p.sams_supermissileready = 0
		if p.sammorphed 
			p.sammorphed = false
			s.friction = 59392
			s.scale = 90000
			S_StartSound(s, sfx_morphb)
			s.flags = $ & ~MF_BOUNCE
		end	
		if (p.sam_st.scale < 95355)
			s.destscale = 32000
			S_StartSound(s, sfx_mario8)
		end
	end
	p.samentercam = true
end

local function InitialGunShip(p,s)
	p.sam_intoship = 33
	p.ssmenu1 = 1
	p.ssmenusub = 1
	p.ssmenusubpage = 1
	p.ssmenudrop = 0
	if YouAreSamus(s)
		if p.samusmusicadded
			SAM_COM_BufInsertText(p, "tunes SAMUSG")
		--	S_ChangeMusic("SAMUSG", true, p)
		else
			SAM_COM_BufInsertText(p, "tunes SAMMU1")
		--	S_ChangeMusic("SAMMU1", true, p)
		end
	end

	if (gametype == GT_COOP)
		if p.sammissiles != nil and p.sampw != nil and p.sam_hyperbeamammo != nil and p.sam_energy != nil
			if p.sammissilesmax and ((p.sammissiles < 5) or p.sam_fullypoweredsuit and (p.sammissiles < 30)) 
				p.sammissiles = (p.sam_fullypoweredsuit) and 30 or 5
			end
			if p.sampwmax and not p.sampw or (p.sam_fullypoweredsuit and p.sampw < 2)
				p.sampw = (p.sam_fullypoweredsuit) and 2 or 1
			end
			if p.samsupermissilesmax and not p.samsupermissiles or (p.sam_fullypoweredsuit and p.samsupermissiles < 5)
				p.samsupermissiles = 5
			end
			if p.sam_energy and (p.sam_energy < 50) or (p.sam_fullypoweredsuit and (p.sam_energy < 99))
				p.sam_energy = (p.sam_fullypoweredsuit) and 99 or 50
			end
			if p.sam_hyperbeam 
				if (p.sam_hyperbeamammo < 20) 
				or (p.sam_fullypoweredsuit and (p.sam_hyperbeamammo < 50))
					p.sam_hyperbeamammo = (p.sam_fullypoweredsuit) and 50 or 20
				end
			end
		end
	elseif G_GametypeHasSpectators()
		p.powers[pw_flashing] = 100
		P_PlayerEmeraldBurst(p)
		P_PlayerFlagBurst(p)
		P_PlayerWeaponAmmoBurst(p)
		S_StartSound(s, sfx_ssmenb)
		p.shipscorelose = 0
		CONS_Printf(p, "\x85You will gradually lose score for entering the ship in middle of a match.")
	end
end

local function FlagScanner(p,s)
	if (leveltime == 2)
		p.samgotbflaghud = 0
		p.samgotrflaghud = 0
	else
		if p.samgotbflaghud and (p.samgotbflaghud != 1)
			p.samgotbflaghud = $-1
		end
		if p.samgotrflaghud and (p.samgotrflaghud != 1)
			p.samgotrflaghud = $-1
		end
	end
	if P_IsFlagAtBase(MT_BLUEFLAG)
		if p.samgotbflaghud
			for z in players.iterate
				z.samgotbflaghud = 0
			end
		end
	elseif p.gotflag == 2 --Then YOU have it!
		for z in players.iterate
			z.samgotbflaghud = 4
		end
	end
	if P_IsFlagAtBase(MT_REDFLAG)
		if p.samgotrflaghud
			for z in players.iterate
				z.samgotrflaghud = 0
			end
		end
	elseif p.gotflag == 1 --You got it!
		for z in players.iterate
			z.samgotrflaghud = 4
		end
	end
end

local function ExitGunShip(p,s)
	if (p.sam_exitship <= 1)
		SamusTutorial(s, "beams")
		if SAM_FirstPerson(p, true) --Temporarily look from third person for cinematic flair!
			SAM_CMD(p, "nil", "true", "false", "15")
		else
			SAM_CMD(p, "nil", "false", "true", "15")
		end
		s.momz = -50000
		p.samentercam = false
		s.flags = $|MF_SHOOTABLE & ~(MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_BOUNCE)
		p.pflags = $ & ~(PF_INVIS|PF_FORCESTRAFE|PF_GODMODE)
		p.sam_exitship = 0
		p.accelstart = skins[s.skin].accelstart
	end
end

--Placed in here to keep the HUD hook pure and untainted.
SAM.HudPlayerThinker = function(p,s) if p.bot return end --

	--Going in or out of the gunship.
	if (p.sam_intoship or p.sam_exitship) and p.sam_st and p.sam_st.valid
		if not p.samentercam
			EnterGunShip(p,s)
		end
		if (s.crystalflashtime and s.crystalflashtime > 2)
			s.crystalflashtime = 2
		end
		if p.sam_intoship == 35
			s.state = S_PLAY_STND
			p.powers[pw_nocontrol] = 2
			p.pflags = $|PF_INVIS|PF_GODMODE|PF_FORCESTRAFE & ~(PF_JUMPED|PF_SPINNING|PF_STARTDASH|PF_STARTJUMP)
		end
		if not p.sam_exitship
			s.flags = $|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT & ~MF_SHOOTABLE
			p.accelstart = 0
		end
		P_TryMove(s, p.sam_st.x, p.sam_st.y, true)
		p.sams_usecd = 9
		p.sams_morphcd = 35
		p.sams_notyet = 3
		p.sams_jumpcd = 10
		p.sams_shotcd = 22
		s.momx,s.momy,p.sams_firecd = 0,0,0

		if p.sam_exitship
			if (s.z < p.sam_st.z+(p.sam_st.height+260355+p.sam_st.momz))
				s.momz = 2<<16+p.sam_st.momz
			elseif (p.sam_exitship > 2)
				P_TryMove (s, s.x+FixedMul(65000, cos(s.angle)), s.y+FixedMul (65000, sin (s.angle)),  true)
				p.sam_exitship = 2
				p.gltimer = 42
			end		
		else
			if (s.z > p.sam_st.z+p.sam_st.height/3)
				s.momz = -2<<16
			else
				s.flags2 = $|MF2_DONTDRAW
				s.momx,s.momy,s.momz = 0,0,0
				s.z = p.sam_st.z+p.sam_st.height/3
				if (p.sam_intoship == 35) --35 is when we've entered the ship!
					InitialGunShip(p,s)
				end
			end
			if p.sam_intoship == 33
				GunShipMenu(p,s)
			end			
		end
	elseif s.starSAM
		s.starSAM = nil
	end
	if p.sam_exitship
		p.sam_exitship = $-1
		ExitGunShip(p,s)
	end
	
	if p.samusloadconfig --Again, give the game time or it'll crash...
		if (p==server)
		or (p.jointime >= 150) --Wait for SRB2 to get it's shit together first. Console commands are difficult, man.
			p.samusloadconfig = $-1
			p.powers[pw_nocontrol] = max($,2)
			if p.sam_saveselect local SAVE = p.sam_saveselect
				SAVE.fadein = 20<<16
				SAVE.transfadebg = T90
				SAVE.transfadebuttons = T90
				SAVE.transfadebuttons2 = T90
				SAVE.begintrans = 3
				SAVE.textbgfade = T90
			end
	
			if p.samusloadconfig == 12
				ConfigSamusSave(s, p, false, true)
			elseif p.samusloadconfig == 6 and not p.samusloadconfig2
				AdminSamusSave(p, false, true)
				p.samusloadconfig2 = true
				SetSamusColor(p.mo, p)
			end	
		end
	end
	
	if YouAreSamus(s)
		DripThinker(p,s) --The YouAreSamus(s) end goes a little further down, the formatting got screwed at some point.	
		--Keep track of your last momz				
		if not P_IsObjectOnGround(s) and not (s.eflags & MFE_JUSTHITFLOOR)
			s.sam_lastmomz = s.momz --Only update off the ground, pls.
		end
		if not p.samuschosefile
			if splitscreen and p == players[1]
				p.samuschosefile = true
			elseif (gametype == GT_COOP)  --Okay, before all else...what save file?
				if modeattacking and not netgame
					SAM_COM_BufInsertText(p, "samusmatch justinbailey") --Too lazy.
					S_StopSound(s)
					p.samuschosefile = true
				else
				/*	if not netgame and not (gamemap == 812) --Record your last gamemap for the save screen
						p.sam_lastlvl = gamemap
						G_SetCustomExitVars(812, 1)	
						G_ExitLevel() */
					if (p.jointime%4==0) or not netgame --Don't spam it.
						StartSamusSaveSelect(p)
					end
				end
			end
		end
		if (gametype == GT_CTF)
			FlagScanner(p,s)
		end
	end
end

SAM.GRPcd = function(p, s)
	if not s.sam_ldclmb return end
	s.sam_ldclmb = $-1
		
	if not p.powers[pw_carry]
	and not p.sam_screwattacking
	and not (s.eflags & MFE_SPRUNG)
	and p.sam_power_grip
--	and not (p.sam_walljumping and p.sam_walljumping > 6) --Not at the same time!
--	and not p.sam_walljumpsound
		if not p.sammorphed
			if (s.sam_ldclmb > 22) --Initial hang. Wait for a little bit...	
				s.wallnopejump = 18
				p.sams_morphcd = 30
				s.momx,s.momy,s.momz = 0,0,$/8 
				p.pflags = $|PF_JUMPED|PF_STASIS 
				s.spritexscale,s.spriteyscale = FRACUNIT*10/11,FRACUNIT*10/9 //min($+1500, 69500)
				s.spriteyoffset = -10<<16
				p.aiming = 1901<<16+3
				p.samybeam = 30<<16 
			else
				s.spritexscale,s.spriteyscale = max($-2000, FRACUNIT),min($+4500, FRACUNIT)
				s.spriteyoffset = min($+5<<16, 0)
				
				if s.sam_ldclmb == 22
					p.aiming = 0
					p.sams_morphcd = 0
					s.spritexscale,s.spriteyscale = FRACUNIT,FRACUNIT
					s.spriteyoffset = 0
					p.sam_spacejumped = false --Get your Space Jump back.
					
					local ghs = P_SpawnGhostMobj(s)
					ghs.destscale = ghs.scalespeed+1
					ghs.spriteyoffset = -10<<16
					
					local force = s.sam_ldforce or 16<<16
					if (s.eflags & MFE_UNDERWATER) force = $/2 end
					
					P_SetObjectMomZ(s, force, true) --Now JUMP up!
					s.state = S_PLAY_ROLL
						
					if (p.cmd.buttons & BT_JUMP) --Leap up the edge like in Metroid Dread!
						S_StartSound(s, sfx_mswing)
						S_StartSound(s, sfx_s3k4a)
						p.samybeam = 14<<16 
						
						A_samquake(s, 50<<16, 3, 15<<16)
						P_TryMove(s, s.x+FixedMul(cos(s.angle), -30<<16), s.y+FixedMul(sin(s.angle), -30<<16), true)
						p.sam_spacejumpedboost = 12
						
						if p.sam_highjump --Your abilities matter!
							P_Thrust(s, s.angle, 12<<16)
							p.sam_highjumpcharge = 4
							p.pflags = $|PF_STARTJUMP|PF_JUMPED
							s.sam_geton = FRACUNIT
							S_StartSound(s, sfx_samllp)
						else
							P_Thrust(s, s.angle, 4<<16)
							s.momz = $*5/8
							p.pflags = $|PF_STARTJUMP|PF_JUMPED
							s.sam_geton = FRACUNIT
						end
					else --Climb normally.
						s.sam_geton = 13
						p.powers[pw_nocontrol] = max($,2)
					end

				elseif s.sam_ldclmb == 19 --Big speed boost.
				and (s.sam_geton and s.sam_geton > 40000) and s.sam_ldspeed != nil
				
					if s.sam_ldspeed > 70<<16
						P_Thrust(s, s.angle, 58<<16)
						p.samspbscharge = 140
						p.samspbschargefull = false
						A_samquake(s, 70<<16, 5, 200<<16)
					else
						P_Thrust(s, s.angle, (s.sam_ldspeed)*10/15)						
					end
				end
			end
		end
				
		if s.sam_geton
			if (s.sam_geton < 14)		
				s.flags2 = $ & ~MF2_DONTDRAW
				if not p.sammorphed and (p.cmd.buttons & BT_SPIN)
					SamMorphSwitch(p, s)
					S_StartSound(s, sfx_smorph)
				end
				s.momz = -9*P_MobjFlip(s)
				p.aiming = 0
				p.powers[pw_nocontrol] = max($,2)
				
				local ANG = s.angle
				if s.sam_ledgeupangle != nil
					ANG = s.sam_ledgeupangle
				end	
				s.angle = ANG
				p.drawangle = ANG
				S_StopSoundByID(s, sfx_sjmp)
				S_StopSoundByID(s, sfx_swljp)
				
				if (s.sam_geton < 12) 
					P_TryMove(s, s.x+FixedMul(cos(ANG), 4<<16), s.y+FixedMul(sin(ANG), 4<<16), true)
				end
				
				if not P_IsObjectOnGround(s)
					if (s.eflags & MFE_VERTICALFLIP)
						if (s.ceilingz < (s.z+101<<16))
							s.z = s.ceilingz
							if (s.sam_geton < 7) 
								s.state = S_PLAY_WALK
								s.sam_geton = 0
							end
						else
							s.z = $-7<<16
						end		
					else
						if (s.floorz > (s.z-71<<16))
							s.z = s.floorz
							if (s.sam_geton < 7) 
								s.state = S_PLAY_WALK
								s.sam_geton = 0
							end
						else
							s.z = $+7<<16
						end
					end
				end
				if P_IsObjectOnGround(s) and (s.sam_geton < 7)
					if not p.sammorphed
						s.state = S_PLAY_WALK
					end
					s.sam_geton = 0
				elseif s.state != S_PLAY_ROLL and not p.sammorphed
					s.state = S_PLAY_ROLL
				end
				if p.sammorphed and not s.sam_geton
					if p.sam_direct > 30 
						P_Thrust(s, p.drawangle, 15<<16)
					end				
					if p.sambsbl 
						if (p.cmd.buttons & BT_CUSTOM1) 
							p.sams_c1cd = 500
							p.sambsblchargefull = true
						else
							local FIREBUTTON = (p.swapfire) and BT_FIRENORMAL or BT_ATTACK
							if (p.cmd.buttons & FIREBUTTON)
								p.sams_firecd = 500
								p.sambsblchargefull = true
							end
						end
					end
				end		
				
			else
			
				if s.anim_duration > 1 s.anim_duration = 1 end
				if s.tics > 1 s.tics = 1 end
				
				if s.sam_ldclmb == 17
					s.state = S_PLAY_SPRING
					if (s.momz*P_MobjFlip(s) > 0) and s.sam_geton and (s.sam_geton < 14)
						s.momz = $/4
					end
				end
				
				--wind effects
				if (s.momz*P_MobjFlip(s) > 7*s.scale)
				
					for d = -1,1,2
						local ghs = P_SpawnMobjFromMobj(s, 
						FixedMul(30<<16+abs(s.momx), cos(s.angle+(ANG1*64*d))),   
						FixedMul(30<<16+abs(s.momy), sin(s.angle+(ANG1*64*d))), 
						0, MT_SAMWINDLINE)
						ghs.scale = 42000
						if leveltime % 2 == 0
							P_SetObjectMomZ(ghs, 40*ghs.scale)
							ghs.flags2 = $|MF2_SHADOW
							ghs.momx,ghs.momy = s.momx*3,s.momy*3
							ghs.momz = $+(s.momz*4)
							ghs.fuse = 9
						else
							ghs.momx,ghs.momy,ghs.momz = s.momx*2,s.momy*2,s.momz*2
							P_SetObjectMomZ(ghs, 50*ghs.scale)
							ghs.momz = $+(s.momz*3)
							ghs.fuse = 12
						end
						ghs.rollangle = ANGLE_90
						ghs.blendmode = AST_ADD
						ghs.destscale = $*99
						if (p != displayplayer) or (CV_FindVar("chasecam").value == 1)	
							ghs.flags2 = $|MF2_DONTDRAW
						end
					end
					
					local rng = P_RandomRange(-80,80)
					local ghs = P_SpawnMobjFromMobj(s,
					rng<<16,
					P_RandomRange(-80,80)<<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 = s.momx ghs.momy = s.momy
					else
						ghs.momx = s.momx/2 ghs.momy = 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
					ghs.momx,ghs.momy = $+s.momx/2,$+s.momy/2
				end
				
				if (p.speed < 36<<16)
				and (p.sam_direct > 2)
					P_Thrust(s, p.sam_turnang, (76000/50)*p.sam_direct)
				end
			end						
		end
	else
		s.sam_ldclmb = 0
		s.sam_geton = 0
	end
	if not s.sam_ldclmb
		s.spritexscale,s.spriteyscale = FRACUNIT,FRACUNIT
		s.spriteyoffset = 0
		s.sam_geton = 0
		if p.aiming == 1901<<16+3
			p.aiming = 0
		end
		s.sam_ldspeed = 8<<16
		s.sam_ldforce = 16<<16
		if s.state == S_PLAY_RIDE and not p.powers[pw_carry]
		and not p.sammorphed and not p.sam_screwattacking
			s.state = S_PLAY_SPRING
		end					
	end
end