--New functions that use the MetroidVanguard table, aimed towards Beam Combos, Match mode, and the Arm Cannon HUD.
local SAM = MetroidVanguard
local HOST = MetroidVanguard.HOST

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.TopPlayer = function(p)
	local TOPPLAYER,TOPSCORE
	for z in players.iterate
		if z 
			if TOPPLAYER == nil
			or (z.score > TOPSCORE)
				TOPSCORE = z.score
				TOPPLAYER = z
			end
		end
	end return TOPPLAYER,TOPSCORE --
end

SAM.ArenaModes = function(p,s)
	local SCORE = p.score or 0
	local PREVSCORE = p.prevsamscore or 0	
	if (leveltime > 3)		
		if p.plushudscoretime
			p.plushudscoretime = $-1 local HSCORE = p.plushudscoretime
			p.plushudscoreflags = //AmperBee will kill me for this... --Update: HA! Take that! From an "elseif" chain to an "or" chain!
			(HSCORE>17) and FF_TRANS40 or
			(HSCORE>14) and FF_TRANS10 or
			(HSCORE>12) and FF_TRANS30 or
			(HSCORE>8) and FF_TRANS50 or
			(HSCORE>5) and FF_TRANS70 or FF_TRANS80
		end
		if PREVSCORE < SCORE
			p.plushudscore,p.plushudscoretime = SCORE-PREVSCORE, 19
			p.plushudscoreflags = FF_TRANS30
		end		
		p.prevsamscore = SCORE
	end		
	if p.powers[pw_flashing] and s.valid
		if s.sam_lastflashing and (s.sam_lastflashing == p.powers[pw_flashing])
			s.sam_lastflashtotal = s.sam_lastflashtotal and $+1 or 1
		else
			s.sam_lastflashtotal = 1
		end
		s.sam_lastflashing = p.powers[pw_flashing]
		
		if (s.sam_lastflashtotal > 150) and p.powers[pw_flashing] 
		and (s.sam_lastflashing == p.powers[pw_flashing])
			p.powers[pw_flashing] = 0 
			s.sam_lastflashtotal = 1
		end
	end
	
	if p.cooptanks and not p.matchtanks
	or (p.cooptanks == nil and p.matchtanks == nil)
		if p.sam_energytanksstart!=nil
			p.sam_energytanksmax = p.sam_energytanksstart
		else
			p.sam_energytanksmax = 2
		end
		p.sam_energytanks = p.sam_energytanksmax
		p.sam_energy = 99+(p.sam_energytanksmax*50)
		p.cooptanks = false
		p.matchtanks = true
		p.match2tanks = (p.samusmatch == 2) and true or false
	end
	if YouAreSamus(s)
		if p.samchallenger --Challenger status?
			if p.samqchallenger and not p.sam_hyperbeam
				p.samqchallenger = nil
				p.samchallenger = 2
				S_StartSound(nil, sfx_kc59, p)
				CONS_Printf(p, "\x87"+"Your commendation rank has been set back to rank 1!")
			end
			p.samcmult = 11
			
			local LVL = p.samchallenger
			s.sammedal = P_SpawnMobj(s.x, s.y, s.z + (s.height+22<<16)*P_MobjFlip(s), MT_THOK)
			local ghs = s.sammedal
			ghs.sprite = SPR_PWBM
			ghs.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
			ghs.tics = 2
			ghs.momx,ghs.momy,ghs.momz = s.momx,s.momy,s.momz				
			ghs.frame = (LVL==1 and B|FF_TRANS50 or LVL==2 and C|FF_TRANS20 or LVL==3 and D|FF_TRANS30 or E|FF_TRANS10)
			ghs.scale = (LVL==1 and 79000 or LVL==2 and 80350 or LVL==3 and 2<<16 or 165000)
		end	
		if leveltime == 3150 and not p.sam_powerbeamcombo and (gametyperules & GTR_RINGSLINGER) 
			S_StartSound(s, sfx_bcrs)
			S_StartSound(nil, sfx_bcrs, p)
		end
		if p.sammatchchars == 2	--Restricted!
			if not p.sams_morphcd
				CONS_Printf(p, "\x85"+"The server has set the battle restriction to Sonic chars only. Switch to any other character to play!")
			end
	
			p.powers[pw_nocontrol] = 3
			p.sams_supermissileready = 0
			p.sams_shotcd,p.sams_mshotcd = 3,3
			p.sams_morphcd = 35
			
		elseif p.powers[pw_emeralds] and not s.samemwarning
		
			s.samemeralds = 0
			local GEMS,GFLAG = p.powers[pw_emeralds], 1
			for i = 1,7
				if (GEMS & GFLAG) s.samemeralds = $+1 end
				GFLAG = $*2
			end
			if (s.samemeralds > 4)	
				s.samemwarning = 700
				S_StartSound(nil, sfx_ding)
				print("\x87"+p.name+" is collecting emeralds. Be careful.")
				for ns in players.iterate			
					ns.samhudmessagetime = 230
					ns.samhudmessage1 = "\x80"+p.name+"\x87 is collecting emeralds."
					ns.samhudmessage2 = "Be careful!"
				end
			end
		end
		if not p.sam_chargebeam --That's not right, you should always have this in match....
			p.sam_chargebeam = true
			if not p.samchallenger
				p.sam_power_grip = true
			end
			if p.samusmatch==2 --Give ALL powerups! ...would I call this method better? ....prolly not.
				local CRS = (not p.sam_beamcombosrestrict) and true or false 
				
				p.samspbs,p.sambsbl,p.sam_spiderball,p.sam_gravitysuit,p.sam_highjump,p.sam_bombs,p.sam_spacejump =
				true,true,true,2,true,true,true,true
				
				p.sam_spazerbeam,p.sam_wavebeam,p.sam_icebeam,p.sam_plasmabeam,p.sam_screwattack,p.sam_power_grip =
				true,true,true,true,true,true
				
				p.sam_powerbeamcombo,p.sam_spazerbeamcombo,p.sam_wavebeamcombo,p.sam_icebeamcombo,p.sam_plasmabeamcombo =
				CRS,CRS,CRS,CRS,CRS
				
				p.sam_hyperbeam,p.sam_fullypoweredsuit,p.sammissilesmax,p.sammissiles,p.sampw,p.sampwmax,p.sampw,
				p.samsupermissilesmax,p.samsupermissiles =
				false,false,15,10,0,1,0,2,0
			end
		end
	else --if NOT Samus!
		if p.samchallenger
			p.samchallenger = 0
			S_StartSound(nil, sfx_kc59, p)
			CONS_Printf(p, "\x85"+"Turned off challenger mode!")
			if p.samcmult == 11 p.samcmult = 8 end	
		end
	end
	
	--My inefficient way of calculating who's on top in a Match.
	--Basically, if you're over 750 points behind, you get a buff to help you catch up!
	--An increase in ammo/energy recovery, slightly increased damage, better odds at rare items,
	--and a 1 in 30 chance to use the Crystal Flash upon death! So never give up, the odds are rigged in your favor! 
	--You can tell when you have this buff by the lights on the top of your visor.
	--This feature should help counteract bad RNG, crappy player skill, and late joins a little.
	
	if not (HOST and HOST.valid)
		HOST = (SAM.PickHost(0))
	end
	if HOST and HOST.valid
		if leveltime == 2
			HOST.sam_topscore = 0
			HOST.sam_topscoreman = nil
			SetSamusColor(s, p)
			SAM.UpdateScoreBracket(HOST, true)	
		elseif (leveltime%30==0) or leveltime == 10498 or leveltime == 20998 or HOST.sam_topscoreman == nil
			SAM.UpdateScoreBracket(HOST)
		end
		local TOPSCORE = (HOST.sam_topscore) or 0
		local SCORE = (p.score) or 0
		
		--Get a buff from RNGjesus if you're far behind!
		p.buffbottomtier = ((SCORE<TOPSCORE-750) and not (gametype == GT_CTF)) and true or false	
		if p.buffbottomtier
			if not p.samchallenger
				p.samcmult = 6
			end
		elseif p.samcmult == 6
			p.samcmult = 8
		end
	end
	if (leveltime==0) and p.samhudmessagetime and p.samhudmessagetime < 229
		p.samhudmessagetime = 0	
		p.samhudmessageget = nil	
	elseif not p.samhudmessageget and not p.samhudmessagetime 
	and not (gametype == GT_TAG) and not (gametype == GT_HIDEANDSEEK) and not (gametype == GT_RACE)	
	
		local HUDmsg,TEXT1,TEXT2
		for i = 1,9
			HUDmsg=P_RandomRange(1,41) if (p.lastsamhmrng!=HUDmsg) break end --	
		end
		
		if not p.lastsamhmrng == HUDmsg 	
			if YouAreSamus(s) 
				if HUDmsg==1
					if (gametype == GT_CTF) 
						TEXT1 = "Use charge shots and mighty blasts"
						TEXT2 = "to make players drop their flag!"
					else
						TEXT1 = "Missiles are more potent than your beams,"
						TEXT2 = "but they are also useful for beam combos!"
					end
				elseif HUDmsg==2
					if (gametype == GT_CTF) 
						TEXT1 = "You can't use movement upgrades"
						TEXT2 = "holding a flag! Stand your ground!"
					else
						TEXT1 = "Only charge shots and other powerful"
						TEXT2 = "attacks make players drop emeralds."
					end					
				elseif HUDmsg==3 
					TEXT1 = "Many shots are explosive! Use nearby"
					TEXT2 = "walls and floors against your enemies!"
				elseif HUDmsg==4 
					TEXT1 = "If someone gets the Hyper Beam, attack"
					TEXT2 = "them immediately to limit their ammo!"
				elseif HUDmsg==5 
					TEXT1 = "Shinesparks annihilate players, but actually"
					TEXT2 = "landing a hit takes serious precision."
				elseif HUDmsg==6 
					TEXT1 = "Charge your beam and morph to drop 8"
					TEXT2 = "bombs around you! Devastating up-close."
				elseif HUDmsg==7 
					TEXT1 = "Weapon Panels and ammo restore"
					TEXT2 = "your missile count. Stock up!"
				elseif HUDmsg==8 
					TEXT1 = "1 powerbomb can change the game."
					TEXT2 = "Be wary around morphed players." 
				elseif HUDmsg==9 
					TEXT1 = "Players that flash or glow are ready to"
					TEXT2 = "unleash devastating attacks. Watch out." 
				elseif HUDmsg==10 
					TEXT1 = "Morph during a Wave Combo to become the"
					TEXT2 = "Death Ball, obliterating all by mere touch." 
				elseif HUDmsg==11 
					TEXT1 = "Samus gains score from damage dealt."
					TEXT2 = "More powerful attacks = more score!" 
				elseif HUDmsg==12 
					TEXT1 = "Samus gains score from damage, but kills"
					TEXT2 = "gain you 50 points extra on top!"
				elseif HUDmsg==13 
					TEXT1 = "Fire the Ice Beam Combo into the"
					TEXT2 = "the sky to make it hail ice bombs!"
				elseif HUDmsg==14 
					TEXT1 = "Hit a charged Spazer Beam at point-blank"
					TEXT2 = "range to send foes flying far away!"
				elseif HUDmsg==15 
					TEXT1 = "The Plasma&Wave combo can be"
					TEXT2 = "canceled at any time with FIRE."
				elseif HUDmsg==16 
					TEXT1 = "The Wave Combo lets you fire up"
					TEXT2 = "to 4 charged wave shots at any time!"
				elseif HUDmsg==17 
					TEXT1 = "Try to memorize a stage's layout"
					TEXT2 = "to take advantage of monitor hotspots!"
				elseif HUDmsg==18 
					TEXT1 = "The Plasma Charge Shot can snake"
					TEXT2 = "across floors when shot from above!"
				elseif HUDmsg==19 
					TEXT1 = "Alternate Ice shots with Missiles"
					TEXT2 = "for unmatched explosive damage!"
				elseif HUDmsg==20 
					TEXT1 = "Super Missiles knock foes back with huge"
					TEXT2 = "explosions. Use them to snatch monitors!"
				elseif HUDmsg==21 
					TEXT1 = "Need to run? Use Super Missiles or "
					TEXT2 = "Morph Ball bombs to keep foes away!"
				elseif HUDmsg==22 
					TEXT1 = "Reflect projectiles with the invincible"
					TEXT2 = "Screw Attack! Ignore even Power Bombs!"
				elseif HUDmsg==23 
					TEXT1 = "Direct Screw Attack hits are deadly,"
					TEXT2 = "but the move leaves you wide open."
				elseif HUDmsg==24 
					TEXT1 = "If you run out of Hyperbeam ammo,"
					TEXT2 = "you'll sacrifice energy to keep firing!"
				elseif HUDmsg==25 
					TEXT1 = "Your default Power Beam is weak, but"
					TEXT2 = "foes killed by it drop extra health!"
				elseif HUDmsg==26 
					TEXT1 = "While charging any beam, ammo"
					TEXT2 = "and health pickups magnetize toward you!"
				elseif HUDmsg==27 
					TEXT1 = "Walljumps can get you to high-up"
					TEXT2 = "monitors earlier and escape from attacks!"
				elseif HUDmsg==28 
					TEXT1 = "Just too good? Enable challenger mode"
					TEXT2 = "in the ship and win to gain rewards!"
				elseif HUDmsg==29 and (p == server or (IsPlayerAdmin(p)) )
					TEXT1 = "Want to switch things up? Go into"
					TEXT2 = "the ship for specific match options!"
				elseif HUDmsg==30 and not (SAM.HUNTERS(s))
					if (p == server) or (IsPlayerAdmin(p))
						TEXT1 = "Samus supports Match as a novelty."
						TEXT2 = "Try HUNTERS for the proper balance!"
					end
				elseif HUDmsg==30
					TEXT1 = "When you fall far behind in points,"
					TEXT2 = "you gain many perks. Never give up!"				
				elseif HUDmsg==31
					TEXT1 = "Fire explosives mid-jump to increase"
					TEXT2 = "evasion AND accuracy at the same time!"
				elseif HUDmsg==32
					TEXT1 = "Use the speedbooster often to keep"
					TEXT2 = "up with foes and reach monitors first!"
				elseif HUDmsg==33
					TEXT1 = "Getting hit by most attacks won't give"
					TEXT2 = "temporary invincibility. Keep moving!"
				elseif HUDmsg==34
					TEXT1 = "Charge shots are slower, but easier"
					TEXT2 = "to land and grant more points+damage!"
				elseif HUDmsg==35
					TEXT1 = "The Boost Ball is particularly useful"
					TEXT2 = "around springs and when underwater."
				elseif HUDmsg==36
					TEXT1 = "The Gravity Suit's features shine"
					TEXT2 = "especially in lava or water stages!"
				elseif HUDmsg==37
					TEXT1 = "Killing players resets their energy"
					TEXT2 = "tanks and drops you health or ammo!"
				elseif HUDmsg==38
					TEXT1 = "You'll lose the Hyperbeam if you"
					TEXT2 = "die. Use it's devastating shots wisely."
				elseif HUDmsg==39
					TEXT1 = "Run if you see the Crystal Flash!"
					TEXT2 = "They'll recover too fast to take down."
				elseif HUDmsg==40
					TEXT1 = "Don't flee from the Hyper Beam, chase"
					TEXT2 = "them down before them get more ammo!"
				elseif HUDmsg==41
					TEXT1 = "You can always scan and charge"
					TEXT2 = "beams in Matches! Use them lots!"
				else
					TEXT1 = "Powering up is crucial to victory!"
					TEXT2 = "Hunt monitors to gain a massive edge."
				end						

			else --Messages to aid non-Samus players!
				local HUDsonic = HUDmsg/6
				if HUDsonic==1
					TEXT1 = "Samus players always drop rings"
					TEXT2 = "and weapons when hit! Be aggressive!"
				elseif HUDsonic==2
					TEXT1 = "Only Samus' stronger blasts flinch"
					TEXT2 = "you. Pierce the small shots fearlessly!"
				elseif HUDsonic==4
					TEXT1 = "Samus is weak before powered up."
					TEXT2 = "Take her down as early as possible!"
				elseif HUDsonic==5
					TEXT1 = "Stay away from floors and walls to"
					TEXT2 = "minimize Samus' chance of hitting you!"
				elseif HUDsonic==6
					TEXT1 = "The auto ring deals constant damage"
					TEXT2 = "to Samus. Use it well for crazy points!"
				elseif HUDsonic==7
					TEXT1 = "Samus will beeline for strong powerups."
					TEXT2 = "Predict her movements for easy hits!"
				else
					TEXT1 = "The scatter ring deals more damage"
					TEXT2 = "to Samus the more shots land."
				end
			end
			p.samhudmessagetime = 230	
		end
		if p.samhudmessagetime
			if TEXT1 and TEXT2
				p.samhudmessage1,p.samhudmessage2 = TEXT1,TEXT2
			end		
			p.samhudmessageget = true
			p.lastsamhmrng = HUDmsg
		end
	end	
	if (p.spectator)
		if ((p.sam_energytanksstart != nil) and (p.sam_energytanksstart > p.sam_energytanksmax))
			p.sam_energytanksmax = p.sam_energytanksstart
			p.sam_energytanks = p.sam_energytanksmax
			local MAXENERGY = p.sam_energytanksmax*50 --Max energy doesn't account for the first 99 energy!
			if (leveltime < 350) and not (p.sam_energytanksmax < 2)
				p.sam_energy = MAXENERGY-1 --Start with an extra bar of energy that's yet to be filled!
			else
				p.sam_energy = 99+MAXENERGY --You joined late? Get FULL energy!
			end
			p.sam_chargebeam = true
		end
	end
