--=================================COLLISION HANDLERS===========================
--Hooks related to object, player, and wall collissions are usually placed here.
--==============================================================================

local function SamJumpCollide(s, m)
	if not s.player
	return
	end
	local p = s.player
		if m and m.valid
			if m.sambeamreflected and not (m.target and m.target.player)
				if not (s.z > m.z+m.height) and not (m.z > s.z+s.height)
				P_DamageMobj(s, m.target, m.target)
				return
				end
			elseif m.metroidleech --Metroid leech are the hypermode type enemies, not actual Metroids
				return false
			elseif ((m.type == MT_METROID and m.state == S_MTRDFROZEN) or (m.type == MT_METROIDLARVA))
				if not YouAreSamus(s) // and m.health  
				and (s.z <= m.z+m.height) and (m.z <= s.z+s.height) --Let non-Samus characters kill frozen Metroids!
					if (s.player.pflags & PF_JUMPED) or (s.player.pflags & PF_SPINNING)
					P_DamageMobj(m, s, s)
					P_SamFP(s.player, PAL_RECYCLE, 4) A_samquake(s, 15*FRACUNIT, 8, 1)
					s.momx = $*-1 s.momy = $*-1
					P_SetObjectMomZ(s, 2*FRACUNIT, true)
					return false
					end
				end
			elseif (m.type == MT_METROID)
			 if s.skin == "dirk" and ((p.pflags & PF_JUMPED) or (p.pflags & PF_SPINNING)) --Dirk OP
			 	if (s.z <= m.z+m.height) and (m.z <= s.z+s.height)
				s.momx = $*-1 s.momy = $*-1
				P_DamageMobj(m, s, s) S_StartSound(s, sfx_icfr)
				P_SamFP(s.player, PAL_RECYCLE, 4) A_samquake(s, 15*FRACUNIT, 8, 1)
				return true
				end
			 elseif s.health and not (m.latchtarget and m.latchtarget == s)
				if p.sam_shinesparkfly or p.sam_screwattacking or (p.sams_morphcd and p.sammorphed) or p.powers[pw_flashing]
				or m.stuntroid or m.paintroid or m.sidesweep or s.metroidsnack
					return false
				end
				if (s.z > m.z+m.height) and (m.z > s.z+s.height)
				else
					m.latchtarget = s
					s.momx = $/5 s.momy = $/5 s.momz = $/2	
				end
			 end
			return false
			end
		end
		if s.player.sam_intoship
		return false
		end 
		if (gamemap == 28) and (curWeather == PRECIP_STORM_NORAIN)
		and m and m.valid and (m.type == MT_CYBRAKDEMON_FLAMEREST or m.type == MT_CYBRAKDEMON_NAPALM_FLAMES)
		return false
		end
		if s.player.samnoflag and m and m.valid and ((m.type == MT_BLUEFLAG) or (m.type == MT_REDFLAG))
			if not s.player.samnoflagmessage
			s.player.samnoflagmessage = 105
			end
			return false
		end
		if m and m.valid and m.sam_deathball
		and not (s.z > m.z+m.height) and not (m.z > s.z+s.height+(s.height/2))
		P_DamageMobj(s, m, m)
		return
		end
		if m and m.valid and (m.flags & MF_MONITOR) and (gametype == GT_COOP)
		and ( (m.samgotme != nil and not (players[tonumber(0)] and s.player.player == players[tonumber(0)]) and (s.player.samusnum and (m.samgotme & (s.player.samusnum)) or m.samgotme == s.player.samusnum) )
		or (players[tonumber(0)] and s.player == players[tonumber(0)] and m.samgotmehost) )
			if not (m.gotmonalready and m.gotmonalready.valid)
				m.ghs = P_SpawnGhostMobj(m)
				m.ghs.destscale = m.scale*10 
				m.ghs.tics = 30
				m.gotmonalready = P_SpawnMobj(m.x, m.y,m.z, MT_FAKESAMUSTHOK)
				m.gotmonalready.scale = m.scale*5/6
				m.gotmonalready.eflags = m.eflags
				m.gotmonalready.state = S_ZAPS1
				m.gotmonalready.fuse = 3
			else
			m.gotmonalready.fuse  = 3
			end
			return false
		end
		
	if YouAreSamus(s)
		if m and m.valid and m.health
			if (s.player.sammorphed and s.samspinpad or s.player.sam_screwattacking or s.sam_deathball) and m and (m.flags & MF_MONITOR)
			return false
			end
			if s.player.samhands and ((m.type == MT_FLINGEMERALD) or (m.type == MT_REDFLAG) or (m.type == MT_BLUEFLAG) or (m.type == MT_BOUNCERING) or (m.type == MT_RAILRING) 
			or (m.type == MT_INFINITYRING) or (m.type == MT_AUTOMATICRING) or (m.type == MT_EXPLOSIONRING) or (m.type == MT_SCATTERRING) or (m.type == MT_GRENADERING))
			return false
			end
			if s.player.sammorphed and ((s.player.pflags & PF_STARTDASH) and (s.player.pflags & PF_SPINNING)) and m.player and m.player.speed and not (m.player.pflags & PF_JUMPED) and not ((gametype == GT_COOP or gametype == GT_RACE) and s.player.morphcoop)
			and not (s.z > m.z+m.height) and not (m.z > s.z+s.height+(s.height/2))
			m.momz = (19*FRACUNIT)*P_MobjFlip(m)
			P_Thrust(m, s.angle, 50*FRACUNIT)
			m.player.pflags = $|PF_JUMPED & ~PF_SPINNING & ~PF_THOKKED
			S_StartSound(m, sfx_zoom)
			S_StartSound(m, sfx_bnce1)
			S_StartSound(m, sfx_bnce2)			
			end
			if (s.player.pflags & PF_JUMPED) or ((s.player.pflags & PF_STARTDASH) and (s.player.pflags & PF_SPINNING))
				if (m.flags & (MF_ENEMY|MF_BOSS)) and not s.player.samspbschargefull and not s.player.bsblboostattack and not s.sam_deathball
					if not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
						if ((m.type == MT_SPRINGSHELL) or (m.type == MT_YELLOWSHELL)) 
						and (s.z > (m.z+(m.height/2)) )
							if not (m.type == MT_YELLOWSHELL)
							m.state = S_SSHELL_SPRING1
							P_SetObjectMomZ(s, 13*FRACUNIT)
							return false
							else
							m.state = S_YSHELL_SPRING1
							P_SetObjectMomZ(s, 18*FRACUNIT)
							return false
							end
						else
							P_DamageMobj(s, m, m)
							return false
						end
					else
					return false
					end
				end
				if ((m.flags & MF_MONITOR) and not (m.flags & MF_NOCLIP))
					if not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
					P_InstaThrust(s, s.angle-ANGLE_180, 7*FRACUNIT)
					P_SetObjectMomZ(s, 5*FRACUNIT)
					S_StartSound(s, sfx_s1a7)
						if s.player.sam_spacejumped
						s.player.sam_spacejumped = false
						end
					return false
					else
					return false
					end
				end
			end
			if ((m.flags & MF_SPRING) or m.type == MT_EGGSHIELD) and (s.player.bsblboost or s.player.sam_shinesparkfly or s.player.sam_screwattacking or s.samspinpad or s.spiderballing)
				if not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
				and not (s.player.bsblboost and not m.info.mass)
					if s.spiderballing and not mobjinfo[m.type].mass
					s.momz = 0
					end
				s.sams_shineframe = 0
				s.spiderballing = 0
				s.player.bsblboost = 0
				s.player.sam_shinesparkfly = 0
				if s.player.sam_screwattacking
				CancelScrewAttack(s,s.player)
				end
					if m and m.valid and m.health and (m.type == MT_EGGSHIELD) and s.player.bsblboost
					P_InstaThrust(s, s.angle, -6*FRACUNIT)
					P_SetObjectMomZ(s, 3*FRACUNIT, false)
					P_KillMobj(m)
					end
					if s.samspinpad
					s.samspinpad = 4
					end
				end
			end
			if (m.flags & MF_SPRING) and not m.info.mass --Horizontal spring hit!
			and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
					if not s.player.sammorphed
					s.samspinpadconfirmed = 12
					s.angle = m.angle
					else
					s.minormorphboost = 1
							if s.player.bsblboost or s.player.bsblboostattack
							S_StartSound(s, sfx_sprong)
							s.player.bsblboost = 0
							s.player.bsblboostattack = 0
							s.minormorphboost = (m.info.damage*2)
							end					
					s.player.pflags = $|PF_SPINNING & ~PF_JUMPED
					s.spiderballing = 0
					s.samspinpad = 50
					s.player.sams_notyet = 3
					s.samspinpadconfirmed = 49
					s.angle = m.angle
					P_InstaThrust(s, s.angle, (m.info.damage*50/38))	
					end
					s.sam_forcemorphslope = 50
					if (m.type >= MT_BOOSTERSEG) and (m.type <= MT_REDBOOSTER)
						if (m.flags2 & MF2_AMBUSH)
							p.bsblboost = 0
							s.scale = 42001
							p.sam_spacejumpedboost = 0
							p.thrustfactor = skins[s.skin].thrustfactor
							p.accelstart = skins[s.skin].accelstart
							p.sams_notyet = 3
							SamCam(p, true)
							p.sammorphed = true
							s.sammorphedghs = 5
							S_StartSound(s, sfx_smorph)
							p.sams_beamcombocharge = 0
							local ghs = P_SpawnGhostMobj(s)
							ghs.destscale = ghs.scalespeed
							CancelScrewAttack(s,p)
						end
					end
			end
			if s.player.samspbschargefull or s.player.bsblboostattack or s.sam_deathball
				if ((m.flags & (MF_ENEMY|MF_BOSS)) and (m.flags & MF_SHOOTABLE) or (m.type == MT_ICBLOCK) or (m.type == MT_TNTBARREL))
				and not (m.type == MT_GSNAPPER)
					if not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
					
						if (m.type == MT_ICBLOCK)
						m.icethisfool = true
							if s.player.bsblboostattack
							s.player.bsblboost = 0
							s.player.bsblboostattack = 0
							P_SetObjectMomZ(s, 15*FRACUNIT, true)
							s.momz = $*-1
							end		
						return false
						
						elseif s.sam_deathball and not (m.flags2 & MF2_FRET)
						
							P_StartQuake(30*FRACUNIT, 6)
							P_SamFP(s.player, PAL_MIXUP, 2)
							s.dsp = P_SpawnMobj(s.x, s.y, s.z+s.height, MT_THOK)
							s.dsp.height = 40*FRACUNIT
							s.dsp.eflags = s.eflags
							s.dsp.target = m
							s.dsp.sprite = SPR_MPR9
							s.dsp.frame = 26|FF_FULLBRIGHT|TR_TRANS10
							s.dsp.scale = 160000
							s.dsp.deathbolt = true
							if not m.player
								DeathBallImpact(s,s)
							end
							S_StartSound(s, sfx_bkpoof)
							A_SAMUSEXPLOSIONS(m, 13, MT_SMOKE, false, 2000, SKINCOLOR_YELLOW)
							A_SAMUSEXPLOSIONS(m, 8, MT_MPR1, false, 17000, SKINCOLOR_GOLD)
							P_DamageMobj(m, s, s, 2)
							return false
						else
							P_DamageMobj(m, s, s)
							if m and m.valid and not m.health
								P_SetObjectMomZ(m, 200000, false)
								P_Thrust(m, s.angle, s.player.speed+12*FRACUNIT)
							end					
							if s.player.bsblboostattack and (((s.eflags & MFE_VERTICALFLIP) and s.momz > 0) or (s.momz < 0 and not (s.eflags & MFE_VERTICALFLIP)))
								s.momz = $*-1+(FRACUNIT*P_MobjFlip(s))
							elseif s.player.samspbschargefull
								A_samquake(s, (s.player.speed/4)+7*FRACUNIT, 3, 100)
							end
							return false
						end
					else
					return false
					end
				end
			end
			if (m.type == MT_ICBLOCK) and m.icethisfool and s.player.sammorphed
			return false
			end
		end
	end
