--=============================GFX Functions 3========================================
--Flame effects dedicated to SPR_SMX5! Because some just want to see Greenflower burn.
--====================================================================================

--Flaming impact! Spawn enormous slanted flames for an incredible impact!
rawset(_G, "SMS_FlamingImpact", function(s, COLOR, NUM, SCALE, ALTFRAME, FUSE, ZANGLE, OFFSET)

	local SCALE = (SCALE) or FRACUNIT
	local dist = FixedDiv(FixedMul(48<<16, SCALE), FRACUNIT)
	local NO = NUM	
	if NO == nil
		NO = 4
	elseif NO == 0
		dist = 2
	end
	local RNGangle = SMSLocalRNG(0,77,s)*ANG1
	local RNGZangle = (ZANGLE) or SMSLocalRNG(0,33,s)
	local COLORTABLE = SKINCOLOR_YELLOW
	if COLOR == "prism"
		COLORTABLE = {SKINCOLOR_SMS3R, SKINCOLOR_ORANGE, SKINCOLOR_RED, SKINCOLOR_RUBY, SKINCOLOR_BLUEBELL, SKINCOLOR_SKY, SKINCOLOR_SMS2R, SKINCOLOR_SMS3R, SKINCOLOR_ORANGE, SKINCOLOR_RED,SKINCOLOR_RUBY, SKINCOLOR_PURPLE}
	end
	OFFSET = (OFFSET) or (RNGZangle and not P_IsObjectOnGround(s)) and RNGZangle*-2 or -1
	
	--Setup done!
	for i = -NO,NO
		if i == NO and NUM != 0 break end
		
		local ghs = P_SpawnMobj(
		s.x+FixedMul(dist, cos(s.angle+RNGangle+((ANGLE_180/(NO or ANGLE_180))*i))),
		s.y+FixedMul(dist, sin(s.angle+RNGangle+((ANGLE_180/(NO or ANGLE_180))*i))),
		s.z+1+OFFSET, MT_SMSAUTOFRAME)
		
		ghs.sprite = SPR_SMX5
		if ALTFRAME and (ALTFRAME & FF_REVERSESUBTRACT)
			ghs.sprite = SPR_SMX4 --Switches to SMX4! Q|FF_TRANS20|FF_REVERSESUBTRACT could be interesting?
			ALTFRAME = $ & ~FF_REVERSESUBTRACT
		end	
		ghs.frame = (ALTFRAME) or A|FF_TRANS10
		ghs.blendmode = AST_ADD
		ghs.flags2 = $|MF2_SPLAT
		if COLOR
			if COLOR == "prism"	
				ghs.color = COLORTABLE[ SMSLocalRNG(1, 12, ghs) ]
			else
				ghs.color = COLOR
			end
			ghs.colorized = true			
		end
		ghs.fuse = (FUSE) or 30
		ghs.sttfade = 22
		ghs.sttspeed = 1
		ghs.sttfirstframe = B
		ghs.sttfinalframe = C
		if SCALE
			ghs.spritexscale = SCALE
			ghs.spriteyscale = SCALE
		end
		ghs.angle = R_PointToAngle2(s.x, s.y, ghs.x, ghs.y)
		ghs.destscale = (OFFSET == -1) and ghs.scale or $*99
		
		if RNGZangle >= 5	
			ghs.renderflags = RF_FLOORSPRITE|RF_NOSPLATBILLBOARD|RF_SLOPESPLAT|RF_FULLBRIGHT|RF_NOCOLORMAPS		
			P_CreateFloorSpriteSlope(ghs)
			ghs.floorspriteslope.o = {x = s.x, y = s.y, z = s.z}
			ghs.floorspriteslope.xydirection = ghs.angle
			ghs.floorspriteslope.zangle = RNGZangle*ANG1
		else --Don't bother if it's too low!
			ghs.renderflags = RF_FLOORSPRITE|RF_NOSPLATBILLBOARD|RF_FULLBRIGHT|RF_NOCOLORMAPS		
		end
		
		P_SetObjectMomZ(ghs, 3<<16, true)
		if OFFSET != -1
			P_Thrust(ghs, ghs.angle, 8<<16)
		else
			ghs.momx = $+s.momx/2
			ghs.momy = $+s.momy/2
		end
		
		if NUM == 0
			return ghs --
		elseif (i % 2)
			if s.target and s.target.player and s.target.player == displayplayer
			or s.player and s.player == displayplayer
				if (CV_FindVar("renderer").value == 1)
					ghs.flags2 = $|MF2_DONTDRAW --Nerf for software.
				end
			end
		end
	end
end)