end

--The Gattling Vortex Combo!
SAM.PlasmaCombo = function(p,s)
	local FIREBUTTON = (p.swapfire) and BT_FIRENORMAL or BT_ATTACK
	local NORMALFIRE = (p.swapfire) and BT_ATTACK or BT_FIRENORMAL
	local GATTLETIME = (s.gattlingtime or 0)+1
	local AMMO = (p.sammissiles) or 0 
	
	s.gattlingtime = GATTLETIME --How long we've been doing this for.
	if s.holdgattle and not (p.cmd.buttons & FIREBUTTON) --Stop players accidentally insta-deactivating the combo by still holding FIRE
		s.holdgattle = nil
	end
	
	--Cancel conditions.
	if p.sammorphed
	or (p.cmd.buttons & FIREBUTTON) and not s.holdgattle
	or (GATTLETIME > 35) and (AMMO < p.samadrain) --Out of ammo!
	or p.sam_beamswitch
--	or p.sam_shinesparkfly
	or not YouAreSamus(s)
	or not s.health
	or p.exiting
	or (p.powers[pw_carry] == CR_ZOOMTUBE)
	or (p.powers[pw_carry] == CR_NIGHTSMODE)
		P_SamFP(p, PAL_NUKE, 3)
		S_StartSound(s, sfx_fizzle)
		p.sam_plasmabeammeltdown = min(1750, max(175, GATTLETIME*5)) --The longer you've been shooting, the longer the meltdown!
		s.gattlingvortex = 0
		s.gattlingtime = 0
	else
		if not s.gattlingvortex or (s.gattlingvortex > 24) --At 25 or higher, reset and give players your position!
			s.gattlingvortex = 1
			if G_GametypeHasSpectators()
				for z in players.iterate
					if z.mo and z.mo.health --Show where it's coming from.
					and not (z.mo == s)
						z.mo.sam_combowarn = 26
						z.mo.sam_combowarntarget = s
						z.mo.sam_combowarnang = R_PointToAngle2(z.mo.x, z.mo.y, s.x, s.y)
					end
				end
			end
		end
		if (s.gattlingvortex%4==0)
			if not (p.panim == PA_PAIN and p.powers[pw_flashing])
				if not p.sam_screwattacking and not p.sam_shinesparkfly --Unless you're in these animations, FIIIRE!
					S_StartSound(s, sfx_plcm)
					p.samxbeam = p.samxbeam+125355
					SamusBeamFire(s, MT_PLSHOT, nil, s.gattlingvortex)
					if p.sams_beamanim
						p.sams_beamanim = 10
					end
				end
				if (s.gattlingvortex%8==0) and not (GATTLETIME < 32) --Missile drain.
					if not p.sam_screwattacking and not p.sam_shinesparkfly
					or (s.gattlingvortex%20==0)
						s.MissileAmmoDrain = 3
						p.sammissiles = max(AMMO-1*p.samadrain, 0)
					end
				end
			end
		end
		p.sams_shotcd,p.sams_mshotcd = 3,3
		s.gattlingvortex = s.gattlingvortex and $+1 or 1	
		if P_IsObjectOnGround(s) and (p.speed < s.scale/3)
			s.state = S_SAMUFIRE
			s.frame = ($ & ~FF_FRAMEMASK)|((sam_gravitysuit) and F or A)
		end	
	end