end

addHook("MobjCollide", SamJumpCollide, MT_PLAYER)
addHook("MobjMoveCollide", SamJumpCollide, MT_PLAYER)

--3 seperate functions for Spazer Charge and Combo, and Ice to reduce lag
local function BeamPopICC(s, m)
	if not (m and m.valid)
	return
	end
	if ((m.flags & MF_MONITOR) and not (m.flags & MF_NOCLIP))
		if not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
			A_SAMITEM(s, m)
		end
		return false
	end
	if (m.samreflecttime or (m.iceresist and s.type == MT_ICSHOT))
	and not (s.z > m.z+(m.height*10/7)) and not (m.z > s.z+s.height)
		if not s.sambossreflect
			SamusBeamReflect(s, m)
			if s.target and s.target.player
				s.target.player.sam_resisthud = 18
			end
			if s.target
				s.sambossreflect = s.target
			else
				s.sambossreflect = m
			end
				
			s.target = m
			return false
		else
			return false
		end
	end
	if (m.type == MT_BIGMINE)
		P_SpawnMobj(m.x, m.y, m.z, MT_UWEXPLODE)
		m.state = S_NULL
		return false
	end
		if not m.health
		return
		end
		if (m.flags & (MF_ENEMY|MF_BOSS)) and (m.flags & MF_SHOOTABLE) and not m.frozenbox
		and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
		and (m.type != MT_EGGSHIELD)
				if (m.type == MT_METROIDLARVA)
				P_DamageMobj(m, s, s.target)
				P_ExplodeMissile(s) --Don't freeze, just kill.
					if s.target and s.target.player
					s.target.player.sam_crithud = 18
					end
				return
				end
				if ((s.type == MT_ICSHOT) and m.iceresist)
					if s.target and s.target.player
					s.target.player.sam_resisthud = 18
					end
				elseif not ((s.type == MT_ICSHOT) and m.iceresist)
					if m.iceweak
						if s.target and s.target.player
						s.target.player.sam_crithud = 18
						end
					A_SAMUSEXPLOSIONS(m, 7, MT_SMOKE, false, 1000, SKINCOLOR_BLACK)
					A_SAMUSEXPLOSIONS(m, 7, MT_MPR8, false, 90000, SKINCOLOR_SKY, "nii")
					A_SAMUSEXPLOSIONS(m, 4, MT_MPR8, false, 8000, SKINCOLOR_WHITE, "nii")
					end
					if (m.type == MT_METROID) or (m.type == MT_METROIDLARVA) or (m.type == MT_SUPERMETROID) or (m.type == MT_METROIDPART) --Metroids use custom behaviour
					P_DamageMobj(m, s, s)
					P_ExplodeMissile(s)
					else
					m.frozenmobj = P_SpawnMobj(m.x, m.y, m.z, MT_FREEZETRACKER)
					m.frozenmobj.chozobox = m
					m.frozenmobj.samusshooter = s.target
					P_ExplodeMissile(s)
					end
				end
		end
		if m and m.valid and (m.type == MT_ICBLOCK)
		and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
			if (s.type == MT_ICSHOT)
				m.refreshiceblock = true
				return true
			else
				m.icethisfool = true
				return true
			end
		end