--A wall of mighty flames rises around the target!
rawset(_G, "SMS_FlameWalls", function(s, SCALE, SPEED, OFFSETS, ALTFRAME, COLOR, FUSE, TRACER)
	local SCALE = (SCALE) or FRACUNIT
	local DIST = FixedDiv(FixedMul(256<<16, SCALE), FRACUNIT)
	local COLORPICK = (COLOR) or SKINCOLOR_FLAME
	if COLOR == "prism"
		local COLORTABLE
		COLORTABLE = {SKINCOLOR_SMS3R, SKINCOLOR_ORANGE, SKINCOLOR_RED, SKINCOLOR_RUBY, SKINCOLOR_BLUEBELL, SKINCOLOR_SKY, SKINCOLOR_SMS2R, SKINCOLOR_SMS3R, SKINCOLOR_ORANGE, SKINCOLOR_RED,SKINCOLOR_RUBY, SKINCOLOR_PURPLE}
		COLORPICK = COLORTABLE[ SMSLocalRNG(1, 12, s) ]
	end	
	for i = -4,3
		local ghs = P_SpawnMobj( 
		s.x+FixedMul(DIST, cos(s.angle+(ANGLE_45*i)) ),
		s.y+FixedMul(DIST, sin(s.angle+(ANGLE_45*i)) ),
		s.z-(DIST/2), MT_SMSAUTOFRAME)

		ghs.sprite = SPR_SMX5
		if ALTFRAME and (ALTFRAME & FF_REVERSESUBTRACT)
			ghs.sprite = SPR_SMX4 --Switches to SMX4! Q|FF_TRANS20|FF_REVERSESUBTRACT could be interesting?
			ALTFRAME = $ & ~FF_REVERSESUBTRACT
		end	
		ghs.frame = (ALTFRAME) or A|FF_TRANS10
		ghs.blendmode = AST_ADD
		ghs.eflags = s.eflags
		ghs.renderflags = RF_PAPERSPRITE|RF_FULLBRIGHT|RF_NOCOLORMAPS
		ghs.color = COLORPICK
		ghs.angle = R_PointToAngle2(s.x, s.y, ghs.x, ghs.y)+ANGLE_90
		ghs.fuse = (FUSE) or 40
		ghs.sttfade = 20
		ghs.sttYspeed = (SPEED) or 28<<16 --Rise up at this speed!
		if (SCALE)
			ghs.spritexscale = SCALE
			ghs.spriteyscale = SCALE
		end
	/*	if TRACER
			ghs.tracer = TRACER
			ghs.GSoffsetX = 256*s.scale
			ghs.GSoffsetY = 256*s.scale
			ghs.GSoffsetZ = -128*s.scale
			ghs.GSoffsetang = s.angle+(ANGLE_45*i)
		end */
		if OFFSETS --Could spawn multiple instantly this way.
			ghs.spriteyoffset = $+OFFSETS
		end
	end
end)