end

--Wave Buffer Combo! ...but also the Death Ball!
SAM.WaveBeamCombo = function(p,s)
	local ANG = (s.wavebufferang) or 0
	local BUFFER = (s.wavebuffering) or 0
	local ghs
	if BUFFER
		s.wavebuffering,BUFFER = BUFFER+1, $+1
		s.wavebufferang = ANG+(14*ANG1)		
		if (BUFFER%2==0)
			S_StartSound(s, sfx_cmol)
			if BUFFER==2
				p.waveguard1 = P_SpawnMobjFromMobj(s,0,0,s.height/2, MT_WVCHARGESHOT)
				p.waveguard2 = P_SpawnMobjFromMobj(s,0,0,s.height/2, MT_WVCHARGESHOT)
				p.waveguard3 = P_SpawnMobjFromMobj(s,0,0,s.height/2, MT_WVCHARGESHOT)
				p.waveguard4 = P_SpawnMobjFromMobj(s,0,0,s.height/2, MT_WVCHARGESHOT)
				for i = 1,4
					ghs = i==1 and p.waveguard1 or i==2 and p.waveguard2 or i==3 and p.waveguard3 or p.waveguard4
					if ghs and ghs.valid
						ghs.target,ghs.flags2,ghs.bufferguard = s, s.flags2, true
					end
				end
			elseif (gametype != GT_COOP) and (BUFFER%8==0)
				for z in players.iterate
					if z.mo and z.mo.sam_scanpowerup
					and not z.mo.wavebuffering
						if not (z.sam_hyperbeampanic and not z.sam_hyperbeam) --Don't stop players from finding the Hyper Beam wielder, tho'
							z.mo.sam_scanpowerup = 0
							z.scannedmons,z.scannedplays = nil,nil
							S_StartSound(z.mo, sfx_dmpain)
							S_StartSound(z.mo, sfx_cmol)
							z.mo.sam_wavestunned = 90
							z.mo.sam_scanning = 0
							z.mo.waittoscan = 0
							z.mo.samusjustscanned = true
							S_StopSoundByID(z.mo, sfx_sscan1)
							P_SamFP(z, PAL_NUKE, 4)
							z.mo.samusmission = nil
							SamusMission(z.mo, "WARNING!! SCAN SENSORS JAMMED!", nil, nil, 1, 0, false)
						end
					end
				end
			end	
		end
	end


	if p.sammorphed
		SAM.DeathBallAbility(p,s) 
	else--if BUFFER
		p.sams_shotcd,p.sams_mshotcd = 3,3
		P_SpawnPlayerMissile(s, MT_SAMMONBREAKER)
		s.sam_deathball = false
		for i = 1,4 --Make them visible again!
			ghs = i==1 and p.waveguard1 or i==2 and p.waveguard2 or i==3 and p.waveguard3 or p.waveguard4
			if ghs and ghs.valid
				ghs.flags = $ & ~MF_NOCLIP 
				ghs.flags2 = $ & ~MF2_DONTDRAW 
			end
		end
	end
	
	local FIREBUTTON = (p.swapfire) and BT_FIRENORMAL or BT_ATTACK
	local NORMALFIRE = (p.swapfire) and BT_ATTACK or BT_FIRENORMAL
	local C2 = (p.sams_c2cd) or 0
	local NF = (p.sams_normfcd) or 0
	BUFFER = s.wavebuffering
	
  	if BUFFER
		for i = 1,4 --Move them to the right spot!
			ghs = i==1 and p.waveguard1 or i==2 and p.waveguard2 or i==3 and p.waveguard3 or p.waveguard4
			if ghs and ghs.valid
				P_MoveOrigin(ghs, 
				s.x+s.momx + FixedMul(120<<16, cos(ANG+(ANGLE_90*i)) ), 
				s.y+s.momy + FixedMul(120<<16, sin(ANG+(ANGLE_90*i)) ), 
				s.z+s.momz + s.height/2)
			end
		end
		if (p.cmd.buttons & BT_CUSTOM2) and not p.c1c2disable and not (C2>1)
		or (p.cmd.buttons & NORMALFIRE) and not (NF>1)
			if not p.sammorphed
				for i = 1,4
					ghs = i==1 and p.waveguard1 or i==2 and p.waveguard2 or i==3 and p.waveguard3 or p.waveguard4
					if ghs and ghs.valid
						ghs.fuse = 1 ghs.state = S_NULL
						SamusBeamFire(s, MT_WVCHARGESHOT)
						S_StartSoundAtVolume(s, sfx_wvchsh, 125)
						S_StartSound(s, sfx_wvchsh)
						if p.plshot
							p.plshot.scale = $*4/3
							p.plshot.color = SKINCOLOR_MAGENTA
						end 
						if i==4 --You lost your last one, end the combo!
							s.sam_deathball = false
							s.wavebuffering = 0
							p.sam_wavebeammeltdown = 700
						end break --
					end
				end
			end
		end
	end
	BUFFER = s.wavebuffering
	
	--Check again, 'cause it could've stopped.
	if BUFFER
		if (p.cmd.buttons & FIREBUTTON) and p.sams_firecd and (p.sams_firecd < 3) and not p.sammorphed
		or p.sammorphed and ( (p.cmd.buttons & NORMALFIRE) or (p.cmd.buttons & BT_CUSTOM2) and not p.c1c2disable )
		or (BUFFER > 580)
		or p.sam_wavebeammeltdown
		or not YouAreSamus(s)
		or (p.waveguard1 == nil and not p.waveguard2 and not p.waveguard3 and not p.waveguard4)
			if s.sam_deathball and p.sam_shinesparkfly --Now THAT's an impact!
				ghs = P_SpawnMobj(s.x, s.y, s.z, MT_SAMSUPERMISSILE)					
				if ghs and ghs.valid and ghs.health	
					ghs.target = s
					ghs.scale = 2<<16
					P_ExplodeMissile(ghs)
				end
			end
			s.wavebuffering = 0
			P_SamFP(p, PAL_MIXUP, 3)
			S_StartSound(s, sfx_wvcm2) S_StartSound(s, sfx_wvcm2)
			p.sam_wavebeammeltdown = 1050
			
			for i = 1,4 --Remove any of your Wave Guards that remain
				ghs = i==1 and p.waveguard1 or i==2 and p.waveguard2 or i==3 and p.waveguard3 or p.waveguard4
				if ghs and ghs.valid
					ghs.flags = $ & ~MF_NOCLIP 
					ghs.flags2 = $ & ~MF2_DONTDRAW 
					ghs.bufferguard = false
					ghs.momz = 0
					P_Thrust(ghs, R_PointToAngle2(ghs.x, ghs.y, s.x, s.y), -60*s.scale)
				end
			end
			return false --
	   	end
	end
end

--Metroid Prime 2 Echoes Multiplayer veterans anywhere?
SAM.DeathBallAbility = function(p,s)
	local ghs
	if not s.sam_deathball
		ghs = P_SpawnMobj(s.x, s.y, s.z+s.height, MT_SAMUSTHOK)
		ghs.height = 40<<16
		ghs.eflags = s.eflags
		ghs.target = s
		ghs.sprite = SPR_MPR9
		ghs.frame = 26|FF_FULLBRIGHT|FF_TRANS10
		ghs.scale = 160000
		ghs.deathbolt = true
		if G_GametypeHasSpectators()
			S_StartSound(nil, sfx_litng4)
			S_StartSound(nil, sfx_litng2)
			S_StartSound(nil, sfx_wvcm2)
		else
			S_StartSound(s, sfx_litng4)
			S_StartSound(s, sfx_litng2)
			S_StartSound(s, sfx_wvcm2)
		end
	end
	A_samquake(s, min(80<<16, p.speed/15), 1, min(5555<<16, FixedInt(p.speed*40)), true)
	P_SpawnGhostMobj(s)
	P_SpawnPlayerMissile(s, MT_SAMMONBREAKER)
	s.sam_deathball = true
	if (s.eflags & MFE_JUSTHITFLOOR)
		S_StartSound(s, sfx_wvbc)
		for d = 1,((p.speed>>16)/5)
			local t = P_SpawnMobj(s.x, s.y, s.z+s.height/2, MT_MINECARTSPARK)
			t.scale = s.scale/15
			t.fuse = 18
			P_InstaThrust(t, P_RandomRange(1,359)*ANG1, P_RandomRange(12,24)<<16)
			t.momz = P_RandomRange(2,7)<<16
			if SAM_displayplayer(p)
				t.flags2 = $|MF2_DONTDRAW --Save performance
			end	
		end	
	end
	if (leveltime % 4 == 0)
		S_StartSound(s, sfx_cmol)
		ghs = P_SpawnMobj(s.x, s.y, s.z+((s.eflags & MFE_VERTICALFLIP) and s.height or s.height/10), MT_SAMUSZAP)
	  	ghs.scale = s.scale
		ghs.blendmode = AST_ADD
	  	ghs.momx,ghs.momy,ghs.momz = s.momx,s.momy,s.momz
	 	ghs.eflags = s.eflags
	  	ghs.color = SKINCOLOR_GREY
	  	ghs.morning = 4
	end
	for i = 1,4 --Make shots invisible.
		ghs = i==1 and p.waveguard1 or i==2 and p.waveguard2 or i==3 and p.waveguard3 or p.waveguard4
		if ghs and ghs.valid
			ghs.flags = $|MF_NOCLIP 
			ghs.flags2 = $|MF2_DONTDRAW 
		end
	end