end
local function BeamPopSPC(s, m)
	if not (m and m.valid)
	return
	end
		if ((m.flags & MF_MONITOR) and not (m.flags & MF_NOCLIP))
			if not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
			A_SAMITEM(s, m)
			return false
			end
		end
		if m.samreflecttime
		and not (s.z > m.z+(m.height*10/7))
		and not (m.z > s.z+s.height)
			if not s.sambossreflect
			SamusBeamReflect(s, m)
				if s.target and s.target.player
				s.target.player.sam_resisthud = 18
				end
				if s.target
				s.sambossreflect = s.target
				else
				s.sambossreflect = m
				end
				s.target = m
			end
			return false
		end
		if (m.type == MT_BIGMINE)
			P_SpawnMobj(m.x, m.y, m.z, MT_UWEXPLODE)
			m.state = S_NULL
			return false
		end	
		if m.health
			if (m.type == MT_METROID or m.type == MT_SUPERMETROID)
			   SamusBeamReflect(s, m)
			   return false
			end
			if ( (m.flags & (MF_ENEMY|MF_BOSS)) or (m.player and G_GametypeHasSpectators()) ) and (m.flags & MF_SHOOTABLE)
				if not (s.z > m.z+m.height+250*FRACUNIT) and not (s.z+s.height < m.z-400*FRACUNIT)
					if not (m.flags2 & MF2_FRET) and not (m.player and m.player.powers[pw_flashing])
						if m.spcombod
							S_StartSound(s.meleeblast, sfx_smexp)
							m.spcombodoverkill = true
						end
						if not m.spcombod or (m.spcombod and (leveltime % 2 == 0))
							s.meleeblast = P_SpawnMobj(s.x, s.y, s.z, MT_SPAZERSHOCK)
							s.meleeblast.rocket = m
							s.meleeblast.mojo = true
							m.spazershocked = true
							m.spcombod = true
							S_StartSound(s.meleeblast, sfx_smexp)
							s.meleeblast.angle = s.angle
						end
						if s.target and s.meleeblast and s.meleeblast.valid
							s.meleeblast.target = s.target
						end
					S_StartSound(s.meleeblast, sfx_smexp)
					end
			   	end
			end
			if ( (m.flags & (MF_ENEMY|MF_BOSS)) or (m.player and G_GametypeHasSpectators() and not (s.target and s.target.valid and m == s.target)) ) and (m.flags & MF_SHOOTABLE)
			and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
				P_DamageMobj(m, s, s.target)
				return true
			end
			if m and m.valid and (m.type == MT_ICBLOCK)
			and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
				if (s.type == MT_ICSHOT)
				m.refreshiceblock = true
				return true
				else
				m.icethisfool = true
					if ((s.type == MT_PLSHOT) or (s.type == MT_PLCHARGESHOT))
					return false
					else
					return true
					end
				end
			end
		end