--Spawn a cloud of realistic smoke particles.
rawset(_G, "SMS_SmokeCircle", function(s, NUM, DIST, TRACER, CSCALE, FUSE, COLOR)
	local NO = NUM
	local dist = (DIST) or 98*s.scale	
	if NO == nil
		NO = 4
	elseif NO == 0 
		dist = 1			
	end
	for i = -NO,NO
		if i == NO and NUM != 0 break end --Break! Topple! Daze!
		local ghs = P_SpawnMobjFromMobj(s, 
		FixedMul(dist, cos(s.angle+((ANGLE_180/(NO or ANGLE_180))*i))),
		FixedMul(dist, sin(s.angle+((ANGLE_180/(NO or ANGLE_180))*i))),
		s.height/8, MT_SMSAUTOFRAME)
		ghs.sprite = SPR_SMX5
		ghs.frame = L|FF_TRANS30
		ghs.blendmode = AST_ADD
		
		if COLOR --Ok then?? 
			ghs.color = COLOR
			ghs.colorized = true
		end
		if CSCALE
			ghs.spriteyscale = CSCALE
			ghs.spritexscale = CSCALE
		end		
		ghs.fuse = (FUSE) or 38
		
		ghs.sttfade = 20
		ghs.sttfinalframe = U
		ghs.sttspeed = 4
		ghs.sttYspeed = SMSLocalRNG(0,FRACUNIT*2+32500,ghs)
		
		if NUM == 0 --Stop and only create one, returning it to the player.
			if TRACER ghs.tracer = TRACER end	
			ghs.renderflags = $ & ~RF_PAPERSPRITE
			return ghs --
		elseif TRACER
			ghs.tracer = TRACER
			ghs.GSoffsetX = dist
			ghs.GSoffsetY = dist
			ghs.GSoffsetZ = s.height/8
			ghs.GSoffsetang = s.angle+((ANGLE_180/(NO or ANGLE_180))*i)	
		end
	end
end)

--Spawn a circle of fire! A circular firewall"! Pretty much identical to SmokeCircle, but optimized to be a flamecircle" instead.
rawset(_G, "SMS_FireCircle", function(s, NUM, DIST, TRACER, CSCALE, FUSE, COLOR)
	if (s.eflags & MFE_TOUCHWATER) return end --Don't spawn in water
	local NO = NUM
	local dist = (DIST) or 98*s.scale
	if NO == nil
		NO = 4
	elseif NO == 0
		dist = 1	
	end	
	for i = -NO,NO
		if i == NO and NO != 0 break end --Break! Topple! Launch! SMASH!
		local ghs = P_SpawnMobjFromMobj(s, 
		FixedMul(dist, cos(s.angle+((ANGLE_180/(NO or ANGLE_180))*i))),
		FixedMul(dist, sin(s.angle+((ANGLE_180/(NO or ANGLE_180))*i))),
		0, MT_SMSAUTOFRAME)
		ghs.sprite = SPR_SMX5
		ghs.flags = (ghs.eflags & MFE_VERTICALFLIP) and $|MF_FIRE & ~(MF_NOCLIPHEIGHT|MF_SCENERY) or $|MF_FIRE & ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_SCENERY) 
		ghs.frame = D|FF_TRANS50
		ghs.height = 1 --So it can collide with platforms.
		ghs.blendmode = AST_ADD
		ghs.renderflags = RF_PAPERSPRITE|RF_FULLBRIGHT
		ghs.angle = R_PointToAngle2(s.x, s.y, ghs.x, ghs.y)+ANGLE_90
		
		if COLOR --Shiny prism fire?
			ghs.color = COLOR
			ghs.colorized = true
		end
		if CSCALE 
			ghs.spriteyscale = CSCALE
			ghs.spritexscale = CSCALE
		end		
		ghs.fuse = (FUSE) or 160
		
		ghs.sttfade = 24
		ghs.sttfirstframe = D
		ghs.sttfinalframe = K
		ghs.sttspeed = 1
		if NUM == 0 --Stop and only create one, returning it to the player.
			if TRACER ghs.tracer = TRACER end	
			ghs.renderflags = $ & ~RF_PAPERSPRITE
			return ghs --
		elseif TRACER --Kind of awkward, but whatever.
			ghs.flags = $ & ~MF_NOCLIPHEIGHT & ~MF_NOGRAVITY 
			ghs.tracer = s
			ghs.GSoffsetX = dist
			ghs.GSoffsetY = dist
			ghs.GSoffsetZ = 0
			ghs.GSoffsetang = s.angle+((ANGLE_180/(NO or ANGLE_180))*i)
		end
	end
end)