end

--Animation and prep system for charging your Beam Combos.
SAM.BeamComboCharge = function(p,s)

	p.sams_beamcombocharge = $+1
	s.sam_stopmult = 2
	
	local ghs
	local CCHARGE = p.sams_beamcombocharge or 0	
	if (CCHARGE%2==0)
		if CCHARGE==2 --Initial start!
			SamusTutorial(s, "beamcombo", true)
			P_SamFP(p, PAL_MIXUP, 2)
			A_samquake(p.mo, 9<<16, 7, 4000<<16)
			
			ghs = P_SpawnMobjFromMobj(s, 
			s.momx/2 + FixedMul(s.radius*5/2, cos(s.angle-ANG2*2)), 
			s.momy/2 + FixedMul(s.radius*5/2, sin(s.angle-ANG2*2)), 
			s.momz/-2 + (s.height*4/11),  MT_SAMCHARGEGFX)
			if ghs and ghs.valid
				ghs.z = $+(FixedMul(FixedMul(50<<16, s.scale), sin(p.aiming)))
				ghs.state = S_SAMCHARGEGFX4
				ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
				ghs.blendmode = AST_ADD
				ghs.ret2sign = true
				ghs.color,ghs.colorized = p.sam_beamcolor, true
				ghs.target = s
				ghs.dontstateme = true
				ghs.sprite = SPR_MBOM
				ghs.frame = R|FF_TRANS50
				ghs.tics,ghs.fuse = 99,16
				ghs.scale = $/8
				ghs.scalespeed = FRACUNIT/6
				ghs.destscale = 99<<16
			end							
		elseif (CCHARGE%4==0)
			local ZHEIGHT = (s.eflags & MFE_VERTICALFLIP) and s.height*10/13 or s.height/4
			ghs = P_SpawnMobj(s.x, s.y, s.z+ZHEIGHT, MT_SAMUSZAP)
			if ghs and ghs.valid
				ghs.blendmode = AST_ADD
				ghs.scale = s.scale*30/41
				ghs.momx,ghs.momy,ghs.momz = s.momx/2,s.momy/2,s.momz/2
				ghs.eflags = s.eflags
				ghs.color = p.sam_beamcolor
				ghs.morning = 4
			end
		end
		p.samxbeam = $+125355
		p.samybeam = $+105355
	end
	p.sam_shinespark,p.sam_shinesparkstop,p.sams_supermissileready,p.sams_screwattackcd = 0,0,0,2
	A_SAMPARTICLE(s, MT_MPR1, 10, 3, 1, 15, p.sam_beamcolor, 35000, true)
	A_SAMPARTICLE(s, MT_MPR1, 20, 6, 1, 45, SKINCOLOR_WHITE, 23000, true)
	A_SAMPARTICLE(s, MT_MPR1, 15, 7, 1, 9, SKINCOLOR_RED, 29000, true)
	
	if (CCHARGE < 4)
		A_SAMPARTICLE(s, MT_MPR5, 35, 4, -4, 4, p.sam_beamcolor, P_RandomRange(35355, 58355)+40000)
		ghs = P_SpawnMobj(s.x, s.y, s.z+24<<16, MT_PBEXPANDW)
		if ghs and ghs.valid
			ghs.scale,ghs.scalespeed = $*3,$*6
			ghs.destscale = $*25
			ghs.momx,ghs.momy,ghs.momz = s.momx,s.momy,s.momz
		end
	elseif (CCHARGE >= 35)
		local MISSILES = p.sammissiles or 0
		local DRAIN = (p.samadrain) and p.samadrain or 1 --Drain multiplier. Is 2x in Fusion Mode or with certain Match Settings!
		
		if p.sam_powerbeamequip
		
			if p.sam_powerbeamcombo
				p.sammissiles = max(0, MISSILES-(10*DRAIN))
				A_samquake(s, 10<<16, 5, 3000<<16)
				SamusBeamFire(s, MT_SAMSUPERMISSILE)		
				P_SamFP(p, PAL_MIXUP, 4)
				S_StartSound(s, sfx_smsh)
				S_StartSound(s, sfx_smsh)
				if not (p.sam_spazerbeam or p.sam_wavebeam or p.sam_icebeam or p.sam_plasmabeam)
					p.sam_powerbeammeltdown = 175 --Fiiine, you'll get mercy points.
				else
					p.sam_powerbeammeltdown = 665
				end
			end
	
		elseif p.sam_spazerbeamequip
			if p.sam_spazerbeam and p.sam_spazerbeamcombo
		
				p.sammissiles = max(0, MISSILES-(15*DRAIN))
				A_samquake(s, 12<<16, 8, 5000<<16)
				SamusBeamFire(s, MT_SPCHARGECOMBO)
				P_SamFP(p, PAL_RECYCLE, 9)
				for i = 1,4 S_StartSound(s, sfx_spcm) end
				p.sam_spazerbeammeltdown = 900
			end
	
		elseif p.sam_wavebeamequip
		
			if p.sam_wavebeam and p.sam_wavebeamcombo
				p.sammissiles = max(0, MISSILES-(15*DRAIN))
				A_samquake(s, 12<<16, 4, 1500<<16)
				s.wavebuffering = 1
				P_SamFP(p, PAL_MIXUP, 4)
				s.sam_flashfade = 9
				s.sam_flashfadecolor = SKINCOLOR_SUPERGOLD5
				S_StartSound(s, sfx_wvcm)
				S_StartSound(s, sfx_wvcm2)
				p.sams_beamanim = 15
			end
	
		elseif p.sam_icebeamequip
		
			if p.sam_icebeam and p.sam_icebeamcombo
				p.sammissiles = max(0, MISSILES-(15*DRAIN))			
				A_samquake(s, 8<<16, 6, 3500<<16)	
				SamusBeamFire(s, MT_ICCHARGECOMBO)
				P_SamFP(p, PAL_MIXUP, 7)
				s.sam_flashfade = 11
				s.sam_flashfadecolor = SKINCOLOR_SKY						
				S_StartSound(s, sfx_iccm)
				S_StartSound(s, sfx_iccm)
				p.sam_icebeammeltdown = 1400
			end
	
		elseif p.sam_plasmabeamequip 
		
			if p.sam_plasmabeam and p.sam_plasmabeamcombo
				p.sammissiles = max(0, MISSILES-(5*DRAIN))
				A_samquake(s, 4<<16, 5, 3800<<16)
				s.gattlingvortex = 1
				s.holdgattle = true
				P_SamFP(p, PAL_NUKE, 8)
				s.sam_flashfade = 16
				s.sam_flashfadecolor = SKINCOLOR_KETCHUP						
				S_StartSound(s, sfx_plchsh)
			end	
		elseif p.sam_hyperbeamequip
		and p.samchallenger and (p.samchallenger > 3)
			p.sammissiles = max(0, MISSILES-(10*DRAIN))
			if p.sam_hyperbeamammo and (p.sam_hyperbeamammo >= 15*DRAIN)
				p.sam_hyperbeamammo = $-(15*DRAIN)
				P_SamFP(p, PAL_WHITE, 2)
				s.sam_flashfade = 9
				s.sam_flashfadecolor = SKINCOLOR_SUPERSKY1
			elseif p.sam_energy and (p.sam_energy > (25*DRAIN))
				p.sam_energy = $-(25*DRAIN)
				P_SamFP(p, PAL_NUKE, 6)
				s.sam_flashfade = 19
				s.sam_flashfadecolor = SKINCOLOR_CRIMSON							
				P_Thrust(s, s.angle, -16<<16)
				P_PlayRinglossSound(s)
			else
				p.sam_hyperbeamammo = 0
			end
			
			p.sams_shotcd,p.sams_mshotcd = 3,3
			A_samquake(s, 18<<16, 12, 7500<<16)
			SamusBeamFire(s, MT_HBSHOT) 
			SamusTutorial(s, "hyperbeam", true)				
			if p.plshot and p.plshot.valid
				p.plshot.color = SKINCOLOR_SUPERGOLD5
				p.plshot.truehyper = true
			end
			if (p.pflags & PF_JUMPED)
				P_SetObjectMomZ(s, 2<<16, true)
			end
			S_StartSound(s, sfx_hbsh)
			P_Thrust(s, s.angle, -16<<16)
			
			S_StartSound(s, sfx_spcm)	
			p.sam_hyperbeamammo = max(0, $)
		end
		s.MissileAmmoDrain = 3
		p.sams_beamcombocharge = 0
	end
end