end
--Spazer Charge Shot
local function BeamPopSPS(s, m)
	if not (m and m.valid)
	return
	end
		if ((m.flags & MF_MONITOR) and not (m.flags & MF_NOCLIP))
			if not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
			A_SAMITEM(s, m)
			return false
			end
		end
		if m.samreflecttime
		and not (s.z > m.z+(m.height*10/7))
		and not (m.z > s.z+s.height)
			if not s.sambossreflect
			SamusBeamReflect(s, m)
				if s.target and s.target.player
				s.target.player.sam_resisthud = 18
				end
				if s.target
				s.sambossreflect = s.target
				else
				s.sambossreflect = m
				end
				s.target = m
			end
			return false
		end
		if (m.type == MT_BIGMINE)
			P_SpawnMobj(m.x, m.y, m.z, MT_UWEXPLODE)
			m.state = S_NULL
			return false
		end	
		if m.health
 			if s.meleeshot == nil or m.spazershocked
				return false
 			end
			if ( (m.flags & (MF_ENEMY|MF_BOSS)) or (m.player and G_GametypeHasSpectators()) ) and (m.flags & MF_SHOOTABLE)
			and not (m.type == MT_METROID or m.type == MT_SUPERMETROID)
			   if s.meleeshot and not (s.z > m.z+m.height+60*FRACUNIT)
			   and not (s.z+s.height < m.z-60*FRACUNIT) or not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
				if s.meleeshot
					s.meleeblast = P_SpawnMobj(s.x, s.y, s.z, MT_SPAZERSHOCK)
					s.meleeblast.rocket = m
					m.spazershocked = true
					s.meleeblast.angle = s.angle
					if s.target
						s.meleeblast.target = s.target
						s.meleeblast.tracer = s.target
					end

					S_StartSound(s.meleeblast, sfx_smexp)
					S_StartSound(s.meleeblast, sfx_smexp)
					P_ExplodeMissile(s)
					return false

				elseif not m.spazershocked
					P_DamageMobj(m, s, s.target, 1)
					return true
				end
			   end
			end
			if ( (m.flags & (MF_ENEMY|MF_BOSS)) or (m.player and G_GametypeHasSpectators() and not (s.target and s.target.valid and m == s.target)) ) and (m.flags & MF_SHOOTABLE)
			and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
				P_DamageMobj(m, s, s.target)
				return true
			end
			if m and m.valid and (m.type == MT_ICBLOCK)
			and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
				if (s.type == MT_ICSHOT)
				m.refreshiceblock = true
				return true
				else
				m.icethisfool = true
					if ((s.type == MT_PLSHOT) or (s.type == MT_PLCHARGESHOT))
					return false
					else
					return true
					end
				end
			end
		end
end
--Plasma Shot variants
local function BeamPopPLS(s, m)
	if not (m and m.valid)
	return false
	end
		if ((m.flags & MF_MONITOR) and not (m.flags & MF_NOCLIP))
			if s.gattlingvortex and not (s.z+s.height+70*FRACUNIT < m.z) and not (s.z > m.z+m.height+70*FRACUNIT)
			or not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
			A_SAMITEM(s, m)
			return false
			end
		end
		if m.samreflecttime
		and not (s.z > m.z+(m.height*10/7)) and not (m.z > s.z+s.height)
			if not s.sambossreflect
			SamusBeamReflect(s, m)
				if s.target and s.target.player
				s.target.player.sam_resisthud = 18
				end
				if s.target
				s.sambossreflect = s.target
				else
				s.sambossreflect = m
				end				
				s.target = m
				return false
			else
			return false
			end
		end
		if (m.type == MT_BIGMINE)
			P_SpawnMobj(m.x, m.y, m.z, MT_UWEXPLODE)
			m.state = S_NULL
			return false
		end
		if not m.health
		return false
		end
		if ( ((m.flags & (MF_ENEMY|MF_BOSS)) and (m.flags & MF_SHOOTABLE)) or (m.type == MT_EGGSHIELD) )
				if s.gattlingvortex and not (s.z+s.height+220*FRACUNIT < m.z) and not (s.z > m.z+m.height+220*FRACUNIT)
				or (s.type == MT_PLCHARGESHOT) and not (s.z > m.z+m.height+(s.height*3)) and not (s.z+(s.height*3) < m.z)
				or not (s.z > m.z+m.height+(s.height*2)) and not (s.z+(s.height*2) < m.z)
			   
					if (m.type == MT_EGGSHIELD)
						if m.target and (m.target.type == MT_EGGGUARD) and (m.target.health)
							m.target.flags = $|MF_ENEMY|MF_SHOOTABLE
						end
						P_KillMobj(m, s, s.target)
					else
						P_DamageMobj(m, s, s.target, 1)
					end
					return false
			  	end
		elseif m.player and G_GametypeHasSpectators()
			if s.gattlingvortex and not (s.z+s.height+170*FRACUNIT < m.z) and not (s.z > m.z+m.height+170*FRACUNIT)
			or (s.type == MT_PLCHARGESHOT) and not (s.z > m.z+m.height+(s.height*3)) and not (s.z+(s.height*3) < m.z)
			or not (s.z > m.z+m.height+(s.height*2)) and not (s.z+(s.height*2) < m.z)
				P_Thrust(m, s.angle, 145355)
				P_DamageMobj(m, s, s.target, 1)
				if not s.pierced
					s.pierced = true
				end
				return false
			end
		end
		if m and m.valid and (m.type == MT_ICBLOCK)
		and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
			m.icethisfool = true
			return false
		end