--Thinker for the Fire HUD, covering the screen.
rawset(_G, "SMS_FireHUD", function(s,p,yu)
	if not yu.timer --We're done.
		s.SMS_FireHUD = nil
		return --
	end
	if yu.init == nil --Setup!
		yu.init = true
		if yu.fadespeed == nil --How quickly the fade happens.
			yu.fadespeed = 2
		end
	end
	yu.timer = $-1
	--Now, fading...
	if (yu.timer < yu.fadetime)
		if not (yu.timer % yu.fadespeed == 0)
			yu.flags = min($+FF_TRANS10, FF_TRANS90)
		end
	end
	--HUD animation.
	if (yu.animspeed == 1) or (yu.timer % yu.animspeed) == 0
		yu.frame = (yu.frame > 8) and 1 or $+1
		
       --Ye olde elseif chain, never lets down a guy having a stroke.		 
		    if yu.frame == 1 yu.string = "SMX5V0"
		elseif yu.frame == 2 yu.string = "SMX5W0"
		elseif yu.frame == 3 yu.string = "SMX5X0"
		elseif yu.frame == 4 yu.string = "SMX5Y0"
		elseif yu.frame == 5 yu.string = "SMX5Z0"
		elseif yu.frame == 6 yu.string = "SMX500"
		elseif yu.frame == 7 yu.string = "SMX510"
		else yu.string = "SMX520"
		end
	end
	return true --
end)

--Inflicts a flaming HUD effect on nearby players. DIST and TIME are required.
rawset(_G, "SMS_InflictFlameHUD", function(s, DIST, TIME, FLAGS, COLOR, FADETIME, ANIMSPEED)
	local RETURNVALUE = false
	for z in players.iterate
		if z.mo and z.mo.valid 
		and not (z.mo.SMS_FireHUD and z.mo.SMS_FireHUD.timer >= TIME)
			if FixedHypot(s.x-z.mo.x, s.y-z.mo.y) <= DIST
			and (abs(s.z-z.mo.z) < DIST*5/12)

				z.mo.SMS_FireHUD = {
				timer = (TIME) or 26,
				flags = (FLAGS) or FF_TRANS30, 
				color = (COLOR) or SKINCOLOR_ORANGE,
				fadetime = (FADETIME) or 24,
				animspeed = (ANIMSPEED) or 1,
				string = "SMX5V0",
				frame = 1
				}

				RETURNVALUE	= true
			end
		end
	end
	return RETURNVALUE --
end)

--Adds a realistic fire trail to an object! Can come with or without a glowhead. Needs to be repeatedly called.
rawset(_G, "SMS_FlamingTrail", function(s, GLOWHEAD, COLOR, CSCALE, FUSE, TRACER)

	--First, spawn the tail.	
	local ghs = P_SpawnMobjFromMobj(s, 
	FixedMul(-16*s.scale, cos(s.angle)),
	FixedMul(-16*s.scale, sin(s.angle)),
	s.height/3, MT_SMSAUTOFRAME)	
	ghs.sprite = SPR_SMX5
	ghs.frame = Z+7|FF_TRANS50
	ghs.blendmode = AST_ADD
	ghs.renderflags = RF_PAPERSPRITE|RF_FULLBRIGHT
	ghs.angle = R_PointToAngle2(s.x, s.y, ghs.x, ghs.y)+(SMSLocalRNG(-36,36)*ANG1)		
	if COLOR
		ghs.color = COLOR
		ghs.colorized = true
	end
	if CSCALE 
		ghs.spriteyscale = CSCALE
		ghs.spritexscale = CSCALE
	end
	ghs.spriteyscale = max(500, $+SMSLocalRNG(30000, -30000, s) )
	ghs.spriteyxscale = max(500, $+SMSLocalRNG(30000, -30000, ghs) )
	if SMSLocalRNG(1,2,ghs) == 1
		ghs.frame = $|FF_VERTICALFLIP
	end
	ghs.fuse = 4
	ghs.sttfade = true
		
	ghs.tracer = s
	ghs.GSoffsetX = -16*s.scale
	ghs.GSoffsetY = -16*s.scale
	ghs.GSoffsetZ = s.height/3
	
	 --Wanna spawn a glowhead at front?
	if GLOWHEAD 
		local ths = P_SpawnMobjFromMobj(s, 
		FixedMul(22*s.scale, cos(s.angle)),
		FixedMul(22*s.scale, sin(s.angle)),
		s.height/2, MT_SMSAUTOFRAME)	
			ths.sprite = SPR_SMX5
			ths.frame = Z+8|FF_TRANS50|FF_FULLBRIGHT
			ths.blendmode = AST_ADD
			ths.renderflags = RF_PAPERSPRITE|RF_FULLBRIGHT
			ths.angle = R_PointToAngle2(s.x, s.y, ths.x, ths.y)+ANGLE_90
			if COLOR
				ths.color = COLOR
				ths.colorized = true
			end
			if CSCALE 
				ths.spriteyscale = CSCALE
				ths.spritexscale = CSCALE
			end
			ths.scale = s.scale/2
			ths.scalespeed = FRACUNIT/3
			ths.destscale = s.scale
			ths.fuse = (tonumber(GLOWHEAD)) and GLOWHEAD or 4
			ths.sttfade = true
			ths.sttroll = (leveltime % 2) and ANG1*SMSLocalRNG(50, 60, ths) or -ANG1*SMSLocalRNG(50, 60, ths)
			
			ths.tracer = s
			ths.GSoffsetX = 22*s.scale
			ths.GSoffsetY = 22*s.scale
			ths.GSoffsetZ = s.height/2
		return ghs,ths --Return both in this case!
	end
	return ghs --
end)