--Small part of the arm swaying code in SAMUS_MAIN
SAM.ArmCannon = function(p,s)
	--Having a Beam "meltdown"! It's smoking!
	if p.sam_powerbeammeltdown and p.sam_powerbeamequip
	or p.sam_spazerbeammeltdown and p.sam_spazerbeamequip
	or p.sam_wavebeammeltdown and p.sam_wavebeamequip
	or p.sam_icebeammeltdown and p.sam_icebeamequip
	or p.sam_plasmabeammeltdown and p.sam_plasmabeamequip
		p.sams_shotcd,p.sams_mshotcd = 3,3
		local RAD,ghs = (s.radius*5/2) or FRACUNIT, nil
		local ZHEIGHT = (s.eflags & MFE_VERTICALFLIP) and (s.height*4/11) or (s.height*2/3)
		ghs = P_SpawnMobj(s.x+FixedMul(RAD,cos(s.angle-ANG2*2)),s.y+FixedMul(RAD,sin(s.angle-ANG2*2)),s.z+ZHEIGHT, MT_SAMCHARGEGFX)
		ghs.z = $+(FixedMul(FixedMul(50<<16, s.scale), sin(p.aiming)))
		ghs.scale = s.scale/(P_RandomRange(10,20))
		ghs.color = SKINCOLOR_BLACK
		ghs.momx,ghs.momy = s.momx*2/3,s.momy*2/3
		ghs.eflags = s.eflags
		ghs.target = s
	end	
	
	if (p.speed < 12<<16)
		p.samboblenght = 3<<16
		p.samboblenght2 = 7<<16
		
		--Scan Visor feature
		if (p.sam_scanvisor or (gametype != GT_COOP))
		and (p.speed <= 0 and ((s.state <= S_PLAY_WAIT) or (s.state == S_PLAY_EDGE))) //and p.sam_scanvisor
		and not p.sammorphed 
		and not p.sam_intoship 
		and P_IsObjectOnGround(s)
		and not (p.pflags & PF_FORCESTRAFE) 
		and not p.powers[pw_nocontrol] and not p.bot
		and not s.samscananim
		and not (gametype == GT_HIDEANDSEEK)
		and not (s.sam_automob and s.sam_automob.valid)
			if s.samusjustscanned
			and (p.cmd.buttons & (BT_CUSTOM1|BT_TOSSFLAG))
				--
			else
				if not (s.sam_scanpowerup and (s.waittoscan != nil))
				and not p.sam_noautoscan
					s.waittoscan = s.waittoscan and $+1 or 1
				end
				if (s.waittoscan == nil or (s.waittoscan < 500))
				and ((p.cmd.buttons & BT_TOSSFLAG)
				or ((p.cmd.buttons & BT_CUSTOM1) and not p.sam_noautoscan or (p.cmd.buttons & BT_CUSTOM1) and p.sam_noautoscan == 1)
				and not (p.sams_c1cd and p.sams_c1cd > 2))
					s.waittoscan = 500
					s.samusjustscanned = false
				elseif s.samusjustscanned
					s.waittoscan = 0
					if p.cmd.forwardmove or p.cmd.sidemove or (p.cmd.buttons & BT_JUMP) or (p.cmd.buttons & BT_SPIN)
						s.samusjustscanned = false
					end
				elseif s.waittoscan and (s.waittoscan > 230)				
					s.sam_scanning = s.sam_scanning and $+1 or 1
					s.sam_scanang = s.sam_scanang and $+(ANG1*4) or (ANG1*4)
					
					if leveltime % 9 == 0
						local ghs = P_SpawnMobjFromMobj(s,0,0,(s.height*5/6), MT_THOK) --waa1
						ghs.sprite = SPR_MXP4
						ghs.frame = X|FF_FULLBRIGHT|FF_TRANS50
						ghs.blendmode = AST_ADD
						if p.samvisorcolor != nil and p.sam_gravitysuit == 2
							ghs.color = p.samvisorcolor
							ghs.colorized = true
						end
						ghs.scale = s.scale/18
						ghs.momz = (-4<<16)*P_MobjFlip(ghs)
						ghs.tics = 30
						ghs.fuse = 10
						ghs.scalespeed = $*2
						ghs.destscale = $*99
						P_InstaThrust(ghs, s.angle, 7<<16)
						if SAM_displayplayer(p) and not CV_FindVar("chasecam").value
							ghs.flags2 = $|MF2_DONTDRAW
						end
					end
					
					if s.sam_scanning == 1 or s.sam_scanning == 55
						S_StopSoundByID(s, sfx_sscan1)
						S_StartSound(s, sfx_sscan1)
						SamusTutorial(s, "scanvisor", true)
						
					elseif (s.sam_scanning > 75)
						if p.sam_hyperbeam and p.sam_hyperbeampanic
							s.sam_scanpowerup = 0
							p.scannedmons = nil
							p.scannedplays = nil
							s.sam_scanning = 0
							s.waittoscan = 0
							s.samusjustscanned = true
							S_StopSoundByID(s, sfx_sscan1)
							S_StartSound(s, sfx_cmol)
							s.samusmission = nil
							SamusMission(s, "   ENERGY OVERLOAD!", "SCANNING IMPOSSIBLE!", nil, 3, 0, false)
						else
							SAM.DoAreaScan(s, p, true)
						end
					end
				end
			end
			if not s.sam_scanning
				s.sam_scansymbol = s.sam_scansymbol and $+2 or 2
				if (s.sam_scansymbol > 49)
					s.sam_scansymbol = 49
				end
			end
		elseif s.waittoscan
			s.sam_scanning = 0
			s.sam_scansymbol = 0
			s.waittoscan = 0
			S_StopSoundByID(s, sfx_sscan1)
		end
	elseif (p.speed < 25<<16) or ((p.samspbscharge > 70) and (p.samspbscharge < 138))
		p.samboblenght = 7<<16
		p.samboblenght2 = 8<<16
	elseif p.samspbschargefull
		p.samboblenght = 3<<16
		p.samboblenght2 = 3<<16
	else
		p.samboblenght = 3<<16
		p.samboblenght2 = 4<<16
	end
	if ((p.speed < FRACUNIT) or not P_IsObjectOnGround(s))
	and not (p.sam_screwattacking or s.sam_ldclmb or p.sam_shinesparkfly or p.beampain or (p.sam_walljumping and p.sam_walljumping >= 1) or p.sams_beamcombocharge)
		if (abs(p.samxbeam) <= 110000)
			p.samxbeam = 0 
			p.samxbeamleft = (not p.samxbeamleft)
		elseif (p.samxbeam < -100000)
			p.samxbeam = $+100000
		elseif (p.samxbeam > 100000)
			p.samxbeam = $-100000
		end
		if (p.samybeam <= 200000)
			p.samybeam = 0 
		elseif (p.samybeam > 100000)
			p.samybeam = $-100000
		end
	else
		if p.sam_screwattacking or p.sam_shinesparkfly or p.sam_walljumping or p.beampain
			if p.sam_screwattacking or p.sam_shinesparkfly
				P_SpawnPlayerMissile(s, MT_SAMMONBREAKER)
			end
		elseif p.samxbeamleft
			if (p.samxbeam > -p.samboblenght)
				if ((p.samspbscharge > 10) and (p.samspbscharge < 138))
					p.samxbeam = $-50000-(p.samspbscharge*440)
				elseif p.samspbschargefull
					p.samxbeam = $-75000
				else
					p.samxbeam = $-50000
				end
			elseif ((p.samxbeam > -(p.samboblenght2)) and (p.samxbeam <= -(p.samboblenght)))
				if (p.samspbscharge > 10) and (p.samspbscharge < 138)
					p.samxbeam = $-25000-(p.samspbscharge*440)
				elseif p.samspbschargefull
					p.samxbeam = $-37500
				else
					p.samxbeam = $-25000
				end
			else
				p.samxbeamleft = false
			end
		else
			if (p.samxbeam < p.samboblenght)
				if (p.samspbscharge > 10) and (p.samspbscharge < 138)
					p.samxbeam = $+50000+(p.samspbscharge*440)
				elseif p.samspbschargefull
					p.samxbeam = $+75000
				else
					p.samxbeam = $+50000
				end
			elseif ((p.samxbeam < (p.samboblenght2)) and (p.samxbeam >= (p.samboblenght)))
				if (p.samspbscharge > 10) and (p.samspbscharge < 138)
					p.samxbeam = $+25000+(p.samspbscharge*440)
				elseif p.samspbschargefull
					p.samxbeam = $+37500
				else
					p.samxbeam = $+25000

				end
			else
				p.samxbeamleft = true
			end
		end

		if p.sam_screwattacking or p.sam_shinesparkfly or p.sam_walljumping or p.beampain
			p.samybeamdest = 1200000
			if p.sam_spacejumpedboost and p.sam_walljumping
				if (p.sam_spacejumpedboost > 4)
					p.samxbeam = $-80000
				elseif (p.sam_spacejumpedboost > 1)
					p.samxbeam = $-30000
				else
					p.samxbeam = $+10000
				end
			end
		elseif (p.samxbeam < 0)
			if (p.speed < 25<<16) or ((p.samspbscharge > 10) and (p.samspbscharge < 138))
				p.samybeamdest = (10<<16)+p.samxbeam
			else
				p.samybeamdest = (10<<16)+(p.samxbeam*2)
			end
		else
			if (p.speed < 25<<16) or ((p.samspbscharge > 10) and (p.samspbscharge < 138))
				p.samybeamdest = (10<<16)-p.samxbeam
			else
				p.samybeamdest = (10<<16)-(p.samxbeam*2)
			end
		end
		if (p.samybeamdest < p.samybeam)
			if (p.samspbscharge > 10) and (p.samspbscharge < 138)
				p.samybeam = $-50000-(p.samspbscharge*510)
			elseif p.samspbschargefull
				p.samybeam = $-75000
			else
				p.samybeam = $-50000
			end
		else
			if (p.samspbscharge > 10) and (p.samspbscharge < 138)
				p.samybeam = $+50000+(p.samspbscharge*510)
			elseif p.samspbschargefull
				p.samybeam = $+75000
			else
				p.samybeam = $+50000
			end
		end
	end
end