end
local function BeamPop(s, m)
	if not (m and m.valid)
	return
	end
		if (s.type == MT_SAMMONBREAKER) 
			if (m.flags & MF_MONITOR) and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
				A_SAMITEM(s, m)
			end
			return false
		elseif ((m.flags & MF_MONITOR) and not (m.flags & MF_NOCLIP))
			if ((s.type == MT_WVCHARGESHOT) and s.bufferguard) and not ((s.z > m.z+m.height+99*FRACUNIT) and not (s.z+s.height+99*FRACUNIT < m.z))
			or not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
				A_SAMITEM(s, m)
			else
				return false
			end
		end
		if (m.samreflecttime or m.missileresist and (s.type == MT_SAMMISSILE))
		and not (s.z > m.z+(m.height*10/7)) and not (m.z > s.z+s.height) and not (s.type == MT_HBSHOT) and not ((s.type == MT_WVCHARGESHOT) and s.bufferguard)
			if not s.sambossreflect
			SamusBeamReflect(s, m)
				if s.target and s.target.player
				s.target.player.sam_resisthud = 18
				end
				if s.target
				s.sambossreflect = s.target
				else
				s.sambossreflect = m
				end
				
				s.target = m
				return false
			else
			return false
			end
		end
		if (m.type == MT_BIGMINE)
			P_SpawnMobj(m.x, m.y, m.z, MT_UWEXPLODE)
			m.state = S_NULL
			return false
		end
		if not m.health
		return
		end
		if (s.type == MT_SPSHOT)
			if ( (m.flags & (MF_ENEMY|MF_BOSS)) or (m.player and G_GametypeHasSpectators()) ) and (m.flags & MF_SHOOTABLE)
			and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
				if s.lilbro1 and s.lilbro1.valid
				P_ExplodeMissile(s.lilbro1)
				end
				if s.lilbro2 and s.lilbro2.valid
				P_ExplodeMissile(s.lilbro2)
				end
				if s.lilbro3 and s.lilbro3.valid
				P_ExplodeMissile(s.lilbro3)
				end
			end
		elseif (s.type == MT_WVCHARGESHOT)
			if ( (m.flags & (MF_ENEMY|MF_BOSS)) or (m.player and G_GametypeHasSpectators()) ) and (m.flags & MF_SHOOTABLE)
			and not ( ((s.z > m.z+m.height+30*FRACUNIT) or (s.z+s.height < m.z-30*FRACUNIT)) and (m.flags & (MF_ENEMY|MF_BOSS)) and s.bufferguard )
			and not ( ((s.z > m.z+m.height) or (s.z+s.height < m.z)) and (m.flags & (MF_ENEMY|MF_BOSS)) and not s.bufferguard)
			and not ( ((s.z > m.z+m.height) or (s.z+s.height < m.z)) and (m.player))
				P_DamageMobj(m, s, s.target, 1)
			return true
			end
		elseif (s.type == MT_WVSHOT)
			if m.player and (s.target and s.target.type == MT_WVCHARGESHOT)
				return false
			end
			if ( (m.flags & (MF_ENEMY|MF_BOSS)) or (m.player and G_GametypeHasSpectators()) ) and (m.flags & MF_SHOOTABLE)
			and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
				if s.lilbro1 and s.lilbro1.valid
					P_ExplodeMissile(s.lilbro1)
				end
				if s.lilbro2 and s.lilbro2.valid
					P_ExplodeMissile(s.lilbro2)
				end
				if s.valid
					s.flags = $ & ~MF_BOUNCE & ~MF_GRENADEBOUNCE
				end
			end
		elseif ((s.type == MT_SAMMBOP) or (s.type == MT_HBSHOT) or (s.type == MT_SAMSUPERMISSILE))
			if (m.type == MT_EGGSHIELD)	and (s.type == MT_HBSHOT)	
				if m.target and (m.target.type == MT_EGGGUARD) and (m.target.health)
					m.target.flags = $|MF_ENEMY|MF_SHOOTABLE
					m.target.state = S_EGGGUARD_RUN1
				end
				m.state = S_NULL
				return false
			elseif ( (m.flags & (MF_ENEMY|MF_BOSS)) or (m.player and G_GametypeHasSpectators()) ) and (m.flags & MF_SHOOTABLE)
			and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
				if (s.type == MT_HBSHOT)
					s.meleeblast = P_SpawnMobj(s.x, s.y, s.z, MT_SPAZERSHOCK)
					s.meleeblast.rocket = m
					m.spazershocked = true
					s.meleeblast.angle = s.angle
					if s.target
					s.meleeblast.target = s.target
					s.meleeblast.hypered = true
					end

					S_StartSound(s.meleeblast, sfx_smexp)
					S_StartSound(s.meleeblast, sfx_smexp)
					P_ExplodeMissile(s)
					return false
				elseif (s.type == MT_SAMMBOP)
					P_DamageMobj(m, s, s.target, 3)
				else
					P_DamageMobj(m, s, s.target, 2)
					return true
				end
			end
		elseif ((s.type == MT_SAMMISSILE) or (s.type == MT_PBCHARGESHOT) or (s.type == MT_WVCHARGESHOT) or (s.type == MT_SPCHARGESHOT))
			if ( (m.flags & (MF_ENEMY|MF_BOSS)) or (m.player and G_GametypeHasSpectators() and not (s.target and s.target.valid and m == s.target)) ) and (m.flags & MF_SHOOTABLE)
			and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
				if (s.type == MT_SAMMISSILE) or (s.type == MT_PBCHARGESHOT)
				P_ExplodeMissile(s)
				return false
				else
				P_DamageMobj(m, s, s.target)
				return true
				end
			end
		end
		if m and m.valid and (m.type == MT_ICBLOCK)
		and not (s.z > m.z+m.height) and not (s.z+s.height < m.z)
			m.icethisfool = true
			return true
		end
end

addHook("MobjMoveCollide", BeamPop, MT_PBSHOT)
addHook("MobjMoveCollide", BeamPop, MT_SAMMONBREAKER)
addHook("MobjMoveCollide", BeamPop, MT_SPSHOT)
addHook("MobjMoveCollide", BeamPopSPS, MT_SPCHARGESHOT)
addHook("MobjMoveCollide", BeamPopSPC, MT_SPCHARGECOMBO)
addHook("MobjMoveCollide", BeamPop, MT_WVSHOT)
addHook("MobjMoveCollide", BeamPop, MT_WVCHARGESHOT)
addHook("MobjMoveCollide", BeamPopICC, MT_ICSHOT)
addHook("MobjCollide", BeamPop, MT_ICSHOT)
addHook("MobjMoveCollide", BeamPopICC, MT_ICCHARGESHOT)
addHook("MobjMoveCollide", BeamPopICC, MT_ICCHARGECOMBO)
addHook("MobjMoveCollide", BeamPopPLS, MT_PLSHOT)
addHook("MobjMoveCollide", BeamPopPLS, MT_PLCHARGESHOT)
addHook("MobjMoveCollide", BeamPop, MT_PBCHARGESHOT)
addHook("MobjMoveCollide", BeamPop, MT_HBSHOT)
addHook("MobjMoveCollide", BeamPop, MT_SAMMISSILE)
addHook("MobjMoveCollide", BeamPop, MT_SAMSUPERMISSILE)
addHook("MobjMoveCollide", BeamPop, MT_SAMMORPHBOMB)


local function NotForSamus(s, m) --Don't steal dropped weapons or rings. Samus is OP enough as is to normal characters
	if G_GametypeHasSpectators() and m and YouAreSamus(m)
		if ((s.flags2 & MF2_DONTRESPAWN) or (s.type == MT_FLINGRING) or (s.type == MT_FLINGCOIN))
		return false
		end
	end
end
for d = MT_BOUNCERING,MT_GRENADEPICKUP
	addHook("MobjCollide", NotForSamus, d)
end
for d = MT_BOUNCERING,MT_GRENADEPICKUP
	addHook("MobjMoveCollide", NotForSamus, d)
end
addHook("MobjCollide", NotForSamus, MT_FLINGRING)
addHook("MobjCollide", NotForSamus, MT_FLINGCOIN) 
addHook("MobjMoveCollide", NotForSamus, MT_FLINGRING)
addHook("MobjMoveCollide", NotForSamus, MT_FLINGCOIN)