--Shortcut to doing HMS' initial flame GFX. p is needed here.
rawset(_G, "HMS_InitialFlameGFX", function(s, p, PARTIAL, PRISM)
	local ANGLE = s.angle
	if (s.hmsspinpass and s.hmsspinang != nil)
		ANGLE = s.hmsspinang
	end
	
	--Strong Flametrail!
	local ghs = P_SpawnMobjFromMobj(s,s.momx,s.momy,s.momz, MT_THOK)
	local RNG1 = SMSLocalRNG(-3,5,s)
	ghs.sprite = SPR_SMX5
	ghs.frame = (Z+9)|FF_TRANS10|FF_FULLBRIGHT
	ghs.blendmode = AST_ADD
	if SMSLocalRNG(3,4,ghs) == 3 --Flatten it out a bit.
		local RNG7 = SMSLocalRNG(0,18000,ghs)
		ghs.spritexscale = FRACUNIT*2+RNG7
		ghs.spriteyscale = FRACUNIT-RNG7
	else
		ghs.rollangle = (RNG1 < 2) and ANGLE_90 or ANGLE_270
	end
	ghs.spritexoffset = $+SMSLocalRNG(25,-25,ghs)<<16
	ghs.spriteyoffset = $+RNG1<<16
	ghs.fuse = 12+abs(RNG1)
	ghs.tics = 99
	ghs.destscale = $*99
	P_InstaThrust(ghs, ANGLE, ((20+RNG1)*s.scale)+p.speed)
	local AIMANGLE,PLUS = SMS_AngleDifference(p.aiming, 0, 2, ANG60, 3) --Our aiming angle affects it too!
	AIMANGLE = AngleFixed($)
	ghs.momz = $+(s.momz/2)+(AIMANGLE*PLUS)
	
	local COLORTABLE = {SKINCOLOR_SMS1R, SKINCOLOR_SMS2R, SKINCOLOR_SMS3R, SKINCOLOR_SMS4R, SKINCOLOR_SMS5R, SKINCOLOR_ORANGE, SKINCOLOR_RED, SKINCOLOR_LIME, SKINCOLOR_MINT}
	local COLORPICK = COLORTABLE[SMSLocalRNG(1,9,s)]	
	if PRISM
		ghs.color = COLORPICK
		ghs.colorized = true
	elseif displayplayer and (p == displayplayer) and not CV_FindVar("chasecam").value 
		ghs.flags2 = $|MF2_DONTDRAW
	end
		
	if PARTIAL or SMS_Graphix(s) == 2 return end --Skip everything, potato user abound.
	
	--A little gold circle effect that shows you're firing stuff.
	local ghs = SMS_WallJumpGFX(s, "simple", nil)
	if ghs and ghs.valid
		ghs.spriteyscale = FRACUNIT-18000
		ghs.spritexscale = FRACUNIT+8000
		ghs.fuse = (p.sms_nflamehold == 1) and 15 or 11
		ghs.blendmode = AST_ADD
		ghs.color = COLORPICK
		ghs.momx = $+s.momx
		ghs.momy = $+s.momy
		ghs.momz = $+(s.momz/2)+((AIMANGLE*PLUS)*3/2)
		P_Thrust(ghs, ANGLE, 16*s.scale)
		for i = 1,3
			P_TryMove(ghs, ghs.x+s.momx+FixedMul(28*s.scale, cos(ANGLE)), ghs.y+s.momy+FixedMul(28*s.scale, sin(ANGLE)), true)
		end
	end
	if p.sms_nflamehold == 1 --Diagionally slanted Circle Waves, only with the initial button press.
		for i = 1,-1,-2
			local ghs = P_SpawnMobjFromMobj(s,
			FixedMul(-24*s.scale, cos(ANGLE+(ANG1*92*i))), 
			FixedMul(-24*s.scale, sin(ANGLE+(ANG1*92*i))), 
			0, MT_HMSNOVAWAVE)
			ghs.scale = s.scale/6
			ghs.spritexscale = FRACUNIT*2+27500
			ghs.spriteyscale = FRACUNIT+15000
			ghs.destscale = ghs.scalespeed+1 
			ghs.tics = 1
			ghs.color = COLORPICK
			P_InstaThrust(ghs, ANGLE, 80*s.scale) --Forwards.	
			ghs.momy = $+(s.momy/2)
			ghs.momx = $+(s.momx/2)	
			ghs.momz = $+s.momz+((AIMANGLE*PLUS)*3/2)
			ghs.rollangle = (i == 1) and FixedAngle(120<<16) or FixedAngle(240<<16) --Diagional slant!
			if PLUS == 1 and p.aiming
				ghs.rollangle = $+ANGLE_180
				ghs.mirrored = true
			end
			P_Thrust(ghs, ANGLE+(ANGLE_90*i), 44*s.scale) --Sideways momentum.
		end
	end
	
	if SMS_Graphix(s) != 0 return end --Max graphics only.
	
	--Glowing light blast. First, this is the setup item to use, mainly for the sound.
	local ghs = P_SpawnMobjFromMobj(s,FixedMul(16*s.scale, cos(ANGLE)),FixedMul(16*s.scale, sin(ANGLE)), s.momz, MT_THOK)
	if p.sms_nflamehold == 1 --SFX!
		S_StartSound(ghs, sfx_s3k48)
		S_StartSound(ghs, sfx_s3k7d)
	end
	ghs.flags2 = $|MF2_DONTDRAW ghs.fuse = 69 ghs.tics = 69
	ghs.momx = s.momx*2/3
	ghs.momy = s.momy*2/3
	P_Thrust(ghs, ANGLE, 55*s.scale)
	ghs.momz = $+s.momz+(AIMANGLE*PLUS)-(11*s.scale)

	--Actual object to take advantage of it the invisible thok item's properties.
	local FRAME = (SMSLocalRNG(0,1,ghs) == 1) and Z+8|FF_TRANS10|FF_REVERSESUBTRACT or Z+9|FF_TRANS10|FF_REVERSESUBTRACT
	
	local ths = SMS_LightFlash(ghs, nil, nil, 6, FRAME)
	ths.tracer = ghs
	ths.ditchtracer = nil
	ths.dispoffset = -30
	ths.fuse = $+5
	ths.spriteyoffset = $+SMSLocalRNG(4, -8, ths)<<16
	ths.spritexscale = max(FRACUNIT/2, $+SMSLocalRNG(15000, FRACUNIT*2, ths))	
	ths.rollangle = $+SMSLocalRNG(-12,12,ths)*ANG1
	if FRAME == (Z+9|FF_TRANS10|FF_REVERSESUBTRACT)
		ths.spriteyoffset = $-18<<16
		ths.spriteyscale = $*2/3
		ths.spritexscale = $*5/8
	else
		ths.spritexscale = $+SMSLocalRNG(0,25000,s)	
	end
	if PRISM
		ghs.color = COLORPICK
		ghs.colorized = true
	end	
--	if displayplayer and (p == displayplayer) and not CV_FindVar("chasecam").value 
--		ghs.flags2 = $|MF2_DONTDRAW
--	end	
end)