--Second HUD stuff part for the Arm Cannon
SAM.ArmCannon2 = function(p,s)
	if s.sam_beamroll == nil s.sam_beamroll = 0 end
	
	local mult,stilt = 5, (s.sam_supertilt) and 1 or 0	
	if not P_IsObjectOnGround(s)
		mult = 11
		if (p.speed > 40*s.scale) and not p.sam_spacejumpedboost
			mult = 9
		end
	else
		if (p.speed < 30<<16)
			mult = 34-(p.speed>>16)
		elseif (p.speed < 46<<16)
			mult = (p.speed < 36<<16) and 9-stilt or 8-stilt	
		elseif p.samspbschargefull
			mult = 4-stilt
		end
	end
	
	if s.sam_forcebeamroll --Ignores multiplier, does forced amount.
		s.sam_forcebeamroll = $-1
		if s.sam_forcebeamnum
			s.sam_beamroll = min(179, max($-s.sam_forcebeamnum,-179))
		end
	end
	
	if (s.sam_stopmult or p.sams_supermissileready) and not s.sam_forcebeamroll
		if s.sam_beamroll
			s.sam_beamroll = ($*mult)/(mult+1)
		else
			s.sam_beamroll = 0
		end
	elseif abs(p.cmd.sidemove) > 15 and not (p.sam_noscreentilt == 2)
		if (p.cmd.sidemove > 15)
			s.sam_beamroll = $-(p.cmd.sidemove/mult)
			if s.sam_beamroll < -179
				s.sam_beamroll = -179
			elseif s.sam_beamroll > 0
				s.sam_beamroll = $-(p.cmd.sidemove/mult)
			end
		else
			s.sam_beamroll = $+(p.cmd.sidemove/-mult)
			if s.sam_beamroll > 179
				s.sam_beamroll = 179
			elseif s.sam_beamroll < 0 
				s.sam_beamroll = $+(p.cmd.sidemove/-mult)
			end
		end
	elseif s.sam_beamroll
		s.sam_beamroll = ($*mult)/(mult+1)
	end
	if s.sam_beamroll
		if (p.speed < 10*s.scale) or not P_IsObjectOnGround(s)
			s.sam_beamroll = $*30/31
		end
		if not s.sam_systemreboot and not s.metroidsnack and not s.myorammer
			if p.sammorphed
			or p.sam_noscreentilt
			or (SAM_displayplayer(p) and CV_FindVar("chasecam").value)			
				p.viewrollangle = 0
			else
				p.viewrollangle = ((s.sam_beamroll*-1)*ANG1)/20 --Visual field change!
			end
		end
	elseif p.viewrollangle
		if not s.sam_systemreboot and not s.metroidsnack and not s.myorammer
			p.viewrollangle = 0
		end					
	end
	
	--Add Visor bobbing as well
	if not P_IsObjectOnGround(s) and s.momz --Momz, speed, and aiming direction affect this all seperately!
	
	 	p.samvisordropdist2 = (s.momz/5)*P_MobjFlip(s)
		
		local MOMZ = (s.momz*P_MobjFlip(s))/32
		if (s.momz*P_MobjFlip(s) > 0)	
			if (p.samvisoraimy < 8<<16) --Top Visor 
				p.samvisoraimy = $+MOMZ
			end
			if (p.samvisoraimy2 < 4<<16) --Bottom Visor
				p.samvisoraimy2 = min(4<<16, $+MOMZ)
			end
		else
			if (p.samvisoraimy > -4<<16) --Top Visor
				p.samvisoraimy = max(-4<<16, $+MOMZ )
			end
			if (p.samvisoraimy2 > -10<<16) --Bottom Visor
				p.samvisoraimy2 = $+ MOMZ
			end
		end
		
	else --Reset!
	
		if (s.eflags & MFE_JUSTHITFLOOR) --landing+dust
			if ((s.sam_lastmomz or 0)*P_MobjFlip(s) < (-6*s.scale))
			and not s.sam_dustcd --landing sound+dust?
				local extraspd = min(27<<16, abs(s.sam_lastmomz))
				for d = 1,16
					local ghs = P_SpawnMobjFromMobj(s, 
					FixedMul(cos(ANGLE_22h*d), 23<<16),
					FixedMul(sin(ANGLE_22h*d), 23<<16),
					-4<<16, MT_SPINDUST)
					if (s.eflags & MFE_UNDERWATER)
						ghs.state = S_SPINDUST_BUBBLE1
						ghs.fuse = 30
					else
						ghs.state = S_SPINDUST1
						ghs.scale = $*3/4
						ghs.fuse = 50
					end
					ghs.scalespeed = $/2
					ghs.destscale = $*99
					P_InstaThrust(ghs, ANGLE_22h*d, ((d%2==0) and 7 or 20)<<16+extraspd )
					ghs.momx = $+(s.momx*5/4)
					ghs.momy = $+(s.momy*5/4)
				end
			/*	for i = -2,2
					local ghs = P_SpawnMobjFromMobj(s,
					FixedMul( cos(s.angle+(ANG1*19*d)), 23<<16) ,
					FixedMul( sin(s.angle+(ANG1*19*d)), 23<<16) ,
					6<<16, MT_SPINDUST)
					ghs.destscale = $*99
					ghs.fuse = 55
					P_InstaThrust(ghs, s.angle+(ANG1*17*d), 40<<16+extraspd)
					ghs.momx = $+s.momx
					ghs.momy = $+s.momy
					if SAM_displayplayer(p) and (CV_FindVar("chasecam").value == 1)
					or (p != displayplayer)
						ghs.flags2 = $|MF2_DONTDRAW
					end
				end */
				s.sam_dustcd = 5
				s.sam_lastmomz = 0
				S_StartSound(s, sfx_samlnd)
			end
		
			if p.samvisordropdist2
				s.samvisordrop = 18
				s.sam_supertilt = 18
			end
		elseif (s.state == S_PLAY_WAIT) --Beam idle sway			
			if not p.beamswaychosen 
			
				if not p.beamswaydistxend or p.beamswaydistxend < 0
					p.beamswaydistxend = 12<<16
				else
					p.beamswaydistxend = P_RandomRange(-2,-1)<<16
				end
				
				p.beamswaydistxdir = (p.beamswaydistxend < 0) and -1 or 1
				p.beamswaydistx = (p.beamswaydistx) or 0
				
				p.beamswaydistyend = (not p.beamswaydistyend) and P_RandomRange(3,4)<<16 or 0
			
				p.beamswaydisty = (p.beamswaydisty) or 0
				p.beamswaydistydir = (p.beamswaydistyend > p.beamswaydisty) and 1 or -1
			
				p.beamswaychosen = true
				p.beamswaytimer = 0
			
			else
				p.beamswaytimer = $+1
				if (p.beamswaydistxend < 0) and (p.beamswaydistx > p.beamswaydistxend)
					p.beamswaydistx = $-p.beamswaytimer*60
					if p.beamswaydistx > 0
						p.beamswaydistx = $-p.beamswaytimer*30
					end	
				elseif (p.beamswaydistxend > 0) and (p.beamswaydistx < p.beamswaydistxend)
					p.beamswaydistx = $+p.beamswaytimer*60
					if p.beamswaydistx < 0 or p.beamswaydistydir == -1
						p.beamswaydistx = $+p.beamswaytimer*60
					end
				end

				if p.beamswaydistydir == 1 and (p.beamswaydisty <= p.beamswaydistyend)
					p.beamswaydisty = $+p.beamswaytimer*90
				elseif p.beamswaydistydir == -1 and (p.beamswaydisty >= p.beamswaydistyend)
					p.beamswaydisty = $-p.beamswaytimer*90
				else
					p.beamswaychosen = false
				end	
			end
		elseif p.beamswaydisty or p.beamswaydistx
			p.beamswaydisty = 0
			p.beamswaydistx = 0
		end
		if p.samvisoraimy
			if (p.samvisoraimy < 0)
				p.samvisoraimy = min(0,$+25000)
			else --if (p.samvisoraimy > 0)
				p.samvisoraimy = max(0,$-25000)
			end
		end
		if p.samvisoraimy2
			if (p.samvisoraimy2 < 0)
				p.samvisoraimy2 = min(0, $+25000)
			else --if (p.samvisoraimy2 > 0)
				p.samvisoraimy2 = max(0, $-25000)
			end
		end
	end				
	
	if not s.samangshiftcd
		if (p.samangshift > 145000)
			p.samangshift = $-145000
		elseif (p.samangshift < -145000)
			p.samangshift = $+145000
		else
			p.samangshift = 0
		end
	end			
	if s.lastsamusangle != nil
		local diff = (s.lastsamusangle - s.angle)			
		if diff
			if (diff > ANGLE_180)
				diff = InvAngle(InvAngle(diff)/1200)
 			else
				diff = $/1200
			end
			p.samangshift = p.samangshift and $+diff or diff
			s.samangshiftcd = 3
		elseif s.samangshiftcd
			s.samangshiftcd = $-1
    	end
		p.samangshift = max(-36<<16, min(36<<16, $))
		p.samangshift = p.samangshift and $+diff or diff
	end
	p.samvisoraimy3 = p.aiming/1000
	local yvisor2 = (p.samvisoraimy2/2)+(p.samybeam/3)+p.samvisoraimy3+p.samvisordropdist
	local yvisor1 = (p.samvisoraimy/2)+(p.samybeam/2)+p.samvisoraimy3+p.samvisordropdist
	p.samvisoraimxtrue = (p.samangshift/2)+p.samxbeam/3
	s.lastsamusangle = s.angle
	
	p.samvisoraimytrue1 = min(16<<16, max(-4<<16, yvisor1))
	p.samvisoraimytrue2 = min(4<<16, max(-16<<16, yvisor2))


	
	if s.crystalflashtime and not p.gotflag
		p.jumpfactor = 98500
	elseif p.sam_highjump and not p.gotflag
		p.jumpfactor = 68500
	else
		p.jumpfactor = skins[s.skin].jumpfactor		
	end
	if ( (p.sams_beamanim == 14) or p.sams_chargetime) and not p.sammorphed
		if (P_IsObjectOnGround(s) and (p.speed < 20000))
			s.state = S_SAMUFIRE
		end
	end
end