addHook("MobjCollide", function(s, v)
	if not (v and v.player and v.valid)
		return
	end
	if not ( YouAreSamus(v) and
	(v.player.samspbschargefull or v.player.bsblboostattack 
	or v.sam_deathball or v.player.sam_screwattacking) )
		return
	end
	if (v.z > s.z+s.height+12*FRACUNIT)
	or (s.z > v.z+v.height)
		return
	else
		P_KillMobj(s, v, v)
		return false
	end
end, MT_SPIKE)

rawset(_G, "SamusBeamReflect", function(s, m) --s = Missile, m = Enemy Mobj
local sammom = false
		if not (s.target == m) --Already reflected....
			if not (S_SoundPlaying(s, sfx_bmrefl))
			and not (S_SoundPlaying(s.target, sfx_bmrefl))
				S_StartSound(s, sfx_bmrefl)
			end
		s.momx = ($*-1)/2
		s.momy = ($*-1)/2
		s.momz = ($*-1)/2
		if s.target and s.target.valid and YouAreSamus(s.target)
			s.target.bmreflwarning = 16
			s.target.player.sam_resisthud = 18
		end
		s.tracer = m
		s.target = m
		s.sambeamreflected = true
			for d = 1,3
			local ghs = P_SpawnMobj(s.x, s.y, s.z+s.height/4, MT_PBEXPAND)
			ghs.scale = (s.scale/5)*d
			ghs.scalespeed = $*(6*d)
			ghs.destscale = $*99
			ghs.tics = 6
			ghs.colorized = true
			ghs.color = SKINCOLOR_SUPERSILVER1+d
			end
		end
end)

local function FuckMinecarts(v, h)
		if (h and h.valid and (h.type == MT_SAMSUPERMISSILE))
		and not (v.flags & MF_NOCLIP)
			if (v.z > h.z+80*FRACUNIT)
			or (h.z > v.z+80*FRACUNIT)
			return false
			end		
				S_StartSound(v, sfx_smexp)
				v.hh = P_SpawnMobj(v.x, v.y, v.z, MT_BOSSEXPLODE)
				v.hh.scale = $*6
				v.hh.flags2 = $|MF2_SHADOW
				v.hh.blendmode = AST_ADD
				for d = 0,12
					local debris = P_SpawnMobj(v.x+(P_RandomRange(-50,50)*v.scale), v.y+(P_RandomRange(-50,50)*v.scale), v.z+(P_RandomRange(5,80)*v.scale), MT_WOODDEBRIS)
					if debris and debris.valid
					debris.flags = $|MF_BOUNCE|MF_GRENADEBOUNCE|MF_NOCLIPTHING
					P_InstaThrust(debris, h.angle+(P_RandomRange(-20,20)*ANG1), 27*FRACUNIT)
					P_SetObjectMomZ(debris, P_RandomRange(-4,11)*FRACUNIT, false)
					end
				end
				
				if (v.type == MT_SALOONDOOR)
				v.flags = $|MF_NOCLIP
				P_KillMobj(v, h, h)
				elseif (v.type == MT_SALOONDOORCENTER)
				v.flags = $|MF_NOCLIP
				end
				return true
		end
end
addHook("MobjCollide", FuckMinecarts, MT_SALOONDOOR)
addHook("MobjMoveCollide", FuckMinecarts, MT_SALOONDOORCENTER)
addHook("MobjCollide", FuckMinecarts, MT_SALOONDOORCENTER)
addHook("MobjMoveCollide", FuckMinecarts, MT_SALOONDOOR)

--Fused Mobjcollide hook for MT_PLAYER		

addHook("MobjCollide", function(s, v)
	if not YouAreSamus(s) and s.player
	return
	end
	if not (v and v.valid)
	return
	end
	if v.player
		if G_GametypeHasSpectators()
		or s.player.bsblboostattack
		or s.sam_deathball
		or s.player.sam_shinesparkfly and (s.player.sam_shinesparkfly > 17)
			or s.player.sam_screwattacking and (s.player.sam_screwattacking >= 25)
			if not ((v.z > s.z+s.height+4*FRACUNIT)
			or (s.z > v.z+v.height+4*FRACUNIT))
			
				if s.player.bsblboostattack and not ((gametype == GT_COOP or gametype == GT_RACE) and s.player.morphcoop)
					if P_IsObjectOnGround(s)
						P_InstaThrust(s, s.angle, -15*FRACUNIT)
						P_SetObjectMomZ(s, 4*FRACUNIT, true)
					else
						P_Thrust(s, s.angle, -8*FRACUNIT)
						s.momz = $*-1
					end
					if not G_GametypeHasSpectators()
					P_DoPlayerPain(v.player, i, so)
					P_PlayRinglossSound(v)
					P_Thrust(v, s.angle, 11*FRACUNIT)
					P_SetObjectMomZ(v, -2*FRACUNIT, true)
					end
				
					P_DamageMobj(v, s, s, 1)
					s.player.bsblboost = 0
					s.player.bsblboostattack = 0
					s.player.sambsblchargefull = false

					if not s.player.powers[pw_flashing] s.player.powers[pw_flashing] = 8 end
					return false
				
				elseif s.player.sam_shinesparkfly
					P_DamageMobj(v, s, s, 2)
					P_InstaThrust(v, s.angle, 35*FRACUNIT)
					if not s.player.powers[pw_flashing] s.player.powers[pw_flashing] = 30 end
					return false
			
				elseif s.player.sam_screwattacking
					P_DamageMobj(v, s, s, 2)
					return false
				end
			end
		end
	end	
	if not (((s.player.sam_shinesparkfly and (s.player.sam_shinesparkfly > 17)) or s.player.sam_screwattacking or s.crystalflashanim))
	or not ((v.flags & (MF_ENEMY|MF_BOSS|MF_MISSILE) or (v.type == MT_ENERGYBALL)))
		return
	end
	if s.player.sam_shinesparkfly and not (v.player and v.player.sammorphed)
		if (v.z > s.z+s.height+16*FRACUNIT) --Very generous hitbox.
		or (s.z > v.z+v.height+16*FRACUNIT)
		return
		end
	else
		if (v.z > s.z+s.height)
		or (s.z > v.z+v.height)
		return 
		end
	end
	if not (v.type == MT_HBSHOT) --Never with Hyper Beam shots.
		if (s.player.sam_shinesparkfly or (s.player.sam_screwattacking and (s.player.sam_screwattacking > 24) and not s.screwattackfling) or s.crystalflashanim)
			if (v.flags & (MF_ENEMY|MF_BOSS)) and v.health		
			P_DamageMobj(v, s, s, 2)
				return false
			elseif ((v.flags & MF_MISSILE) or (v.type == MT_ENERGYBALL)) and not (v.target and (v.target == s))
				SamusBeamReflect(v, s)
				if (v.type == MT_ENERGYBALL)
				v.flags = $|MF_MISSILE & ~MF_PAIN
				v.fuse = 60
				end
				return false
			else
				return false
			end
		end
	end
	if s.crystalflashanim
		return false
	end
end, MT_PLAYER)


addHook("MobjMoveCollide", function(s, v)
	if (v and YouAreSamus(v))
		return false
	end
end, MT_EXTRALARGEBUBBLE)
addHook("MobjCollide", function(s, v)
	if (v and YouAreSamus(v))
		return false
	end
end, MT_EXTRALARGEBUBBLE)

addHook("MobjThinker", function(s)
		if not s.givesamusatimer
		s.givesamusatimer = 0
		end
		if (s.givesamusatimer < 4)
			for p in players.iterate
			p.samushasatimer = true
			end
		elseif (s.givesamusatimer < 180)
		s.givesamusatimer = 0
		end
		s.givesamusatimer = $+1
end, MT_METALSONIC_RACE)

local function TokenSamCol(chaosany, s)
if (CBW_Chaos and gametype == GT_CHAOS)
return
end
	if chaosany and chaosany.valid and s and s.player
		if (((YouAreSamus(s)) and not s.player.tokensrb2style) or (s.player.tokensrb2style and s.player.tokensrb2style == 1))
		and s.health
		and not (chaosany.z > s.z+(s.height*3/2))
		and not (s.z > chaosany.z+chaosany.height*2)
	  		if All7Emeralds(emeralds)
			S_StartSound(s, sfx_s3k34)
			P_GivePlayerRings(s.player, 50) --'cause screw points.
	   		else
			print("\x83"+s.player.name+" will get a Chaos Emerald if they finish the stage without taking damage!")
			s.sam_flashfade = 19
			s.sam_flashfadecolor = SKINCOLOR_BEIGE	
			s.player.samtoken = s.player.samtoken and $+1 or 1
			S_StartSound(nil, sfx_s3k9c)
	   		end
			
	   		if chaosany
	   	   		if chaosany.tracer
	   	  	 	P_KillMobj(chaosany.tracer)
	   	   		end
	   		P_KillMobj(chaosany)
	   		end
			
	  	return false
		
		elseif chaosany and chaosany.health and s and (YouAreSamus(s) and not s.player.tokensrb2style)
		return false
		end
	end
end
addHook("MobjCollide", TokenSamCol, MT_TOKEN)
addHook("MobjMoveCollide", TokenSamCol, MT_TOKEN)

//Burn Cacti with the Plasma Beam!

local function CactiBurn(f, s)
	if s and s.valid and (s.type >= MT_CACTI1 and s.type <= MT_CACTISMALLSEG) and (s.flags & MF_PAIN)
	and (f.readyforonemoreplant or not ((f.z > s.z+s.height) and not (f.z+f.height < s.z)) )
	s.flags = $ & ~MF_PAIN & ~MF_SOLID & ~MF_NOGRAVITY
	s.flags2 = $|MF2_DONTDRAW
	s.scale = $*P_RandomRange(0, 4)
		if not P_RandomRange(0,2)
			if P_RandomRange(0,4)
			P_SpawnMobj(f.x, f.y, f.z+f.height, MT_NRGA)
			else
			P_SpawnMobj(f.x, f.y, f.z+f.height, MT_MPKU)
			end
		end
		for d = 1,11
			A_SAMPARTICLE(s, MT_MPR5, 7, 4, -2, 8, SKINCOLOR_RED, P_RandomRange(79355, 99999))		
			if d == 1
				s.benope = P_SpawnMobj(s.x, s.y, s.z, MT_FLAMEJETFLAME)
				if s.benope and s.benope.valid
					s.benope.flags = MF_NOGRAVITY|MF_SCENERY
					s.benope.destscale = $*3
					s.benope.scalespeed = $/2
					s.benope.fuse = P_RandomRange(20, 35)
				end				
			else
				s.benope = P_SpawnMobj(s.x+(P_RandomRange(-30,30)*FRACUNIT), s.y+(P_RandomRange(-30,30)*FRACUNIT), s.z+(P_RandomRange(10,120)*FRACUNIT), MT_FLAMEJETFLAME)
				if s.benope and s.benope.valid
					s.benope.flags = MF_NOGRAVITY|MF_SCENERY
					s.benope.scale = $/P_RandomRange(2,8)
					s.benope.destscale = $*99
					s.benope.scalespeed = $/P_RandomRange(2,4)
					s.benope.fuse = P_RandomRange(20, 38)
					
					if d > 4
					s.benope.momz = P_RandomRange(2,8)*FRACUNIT
					P_InstaThrust(s.benope, P_RandomRange(1,359)*ANG1, 2*FRACUNIT)
					s.benope.scale = $/2
					s.benope.flags2 = $|MF2_SHADOW
					else
						s.benope = P_SpawnMobj(s.x+(P_RandomRange(-30,30)*FRACUNIT), s.y+(P_RandomRange(-30,30)*FRACUNIT), s.z+(P_RandomRange(10,120)*FRACUNIT), MT_SMOKE)
						if s.benope and s.benope.valid
							s.benope.flags = MF_NOGRAVITY|MF_SCENERY
							s.benope.scale = $/P_RandomRange(1,3)
							s.benope.destscale = $*99
							s.benope.scalespeed = $/P_RandomRange(2,3)
							s.benope.fuse = P_RandomRange(20, 38)
							s.benope.momz = P_RandomRange(3,8)*FRACUNIT
							P_InstaThrust(s.benope, P_RandomRange(1,359)*ANG1, 4*FRACUNIT)
						end						
					end
				end
			end
		end
		S_StartSound(s, sfx_s3k7f)
		S_StartSound(s, sfx_s248)
	end
end
addHook("MobjMoveCollide", CactiBurn, MT_PLSHOT)
addHook("MobjMoveCollide", CactiBurn, MT_PLCHARGESHOT)

local function ShieldNope(f, s)
	if s and s.valid and (s.zap or (s.type == MT_EGGGUARD))
	return false
	end