SAM.HyperBeamPassive = function(p,s, PANIC)
	if PANIC == true
		if (leveltime % 35 == 0) --Scan every second.
			for z in players.iterate
				if z.mo and z.mo.health
				and not z.sam_hyperbeampanic
					z.sam_hyperbeampanic = 84
					if not z.sam_hyperbeam
						if z.mo
							SAM.DoAreaScan(z.mo, z)
						end
					
						z.samhudmessagetime = 230
						z.samhudmessage1 = "\x80"+p.name+"\x81 captured the Hyper Beam! Kill them"
						z.samhudmessage2 = "before they gather more ammo and destroy everyone!"
					else
					
						z.mo.sam_scanpowerup = 0
						z.scannedmons = nil
						z.scannedplays = nil
					
						z.samhudmessagetime = 230
						z.samhudmessage1 = "\x81"+"You are hunted!\x82 Use the Hyper Beam to wreak"
						z.samhudmessage2 = "\x82"+"as much havoc as possible before dying!"
					end
					P_SamFP(z, PAL_NUKE, 12)
					if not z.nosammusic
						SAM_COM_BufInsertText(z, "tunes -none; tunes SAMUSH")
					end
				end
			end
		end
		
		if s.sam_lasthyperbeamammo and (s.sam_lasthyperbeamammo < p.sam_hyperbeamammo)
			local NEWAMMO = (p.sam_hyperbeamammo-s.sam_lasthyperbeamammo)
			if NEWAMMO > 25
				S_StartSound(nil, sfx_litng4)
				S_StartSound(nil, sfx_litng3)
				S_StartSound(nil, sfx_litng2)
				S_StartSound(nil, sfx_litng1)
				S_StartSound(nil, sfx_s3k6f)
			else
				S_StartSound(nil, (P_RandomRange(sfx_rocks1, sfx_rocks4)))
			end
			for z in players.iterate
				if z.mo
					if NEWAMMO > 24
						P_SamFP(z, PAL_NUKE, 3)
						A_samquake(z.mo, 55<<16, 35, 1)
					else
						A_samquake(z.mo, (NEWAMMO*3)<<16, NEWAMMO*2, 1)
					end
				end
			end
		end
		s.sam_lasthyperbeamammo = p.sam_hyperbeamammo
	end

	if p.sam_hyperbeampanic
		local ZHEIGHT = (s.eflags & MFE_VERTICALFLIP) and -(s.height*10/12) or (s.height*10/12)
		local ghs = P_SpawnMobjFromMobj(s, 0,0, ZHEIGHT, MT_THOK)
		ghs.destscale = s.scale/(P_RandomRange(1,5))
		ghs.renderflags = $|RF_FULLBRIGHT|RF_NOCOLORMAPS
		ghs.momx,ghs.momy = s.momx,s.momy
		ghs.momz = s.momz+((P_RandomRange(30, 100))<<16)*P_MobjFlip(s)
		ghs.tics,ghs.fuse = 8,12
		ghs.color = P_RandomRange(SKINCOLOR_PEPPER, SKINCOLOR_KETCHUP)
	end
	if not p.sam_hyperbeamtime
		p.sam_hyperbeamtime = 18
		p.hyperbeamco = SKINCOLOR_SKY
	else
		p.sam_hyperbeamtime = $-1
		if (p.sam_hyperbeamtime > 16)
			p.hyperbeamco = SKINCOLOR_SKY
		elseif (p.sam_hyperbeamtime > 14)
			p.hyperbeamco = SKINCOLOR_BLUE
		elseif (p.sam_hyperbeamtime > 12)
			p.hyperbeamco = SKINCOLOR_MAGENTA
		elseif (p.sam_hyperbeamtime > 10)
			p.hyperbeamco = SKINCOLOR_PINK
		elseif (p.sam_hyperbeamtime > 8)
			p.hyperbeamco = SKINCOLOR_CLOUDY
		elseif (p.sam_hyperbeamtime > 6)
			p.hyperbeamco = SKINCOLOR_GOLD
		elseif (p.sam_hyperbeamtime > 4)
			p.hyperbeamco = SKINCOLOR_SUPERGOLD4
		elseif (p.sam_hyperbeamtime > 2)
			p.hyperbeamco = SKINCOLOR_SUPERRED2
		else
			p.hyperbeamco = SKINCOLOR_EMERALD
		end			
	end
end

SAM.TryBeamShot = function(p,s)
	local READYTOFIRE = 0
	if not p.sams_shotcd and not p.sammorphed	
		local NORMALFIRE = (p.swapfire) and BT_ATTACK or BT_FIRENORMAL
		if (p.cmd.buttons & (BT_CUSTOM2|NORMALFIRE))
			local C2 = (p.sams_c2cd) or 0
			local NF = (p.sams_normfcd) or 0
			if (p.cmd.buttons & BT_CUSTOM2) and not (C2>1) and not p.c1c2disable 
			or (p.cmd.buttons & NORMALFIRE) and not (NF>1)
				if not p.exiting and not p.powers[pw_nocontrol]
					READYTOFIRE = 1
				end
			end
		elseif p.sam_chargebeam	
			if (p.sams_chargetime > 3)
				local FIREBUTTON = (p.swapfire) and BT_FIRENORMAL or BT_ATTACK
				if not (p.cmd.buttons & FIREBUTTON)	
					READYTOFIRE = (p.sams_chargetime > 40) and 3 or 2
				end
			end
		end
	end
	if READYTOFIRE != 0 or s.waveoverfire	
		S_StopSoundByID(s, sfx_pbcha)
		S_StopSoundByID(s, sfx_pbchao)
		s.waveoverfire = nil
			
		if not ((p.sams_chargetime > 41) and p.sam_chargebeam)
		and not (s.crystalflashtime and not p.sam_hyperbeamequip)
			--Regular shots fired.
			if p.sam_powerbeamequip
				p.sams_shotcd, p.sams_mshotcd = 3, 4
				SamusBeamFire(s, MT_PBSHOT)
				SamusTutorial(s, "beams", true) 
				s.pbshotsmoke = s.pbshotsmoke and $+12 or 12
				if s.pbshotsmoker and (s.pbshotsmoker < 300)
					s.pbshotsmoker, s.pbshotsmoker2 = $+12, 12
				end
				if (leveltime < 3150) and (gametyperules & GTR_RINGSLINGER) and G_GametypeHasSpectators() and not p.sam_powerbeamcombo
					S_StartSound(s, sfx_pbshsh) --Short Beam.
				else
					S_StartSoundAtVolume(s, sfx_pbsh,200) --Long Beam.
				end
			elseif p.sam_spazerbeamequip
				p.sams_shotcd, p.sams_mshotcd = 8, 11
				SamusBeamFire(s, MT_SPSHOT, 1)
				S_StartSound(s, sfx_spsh)
			elseif p.sam_wavebeamequip
				p.sams_shotcd, p.sams_mshotcd = 14, 13
				SamusBeamFire(s, MT_WVSHOT, 2)
				S_StartSoundAtVolume(s, sfx_wvsh, 210)
				for i = 1,2
					local ghs = (i==1) and p.plshot or p.plshot2 
					if ghs and ghs.valid
						ghs.scale, ghs.color = $*3/4, SKINCOLOR_MAGENTA
					end
				end
			elseif p.sam_icebeamequip
				p.sams_shotcd, p.sams_mshotcd = 20, 8
				S_StartSound(s, sfx_icchsh)
				SamusBeamFire(s, MT_ICSHOT)
				if p.plshot and p.plshot.valid 
					p.plshot.scale, p.plshot.color = $*5/3, SKINCOLOR_CLOUDY
				end
			elseif p.sam_plasmabeamequip 
				p.sams_shotcd, p.sams_mshotcd = 13, 13
				SamusBeamFire(s, MT_PLSHOT)
				if p.plshot and p.plshot.valid 
					p.plshot.scale, p.plshot.color = $*5/6, SKINCOLOR_RED
				end
				S_StartSoundAtVolume(s, sfx_plsh, 230)
			elseif p.sam_hyperbeamequip
			
				local MULT = ((p.sam_fullypoweredsuit) and 5 or 10)*p.samadrain
				local HAMMO = (p.sam_hyperbeamammo) or 0
				local ENERGY = (p.sam_energy) or 0
				
				if ( (HAMMO>=MULT) or (ENERGY>25) and G_GametypeHasSpectators() )
					if (p.gotflag or p.sam_restricthyper or p.hypernetgo)
					and not gamemap == 28
						if p.sam_restricthyper and not p.hypernetgo
							CONS_Printf(p, "\x85"+"The server restricted Hyper Beam in netgame boss battles.")
						elseif p.gotflag
							CONS_Printf(p, "\x85"+"Hyper Beam is restricted when carrying the flag.")
						end
						p.sams_hbdenid = 13
						p.sams_shotcd = 13
						S_StartSound(s, sfx_sdenid)
					else
						p.sam_hyperbeamammo = p.sam_hyperbeamammo or 0
						p.sams_shotcd = 13
						p.sams_mshotcd = 14
						SamusBeamFire(s, MT_HBSHOT) SamusTutorial(s, "hyperbeam", true)
						if p.plshot and p.plshot.valid
							p.plshot.color = SKINCOLOR_PINK
						end
						if (HAMMO >= MULT)
							p.sam_hyperbeamammo = max($-MULT,0)
						else --if (ENERGY > 25)
							p.sam_energy = max($-25,1)
							A_samquake(s, 10<<16, 5, 2500<<16)
							P_SamFP(p, PAL_NUKE, 6)
							P_Thrust(s, s.angle, -16<<16)
							P_PlayRinglossSound(s)
						end
						if G_GametypeHasSpectators()
							local TOTAL = 0
							for z in players.iterate
								if z and z.valid and z.mo and not z.sam_hyperbeam
									TOTAL = $+1
									if (FixedHypot(FixedHypot(s.x-z.mo.x, s.y-z.mo.y), s.z-z.mo.z) < 5000<<16)
										z.mo.omegarushpanic = 20 --Add danger lines to their HUD.
									end
								end
							end
							if (TOTAL > 5) and (HAMMO >= MULT) --Drain more if there's a ton of players.
								p.sam_hyperbeamammo = max($-MULT,0)
							end				
						end	
						S_StartSound(s, sfx_hbsh)
					end
				end
			end
		else
			p.sams_chargetime = 0
			p.sams_chargetimecd = 32				
			if p.sam_powerbeamequip
				p.sams_shotcd,p.sams_mshotcd = 5,10
				SamusBeamFire(s, MT_PBCHARGESHOT)
				S_StartSound(s, sfx_pbchaf)
			elseif p.sam_spazerbeamequip
				p.sams_shotcd,p.sams_mshotcd,p.sams_chargetimecd = 10,12,24
				SamusBeamFire(s, MT_SPCHARGESHOT, 3)
				if not s.crystalflashtime P_SamFP(p, PAL_RECYCLE, 2) end
				S_StartSound(s, sfx_spchsh)
			elseif p.sam_wavebeamequip
				p.sams_shotcd, p.sams_mshotcd = 14,13
				SamusBeamFire(s, MT_WVCHARGESHOT)
				S_StartSoundAtVolume(s, sfx_wvchsh, 125)
				S_StartSound(s, sfx_wvchsh)
				if p.plshot and p.plshot.valid p.plshot.scale, p.plshot.color = $*4/3, SKINCOLOR_MAGENTA end
			elseif p.sam_icebeamequip
				p.sams_shotcd,p.sams_mshotcd,p.sams_chargetimecd = 21,9,30
				S_StartSound(s, sfx_icsh)
				SamusBeamFire(s, MT_ICCHARGESHOT)
			elseif p.sam_plasmabeamequip
				p.sams_shotcd, p.sams_mshotcd = 18, 18
				SamusBeamFire(s, MT_PLCHARGESHOT)
				if not s.crystalflashtime P_SamFP(p, PAL_NUKE, 3) end
				S_StartSound(s, sfx_plchsh)
			end
			if s.crystalflashtime
				p.sams_shotcd = 13		
			end
		end
	end