end
addHook("MobjMoveCollide", ShieldNope, MT_EGGSHIELD)
addHook("MobjCollide", ShieldNope, MT_EGGSHIELD)

local function LockOn(s, m)
	if s.target and s.target.valid and s.target.player
	and m.valid and m.health
		if ( (m.flags & MF_ENEMY) or (m.flags & MF_BOSS) or (m.type == MT_METROIDPART and m.hitbox) or (m.type == MT_SAMDUMMYTRACKER)
		or (m.type == MT_ICBLOCK) or (m.type == MT_EGGGUARD) or (m.type == MT_EGGSHIELD)
		
		or (  ((m.flags & MF_MONITOR) and not s.target.player.sam_lockonnomon and (FixedHypot(m.x-s.target.x, m.y-s.target.y) < 1400*FRACUNIT))
		and not (m.type == MT_EGGMAN_BOX) and not (m.type == MT_EGGMAN_GOLDBOX)
		and not (G_GametypeHasTeams() and ((m.type == MT_RING_REDBOX) and s.target.player.ctfteam == 2) or ((m.type == MT_RING_BLUEBOX) and s.target.player.ctfteam == 1)) 
		
		or (m.player and G_GametypeHasSpectators() and m != s.target and not (G_GametypeHasTeams() and s.target.player.ctfteam == m.player.ctfteam) ) ) )
				if not P_CheckSight(s.target, m)
				or (m.brakandco and not ((m.type == MT_POPUPTURRET) or m.superbrak))
				or m.metroidstatue
				or (m.flags & MF_MONITOR) and s.target.player.sam_lockonnomon
				return false
				end
				if (s.z > m.z+2000*FRACUNIT) --Generous height difference
				or (m.z > s.z+2000*FRACUNIT)
				return false
				end
				if s.target.sam_lockclosest == nil --Don't prioritize this target if it's further away than our last checked target.
				or ((FixedHypot(m.x-s.target.x, m.y-s.target.y)) <= (s.target.sam_lockclosest))
					if (m.flags & MF_MONITOR)
						if s.target.sam_lockchosen and s.target.sam_lockchosen.valid 
						and not (s.target.sam_lockchosen.flags & MF_MONITOR)
							return false
						elseif not G_GametypeHasSpectators()
							if (s.target.player.samusnum and m.samgotme and (m.samgotme & (s.target.player.samusnum)))
							or m.samgotme and (m.samgotme == s.target.player.samusnum) 
							or (players[0] and s.target.player == players[0] and m.samgotmehost) 
							return false
							end
						end
					end
					s.target.sam_lockclosest = (FixedHypot(m.x-s.target.x, m.y-s.target.y))
					s.target.target = m
					s.target.sam_lockchosen = m		
				end
		end
	end
return false -- Always return false.	
end
addHook("MobjMoveCollide", LockOn, MT_SAMUSLOCKSEEK)
addHook("MobjCollide", LockOn, MT_SAMUSLOCKSEEK)


--But Samus-chan, I have no hitbooox.....fuck you, game. You do now.
local function DummyHBadd(s)
	if s.valid and not s.dummyhb2 and s.health
	and not (s.brakandco or s.metroidstatue)
	s.dummyhb2 = P_SpawnMobj(s.x, s.y, s.z, MT_SAMDUMMYTRACKER)
	s.dummyhb2.target = s
	s.dummyhb2.height = s.height
	s.dummyhb2.raidus = s.radius
	s.dummyhb2.tics = -1
	s.dummyhb2.flags2 = $|MF2_DONTDRAW
	s.dummyhb2.dummyhbx2 = true
	end
end

addHook("MobjThinker", DummyHBadd, MT_METALSONIC_BATTLE)
addHook("MobjThinker", DummyHBadd, MT_BLACKEGGMAN)

local function TrackerCollide(s, v)
	if v
		if v.type == MT_SAMUSLOCKSEEK
		return
		else
		return false
		end
	end
return false
end

addHook("MobjCollide", TrackerCollide, MT_SAMDUMMYTRACKER)
addHook("MobjMoveCollide", TrackerCollide, MT_SAMDUMMYTRACKER)

local function SamWJCollide(s, v)
	if v and v.valid
		if v.player or (v.flags & MF_MONITOR) or (v.flags & MF_ENEMY)
		or (v.flags & MF_PAIN) or (v.flags & MF_MISSILE) or (v.flags & MF_BOSS)
		return false
		end
	end
return false
end
addHook("MobjCollide", SamWJCollide, MT_SAMWALLJUMP)
addHook("MobjMoveCollide", SamWJCollide, MT_SAMWALLJUMP)

addHook("MobjThinker", function(s)
	if s.target
local t = s.target
			if s.target.valid and s.target.health
				P_MoveOrigin(s, t.x, t.y, t.z)
			elseif s.valid
				s.state = S_NULL
			end
			return
	elseif s.valid
		P_KillMobj(s, s)
		return
	end
end, MT_SAMDUMMYTRACKER)

--Give some wall collission grace.
/*
addHook("MobjMoveBlocked", function(s)
	if YouAreSamus(s) and s.player
	and not s.player.powers[pw_carry]
	and not s.currentaxis and not (s.flags2 & MF2_TWOD or twodlevel)
local p = s.player
		if (p.cmd.forwardmove or p.cmd.sidemove)
		and ( ((p.speed > 20*s.scale) and (p.sammorphed or p.samspbschargefull)) or (p.sam_walljumping > 10) )
			if (p.sam_negatewallc < 5)
				p.sam_negatewallc = $+3
				print("Negate, boi")
				return true
			end
		end
	end
end, MT_PLAYER)*/

--Correct where the shot lands, since SRB2's default detection sucks.

local function MoveCorrector(s, thing, line)
	if line and line.valid
		if s.valid
		local x,y = P_ClosestPointOnLine(s.x, s.y, line)
		s.sam_correctangle = R_PointToAngle2(s.x, s.y, x, y)
		s.sam_correctdist = R_PointToDist2(s.x, s.y, x, y)-(s.radius+(s.radius/11))
		s.sam_hitline = line
		end
	end
end
addHook("MobjMoveBlocked", MoveCorrector, MT_PBSHOT)
addHook("MobjMoveBlocked", MoveCorrector, MT_PLSHOT)
addHook("MobjMoveBlocked", MoveCorrector, MT_PLCHARGESHOT)
addHook("MobjMoveBlocked", MoveCorrector, MT_SPSHOT)