end

--Originally Chargehomer.
SAM.AttractPickUps = function(s, DIST, ATTRACTSPEED)
	local truth = false
	local CHECKDIST = (ATTRACTSPEED<2) and DIST or DIST*3/4

	searchBlockmap("objects", function(s, m)	
		if not m.valid 
		or not ( (m.type >= MT_MPKU) and (m.type <= MT_NRGH) )
			return --Only attract these!
		end
		if (m.z < s.z+DIST) and (m.z > s.z-DIST) --Within range vertically too?
		and not (m.flags2 & MF2_AMBUSH) 
		and not m.dontsuckme
		and m.health
		
			local XYDIST = FixedHypot(m.x-s.x, m.y-s.y)
			if (XYDIST < CHECKDIST) --Welp, gotta do this again anyway, I guess.
			
				if (ATTRACTSPEED < 2)	--Use regular homing
					local ghs = P_SpawnGhostMobj(m)
					ghs.fuse,ghs.tics = 11,14
					ghs.scale = s.scale*6/5
					ghs.renderflags = RF_NOCOLORMAPS|RF_FULLBRIGHT
					ghs.blendmode = AST_ADD
					ghs.color = SKINCOLOR_SILVER
					ghs.colorized = true
					ghs.scalespeed = ghs.scale/11
					ghs.dispoffset = -88
					ghs.destscale = 1
					P_HomingAttack(m, s)
					if m and m.valid
						ghs.momx,ghs.momy,ghs.momz = m.momx/2,m.momy/2,m.momz/2
					end
				else --Instant!
					local ANG = R_PointToAngle2(m.x, m.y, s.x+s.momx, s.y+s.momy)
					local ex = max(XYDIST,4) / (8<<16)
					ex = max(4,min($,24)) --minmax stuff!
					
					local ghs,ghs2
					local zet = s.z
					for i = 1,ex
						ghs = P_SpawnGhostMobj(m)
						ghs.blendmode = AST_ADD
						P_MoveOrigin(ghs, ghs.x+FixedMul(24<<16*i, cos(ANG)), ghs.y+FixedMul(24<<16*i, sin(ANG)), s.z)
						ghs.destscale = 1
						ghs.scalespeed = ghs.scale/11
						ghs.momx,ghs.momy,ghs.momz = s.momx,s.momy,s.momz
						
						if (i==ex) and m --On the last one, spawn a special ghostmobj!
							ghs2 = P_SpawnGhostMobj(m)
							ghs2.sprite = SPR_MBOM
							ghs2.renderflags = RF_FULLBRIGHT|RF_NOCOLORMAPS
							ghs2.blendmode = AST_ADD
							ghs2.frame = I|FF_TRANS60
							ghs2.scale = $/8
							ghs2.destscale = $*99
							ghs2.scalespeed = FRACUNIT/6
							ghs2.colorized = true
							ghs2.color = SKINCOLOR_SUPERSILVER1
							P_HomingAttack(ghs2, s)
							truth = true
							P_MoveOrigin(m, s.x+s.momx, s.y+s.momy, s.z+s.momz) break --
						end
					end
				end
				if m and m.valid
					m.chargehomertime = 3
					truth = true
				end
			end
		end
	end, s, s.x-DIST, s.x+DIST, s.y-DIST, s.y+DIST)
	
	if truth
		return true --
	end return false --
end

 --Does the scan visor finding thing.
SAM.DoAreaScan = function(s, p, scanmsg, SKIP)

	s.sam_scanning = 0
	s.waittoscan = 0
	s.samusjustscanned = true
	p.scannedmons,p.scannedplays = {},{}
	s.totalscannedmons = 0
	s.totalscannedplays = 0
	s.totalscannedplayshidden = 0
	S_StopSoundByID(s, sfx_sscan1)
		
	if p.sam_hyperbeampanic and p.sam_hyperbeam
		return --
	end
	
	--Scan!
	if SKIP != "skipplayers"
		if not ((leveltime < 2000) and (gametyperules & GTR_RINGSLINGER) and G_GametypeHasSpectators() )
			local SCORE = (p.score) or 0
			for z in players.iterate
				if z.mo and (z.mo != s) and z.mo.health
					if (gametype == GT_COOP)
						s.totalscannedplays = $+1
					else
						local FOUNDYOU = false
						if not ((z.sammorphed or z.mo.wavebuffering or z.mo.samspawnprotect) and not z.sam_hyperbeam)
							if (SCORE <= z.score) or z.sam_hyperbeam
								FOUNDYOU = true
								table.insert(p.scannedplays, z.mo)
								s.totalscannedplays = $+1
							end
						end
						if FOUNDYOU == false
							s.totalscannedplayshidden = $+1
						end
					end
				end
			end
		end
	end
	if SKIP != "skipmonitors"
		for m in mobjs.iterate() if not m.valid continue end --
			if (m.type == MT_TOKEN)
			or (m.type >= MT_EMERALD1) and (m.type <= MT_EMERALD7)
				if not (gametyperules & GTR_RINGSLINGER) --Not in Hunters, duh.
				and (FixedHypot(s.x-m.x, s.y-m.y) < 4001<<16)
					table.insert(p.scannedmons, m)
					s.totalscannedmons = $+1
				end
			elseif (m.flags & MF_MONITOR) and m.health and not (m.flags2 & MF2_DONTDRAW)
				if (m.type == MT_EGGMAN_BOX) or (m.type == MT_EGGMAN_GOLDBOX) or (m.type == MT_GRAVITY_BOX)
					continue --
				elseif G_GametypeHasTeams()
					if (m.type == MT_RING_REDBOX) and p.ctfteam == 2
					or (m.type == MT_RING_BLUEBOX) and p.ctfteam == 1
						continue --
					end
				end
				if (FixedHypot(s.x-m.x, s.y-m.y) < 4001<<16)
					local IGNORE = false
					if m.gotplayers and (gametype == GT_COOP)
						for i,z in pairs(m.gotplayers) --Check to make sure we didn't get it.
							if (p == z)
								IGNORE = true 
							end
						end
					end
					if IGNORE != true
						table.insert(p.scannedmons, m)
						s.totalscannedmons = $+1
					end
				end
			end
		end
	end
	
	--Found something?
	if s.totalscannedmons <= 0 --Nope.
		p.scannedmons,p.scannedplays = nil,nil
		s.sam_scanpowerup = 0
		s.samradaranim = 9
		s.samradaranimd = false
		S_StartSound(s, sfx_sdenid, p)
		P_SamFP(p, PAL_NUKE, 4)
	else --Yes!
		s.samradaranim = 1
		s.samradaranimd = true
		P_SamFP(p, PAL_RECYCLE, 5)
		S_StartSound(s, sfx_sscan2, p)
		s.sam_scanpowerup = (gametype == GT_COOP) and 2100 or 800
	end
	if scanmsg and not (s.samusmission and s.samusmission.active)
		if (gametype != GT_COOP)
			if s.totalscannedplays
				if s.totalscannedplayshidden
					SamusMission(s, "   TRACKING\x82 "+s.totalscannedplays+"\x80 TARGET LOCATION(S).", "\x85"+s.totalscannedplayshidden+"\x80 TARGET(S) EVADED TRACKING.", nil, 4, 0, false)
				else
					SamusMission(s, "   TRACKING\x82 "+s.totalscannedplays+"\x80 TARGET LOCATION(S).", nil, nil, 4, 0, false)
				end
			elseif s.totalscannedplayshidden
				if s.totalscannedplayshidden == 1
					SamusMission(s, "THE TARGET HAS EVADED DETECTION. ", nil, nil, 4, 0, false)
				else
					SamusMission(s, "ALL TARGETS HAVE EVADED DETECTION.", nil, nil, 4, 0, false)
				end
			else
				if not s.totalscannedmons
					SamusMission(s, "FAILED TO ACQUIRE NEARBY TARGET(S).", nil, nil, 4, 0, false)
				else
					SamusMission(s, "ACQUIRED\x84 "+s.totalscannedmons+"\x80 NEARBY ARTIFACT SIGNAL(S). ", nil, nil, 4, 0, false)
					s.totalscannedmons = $+1
				end
			end
		else
			if not s.totalscannedmons
				SamusMission(s, "FAILED TO ACQUIRE NEARBY TARGET(S).", nil, nil, 4, 0, false)
			else
				SamusMission(s, "ACQUIRED\x84 "+s.totalscannedmons+"\x80 NEARBY ARTIFACT SIGNAL(S). ", nil, nil, 4, 0, false)
				s.totalscannedmons = $+1
			end
		end	
	end
end

